diff --git a/src/apps/cdplayer/CDDBSupport.cpp b/src/apps/cdplayer/CDDBSupport.cpp index e227ca2839..d73fb4ba89 100644 --- a/src/apps/cdplayer/CDDBSupport.cpp +++ b/src/apps/cdplayer/CDDBSupport.cpp @@ -76,18 +76,38 @@ CDDBQuery::SetToSite(const char *server, int32 port) } void -CDDBQuery::SetToCD(const scsi_toc *toc) +CDDBQuery::SetToCD(const char *path) { - if (state == kInitial) { - GetDiscID(toc, discID, numTracks, discLength, frameOffsetString, discIDStr); - } else { + if(!path) + return; + + // Get the SCSI table of contents from the device passed to us + int device = open(path, O_RDONLY); + if(device < 0) + return; + + scsi_toc toc; + status_t result = ioctl(device, B_SCSI_GET_TOC, &toc); + + close(device); + + if(result != B_OK) + return; + + + if (state == kInitial) + { + GetDiscID(&toc, discID, numTracks, discLength, frameOffsetString, discIDStr); + } + else + { int32 tmpDiscID; int32 tmpDiscLength; int32 tmpNumTracks; BString tmpFrameOffsetString; BString tmpDiscIDStr; - GetDiscID(toc, tmpDiscID, tmpNumTracks, tmpDiscLength, tmpFrameOffsetString, + GetDiscID(&toc, tmpDiscID, tmpNumTracks, tmpDiscLength, tmpFrameOffsetString, tmpDiscIDStr); if (discID == tmpDiscID && discLength == tmpDiscLength && numTracks == tmpNumTracks @@ -343,8 +363,10 @@ CDDBQuery::ReadFromServer(BDataIO *stream) BString tmp; ReadLine(tmp); if (tmp.FindFirst("200") != 0) + { + printf("Error: %s\n",tmp.String()); return; - + } BString category; GetToken(tmp.String() + 3, category); if (!category.Length()) @@ -474,7 +496,7 @@ CDDBQuery::IdentifySelf() strcpy(hostname, "unknown"); BString tmp; - tmp << "cddb hello " << username << " " << hostname << " CDButton v1.0\n"; + tmp << "cddb hello " << username << " " << hostname << " Haiku_CD_Player v1.0\n"; if (log) printf(">%s", tmp.String()); @@ -535,7 +557,9 @@ CDDBQuery::FindOrCreateContentFileForDisk(BFile *file, entry_ref *fileRef, int32 return false; } -#if 0 +/* + +#include "CDEngine.h" bool PrintSite(const char *site, int port, const char *latitude, @@ -549,35 +573,33 @@ PrintSite(const char *site, int port, const char *latitude, int main() { - try { - CDDBQuery query("us.cddb.com", 888, true); - // query.GetSites(&PrintSite, NULL); + CDDBQuery query("us.freedb.org", 888, true); int32 device = CDEngine::FindCDPlayerDevice(); - if (!device) { + if (!device) + { printf("no device %s\n", strerror(device)); return 0; } - CDEngine engine(device); + scsi_toc toc; - engine.GetToc(&toc); + ioctl(device, B_SCSI_GET_TOC, &toc); + int32 discID = query.GetDiscID(&toc); + query.SetToCD(&toc); BString title; vector trackTitles; - query.GetTitles(title, trackTitles, 10000000); + query.GetTitles(&title, &trackTitles, 10000000); - printf("CD Title:%s\n", title.String()); + printf("CD Title: %s, ID: %lx\n", title.String(), discID); int32 index = 0; for (vector::iterator iterator = trackTitles.begin(); iterator != trackTitles.end(); index++, iterator++) - printf("%d: %s\n", index, (*iterator).String()); + printf("%ld: %s\n", index, (*iterator).String()); - } catch(status_t error) { - printf("error %s\n", strerror(error)); - } return 0; } -#endif \ No newline at end of file +*/ diff --git a/src/apps/cdplayer/CDDBSupport.h b/src/apps/cdplayer/CDDBSupport.h index bbbfc7169f..954f552d87 100644 --- a/src/apps/cdplayer/CDDBSupport.h +++ b/src/apps/cdplayer/CDDBSupport.h @@ -9,14 +9,15 @@ // based on Jukebox by Chip Paul -class CDDBQuery { +class CDDBQuery +{ public: CDDBQuery(const char *server, int32 port = 888, bool log = false); void SetToSite(const char *server, int32 port); void GetSites(bool (*)(const char *site, int port, const char *latitude, const char *longitude, const char *description, void *state), void *); - void SetToCD(const scsi_toc *); + void SetToCD(const char *devicepath); bool GetTitles(BString *title, vector *tracks, bigtime_t timeout); // title or tracks may be NULL if you are only interrested in one, not the other @@ -39,25 +40,26 @@ private: static int32 LookupBinder(void *); - class Connector { - public: - Connector(CDDBQuery *client) - : client(client), - wasConnected(client->IsConnected()) - { - if (!wasConnected) - client->Connect(); - } - - ~Connector() - { - if (!wasConnected) - client->Disconnect(); - } + class Connector + { + public: + Connector(CDDBQuery *client) + : client(client), + wasConnected(client->IsConnected()) + { + if (!wasConnected) + client->Connect(); + } - private: - CDDBQuery *client; - bool wasConnected; + ~Connector() + { + if (!wasConnected) + client->Disconnect(); + } + + private: + CDDBQuery *client; + bool wasConnected; }; bool FindOrCreateContentFileForDisk(BFile *file, entry_ref *ref, int32 discID); @@ -87,7 +89,8 @@ private: BString discIDStr; // cached retrieved data - enum State { + enum State + { kInitial, kReading, kDone, diff --git a/src/apps/cdplayer/CDEngine.cpp b/src/apps/cdplayer/CDEngine.cpp index 0befe0abad..b953fdbde1 100644 --- a/src/apps/cdplayer/CDEngine.cpp +++ b/src/apps/cdplayer/CDEngine.cpp @@ -14,23 +14,18 @@ #include #include "scsi.h" #include "CDEngine.h" +#include "PlayList.h" + +static PlayList sPlayList; +static CDAudioDevice sCDDevice; const bigtime_t kPulseRate = 500000; -PeriodicWatcher::PeriodicWatcher(int devicefd) - : Notifier(), - devicefd(devicefd) +PeriodicWatcher::PeriodicWatcher(void) { } -PeriodicWatcher::PeriodicWatcher(BMessage *) - : devicefd(-1) -{ - // not implemented yet - PRINT(("under construction")); -} - BHandler * PeriodicWatcher::RecipientHandler() const { @@ -52,34 +47,29 @@ PeriodicWatcher::UpdateNow() } -PlayState::PlayState(int devicefd) - : PeriodicWatcher(devicefd), - oldState(kNoCD) +PlayState::PlayState(CDEngine *engine) + : oldState(kNoCD), + fEngine(engine) { } bool -PlayState::UpdateState() +PlayState::UpdateState(void) { - // check the current CD play state and force a notification to - // be sent if it changed from last time - scsi_position pos; - status_t media_status = B_DEV_NO_MEDIA; - ioctl(devicefd, B_GET_MEDIA_STATUS, &media_status, sizeof(media_status)); - if (media_status != B_NO_ERROR) - return CurrentState(kNoCD); - - status_t result = ioctl(devicefd, B_SCSI_GET_POSITION, &pos); - - if (result != B_NO_ERROR) - return CurrentState(kNoCD); - else if ((!pos.position[1]) || (pos.position[1] >= 0x13) || - ((pos.position[1] == 0x12) && (!pos.position[6]))) - return CurrentState(kStopped); - else if (pos.position[1] == 0x11) - return CurrentState(kPlaying); - else - return CurrentState(kPaused); + CDState state = sCDDevice.GetState(); + if( state == kStopped && fEngine->GetState() == kPlaying) + { + // this means we have come to the end of a song, but probably not + // the last song in the playlist + int16 next = sPlayList.GetNextTrack(); + if(next > 0) + { + sCDDevice.Play(next); + return CurrentState(kPlaying); + } + } + + return CurrentState(state); } CDState @@ -91,16 +81,16 @@ PlayState::GetState() const bool PlayState::CurrentState(CDState newState) { - if (newState != oldState) { + if (newState != oldState) + { oldState = newState; return true; } return false; } -TrackState::TrackState(int devicefd) - : PeriodicWatcher(devicefd), - currentTrack(0) +TrackState::TrackState(void) + : currentTrack(0) { } @@ -113,46 +103,20 @@ TrackState::GetTrack() const bool TrackState::UpdateState() { - // check the current CD track number and force a notification to - // be sent if it changed from last time - scsi_position pos; - - status_t media_status = B_DEV_NO_MEDIA; - ioctl(devicefd, B_GET_MEDIA_STATUS, &media_status, sizeof(media_status)); - if (media_status != B_NO_ERROR) - return CurrentState(-1); - - status_t result = ioctl(devicefd, B_SCSI_GET_POSITION, &pos); - - if (result != B_NO_ERROR) - return CurrentState(-1); - - if (!pos.position[1] || pos.position[1] >= 0x13 - || (pos.position[1] == 0x12 && !pos.position[6])) - return CurrentState(0); - else - return CurrentState(pos.position[6]); + return CurrentState(sPlayList.GetCurrentTrack()); } int32 TrackState::GetNumTracks() const { - // get the number of tracks on the current CD - - scsi_toc toc; - - status_t result = ioctl(devicefd, B_SCSI_GET_TOC, &toc); - - if (result != B_NO_ERROR) - return 0; - - return toc.toc_data[3]; + return sCDDevice.CountTracks(); } bool TrackState::CurrentState(int32 track) { - if (track != currentTrack) { + if (track != currentTrack) + { currentTrack = track; return true; } @@ -165,28 +129,19 @@ TimeState::UpdateState() // check the current CD time and force a notification to // be sent if it changed from last time // currently only supports global time - scsi_position pos; - - status_t media_status = B_DEV_NO_MEDIA; - ioctl(devicefd, B_GET_MEDIA_STATUS, &media_status, sizeof(media_status)); - if (media_status != B_NO_ERROR) - return CurrentState(-1, -1, -1, -1); - status_t result = ioctl(devicefd, B_SCSI_GET_POSITION, &pos); + cdaudio_time track; + cdaudio_time disc; - if (result != B_NO_ERROR) - return CurrentState(-1, -1, -1, -1); - else - if ((!pos.position[1]) || (pos.position[1] >= 0x13) || - ((pos.position[1] == 0x12) && (!pos.position[6]))) + if(sCDDevice.GetTime(track,disc)) { - // This indicates that we have a CD, but we are stopped. We *could* simply - // return all 0's, but because the GUI expects valid numbers or -1's, we - // return -1's. - return CurrentState(-1, -1, -1, -1); + return CurrentState(disc.minutes, disc.seconds, track.minutes, track.seconds); } else - return CurrentState(pos.position[9], pos.position[10], pos.position[13], pos.position[14]); + { + CurrentState(-1, -1, -1, -1); + return false; + } } bool @@ -218,17 +173,8 @@ TimeState::GetTrackTime(int32 &minutes, int32 &seconds) const } -CDContentWatcher::CDContentWatcher(int devicefd) - : PeriodicWatcher(devicefd), - cddbQuery("us.freedb.org", 888, true), - discID(-1), - fReady(false) -{ -} - -CDContentWatcher::CDContentWatcher(BMessage *message) - : PeriodicWatcher(message), - cddbQuery("us.freedb.org", 888, true), +CDContentWatcher::CDContentWatcher(void) + : cddbQuery("us.freedb.org", 888, true), discID(-1), fReady(false) { @@ -249,15 +195,13 @@ CDContentWatcher::UpdateState() // from the old one whenever there is a CD in the drive if (engine->PlayStateWatcher()->GetState() != kNoCD) { - scsi_toc toc; - ioctl(devicefd, B_SCSI_GET_TOC, &toc); - newDiscID = cddbQuery.GetDiscID(&toc); + newDiscID = sCDDevice.GetDiscID(); if (discID == newDiscID) return false; // We have changed CDs, so we are not ready until the CDDB lookup finishes - cddbQuery.SetToCD(&toc); + cddbQuery.SetToCD(sCDDevice.GetDrivePath()); fReady=false; } @@ -274,21 +218,19 @@ CDContentWatcher::UpdateState() return result; } -VolumeState::VolumeState(int devicefd) - : PeriodicWatcher(devicefd), - fVolume(-1) +VolumeState::VolumeState(void) + : fVolume(-1) { } bool VolumeState::UpdateState(void) { - scsi_volume vol; - ioctl(devicefd, B_SCSI_GET_VOLUME, &vol); - if(vol.port0_volume == fVolume) + uint8 volume = sCDDevice.GetVolume(); + if(fVolume == volume) return false; - fVolume = vol.port0_volume; + fVolume = volume; return true; } @@ -298,32 +240,16 @@ VolumeState::GetVolume(void) const return fVolume; } -CDEngine::CDEngine(int devicefd) +CDEngine::CDEngine(void) : BHandler("CDEngine"), - devicefd(devicefd), - playState(devicefd), - trackState(devicefd), - timeState(devicefd), - volumeState(devicefd), - contentWatcher(devicefd) -{ -} - -CDEngine::CDEngine(BMessage *message) - : BHandler(message), - devicefd(-1), - playState(message), - trackState(message), - timeState(message), - volumeState(message), - contentWatcher(devicefd) + playState(this), + fEngineState(kStopped) { + sPlayList.SetTrackCount(sCDDevice.CountTracks()); } CDEngine::~CDEngine() { - if(devicefd >= 0) - close(devicefd); } void @@ -337,249 +263,137 @@ CDEngine::AttachedToLooper(BLooper *looper) contentWatcher.AttachedToLooper(this); } -void -CDEngine::PlayOrPause() -{ - // if paused, or stopped, plays, if playing, pauses - playState.UpdateNow(); - switch (playState.GetState()) { - case kNoCD: - Play(); - return; - case kStopped: - Play(); - break; - case kPaused: - PlayContinue(); - break; - case kPlaying: - Pause(); - break; - default: - break; - } -} - void CDEngine::Pause() { - // pause the CD - status_t result = ioctl(devicefd, B_SCSI_PAUSE_AUDIO); - if (result != B_NO_ERROR) { - PRINT(("error %s pausing\n", strerror(errno))); - return; - } + sCDDevice.Pause(); + fEngineState = sCDDevice.GetState(); } void CDEngine::Play() { - // play the CD - if (playState.GetState() == kNoCD) + if(fEngineState == kPaused) { - // no CD available, bail out - ioctl(devicefd, B_LOAD_MEDIA, 0, 0); - return; + sCDDevice.Resume(); + fEngineState = sCDDevice.GetState(); } - - scsi_play_track track; - - track.start_track = 1; - track.start_index = 1; - track.end_track = 99; - track.end_index = 1; - - status_t result = ioctl(devicefd, B_SCSI_PLAY_TRACK, &track); - if (result != B_NO_ERROR) + else + if(fEngineState == kPlaying) { - PRINT(("error %s playing track\n", strerror(errno))); - return; + Pause(); } -} - -void -CDEngine::PlayContinue() -{ - // continue after a pause - status_t result = ioctl(devicefd, B_SCSI_RESUME_AUDIO); - if (result != B_NO_ERROR) + else { - PRINT(("error %s resuming\n", strerror(errno))); - return; + sCDDevice.Play(sPlayList.GetCurrentTrack()); + fEngineState = sCDDevice.GetState(); } } void CDEngine::Stop() { - // stop a playing CD - status_t result = ioctl(devicefd, B_SCSI_STOP_AUDIO); - if (result != B_OK) - { - PRINT(("error %s stopping\n", strerror(errno))); - return; - } + fEngineState = kStopped; + sCDDevice.Stop(); } void CDEngine::Eject() { - // eject or load a CD - status_t media_status = B_DEV_NO_MEDIA; - - // get the status first - ioctl(devicefd, B_GET_MEDIA_STATUS, &media_status, sizeof(media_status)); - - // if door open, load the media, else eject the CD - status_t result = ioctl(devicefd, - media_status == B_DEV_DOOR_OPEN ? B_LOAD_MEDIA : B_EJECT_DEVICE); - - if (result != B_OK) - { - PRINT(("error %s ejecting\n", strerror(errno))); - return; - } + sCDDevice.Eject(); + fEngineState = sCDDevice.GetState(); } void CDEngine::SkipOneForward() { - // skip forward by one track - CDState state = playState.GetState(); - - if (state == kNoCD) + int16 track = sPlayList.GetNextTrack(); + if(track <= 0) return; - - bool wasPaused = state == kPaused - || state == kStopped; - - SelectTrack(trackState.GetTrack() + 1); - if (wasPaused) - // make sure we don't start playing if we were paused before - Pause(); + + CDState state = sCDDevice.GetState(); + if(state == kPlaying) + sCDDevice.Play(track); + +// if(state == kPaused) +// sCDDevice.Pause(); } void CDEngine::SkipOneBackward() { - // skip backward by one track - CDState state = playState.GetState(); - - if (state == kNoCD) + int16 track = sPlayList.GetPreviousTrack(); + if(track <= 0) return; - - bool wasPaused = state == kPaused - || state == kStopped; - - int32 track = trackState.GetTrack(); - if (track > 1) - track--; + CDState state = sCDDevice.GetState(); - SelectTrack(track); - - if (wasPaused) - // make sure we don't start playing if we were paused before - Pause(); + if(state == kPlaying) + sCDDevice.Play(track); + +// if(state == kPaused) +// sCDDevice.Pause(); } void CDEngine::StartSkippingBackward() { - // start skipping - CDState state = playState.GetState(); - - if (state == kNoCD) - return; - - scsi_scan scan; - scan.direction = -1; - scan.speed = 1; - status_t result = ioctl(devicefd, B_SCSI_SCAN, &scan); - if (result != B_NO_ERROR) { - PRINT(("error %s skipping backward\n", strerror(errno))); - return; - } + sCDDevice.StartRewind(); } void CDEngine::StartSkippingForward() { - // start skipping - CDState state = playState.GetState(); - - if (state == kNoCD) - return; - - scsi_scan scan; - scan.direction = 1; - scan.speed = 1; - status_t result = ioctl(devicefd, B_SCSI_SCAN, &scan); - if (result != B_NO_ERROR) { - PRINT(("error %s skipping forward\n", strerror(errno))); - return; - } + sCDDevice.StartFastFwd(); } void CDEngine::StopSkipping() { - // stop skipping - CDState state = playState.GetState(); - - if (state == kNoCD) - return; - - scsi_scan scan; - scan.direction = 0; - scan.speed = 1; - status_t result = ioctl(devicefd, B_SCSI_SCAN, &scan); - if (result != B_NO_ERROR) { - PRINT(("error %s in stop skipping\n", strerror(errno))); - return; - } - - result = ioctl(devicefd, B_SCSI_RESUME_AUDIO); - if (result != B_NO_ERROR) { - PRINT(("error %s resuming\n", strerror(errno))); - return; - } - + sCDDevice.StopFastFwd(); } void CDEngine::SelectTrack(int32 trackNumber) { - // go to a selected track - if (playState.GetState() == kNoCD) - return; - - scsi_play_track track; - - track.start_track = trackNumber; - track.start_index = 1; - track.end_track = 99; - track.end_index = 1; - - status_t result = ioctl(devicefd, B_SCSI_PLAY_TRACK, &track); - if (result != B_NO_ERROR) { - PRINT(("error %s playing track\n", strerror(errno))); - return; - } + sCDDevice.Play(trackNumber); } void CDEngine::SetVolume(uint8 value) { - scsi_volume vol; - - // change only port0's volume - vol.flags=2; - vol.port0_volume=value; - - ioctl(devicefd,B_SCSI_SET_VOLUME,&vol); + sCDDevice.SetVolume(value); } +void +CDEngine::ToggleShuffle(void) +{ + if(sPlayList.IsShuffled()) + { + // If already in random mode, we will play to the end of the cd + int16 track = sPlayList.GetCurrentTrack(); + sPlayList.SetShuffle(false); + sPlayList.SetStartingTrack(track); + sPlayList.SetTrackCount(sCDDevice.CountTracks()); + } + else + { + // Not shuffled, so we will play the entire CD and randomly pick + sPlayList.SetTrackCount(sCDDevice.CountTracks()); + sPlayList.SetShuffle(true); + } +} + +void +CDEngine::ToggleRepeat(void) +{ + if(sPlayList.IsLoop()) + sPlayList.SetLoop(false); + else + sPlayList.SetLoop(true); +} + + void CDEngine::DoPulse() { @@ -605,75 +419,8 @@ CDEngine::DoPulse() void CDEngine::MessageReceived(BMessage *message) { - if (message->what == 'slTk') { - // handle message from menu selection - int32 track; - if (message->FindInt32("track", &track) == B_OK) - SelectTrack(track); - - } else - // handle observing - if (!Notifier::HandleObservingMessages(message) - && !CDEngineFunctorFactory::DispatchIfFunctionObject(message)) + // handle observing + if (!Notifier::HandleObservingMessages(message) && + !CDEngineFunctorFactory::DispatchIfFunctionObject(message)) BHandler::MessageReceived(message); } - - -static int -try_dir(const char *directory) -{ - BDirectory dir; - dir.SetTo(directory); - if(dir.InitCheck() != B_NO_ERROR) { - return false; - } - dir.Rewind(); - BEntry entry; - while(dir.GetNextEntry(&entry) >= 0) { - BPath path; - const char *name; - entry_ref e; - - if(entry.GetPath(&path) != B_NO_ERROR) - continue; - name = path.Path(); - - if(entry.GetRef(&e) != B_NO_ERROR) - continue; - - if(entry.IsDirectory()) { - if(strcmp(e.name, "floppy") == 0) - continue; // ignore floppy (it is not silent) - int devfd = try_dir(name); - if(devfd >= 0) - return devfd; - } - else { - int devfd; - device_geometry g; - - if(strcmp(e.name, "raw") != 0) - continue; // ignore partitions - - devfd = open(name, O_RDONLY); - if(devfd < 0) - continue; - - if(ioctl(devfd, B_GET_GEOMETRY, &g, sizeof(g)) >= 0) { - if(g.device_type == B_CD) - { - return devfd; - } - } - close(devfd); - } - } - return B_ERROR; -} - -int -CDEngine::FindCDPlayerDevice() -{ - return try_dir("/dev/disk"); -} - diff --git a/src/apps/cdplayer/CDEngine.h b/src/apps/cdplayer/CDEngine.h index 0ba2a2924d..9aa85c1fbe 100644 --- a/src/apps/cdplayer/CDEngine.h +++ b/src/apps/cdplayer/CDEngine.h @@ -15,222 +15,209 @@ #include +#include "CDAudioDevice.h" #include "Observer.h" #include "FunctionObjectMessage.h" #include "CDDBSupport.h" +#include "PlayList.h" class CDEngine; -class PeriodicWatcher : public Notifier { + // watcher sits somewhere were it can get pulses and makes sure // notices get sent if state changes +class PeriodicWatcher : public Notifier +{ public: - PeriodicWatcher(int devicefd); - PeriodicWatcher(BMessage *); - - virtual ~PeriodicWatcher() {} + PeriodicWatcher(void); + virtual ~PeriodicWatcher() {} - void DoPulse(); - void UpdateNow(); - - void AttachedToLooper(CDEngine *engine) - { this->engine = engine; } - - virtual BHandler *RecipientHandler() const; + void DoPulse(); + void UpdateNow(); + + void AttachedToLooper(CDEngine *engine) + { this->engine = engine; } + virtual BHandler *RecipientHandler() const; protected: - virtual bool UpdateState() = 0; + virtual bool UpdateState() = 0; - int devicefd; - CDEngine *engine; + CDEngine *engine; }; -enum CDState { - kNoCD=0, - kStopped, - kPaused, - kPlaying, - kSkipping -}; - -class PlayState : public PeriodicWatcher { - // this watcher sends notices to observers that are interrested - // about play state changes +// this watcher sends notices to observers that are interrested +// about play state changes +class PlayState : public PeriodicWatcher +{ public: - PlayState(int devicefd); - PlayState(BMessage *message) - : PeriodicWatcher(message) - {} + PlayState(CDEngine *engine); - CDState GetState() const; + CDState GetState() const; private: - bool UpdateState(); - bool CurrentState(CDState); - CDState oldState; + bool UpdateState(); + bool CurrentState(CDState); + CDState oldState; + + CDEngine *fEngine; }; -class TrackState : public PeriodicWatcher { - // this watcher sends notices to observers that are interested - // about changes in the current track +// this watcher sends notices to observers that are interested +// about changes in the current track +class TrackState : public PeriodicWatcher +{ public: - TrackState(int devicefd); - TrackState(BMessage *message) - : PeriodicWatcher(message) - {} + TrackState(void); - int32 GetTrack() const; - int32 GetNumTracks() const; + int32 GetTrack() const; + int32 GetNumTracks() const; private: - bool UpdateState(); - bool CurrentState(int32); - int32 currentTrack; + bool UpdateState(); + bool CurrentState(int32); + int32 currentTrack; }; -class TimeState : public PeriodicWatcher { - // this watcher sends notices to observers that are interested - // about changes in the current time +// this watcher sends notices to observers that are interested +// about changes in the current time +class TimeState : public PeriodicWatcher +{ public: - TimeState(int devicefd) - : PeriodicWatcher(devicefd) - { } - TimeState(BMessage *message) - : PeriodicWatcher(message) - {} + TimeState(void) : PeriodicWatcher() { } - void GetDiscTime(int32 &minutes, int32 &seconds) const; - void GetTrackTime(int32 &minutes, int32 &seconds) const; + void GetDiscTime(int32 &minutes, int32 &seconds) const; + void GetTrackTime(int32 &minutes, int32 &seconds) const; private: - bool UpdateState(); - bool CurrentState(int32 dmin, int32 dsec, int32 tmin, int32 tsec); + bool UpdateState(); + bool CurrentState(int32 dmin, int32 dsec, int32 tmin, int32 tsec); - int32 fDiscMinutes; - int32 fDiscSeconds; + int32 fDiscMinutes; + int32 fDiscSeconds; - int32 fTrackMinutes; - int32 fTrackSeconds; + int32 fTrackMinutes; + int32 fTrackSeconds; }; -class CDContentWatcher : public PeriodicWatcher { +class CDContentWatcher : public PeriodicWatcher +{ public: - CDContentWatcher(int devicefd); - CDContentWatcher(BMessage *message); + CDContentWatcher(void); - bool GetContent(BString *title, vector *tracks); + bool GetContent(BString *title, vector *tracks); private: - bool UpdateState(); + bool UpdateState(); - CDDBQuery cddbQuery; - int32 discID; - bool fReady; + CDDBQuery cddbQuery; + int32 discID; + bool fReady; }; -class VolumeState : public PeriodicWatcher { - // this watcher sends notices to observers that are interested - // about changes in the current volume - // currently not used yet +// this watcher sends notices to observers that are interested +// about changes in the current volume +// currently not used yet +class VolumeState : public PeriodicWatcher +{ public: - VolumeState(int devicefd); - VolumeState(BMessage *message) - : PeriodicWatcher(message) - {} - bool UpdateState(); - int32 GetVolume() const; + VolumeState(void); + + bool UpdateState(); + int32 GetVolume() const; private: - int32 fVolume; + int32 fVolume; }; -class CDEngine : public BHandler { - // The CD engine defines all the different CD control calls; also, - // it hosts the different state watchers and helps them send notices - // to observers about the CD state changes +// The CD engine defines all the different CD control calls; also, +// it hosts the different state watchers and helps them send notices +// to observers about the CD state changes +class CDEngine : public BHandler +{ public: - CDEngine(int devicefd); - CDEngine(BMessage *); + CDEngine(void); - virtual ~CDEngine(); + virtual ~CDEngine(); - // observing supprt - virtual void MessageReceived(BMessage *); - void AttachedToLooper(BLooper *); - void DoPulse(); + // observing support + virtual void MessageReceived(BMessage *); + void AttachedToLooper(BLooper *); + void DoPulse(); - // control calls - void PlayOrPause(); - void PlayContinue(); - void Play(); - void Pause(); - void Stop(); - void Eject(); - void SkipOneForward(); - void SkipOneBackward(); - void StartSkippingBackward(); - void StartSkippingForward(); - void StopSkipping(); - void SelectTrack(int32); + // control calls + void Play(); + void Pause(); + void Stop(); + void Eject(); + void SkipOneForward(); + void SkipOneBackward(); + void StartSkippingBackward(); + void StartSkippingForward(); + void StopSkipping(); + void SelectTrack(int32); + + void SetVolume(uint8 value); + + void ToggleShuffle(void); + void ToggleRepeat(void); - void SetVolume(uint8 value); + CDState GetState(void) const { return fEngineState; } + // to find the current Track, you may call the GetTrack function + // TrackState defines TrackState *TrackStateWatcher() { return &trackState; } - // to find the current Track, you may call the GetTrack function - // TrackState defines + // to find the current play state, you may call the GetState function + // PlayState defines PlayState *PlayStateWatcher() { return &playState; } - // to find the current play state, you may call the GetState function - // PlayState defines + // to find the current location on the CD, you may call the GetTime function + // TimeState defines TimeState *TimeStateWatcher() { return &timeState; } - // to find the current location on the CD, you may call the GetTime function - // TimeState defines CDContentWatcher *ContentWatcher() { return &contentWatcher; } + // to find the current location on the CD, you may call the GetVolume function + // VolumeState defines VolumeState *VolumeStateWatcher() - // to find the current location on the CD, you may call the GetVolume function - // VolumeState defines { return &volumeState; } - static int FindCDPlayerDevice(); - private: - int devicefd; + PlayState playState; + TrackState trackState; + TimeState timeState; + VolumeState volumeState; + CDContentWatcher contentWatcher; - PlayState playState; - TrackState trackState; - TimeState timeState; - VolumeState volumeState; - CDContentWatcher contentWatcher; - - bigtime_t lastPulse; + bigtime_t lastPulse; + + CDState fEngineState; }; // some function object glue -class CDEngineFunctorFactory : public FunctorFactoryCommon { +class CDEngineFunctorFactory : public FunctorFactoryCommon +{ public: static BMessage *NewFunctorMessage(void (CDEngine::*func)(), - CDEngine *target) - { - PlainMemberFunctionObject tmp(func, target); - return NewMessage(&tmp); - } + CDEngine *target) + { + PlainMemberFunctionObject tmp(func, target); + return NewMessage(&tmp); + } static BMessage *NewFunctorMessage(void (CDEngine::*func)(ulong), - CDEngine *target, ulong param) - { - SingleParamMemberFunctionObject tmp(func, target, param); - return NewMessage(&tmp); - } + CDEngine *target, ulong param) + { + SingleParamMemberFunctionObject tmp(func, target, param); + return NewMessage(&tmp); + } }; diff --git a/src/apps/cdplayer/CDButton.cpp b/src/apps/cdplayer/CDPlayer.cpp similarity index 86% rename from src/apps/cdplayer/CDButton.cpp rename to src/apps/cdplayer/CDPlayer.cpp index 008e7cda53..2e3d12449f 100644 --- a/src/apps/cdplayer/CDButton.cpp +++ b/src/apps/cdplayer/CDPlayer.cpp @@ -21,7 +21,7 @@ #include #include -#include "CDButton.h" +#include "CDPlayer.h" #include "DrawButton.h" #include "TwoStateDrawButton.h" #include @@ -45,13 +45,13 @@ enum M_SET_CD_TITLE }; -CDButton::CDButton(BRect frame, const char *name, uint32 resizeMask, uint32 flags) +CDPlayer::CDPlayer(BRect frame, const char *name, uint32 resizeMask, uint32 flags) : BView(frame, name, resizeMask, flags | B_FRAME_EVENTS) { SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); // TODO: Support multiple CD drives - engine = new CDEngine(CDEngine::FindCDPlayerDevice()); + engine = new CDEngine; BuildGUI(); @@ -66,18 +66,29 @@ CDButton::CDButton(BRect frame, const char *name, uint32 resizeMask, uint32 flag fFastFwd->SetEnabled(false); fRewind->SetEnabled(false); fSave->SetEnabled(false); + + fCurrentTrack->SetHighColor(fStopColor); } } -CDButton::~CDButton() +CDPlayer::~CDPlayer() { engine->Stop(); - delete engine; } -void CDButton::BuildGUI(void) +void CDPlayer::BuildGUI(void) { + fStopColor.red = 80; + fStopColor.green = 164; + fStopColor.blue = 80; + fStopColor.alpha = 255; + + fPlayColor.red = 40; + fPlayColor.green = 230; + fPlayColor.blue = 40; + fPlayColor.alpha = 255; + BRect r(5,5,230,25); // Assemble the CD Title box @@ -88,7 +99,7 @@ void CDButton::BuildGUI(void) view->SetViewColor(20,20,20); fCDBox->AddChild(view); - fCDTitle = new BStringView(view->Bounds(),"CDTitle",""); + fCDTitle = new BStringView(view->Bounds(),"CDTitle","", B_FOLLOW_ALL); view->AddChild(fCDTitle); fCDTitle->SetHighColor(200,200,200); fCDTitle->SetFont(be_bold_font); @@ -103,7 +114,7 @@ void CDButton::BuildGUI(void) fCurrentTrack = new BStringView( view->Bounds(),"TrackNumber","Track:",B_FOLLOW_ALL); view->AddChild(fCurrentTrack); - fCurrentTrack->SetHighColor(40,230,40); + fCurrentTrack->SetHighColor(fPlayColor); fCurrentTrack->SetFont(be_bold_font); r.OffsetBy(0, r.Height() + 5); @@ -142,7 +153,6 @@ void CDButton::BuildGUI(void) fStop->SetDisabled(BTranslationUtils::GetBitmap(B_PNG_FORMAT,"stop_disabled")); AddChild(fStop); - // TODO: Play is a special button. Implement as two-state buttons fPlay = new DrawButton( BRect(0,0,1,1), "Play", BTranslationUtils::GetBitmap(B_PNG_FORMAT,"play_up"), BTranslationUtils::GetBitmap(B_PNG_FORMAT,"play_down"), new BMessage(M_PLAY), B_FOLLOW_BOTTOM, B_WILL_DRAW); @@ -201,29 +211,30 @@ void CDButton::BuildGUI(void) AddChild(fSave); fSave->SetEnabled(false); - // TODO: Shuffle and Repeat are special buttons. Implement as two-state buttons - fShuffle = new DrawButton( BRect(0,0,1,1), "Shuffle", BTranslationUtils::GetBitmap(B_PNG_FORMAT,"shuffle_up"), - BTranslationUtils::GetBitmap(B_PNG_FORMAT,"shuffle_down"), new BMessage(M_SHUFFLE), - B_FOLLOW_NONE, B_WILL_DRAW); + fShuffle = new TwoStateDrawButton( BRect(0,0,1,1), "Shuffle", + BTranslationUtils::GetBitmap(B_PNG_FORMAT,"shuffle_up"), + BTranslationUtils::GetBitmap(B_PNG_FORMAT,"shuffle_down"), + BTranslationUtils::GetBitmap(B_PNG_FORMAT,"shuffle_up_on"), + BTranslationUtils::GetBitmap(B_PNG_FORMAT,"shuffle_down_on"), + new BMessage(M_SHUFFLE), B_FOLLOW_NONE, B_WILL_DRAW); fShuffle->ResizeToPreferred(); fShuffle->MoveTo(fSave->Frame().right + 2, Bounds().bottom - 5 - fShuffle->Frame().Height()); - fShuffle->SetDisabled(BTranslationUtils::GetBitmap(B_PNG_FORMAT,"shuffle_disabled")); AddChild(fShuffle); - fShuffle->SetEnabled(false); - fRepeat = new DrawButton( BRect(0,0,1,1), "Repeat", BTranslationUtils::GetBitmap(B_PNG_FORMAT,"repeat_up"), - BTranslationUtils::GetBitmap(B_PNG_FORMAT,"repeat_down"), new BMessage(M_REPEAT), - B_FOLLOW_NONE, B_WILL_DRAW); + fRepeat = new TwoStateDrawButton( BRect(0,0,1,1), "Repeat", + BTranslationUtils::GetBitmap(B_PNG_FORMAT,"repeat_up"), + BTranslationUtils::GetBitmap(B_PNG_FORMAT,"repeat_down"), + BTranslationUtils::GetBitmap(B_PNG_FORMAT,"repeat_up_on"), + BTranslationUtils::GetBitmap(B_PNG_FORMAT,"repeat_down_on"), + new BMessage(M_REPEAT), B_FOLLOW_NONE, B_WILL_DRAW); fRepeat->ResizeToPreferred(); fRepeat->MoveTo(fShuffle->Frame().right + 2, Bounds().bottom - 5 - fRepeat->Frame().Height()); - fRepeat->SetDisabled(BTranslationUtils::GetBitmap(B_PNG_FORMAT,"repeat_disabled")); AddChild(fRepeat); - fRepeat->SetEnabled(false); } void -CDButton::MessageReceived(BMessage *msg) +CDPlayer::MessageReceived(BMessage *msg) { if(msg->WasDropped()) { @@ -292,7 +303,7 @@ CDButton::MessageReceived(BMessage *msg) } case M_STOP: { - if(engine->PlayStateWatcher()->GetState()==kPlaying) + if(engine->GetState()==kPlaying) { fPlay->SetBitmaps(BTranslationUtils::GetBitmap(B_PNG_FORMAT,"play_up"), BTranslationUtils::GetBitmap(B_PNG_FORMAT,"play_down")); @@ -304,7 +315,7 @@ CDButton::MessageReceived(BMessage *msg) { // If we are currently playing, then we will be showing // the pause images and will want to switch back to the play images - if(engine->PlayStateWatcher()->GetState()==kPlaying) + if(engine->GetState()==kPlaying) { fPlay->SetBitmaps(BTranslationUtils::GetBitmap(B_PNG_FORMAT,"play_up"), BTranslationUtils::GetBitmap(B_PNG_FORMAT,"play_down")); @@ -315,7 +326,7 @@ CDButton::MessageReceived(BMessage *msg) fPlay->SetBitmaps(BTranslationUtils::GetBitmap(B_PNG_FORMAT,"pause_up"), BTranslationUtils::GetBitmap(B_PNG_FORMAT,"pause_down")); } - engine->PlayOrPause(); + engine->Play(); break; } case M_NEXT_TRACK: @@ -350,12 +361,12 @@ CDButton::MessageReceived(BMessage *msg) } case M_SHUFFLE: { - // TODO: Implement + engine->ToggleShuffle(); break; } case M_REPEAT: { - // TODO: Implement + engine->ToggleRepeat(); break; } default: @@ -372,7 +383,7 @@ CDButton::MessageReceived(BMessage *msg) } void -CDButton::NoticeChange(Notifier *notifier) +CDPlayer::NoticeChange(Notifier *notifier) { PlayState *ps; TrackState *trs; @@ -402,10 +413,10 @@ CDButton::NoticeChange(Notifier *notifier) fRewind->SetEnabled(false); fSave->SetEnabled(false); } + fCurrentTrack->SetHighColor(fStopColor); fCurrentTrack->SetText("Track: "); fTrackTime->SetText("Track --:-- / --:--"); fDiscTime->SetText("Disc --:-- / --:--"); - printf("Notification: No CD\n"); break; } case kStopped: @@ -418,12 +429,14 @@ CDButton::NoticeChange(Notifier *notifier) fPrevTrack->SetEnabled(true); fFastFwd->SetEnabled(true); fRewind->SetEnabled(true); - fSave->SetEnabled(true); + + // TODO: Enable when Save is implemented +// fSave->SetEnabled(true); } - fCurrentTrack->SetText("Track: "); + fCurrentTrack->SetHighColor(fStopColor); + fCurrentTrack->Invalidate(); fTrackTime->SetText("Track --:-- / --:--"); fDiscTime->SetText("Disc --:-- / --:--"); - printf("Notification: CD Stopped\n"); break; } case kPaused: @@ -437,9 +450,11 @@ CDButton::NoticeChange(Notifier *notifier) fPrevTrack->SetEnabled(true); fFastFwd->SetEnabled(true); fRewind->SetEnabled(true); - fSave->SetEnabled(true); + + // TODO: Enable when Save is implemented +// fSave->SetEnabled(true); } - printf("Notification: CD Paused\n"); + fCurrentTrack->SetHighColor(fPlayColor); break; } case kPlaying: @@ -452,9 +467,12 @@ CDButton::NoticeChange(Notifier *notifier) fPrevTrack->SetEnabled(true); fFastFwd->SetEnabled(true); fRewind->SetEnabled(true); - fSave->SetEnabled(true); + + // TODO: Enable when Save is implemented +// fSave->SetEnabled(true); } - printf("Notification: CD Playing\n"); + fCurrentTrack->SetHighColor(fPlayColor); + fCurrentTrack->Invalidate(); break; } case kSkipping: @@ -467,9 +485,11 @@ CDButton::NoticeChange(Notifier *notifier) fPrevTrack->SetEnabled(true); fFastFwd->SetEnabled(true); fRewind->SetEnabled(true); - fSave->SetEnabled(true); + + // TODO: Enable when Save is implemented +// fSave->SetEnabled(true); } - printf("Notification: CD Skipping\n"); + fCurrentTrack->SetHighColor(fStopColor); break; } default: @@ -502,7 +522,7 @@ CDButton::NoticeChange(Notifier *notifier) } void -CDButton::UpdateCDInfo(void) +CDPlayer::UpdateCDInfo(void) { BString CDName, currentTrackName; vector trackNames; @@ -525,7 +545,7 @@ CDButton::UpdateCDInfo(void) } void -CDButton::UpdateTimeInfo(void) +CDPlayer::UpdateTimeInfo(void) { int32 min,sec; char string[1024]; @@ -546,7 +566,7 @@ CDButton::UpdateTimeInfo(void) } void -CDButton::AttachedToWindow() +CDPlayer::AttachedToWindow() { // start observing engine->AttachedToLooper(Window()); @@ -570,7 +590,7 @@ CDButton::AttachedToWindow() } void -CDButton::FrameResized(float new_width, float new_height) +CDPlayer::FrameResized(float new_width, float new_height) { // We implement this method because there is no resizing mode to split the window's // width into two and have a box fill each half @@ -595,13 +615,13 @@ CDButton::FrameResized(float new_width, float new_height) } void -CDButton::Pulse() +CDPlayer::Pulse() { engine->DoPulse(); } void -CDButton::SetBitmap(BBitmap *bitmap) +CDPlayer::SetBitmap(BBitmap *bitmap) { if(!bitmap) { @@ -615,14 +635,14 @@ CDButton::SetBitmap(BBitmap *bitmap) Invalidate(); } -class CDButtonWindow : public BWindow +class CDPlayerWindow : public BWindow { public: - CDButtonWindow(void); + CDPlayerWindow(void); bool QuitRequested(void); }; -CDButtonWindow::CDButtonWindow(void) +CDPlayerWindow::CDPlayerWindow(void) : BWindow(BRect (100, 100, 610, 200), "CD Player", B_TITLED_WINDOW, B_NOT_V_RESIZABLE | B_NOT_ZOOMABLE | B_ASYNCHRONOUS_CONTROLS) { @@ -634,17 +654,17 @@ CDButtonWindow::CDButtonWindow(void) SetSizeLimits(wmin,wmax,hmin,hmax); } -bool CDButtonWindow::QuitRequested(void) +bool CDPlayerWindow::QuitRequested(void) { be_app->PostMessage(B_QUIT_REQUESTED); return true; } -CDButtonApplication::CDButtonApplication() +CDPlayerApplication::CDPlayerApplication() : BApplication("application/x-vnd.Haiku-CDPlayer") { - BWindow *window = new CDButtonWindow(); - BView *button = new CDButton(window->Bounds(), "CD"); + BWindow *window = new CDPlayerWindow(); + BView *button = new CDPlayer(window->Bounds(), "CD"); window->AddChild(button); window->Show(); } @@ -652,7 +672,7 @@ CDButtonApplication::CDButtonApplication() int main(int, char **argv) { - (new CDButtonApplication())->Run(); + (new CDPlayerApplication())->Run(); return 0; } diff --git a/src/apps/cdplayer/CDButton.h b/src/apps/cdplayer/CDPlayer.h similarity index 52% rename from src/apps/cdplayer/CDButton.h rename to src/apps/cdplayer/CDPlayer.h index 38e00506f8..aae5dfaccb 100644 --- a/src/apps/cdplayer/CDButton.h +++ b/src/apps/cdplayer/CDPlayer.h @@ -4,8 +4,8 @@ */ // This defines the replicant button -#ifndef __CD_BUTTON__ -#define __CD_BUTTON__ +#ifndef CDPLAYER_H +#define CDPLAYER_H #include #include @@ -16,21 +16,20 @@ #include #include -#include "PlayList.h" #include "Observer.h" #include "CDEngine.h" class DrawButton; class TwoStateDrawButton; -class CDButton : public BView, private Observer +class CDPlayer : public BView, private Observer { public: - CDButton(BRect frame, const char *name, + CDPlayer(BRect frame, const char *name, uint32 resizeMask = B_FOLLOW_ALL, uint32 flags = B_WILL_DRAW | B_NAVIGABLE | B_PULSE_NEEDED); - virtual ~CDButton(); + virtual ~CDPlayer(); void BuildGUI(void); @@ -46,36 +45,46 @@ public: virtual void NoticeChange(Notifier *); private: - void UpdateCDInfo(void); - void UpdateTimeInfo(void); - void SetBitmap(BBitmap *bitmap); + void UpdateCDInfo(void); + void UpdateTimeInfo(void); + void SetBitmap(BBitmap *bitmap); - CDEngine *engine; + CDEngine *engine; - DrawButton *fStop, *fPlay, *fNextTrack, *fPrevTrack; - DrawButton *fFastFwd, *fRewind, *fEject, *fSave, *fShuffle, *fRepeat; - - - BSlider *fVolume; - - BStringView *fCDTitle; - BStringView *fCurrentTrack; - BStringView *fTrackTime; - BStringView *fDiscTime; - - BBox *fCDBox; - BBox *fTrackBox; - BBox *fTimeBox; - - CDState fCDState; - PlayList fPlaylist; + DrawButton *fStop, + *fPlay, + *fNextTrack, + *fPrevTrack, + *fFastFwd, + *fRewind, + *fEject, + *fSave; + + TwoStateDrawButton *fShuffle, + *fRepeat; + + BSlider *fVolume; + + BStringView *fCDTitle, + *fCurrentTrack, + *fTrackTime, + *fDiscTime; + + BBox *fCDBox, + *fTrackBox, + *fTimeBox; + + CDState fCDState; + + rgb_color fStopColor; + rgb_color fPlayColor; }; -class CDButtonApplication : public BApplication +class CDPlayerApplication : public BApplication { public: - CDButtonApplication(); + CDPlayerApplication(); }; diff --git a/src/apps/cdplayer/Jamfile b/src/apps/cdplayer/Jamfile index c6a4d85997..3de58c1ff3 100644 --- a/src/apps/cdplayer/Jamfile +++ b/src/apps/cdplayer/Jamfile @@ -2,9 +2,10 @@ SubDir OBOS_TOP src apps cdplayer ; AddResources CDPlayer : CDPlayer.rdef ; App CDPlayer : - CDButton.cpp + CDAudioDevice.cpp CDDBSupport.cpp CDEngine.cpp + CDPlayer.cpp DrawButton.cpp FunctionObjectMessage.cpp Observer.cpp diff --git a/src/apps/cdplayer/PlayList.cpp b/src/apps/cdplayer/PlayList.cpp index 1f02a73373..efccc35b87 100644 --- a/src/apps/cdplayer/PlayList.cpp +++ b/src/apps/cdplayer/PlayList.cpp @@ -3,20 +3,36 @@ #include #include -PlayList::PlayList(int16 tracks) - : fTrackCount(0), +PlayList::PlayList(int16 count, int16 start) + : fTrackCount(count), fTrackIndex(0), + fStartingTrack(start), fRandom(false), fLoop(false) { srand(real_time_clock_usecs()); - SetTrackCount(tracks); + if(fTrackCount < 0) + fTrackCount = 0; + else + if(fTrackCount > 500) + fTrackCount = 500; + + if(fStartingTrack >= fTrackCount) + fStartingTrack = fTrackCount - 1; + + if(fStartingTrack < 1) + fStartingTrack = 1; + + memset(fTrackList,-1,500); + Unrandomize(); } void PlayList::SetTrackCount(const int16 &count) { + fLocker.Lock(); + if(count < 0) fTrackCount = 0; else @@ -27,57 +43,140 @@ PlayList::SetTrackCount(const int16 &count) memset(fTrackList,-1,500); SetShuffle(IsShuffled()); + + fLocker.Unlock(); +} + +void +PlayList::SetStartingTrack(const int16 &start) +{ + fLocker.Lock(); + + if(start >= TrackCount()) + fStartingTrack = TrackCount() - 1; + else + if(start < 1) + fStartingTrack = 1; + else + fStartingTrack = start; + + fLocker.Unlock(); } void PlayList::Rewind(void) { + fLocker.Lock(); + fTrackIndex = 0; + + fLocker.Unlock(); } void PlayList::SetShuffle(const bool &random) { + fLocker.Lock(); + if(random) Randomize(); else Unrandomize(); + + fLocker.Unlock(); } void PlayList::SetLoop(const bool &loop) { + fLocker.Lock(); + fLoop = loop; + + fLocker.Unlock(); } +int16 +PlayList::GetCurrentTrack(void) +{ + fLocker.Lock(); + + int16 value = fTrackList[fTrackIndex]; + + fLocker.Unlock(); + return value; +} + int16 PlayList::GetNextTrack(void) { - if(fTrackCount < 1) - return -1; + fLocker.Lock(); - if(fTrackIndex == fTrackCount) + if(fTrackCount < 1) + { + fLocker.Unlock(); + return -1; + } + + if(fTrackIndex > (fTrackCount - fStartingTrack)) { if(fLoop) fTrackIndex = 0; else + { + fLocker.Unlock(); return -1; + } + } + else + fTrackIndex++; + + int16 value = fTrackList[fTrackIndex]; + fLocker.Unlock(); + return value; +} + +int16 +PlayList::GetPreviousTrack(void) +{ + fLocker.Lock(); + + if(fTrackCount < 1) + { + fLocker.Unlock(); + return -1; } - return fTrackList[fTrackIndex++]; + if(fTrackIndex == 0) + { + if(fLoop) + fTrackIndex = (fTrackCount - fStartingTrack); + else + { + fLocker.Unlock(); + return -1; + } + } + else + fTrackIndex--; + + int16 value = fTrackList[fTrackIndex]; + fLocker.Unlock(); + return value; } void PlayList::Randomize(void) { // Reinitialize the count - for(int16 i=0; i +#include class PlayList { public: - PlayList(int16 tracks = 0); + PlayList(int16 tracks = 0, int16 startingtrack = 1); void SetTrackCount(const int16 &count); int16 TrackCount(void) const { return fTrackCount; } + void SetStartingTrack(const int16 &start); + int16 StartingTrack(void) const { return fStartingTrack; } + void Rewind(void); void SetShuffle(const bool &random); @@ -19,7 +23,9 @@ public: void SetLoop(const bool &loop); bool IsLoop(void) const { return fLoop; } + int16 GetCurrentTrack(void); int16 GetNextTrack(void); + int16 GetPreviousTrack(void); private: void Randomize(void); @@ -27,12 +33,13 @@ private: int16 fTrackCount; int16 fTrackIndex; + int16 fStartingTrack; int16 fTrackList[500]; // This should be big enough. :) bool fRandom; bool fLoop; - + BLocker fLocker; }; #endif diff --git a/src/apps/cdplayer/TwoStateDrawButton.h b/src/apps/cdplayer/TwoStateDrawButton.h index 8910ba50b6..61300b5b55 100644 --- a/src/apps/cdplayer/TwoStateDrawButton.h +++ b/src/apps/cdplayer/TwoStateDrawButton.h @@ -25,6 +25,8 @@ public: void MouseUp(BPoint pt); // void MessageReceived(BMessage *msg); + int32 GetState(void) { return fButtonState ? 1 : 0; }; + private: BBitmap *fUpOne,