diff --git a/src/apps/cdplayer/CDEngine.cpp b/src/apps/cdplayer/CDEngine.cpp deleted file mode 100644 index 2af351d1d4..0000000000 --- a/src/apps/cdplayer/CDEngine.cpp +++ /dev/null @@ -1,558 +0,0 @@ -/* - Copyright 1999, Be Incorporated. All Rights Reserved. - This file may be used under the terms of the Be Sample Code License. -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "scsi.h" -#include "CDEngine.h" -#include "PlayList.h" - -static PlayList sPlayList; -CDAudioDevice gCDDevice; - -const bigtime_t kPulseRate = 500000; - -PeriodicWatcher::PeriodicWatcher(void) -{ -} - - -BHandler * -PeriodicWatcher::RecipientHandler() const -{ - return engine; -} - -void -PeriodicWatcher::DoPulse() -{ - // control the period here - if(UpdateState()) - Notify(); -} - -void -PeriodicWatcher::UpdateNow() -{ - if(UpdateState()) - Notify(); -} - - -PlayState::PlayState(CDEngine *engine) - : oldState(kInit), - fEngine(engine) -{ -} - -bool -PlayState::UpdateState(void) -{ - CDState state = gCDDevice.GetState(); - if(state == kStopped) - { - if(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) - { - gCDDevice.Play(next); - return CurrentState(kPlaying); - } - } - else - { - int16 count = gCDDevice.CountTracks(); - if(count != sPlayList.TrackCount()) - sPlayList.SetTrackCount(count); - - // TODO: Is this correct? - - /* - int16 start = gCDDevice.GetTrack(); - if(start != sPlayList.StartingTrack()) - sPlayList.SetStartingTrack(start); - */ - - return CurrentState(kStopped); - } - } - - if(state == kPlaying && fEngine->GetState() == kStopped) - { - // This happens when the CD drive is started by R5's player - // or this app is started while the drive is playing. We should - // reset the to start at the current track and finish at the - // last one and send a notification. - sPlayList.SetTrackCount(gCDDevice.CountTracks()); - sPlayList.SetStartingTrack(gCDDevice.GetTrack()); - return CurrentState(kPlaying); - } - - return CurrentState(state); -} - -CDState -PlayState::GetState() const -{ - return oldState; -} - -bool -PlayState::CurrentState(CDState newState) -{ - if (newState != oldState) - { - oldState = newState; - return true; - } - return false; -} - -TrackState::TrackState(void) - : currentTrack(0) -{ -} - -int32 -TrackState::GetTrack() const -{ - return currentTrack; -} - -bool -TrackState::UpdateState() -{ - // It's possible that the state of the cd drive was changed by outside means - // As a result, we want to make sure this hasn't happened. If it has, then we - // need to update the playlist's position. - int16 cdTrack, count; - - if(gCDDevice.GetState() == kPlaying) - { - cdTrack = gCDDevice.GetTrack(); - if(cdTrack != sPlayList.GetCurrentTrack()) - sPlayList.SetCurrentTrack(cdTrack); - return CurrentState(cdTrack, trackCount); - } - - // If we're not playing, just monitor the current track in the playlist - count = gCDDevice.CountTracks(); - if(count>0) - { - cdTrack = sPlayList.GetCurrentTrack(); - } - else - { - sPlayList.SetTrackCount(0); - cdTrack=-1; - } - return CurrentState(cdTrack,count); -} - -int32 -TrackState::GetNumTracks() const -{ - return gCDDevice.CountTracks(); -} - -bool -TrackState::CurrentState(int32 track, int32 count) -{ - if( (track != currentTrack) || (count != trackCount) ) - { - currentTrack = track; - trackCount = count; - return true; - } - return false; -} - -bool -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 - - cdaudio_time track; - cdaudio_time disc; - - if(gCDDevice.GetTime(track,disc)) - { - cdaudio_time ttrack; - cdaudio_time tdisc; - int16 ctrack = gCDDevice.GetTrack(); - - gCDDevice.GetTimeForDisc(tdisc); - gCDDevice.GetTimeForTrack(ctrack,ttrack); - - return CurrentState(track,ttrack,disc,tdisc); - } - else - { - track.minutes = -1; - track.seconds = -1; - disc.minutes = -1; - disc.seconds = -1; - return CurrentState(disc,disc,track,track); - } -} - -bool -TimeState::CurrentState(cdaudio_time tracktime, cdaudio_time totaltracktime, - cdaudio_time disctime, cdaudio_time totaldisctime) -{ - if (disctime.minutes == fDiscTime.minutes && disctime.seconds == fDiscTime.seconds) - return false; - - fDiscTime = disctime; - fTotalDiscTime = totaldisctime; - - fTrackTime = tracktime; - fTotalTrackTime = totaltracktime; - - return true; -} - -void -TimeState::GetDiscTime(int32 &minutes, int32 &seconds) const -{ - minutes = fDiscTime.minutes; - seconds = fDiscTime.seconds; -} - -void -TimeState::GetTotalDiscTime(int32 &minutes, int32 &seconds) const -{ - minutes = fTotalDiscTime.minutes; - seconds = fTotalDiscTime.seconds; -} - -void -TimeState::GetTrackTime(int32 &minutes, int32 &seconds) const -{ - minutes = fTrackTime.minutes; - seconds = fTrackTime.seconds; -} - -void -TimeState::GetTotalTrackTime(int32 &minutes, int32 &seconds) const -{ - minutes = fTotalTrackTime.minutes; - seconds = fTotalTrackTime.seconds; -} - - -CDContentWatcher::CDContentWatcher(void) - : cddbQuery("us.freedb.org", 888), - discID(-1) -{ -} - -bool -CDContentWatcher::GetContent(BString *title, vector *tracks) -{ - if(discID == -1) - { - title->SetTo(""); - tracks->empty(); - tracks->push_back(""); - return true; - } - - return cddbQuery.GetTitles(title, tracks, 1000000); -} - -bool -CDContentWatcher::UpdateState() -{ - int32 newDiscID = -1; - - if (engine->PlayStateWatcher()->GetState() == kNoCD) - { - if(discID != -1) - { - discID = -1; - return true; - } - else - return false; - } - - // Check the table of contents to see if the new one is different - // from the old one whenever there is a CD in the drive - newDiscID = gCDDevice.GetDiscID(); - - if (discID == newDiscID) - return false; - - // We have changed CDs, so we are not ready until the CDDB lookup finishes - cddbQuery.SetToCD(gCDDevice.GetDrivePath()); - - // Notify when the query is ready - if(cddbQuery.Ready()) - { - discID = newDiscID; - return true; - } - - return false; -} - -VolumeState::VolumeState(void) - : fVolume(-1) -{ -} - -bool -VolumeState::UpdateState(void) -{ - uint8 volume = gCDDevice.GetVolume(); - if(fVolume == volume) - return false; - - fVolume = volume; - return true; -} - -int32 -VolumeState::GetVolume(void) const -{ - return fVolume; -} - -CDEngine::CDEngine(void) - : BHandler("CDEngine"), - playState(this), - fEngineState(kStopped) -{ - sPlayList.SetTrackCount(gCDDevice.CountTracks()); -} - -CDEngine::~CDEngine() -{ -} - -void -CDEngine::AttachedToLooper(BLooper *looper) -{ - looper->AddHandler(this); - playState.AttachedToLooper(this); - trackState.AttachedToLooper(this); - timeState.AttachedToLooper(this); - volumeState.AttachedToLooper(this); - contentWatcher.AttachedToLooper(this); -} - -void -CDEngine::Pause() -{ - gCDDevice.Pause(); - fEngineState = gCDDevice.GetState(); -} - -void -CDEngine::Play() -{ - if(fEngineState == kPaused) - { - gCDDevice.Resume(); - fEngineState = gCDDevice.GetState(); - } - else - if(fEngineState == kPlaying) - { - Pause(); - } - else - { - gCDDevice.Play(sPlayList.GetCurrentTrack()); - fEngineState = gCDDevice.GetState(); - } -} - -void -CDEngine::Stop() -{ - fEngineState = kStopped; - gCDDevice.Stop(); -} - -void -CDEngine::Eject() -{ - gCDDevice.Eject(); - fEngineState = gCDDevice.GetState(); -} - -void -CDEngine::SkipOneForward() -{ - int16 track = sPlayList.GetNextTrack(); - - if(track <= 0) - { - // force a "wrap around" when possible. This makes it - // possible for the user to be able to, for example, jump - // back to the first track from the last one with 1 button push - track = sPlayList.GetFirstTrack(); - - if(track <= 0) - return; - } - - CDState state = gCDDevice.GetState(); - if(state == kPlaying) - gCDDevice.Play(track); - - if(state == kPaused) - { - gCDDevice.Play(track); - gCDDevice.Pause(); - } - trackState.UpdateNow(); -} - -void -CDEngine::SkipOneBackward() -{ - int16 track = sPlayList.GetPreviousTrack(); - - if(track <= 0) - { - // force a "wrap around" when possible. This way the user - // can search backwards to get to a later track - track = sPlayList.GetLastTrack(); - - if(track <= 0) - return; - } - - CDState state = gCDDevice.GetState(); - - if(state == kPlaying) - gCDDevice.Play(track); - - if(state == kPaused) - { - gCDDevice.Play(track); - gCDDevice.Pause(); - } - trackState.UpdateNow(); -} - -void -CDEngine::StartSkippingBackward() -{ - gCDDevice.StartRewind(); -} - -void -CDEngine::StartSkippingForward() -{ - gCDDevice.StartFastFwd(); -} - -void -CDEngine::StopSkipping() -{ - gCDDevice.StopFastFwd(); -} - -void -CDEngine::SelectTrack(int32 trackNumber) -{ - sPlayList.SetCurrentTrack(trackNumber); - if(GetState() == kPlaying) - gCDDevice.Play(trackNumber); - trackState.UpdateNow(); -} - -void -CDEngine::SetVolume(uint8 value) -{ - gCDDevice.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(gCDDevice.CountTracks()); - } - else - { - // Not shuffled, so we will play the entire CD and randomly pick - sPlayList.SetTrackCount(gCDDevice.CountTracks()); - sPlayList.SetShuffle(true); - } -} - -bool -CDEngine::IsShuffled(void) -{ - return sPlayList.IsShuffled(); -} - -void -CDEngine::ToggleRepeat(void) -{ - if(sPlayList.IsLoop()) - sPlayList.SetLoop(false); - else - sPlayList.SetLoop(true); -} - -bool -CDEngine::IsRepeated(void) -{ - return sPlayList.IsLoop(); -} - -void -CDEngine::DoPulse() -{ - // this is the CDEngine's heartbeat; Since it is a Notifier, it checks if - // any values changed since the last hearbeat and sends notices to observers - - bigtime_t time = system_time(); - if (time > lastPulse && time < lastPulse + kPulseRate) - return; - - // every pulse rate have all the different state watchers check the - // curent state and send notifications if anything changed - - lastPulse = time; - - playState.DoPulse(); - trackState.DoPulse(); - timeState.DoPulse(); - volumeState.DoPulse(); - contentWatcher.DoPulse(); -} - -void -CDEngine::MessageReceived(BMessage *message) -{ - // handle observing - if (!Notifier::HandleObservingMessages(message) && - !CDEngineFunctorFactory::DispatchIfFunctionObject(message)) - BHandler::MessageReceived(message); -} diff --git a/src/apps/cdplayer/CDEngine.h b/src/apps/cdplayer/CDEngine.h deleted file mode 100644 index 0d45060f55..0000000000 --- a/src/apps/cdplayer/CDEngine.h +++ /dev/null @@ -1,232 +0,0 @@ -/* - Copyright 1999, Be Incorporated. All Rights Reserved. - This file may be used under the terms of the Be Sample Code License. -*/ - -// This defines an engine that tracks the state of the CD player -// and supports the CD player control and status calls - -#ifndef __CD_ENGINE__ -#define __CD_ENGINE__ - -#include -#include -#include - -#include - -#include "CDAudioDevice.h" -#include "Observer.h" -#include "FunctionObjectMessage.h" -#include "CDDBSupport.h" -#include "PlayList.h" - -class CDEngine; - -// watcher sits somewhere were it can get pulses and makes sure -// notices get sent if state changes -class PeriodicWatcher : public Notifier -{ -public: - PeriodicWatcher(void); - virtual ~PeriodicWatcher() {} - - void DoPulse(); - void UpdateNow(); - - void AttachedToLooper(CDEngine *engine) - { this->engine = engine; } - virtual BHandler *RecipientHandler() const; - -protected: - virtual bool UpdateState() = 0; - CDEngine *engine; -}; - -// this watcher sends notices to observers that are interrested -// about play state changes -class PlayState : public PeriodicWatcher -{ -public: - PlayState(CDEngine *engine); - - CDState GetState() const; - -private: - bool UpdateState(); - bool CurrentState(CDState); - CDState oldState; - - CDEngine *fEngine; -}; - -// this watcher sends notices to observers that are interested -// about changes in the current track -class TrackState : public PeriodicWatcher -{ -public: - TrackState(void); - - int32 GetTrack() const; - int32 GetNumTracks() const; - -private: - bool UpdateState(); - bool CurrentState(int32,int32); - int32 currentTrack; - int32 trackCount; -}; - -// this watcher sends notices to observers that are interested -// about changes in the current time -class TimeState : public PeriodicWatcher -{ -public: - TimeState(void) : PeriodicWatcher() { } - - void GetDiscTime(int32 &minutes, int32 &seconds) const; - void GetTotalDiscTime(int32 &minutes, int32 &seconds) const; - - void GetTrackTime(int32 &minutes, int32 &seconds) const; - void GetTotalTrackTime(int32 &minutes, int32 &seconds) const; - -private: - bool UpdateState(); - bool CurrentState(cdaudio_time tracktime, - cdaudio_time totaltracktime, - cdaudio_time disctime, - cdaudio_time totaldisctime); - - cdaudio_time fDiscTime, - fTotalDiscTime, - fTrackTime, - fTotalTrackTime; -}; - -class CDContentWatcher : public PeriodicWatcher -{ -public: - CDContentWatcher(void); - - bool GetContent(BString *title, vector *tracks); - -private: - bool UpdateState(); - - CDDBQuery cddbQuery; - int32 discID; -}; - -// 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(void); - - int32 GetVolume() const; - -private: - bool UpdateState(); - int32 fVolume; - -}; - -// 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(void); - - virtual ~CDEngine(); - - // observing support - virtual void MessageReceived(BMessage *); - void AttachedToLooper(BLooper *); - void DoPulse(); - - // 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); - bool IsShuffled(void); - - void ToggleRepeat(void); - bool IsRepeated(void); - - 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 play state, you may call the GetState function - // PlayState defines - PlayState *PlayStateWatcher() - { return &playState; } - - // to find the current location on the CD, you may call the GetTime function - // TimeState defines - TimeState *TimeStateWatcher() - { return &timeState; } - - CDContentWatcher *ContentWatcher() - { return &contentWatcher; } - - // to find the current location on the CD, you may call the GetVolume function - // VolumeState defines - VolumeState *VolumeStateWatcher() - { return &volumeState; } - -private: - PlayState playState; - TrackState trackState; - TimeState timeState; - VolumeState volumeState; - CDContentWatcher contentWatcher; - - bigtime_t lastPulse; - - CDState fEngineState; -}; - - -// some function object glue -class CDEngineFunctorFactory : public FunctorFactoryCommon -{ -public: - static BMessage *NewFunctorMessage(void (CDEngine::*func)(), - 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); - } -}; - -extern CDAudioDevice gCDDevice; - -#endif \ No newline at end of file diff --git a/src/apps/cdplayer/CDPlayer.cpp b/src/apps/cdplayer/CDPlayer.cpp index ecf2320aaa..220b8a9ee8 100644 --- a/src/apps/cdplayer/CDPlayer.cpp +++ b/src/apps/cdplayer/CDPlayer.cpp @@ -48,17 +48,18 @@ enum }; CDPlayer::CDPlayer(BRect frame, const char *name, uint32 resizeMask, uint32 flags) - : BView(frame, name, resizeMask, flags | B_FRAME_EVENTS) + : BView(frame, name, resizeMask, flags | B_FRAME_EVENTS), + fCDQuery("freedb.freedb.org") { SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); - // TODO: Support multiple CD drives - engine = new CDEngine; + fDiscID=-1; + fVolume=255; + fUseTrackNames=false; BuildGUI(); - CDAudioDevice cd; - if(cd.CountDrives()<1) + if(fCDDrive.CountDrives()<1) { BAlert *alert = new BAlert("CDPlayer","It appears that there are no CD drives on your" "computer or there is no system software to support one." @@ -66,12 +67,15 @@ CDPlayer::CDPlayer(BRect frame, const char *name, uint32 resizeMask, uint32 flag alert->Go(); be_app->PostMessage(B_QUIT_REQUESTED); } + + fWindowState=fCDDrive.GetState(); + fVolumeSlider->SetValue(fCDDrive.GetVolume()); + WatchCDState(); } CDPlayer::~CDPlayer() { - engine->Stop(); - delete engine; + fCDDrive.Stop(); } void CDPlayer::BuildGUI(void) @@ -120,7 +124,7 @@ void CDPlayer::BuildGUI(void) fCurrentTrack = new BStringView( view->Bounds(),"TrackNumber","Track:",B_FOLLOW_ALL); view->AddChild(fCurrentTrack); - fCurrentTrack->SetHighColor(fPlayColor); + fCurrentTrack->SetHighColor(fStopColor); fCurrentTrack->SetFont(be_bold_font); r.OffsetBy(0, r.Height() + 5); @@ -147,15 +151,15 @@ void CDPlayer::BuildGUI(void) fDiscTime->SetHighColor(120,120,255); fDiscTime->SetFont(be_bold_font); - fVolume = new BSlider( BRect(0,0,75,30), "VolumeSlider", "Volume", new BMessage(M_SET_VOLUME),0,255); - fVolume->MoveTo(5, Bounds().bottom - 10 - fVolume->Frame().Height()); - AddChild(fVolume); + fVolumeSlider = new BSlider( BRect(0,0,75,30), "VolumeSlider", "Volume", new BMessage(M_SET_VOLUME),0,255); + fVolumeSlider->MoveTo(5, Bounds().bottom - 10 - fVolumeSlider->Frame().Height()); + AddChild(fVolumeSlider); fStop = new DrawButton( BRect(0,0,1,1), "Stop", BTranslationUtils::GetBitmap(B_PNG_FORMAT,"stop_up"), BTranslationUtils::GetBitmap(B_PNG_FORMAT,"stop_down"), new BMessage(M_STOP), B_FOLLOW_BOTTOM, B_WILL_DRAW); fStop->ResizeToPreferred(); - fStop->MoveTo(fVolume->Frame().right + 10, Bounds().bottom - 5 - fStop->Frame().Height()); + fStop->MoveTo(fVolumeSlider->Frame().right + 10, Bounds().bottom - 5 - fStop->Frame().Height()); fStop->SetDisabled(BTranslationUtils::GetBitmap(B_PNG_FORMAT,"stop_disabled")); AddChild(fStop); @@ -252,70 +256,123 @@ CDPlayer::MessageReceived(BMessage *msg) { case M_SET_VOLUME: { - engine->SetVolume(fVolume->Value()); + fCDDrive.SetVolume(fVolumeSlider->Value()); break; } case M_STOP: { - if(engine->GetState()==kPlaying) - fPlay->SetState(0); - - engine->Stop(); + fWindowState=kStopped; + fCDDrive.Stop(); break; } case M_PLAY: { // 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->GetState()==kPlaying) + // the pause images and will want to switch back to the play images + if(fWindowState==kPlaying) { - fPlay->SetState(0); - engine->Pause(); + fWindowState=kPaused; + fCDDrive.Pause(); + } + else + if(fWindowState==kPaused) + { + fWindowState=kPlaying; + fCDDrive.Resume(); } else { - fPlay->SetState(1); - engine->Play(); + fWindowState=kPlaying; + fCDDrive.Play(fPlayList.GetCurrentTrack()); } break; } case M_SELECT_TRACK: { - engine->SelectTrack(fTrackMenu->Value()+1); - break; - } - case M_NEXT_TRACK: - { - engine->SkipOneForward(); - break; - } - case M_PREV_TRACK: - { - engine->SkipOneBackward(); + fPlayList.SetCurrentTrack(fTrackMenu->Value()+1); + fWindowState=kPlaying; + fCDDrive.Play(fPlayList.GetCurrentTrack()); break; } case M_EJECT: { - engine->Eject(); + fCDDrive.Eject(); + break; + } + case M_NEXT_TRACK: + { + int16 next = fPlayList.GetNextTrack(); + if(next <= 0) + { + // force a "wrap around" when possible. This makes it + // possible for the user to be able to, for example, jump + // back to the first track from the last one with 1 button push + next = fPlayList.GetFirstTrack(); + } + + if(next > 0) + { + CDState state = fCDDrive.GetState(); + if(state == kPlaying) + fCDDrive.Play(next); + else + if(state == kPaused) + { + fCDDrive.Play(next); + fCDDrive.Pause(); + } + else + fPlayList.SetCurrentTrack(next); + + // Force an update for better responsiveness + WatchCDState(); + } + break; + } + case M_PREV_TRACK: + { + int16 prev = fPlayList.GetPreviousTrack(); + if(prev <= 0) + { + // force a "wrap around" when possible. This makes it + // possible for the user to be able to, for example, jump + // back to the first track from the last one with 1 button push + prev = fPlayList.GetLastTrack(); + } + + if(prev > 0) + { + CDState state = fCDDrive.GetState(); + if(state == kPlaying) + fCDDrive.Play(prev); + else + if(state == kPaused) + { + fCDDrive.Play(prev); + fCDDrive.Pause(); + } + else + fPlayList.SetCurrentTrack(prev); + + // Force an update for better responsiveness + WatchCDState(); + } break; } - - - case M_FFWD: { if(fFastFwd->Value() == B_CONTROL_ON) - engine->StartSkippingForward(); + fCDDrive.StartFastFwd(); else - engine->StopSkipping(); + fCDDrive.StopFastFwd(); break; } case M_REWIND: { if(fRewind->Value() == B_CONTROL_ON) - engine->StartSkippingBackward(); + fCDDrive.StartRewind(); else - engine->StopSkipping(); + fCDDrive.StopRewind(); break; } case M_SAVE: @@ -326,131 +383,40 @@ CDPlayer::MessageReceived(BMessage *msg) case M_SHUFFLE: { - engine->ToggleShuffle(); - - if(engine->IsShuffled() && fShuffle->GetState()==0) + if(fPlayList.IsShuffled()) { - fShuffle->SetState(1); + int16 track = fPlayList.GetCurrentTrack(); + fPlayList.SetShuffle(false); + fPlayList.SetStartingTrack(track); + fPlayList.SetTrackCount(fCDDrive.CountTracks()); + fShuffle->SetState(0); } else { - if(fShuffle->GetState()==1) - fShuffle->SetState(0); + fPlayList.SetTrackCount(fCDDrive.CountTracks()); + fPlayList.SetShuffle(true); + fShuffle->SetState(1); } break; } case M_REPEAT: { - engine->ToggleRepeat(); - if(engine->IsRepeated() && fRepeat->GetState()==0) + if(fPlayList.IsLoop()) { - fRepeat->SetState(1); + fPlayList.SetLoop(false); + fRepeat->SetState(0); } else { - if(fRepeat->GetState()==1) - fRepeat->SetState(0); + fPlayList.SetLoop(true); + fRepeat->SetState(1); } break; } - - default: - { - - if (!Observer::HandleObservingMessages(msg)) - { - // just support observing messages - BView::MessageReceived(msg); - break; - } - } - } -} - -void -CDPlayer::NoticeChange(Notifier *notifier) -{ - PlayState *ps; - TrackState *trs; - TimeState *tms; - CDContentWatcher *ccw; - VolumeState *vs; - - ps = dynamic_cast(notifier); - trs = dynamic_cast(notifier); - tms = dynamic_cast(notifier); - ccw = dynamic_cast(notifier); - vs = dynamic_cast(notifier); - - if(ps) - { - AdjustButtonStates(); - HandlePlayState(); - } - else - if(trs) - { - - if(fTrackMenu->CountItems() != engine->TrackStateWatcher()->GetNumTracks()) - fTrackMenu->SetItemCount(engine->TrackStateWatcher()->GetNumTracks()); - - fTrackMenu->SetValue(engine->TrackStateWatcher()->GetTrack()-1); - - UpdateCDInfo(); - } - else - if(tms) - { - UpdateTimeInfo(); - } - else - if(ccw) - { - UpdateCDInfo(); - } - else - if(vs) - { - fVolume->SetValue(engine->VolumeStateWatcher()->GetVolume()); - } -} - -void -CDPlayer::HandlePlayState(void) -{ - switch(engine->PlayStateWatcher()->GetState()) - { - case kNoCD: - { - fCurrentTrack->SetHighColor(fStopColor); - fCurrentTrack->Invalidate(); - break; - } - case kStopped: - { - fCurrentTrack->SetHighColor(fStopColor); - fCurrentTrack->Invalidate(); - break; - } - case kPaused: - { - fCurrentTrack->SetHighColor(fPlayColor); - break; - } - case kPlaying: - { - fCurrentTrack->SetHighColor(fPlayColor); - fCurrentTrack->Invalidate(); - break; - } - case kSkipping: - { - fCurrentTrack->SetHighColor(fStopColor); - break; - } default: { - break; + BView::MessageReceived(msg); + break; } } } @@ -458,7 +424,7 @@ CDPlayer::HandlePlayState(void) void CDPlayer::AdjustButtonStates(void) { - CDState state = gCDDevice.GetState(); +/* CDState state = gCDDevice.GetState(); if(state==kNoCD) { @@ -485,56 +451,13 @@ CDPlayer::AdjustButtonStates(void) fPlay->SetState(1); else fPlay->SetState(0); -} - -void -CDPlayer::UpdateCDInfo(void) -{ - BString CDName, currentTrackName; - vector trackNames; - - int32 currentTrack = engine->TrackStateWatcher()->GetTrack(); - - bool trackresult = engine->ContentWatcher()->GetContent(&CDName,&trackNames); - - if(currentTrack < 0) - { - fCDTitle->SetText(""); - fCurrentTrack->SetText(""); - return; - } - - if(currentTrack == 0) - currentTrack++; - - if(trackresult) - { - if(CDName.CountChars()<1) - { - // if the CD name is NULL, then it means we have no disc in the drive. - fCDTitle->SetText(""); - fCurrentTrack->SetText(""); - } - else - { - currentTrackName << "Track " << currentTrack << ": " << trackNames[ currentTrack - 1]; - fCurrentTrack->SetText(currentTrackName.String()); - fCDTitle->SetText(CDName.String()); - } - - return; - } - else - { - fCDTitle->SetText("Audio CD"); - currentTrackName << "Track " << currentTrack; - fCurrentTrack->SetText(currentTrackName.String()); - } +*/ } void CDPlayer::UpdateTimeInfo(void) { +/* int32 min,sec; char string[1024]; @@ -561,21 +484,13 @@ CDPlayer::UpdateTimeInfo(void) else sprintf(string,"Track --:-- / --:--"); fTrackTime->SetText(string); +*/ } void CDPlayer::AttachedToWindow() { - - // start observing - engine->AttachedToLooper(Window()); - StartObserving(engine->TrackStateWatcher()); - StartObserving(engine->PlayStateWatcher()); - StartObserving(engine->ContentWatcher()); - StartObserving(engine->TimeStateWatcher()); - StartObserving(engine->VolumeStateWatcher()); - - fVolume->SetTarget(this); + fVolumeSlider->SetTarget(this); fStop->SetTarget(this); fPlay->SetTarget(this); fNextTrack->SetTarget(this); @@ -619,7 +534,243 @@ CDPlayer::FrameResized(float new_width, float new_height) void CDPlayer::Pulse() { - engine->DoPulse(); + WatchCDState(); +} + +void CDPlayer::WatchCDState(void) +{ + // One watcher function to rule them all + + // first, watch the one setting independent of having a CD: volume + uint8 drivevolume = fCDDrive.GetVolume(); + if(fVolume == drivevolume) + { + fVolume=drivevolume; + fVolumeSlider->SetValue(fVolume); + } + + // Second, establish whether or not we have a CD in the drive + CDState playstate = fCDDrive.GetState(); + + if(playstate == kNoCD) + { + // Yes, we have no bananas! + + if(fWindowState != kNoCD) + { + // We have just discovered that we have no bananas + fWindowState = kNoCD; + + // Because we are changing play states, we will need to update the GUI + + fDiscID=-1; + fCDTitle->SetText("No CD"); + + fCurrentTrack->SetText(""); + fCurrentTrack->SetHighColor(fStopColor); + fCurrentTrack->Invalidate(); + fTrackMenu->SetItemCount(0); + fTrackTime->SetText("Track --:-- / --:--"); + fDiscTime->SetText("Disc --:-- / --:--"); + fPlayList.SetTrackCount(0); + fPlayList.SetStartingTrack(1); + fPlayList.SetCurrentTrack(1); + + if(fPlay->GetState()==1) + fPlay->SetState(0); + } + else + { + // No change in the app's play state, so do nothing + } + + return; + } + +//------------------------------------------------------------------------------------------------ + // Now otherwise handle the play state + if(playstate == kStopped) + { + if(fWindowState == kPlaying) + { + // This means that the drive finished playing the song, so get the next one + // from the list and play it + int16 next = fPlayList.GetNextTrack(); + if(next > 0) + fCDDrive.Play(next); + } + + if(fPlay->GetState()==1) + { + fPlay->SetState(0); + fCurrentTrack->SetHighColor(fStopColor); + fCurrentTrack->Invalidate(); + } + } + else + if(playstate == kPlaying) + { + if(fPlay->GetState()==0) + fPlay->SetState(1); + fCurrentTrack->SetHighColor(fPlayColor); + fCurrentTrack->Invalidate(); + } + else + if(playstate == kPaused) + { + fPlay->SetState(0); + } + +//------------------------------------------------------------------------------------------------ + // If we got this far, then there must be a CD in the drive. The next order on the agenda + // is to find out which CD it is + int32 discid = fCDDrive.GetDiscID(); + bool update_track_gui=false; + + if(discid != fDiscID) + { + update_track_gui = true; + + // Apparently the disc has changed since we last looked. + if(fCDQuery.CurrentDiscID()!=discid) + { + fCDQuery.SetToCD(fCDDrive.GetDrivePath()); + } + + if(fCDQuery.Ready()) + { + fDiscID = discid; + + // Note that we only update the CD title for now. We still need a track number + // in order to update the display for the selected track + if(fCDQuery.GetTitles(&fCDName, &fTrackNames, 1000000)) + { + fCDTitle->SetText(fCDName.String()); + fUseTrackNames=true; + } + else + { + fCDName="Audio CD"; + fCDTitle->SetText("Audio CD"); + fUseTrackNames=false; + } + } + } + +//------------------------------------------------------------------------------------------------ + // Now that we know which CD it is, update the track info + int16 drivecount = fCDDrive.CountTracks(); + int16 drivetrack = fCDDrive.GetTrack(); + + int16 playlisttrack = fPlayList.GetCurrentTrack(); + int16 playlistcount = fPlayList.TrackCount(); + + if(playstate == kPlaying) + { + // The main thing is that we need to make sure that the playlist and the drive's track + // stay in sync. The CD's track may have been changed by an outside source, so if + // the drive is playing, check for playlist sync. + if(playlisttrack != drivetrack) + { + playlisttrack = drivetrack; + fPlayList.SetTrackCount(drivecount); + fPlayList.SetCurrentTrack(drivetrack); + } + update_track_gui=true; + } + else + { + if(playlistcount != drivecount) + { + // This happens only when CDs are changed + if(drivecount<0) + { + // There is no CD in the drive. The playlist needs to have its track + // count set to 0 and it also needs to be rewound. + fPlayList.SetStartingTrack(1); + fPlayList.SetTrackCount(0); + playlisttrack=1; + playlistcount=0; + } + else + { + // Two possible cases here: playlist is empty or playlist has a different + // number of tracks. In either case, the playlist needs to be reinitialized + // to the current track data + fPlayList.SetStartingTrack(1); + fPlayList.SetTrackCount(drivecount); + playlisttrack=fPlayList.GetCurrentTrack(); + playlistcount=drivecount; + } + } + else + { + // CD has not changed, so check for change in tracks + if(playlisttrack != drivetrack) + { + update_track_gui=true; + } + else + { + // do nothing. Everything is hunky-dory + } + } + } + + if(update_track_gui) + { + BString currentTrackName; + + if(playlisttrack >= 0) + { + int16 whichtrack = playlisttrack; + + if(whichtrack == 0) + whichtrack++; + + if(fUseTrackNames && fTrackNames.size()>0) + currentTrackName << "Track " << whichtrack << ": " << fTrackNames[ whichtrack - 1]; + else + currentTrackName << "Track " << whichtrack; + + fCurrentTrack->SetText(currentTrackName.String()); + + fTrackMenu->SetItemCount(playlistcount); + fTrackMenu->SetValue(playlisttrack-1); + } + else + { + fCurrentTrack->SetText(""); + fTrackMenu->SetItemCount(0); + fTrackMenu->SetValue(1); + } + } + +//------------------------------------------------------------------------------------------------ + // Now update the time info + cdaudio_time tracktime; + cdaudio_time disctime; + cdaudio_time tracktotal; + cdaudio_time disctotal; + char timestring[1024]; + + if(fCDDrive.GetTime(tracktime, disctime)) + { + fCDDrive.GetTimeForDisc(disctotal); + sprintf(timestring,"Disc %ld:%.2ld / %ld:%.2ld",disctime.minutes,disctime.seconds, + disctotal.minutes,disctotal.seconds); + fDiscTime->SetText(timestring); + + fCDDrive.GetTimeForTrack(playlisttrack,tracktotal); + sprintf(timestring,"Track %ld:%.2ld / %ld:%.2ld",tracktime.minutes,tracktime.seconds, + tracktotal.minutes,tracktotal.seconds); + fTrackTime->SetText(timestring); + } + else + { + fTrackTime->SetText("Track --:-- / --:--"); + fDiscTime->SetText("Disc --:-- / --:--"); + } } class CDPlayerWindow : public BWindow @@ -631,7 +782,7 @@ public: CDPlayerWindow::CDPlayerWindow(void) : BWindow(BRect (100, 100, 610, 200), "CD Player", B_TITLED_WINDOW, B_NOT_V_RESIZABLE | - B_NOT_ZOOMABLE) + B_NOT_ZOOMABLE | B_ASYNCHRONOUS_CONTROLS) { float wmin,wmax,hmin,hmax; diff --git a/src/apps/cdplayer/CDPlayer.h b/src/apps/cdplayer/CDPlayer.h index 0ec2031bdb..e4fd8cfbd7 100644 --- a/src/apps/cdplayer/CDPlayer.h +++ b/src/apps/cdplayer/CDPlayer.h @@ -16,15 +16,16 @@ #include #include -#include "Observer.h" -#include "CDEngine.h" #include "TrackMenu.h" +#include "CDAudioDevice.h" +#include "CDDBSupport.h" +#include "PlayList.h" class DrawButton; class DoubleShotDrawButton; class TwoStateDrawButton; -class CDPlayer : public BView, private Observer +class CDPlayer : public BView { public: CDPlayer(BRect frame, const char *name, @@ -40,19 +41,11 @@ public: virtual void FrameResized(float new_width, float new_height); virtual void MessageReceived(BMessage *); - // observing overrides - virtual BHandler *RecipientHandler() const { return (BHandler *)this; } - - virtual void NoticeChange(Notifier *); - private: - void HandlePlayState(void); - void UpdateCDInfo(void); + void WatchCDState(void); void UpdateTimeInfo(void); void AdjustButtonStates(void); - CDEngine *engine; - DrawButton *fStop, *fNextTrack, *fPrevTrack, @@ -67,7 +60,7 @@ private: *fRepeat, *fPlay; - BSlider *fVolume; + BSlider *fVolumeSlider; BStringView *fCDTitle, *fCurrentTrack, @@ -84,6 +77,16 @@ private: rgb_color fStopColor; rgb_color fPlayColor; + + CDAudioDevice fCDDrive; + PlayList fPlayList; + CDState fWindowState; + int32 fDiscID; + CDDBQuery fCDQuery; + uint8 fVolume; + bool fUseTrackNames; + vector fTrackNames; + BString fCDName; }; diff --git a/src/apps/cdplayer/FunctionObjectMessage.cpp b/src/apps/cdplayer/FunctionObjectMessage.cpp deleted file mode 100644 index 446b879f0e..0000000000 --- a/src/apps/cdplayer/FunctionObjectMessage.cpp +++ /dev/null @@ -1,50 +0,0 @@ -/* - Copyright 1999, Be Incorporated. All Rights Reserved. - This file may be used under the terms of the Be Sample Code License. -*/ - -// This defines code for sending funciton objects in messages - -#ifndef _BE_H -#include -#endif - -#include "FunctionObjectMessage.h" - - -BMessage * -FunctorFactoryCommon::NewMessage(const FunctionObject *functor) -{ - BMessage *result = new BMessage('fCmG'); - ASSERT(result); - - long error = result->AddData("functor", B_RAW_TYPE, - functor, functor->Size()); - - if (error != B_NO_ERROR) { - delete result; - result = NULL; - } - - return result; -} - -bool -FunctorFactoryCommon::DispatchIfFunctionObject(BMessage *message) -{ - if (message->what != 'fCmG') - return false; - - // find the functor - long size; - FunctionObject *functor; - status_t error = message->FindData("functor", B_RAW_TYPE, (const void**)&functor, &size); - if (error != B_NO_ERROR) - return false; - - ASSERT(functor); - // functor found, call it - (*functor)(); - return true; -} - diff --git a/src/apps/cdplayer/FunctionObjectMessage.h b/src/apps/cdplayer/FunctionObjectMessage.h deleted file mode 100644 index 0674435177..0000000000 --- a/src/apps/cdplayer/FunctionObjectMessage.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - Copyright 1999, Be Incorporated. All Rights Reserved. - This file may be used under the terms of the Be Sample Code License. -*/ - -// This defines some function object glue code - -// See the Be Newsletter article about using Function Objects in the Be messaging -// model for more information - -#ifndef __FUNCTION_OBJECT_MESSAGE__ -#define __FUNCTION_OBJECT_MESSAGE__ - -#ifndef _BE_H -#include -#include -#endif - -class FunctionObject { -public: - virtual void operator()() = 0; - virtual ~FunctionObject() {} - virtual ulong Size() const = 0; -}; - -template -class PlainMemberFunctionObject : public FunctionObject { -public: - PlainMemberFunctionObject(FT callThis, T *onThis) - : function(callThis), - target(onThis) - { - } - virtual ~PlainMemberFunctionObject() {} - - virtual void operator()() - { (target->*function)(); } - - virtual ulong Size() const { return sizeof(*this); } -private: - FT function; - T *target; -}; - -template -class SingleParamMemberFunctionObject : public FunctionObject { -public: - SingleParamMemberFunctionObject(FT callThis, T *onThis, P withThis) - : function(callThis), - target(onThis), - parameter(withThis) - { - } - virtual ~SingleParamMemberFunctionObject() {} - - virtual void operator()() - { (target->*function)(parameter); } - - virtual ulong Size() const { return sizeof(*this); } -private: - FT function; - T *target; - P parameter; -}; - -class FunctorFactoryCommon { -public: - static bool DispatchIfFunctionObject(BMessage *); -protected: - static BMessage *NewMessage(const FunctionObject *); -}; - -#endif \ No newline at end of file diff --git a/src/apps/cdplayer/Jamfile b/src/apps/cdplayer/Jamfile index 7e80ff54e1..65a330d6ff 100644 --- a/src/apps/cdplayer/Jamfile +++ b/src/apps/cdplayer/Jamfile @@ -4,15 +4,11 @@ AddResources CDPlayer : CDPlayer.rdef ; App CDPlayer : CDAudioDevice.cpp CDDBSupport.cpp - CDEngine.cpp CDPlayer.cpp DoubleShotDrawButton.cpp DrawButton.cpp - FunctionObjectMessage.cpp - Observer.cpp PlayList.cpp TrackMenu.cpp TwoStateDrawButton.cpp - TypedList.cpp ; LinkSharedOSLibs CDPlayer : be net netapi translation ; diff --git a/src/apps/cdplayer/Observer.cpp b/src/apps/cdplayer/Observer.cpp deleted file mode 100644 index 631012b895..0000000000 --- a/src/apps/cdplayer/Observer.cpp +++ /dev/null @@ -1,180 +0,0 @@ -/* - Copyright 1999, Be Incorporated. All Rights Reserved. - This file may be used under the terms of the Be Sample Code License. -*/ - -// This defines the Observer and Notifier classes - -#include -#include -#include -#include "Observer.h" - -Observer::Observer(Notifier *target) - : observedList(4, true) -{ - if (target) - StartObserving(target); -} - -Observer::~Observer() -{ - StopObserving(); - // tell everyone to stop sending us notices -} - -void -Observer::StartObserving(Notifier *target) -{ - ASSERT(target->RecipientHandler()); - ASSERT(RecipientHandler()->Looper()); - - // send a message to the notifier to start sending us notices - if (target->RecipientHandler()->Looper()) { - BMessage *message = new BMessage(kStartObserving); - message->AddPointer("observer", this); - message->AddPointer("observed", target); - - // send the message to the looper associated with the - // notifier - target->RecipientHandler()->Looper()->PostMessage(message, - target->RecipientHandler()); - NotifierListEntry *entry = new NotifierListEntry; - - entry->observed = target; - entry->handler = target->RecipientHandler(); - entry->looper = target->RecipientHandler()->Looper(); - - observedList.AddItem(entry); - } -} - -void -Observer::SendStopObserving(NotifierListEntry *target) -{ - // send a message to the notifier to start sending us notices - if (target->looper) { - BMessage *message = new BMessage(kEndObserving); - message->AddPointer("observer", this); - message->AddPointer("observed", target->observed); - target->looper->PostMessage(message, target->handler); - } -} - -NotifierListEntry * -StopObservingOne(NotifierListEntry *observed, void *castToObserver) -{ - ((Observer *)castToObserver)->SendStopObserving(observed); - return 0; -} - -void -Observer::StopObserving() -{ - // send a message to all the notifiers to start sending us notices - observedList.EachElement(StopObservingOne, this); - observedList.MakeEmpty(); -} - -bool -Observer::HandleObservingMessages(const BMessage *message) -{ - switch (message->what) { - case kNoticeChange: - { - // look for notice messages from notifiers - Notifier *observed = NULL; - Observer *observer = NULL; - message->FindPointer("observed", (void**)&observed); - message->FindPointer("observer", (void**)&observer); - ASSERT(observed); - ASSERT(observer); - if (!observed || !observer) - return false; - - ASSERT(dynamic_cast(observer)); - - // this is a notice for us, call the NoticeChange function - observer->NoticeChange(observed); - return true; - } - default: - return false; - } -} - -static ObserverListEntry * -NotifyOne(ObserverListEntry *observer, void *castToObserved) -{ - if (observer->looper) { - BMessage *message = new BMessage(kNoticeChange); - message->AddPointer("observed", castToObserved); - message->AddPointer("observer", observer->observer); - observer->looper->PostMessage(message, observer->handler); - } - return 0; -} - -void -Notifier::Notify() -{ - // send notices to all the observers - observerList.EachElement(NotifyOne, this); -} - -static ObserverListEntry * -FindItemWithObserver(ObserverListEntry *item, void *castToObserver) -{ - if (item->observer == castToObserver) - return item; - return 0; -} - -void -Notifier::AddObserver(Observer *observer) -{ - ObserverListEntry *item = new ObserverListEntry; - item->observer = observer; - item->handler = observer->RecipientHandler(); - item->looper = observer->RecipientHandler()->Looper(); - ASSERT(item->looper); - observerList.AddUnique(item); -} - -void -Notifier::RemoveObserver(Observer *observer) -{ - ObserverListEntry *item = observerList.EachElement( - FindItemWithObserver, observer); - - observerList.RemoveItem(item); - delete item; -} - -bool -Notifier::HandleObservingMessages(const BMessage *message) -{ - switch (message->what) { - case kStartObserving: - case kEndObserving: - { - // handle messages about stopping and starting observing - Observer *observer = 0; - Notifier *observed = 0; - message->FindPointer("observer", (void**)&observer); - message->FindPointer("observed", (void**)&observed); - ASSERT(observer); - ASSERT(observed); - if (!observer || !observed) - return false; - - if (message->what == kStartObserving) - observed->AddObserver(observer); - else - observed->RemoveObserver(observer); - return true; - } - default: - return false; - } -} diff --git a/src/apps/cdplayer/Observer.h b/src/apps/cdplayer/Observer.h deleted file mode 100644 index d17c0c6a62..0000000000 --- a/src/apps/cdplayer/Observer.h +++ /dev/null @@ -1,98 +0,0 @@ -/* - Copyright 1999, Be Incorporated. All Rights Reserved. - This file may be used under the terms of the Be Sample Code License. -*/ - -// This defines the Observer and Notifier classes - -// The idea of observing is make it easier to support a client-server -// setup where a client want's to react to changes in the server state, -// for instance a view displaying a track number needs to change whenever -// a track changes. Normally this is done by the client periodically checking -// the server from within a Pulse call or a simillar mechanism. With Observer -// and Notifier, the Observer (client) starts observing a Notifier (server) -// and then just sits back and wait to get a notice, whenever the Notifier -// changes. - -#ifndef __OBSERVER__ -#define __OBSERVER__ - -#include "TypedList.h" -#include - -const uint32 kNoticeChange = 'notc'; -const uint32 kStartObserving = 'stob'; -const uint32 kEndObserving = 'edob'; - -class Notifier; - -class NotifierListEntry { -public: - Notifier *observed; - BHandler *handler; - BLooper *looper; -}; - -class Observer { -public: - Observer(Notifier *target = NULL); - virtual ~Observer(); - - void StartObserving(Notifier *); - // start observing a speficied notifier - void StopObserving(Notifier *); - // stop observing a speficied notifier - void StopObserving(); - // stop observing all the observed notifiers - - virtual void NoticeChange(Notifier *) = 0; - // override this to get your job done, your class will get called - // whenever the Notifier changes - - static bool HandleObservingMessages(const BMessage *message); - // call this from subclasses MessageReceived - virtual BHandler *RecipientHandler() const = 0; - // hook this up to return subclasses looper -private: - void SendStopObserving(NotifierListEntry *); - - // keep a list of all the observed notifiers - TypedList observedList; - -friend NotifierListEntry *StopObservingOne(NotifierListEntry *, void *); -}; - -class ObserverListEntry { -public: - Observer *observer; - BHandler *handler; - BLooper *looper; -}; - -class Notifier { -public: - Notifier() - {} - virtual ~Notifier() - {} - - virtual void Notify(); - // call this when the notifier object changes to send notices - // to all the observers - - static bool HandleObservingMessages(const BMessage *message); - // call this from subclasses MessageReceived - virtual BHandler *RecipientHandler() const = 0; - // hook this up to return subclasses looper - - // keep a list of all the observers so that we can send them notices - void AddObserver(Observer *); - void RemoveObserver(Observer *); - -private: - TypedList observerList; - -friend class Observer; -}; - -#endif \ No newline at end of file diff --git a/src/apps/cdplayer/PlayList.cpp b/src/apps/cdplayer/PlayList.cpp index 77519f96c1..b4e2e96cc9 100644 --- a/src/apps/cdplayer/PlayList.cpp +++ b/src/apps/cdplayer/PlayList.cpp @@ -3,7 +3,7 @@ #include #include -#define DEBUG_PLAYLIST +//#define DEBUG_PLAYLIST #ifdef DEBUG_PLAYLIST #include @@ -47,7 +47,7 @@ PlayList::SetTrackCount(const int16 &count) STRACE(("PlayList::SetTrackCount(%d)\n",count)); - if(count < 0) + if(count <= 0) { fTrackCount = 0; fTrackIndex = 0; @@ -71,13 +71,7 @@ PlayList::SetStartingTrack(const int16 &start) STRACE(("PlayList::SetStartingTrack(%d)\n",start)); - if(start >= TrackCount()) - fStartingTrack = TrackCount() - 1; - else - if(start < 1) - fStartingTrack = 1; - else - fStartingTrack = start; + fStartingTrack = start; fLocker.Unlock(); } diff --git a/src/apps/cdplayer/TrackMenu.cpp b/src/apps/cdplayer/TrackMenu.cpp index 5bc1ee603d..b1e43351c5 100644 --- a/src/apps/cdplayer/TrackMenu.cpp +++ b/src/apps/cdplayer/TrackMenu.cpp @@ -109,7 +109,6 @@ void TrackMenu::MouseDown(BPoint point) { BPoint pt(point); - int32 saveditem = fCurrentItem; int32 item = ItemAt(pt); diff --git a/src/apps/cdplayer/TypedList.cpp b/src/apps/cdplayer/TypedList.cpp deleted file mode 100644 index 56ce164be0..0000000000 --- a/src/apps/cdplayer/TypedList.cpp +++ /dev/null @@ -1,87 +0,0 @@ -/* - Copyright 1999, Be Incorporated. All Rights Reserved. - This file may be used under the terms of the Be Sample Code License. -*/ - -// TypedList is a type-safe template version of BList - -#include -#include "TypedList.h" - -void * -_PointerList::EachElement(GenericEachFunction func, void *passThru) -{ - // iterates through all elements, calling func on each - // if each function returns a nonzero value, terminates early - void *result = NULL; - int32 numElements = CountItems(); - - for (int32 index = 0; index < numElements; index++) - if ((result = func(ItemAtFast(index), passThru)) != NULL) - break; - - return result; -} - -_PointerList::_PointerList(const _PointerList &list) - : BList(list), - owning(list.owning) -{ -} - -_PointerList::_PointerList(int32 itemsPerBlock = 20, bool owningList) - : BList(itemsPerBlock), - owning(owningList) -{ -} - -_PointerList::~_PointerList() -{ -} - -bool -_PointerList::Owning() const -{ - return owning; -} - -bool -_PointerList::AddUnique(void *newItem) -{ - if (IndexOf(newItem) >= 0) - return false; - - return AddItem(newItem); -} - -struct OneMatchParams { - void *matchThis; - _PointerList::GenericCompareFunction matchFunction; -}; - - -static void * -MatchOne(void *item, void *castToParams) -{ - OneMatchParams *params = (OneMatchParams *)castToParams; - if (params->matchFunction(item, params->matchThis) == 0) - // got a match, terminate search - return item; - - return 0; -} - -bool -_PointerList::AddUnique(void *newItem, GenericCompareFunction function) -{ - OneMatchParams params; - params.matchThis = newItem; - params.matchFunction = function; - - if (EachElement(MatchOne, ¶ms)) - // already in list - return false; - - return AddItem(newItem); -} - diff --git a/src/apps/cdplayer/TypedList.h b/src/apps/cdplayer/TypedList.h deleted file mode 100644 index de10d87506..0000000000 --- a/src/apps/cdplayer/TypedList.h +++ /dev/null @@ -1,326 +0,0 @@ -/* - Copyright 1999, Be Incorporated. All Rights Reserved. - This file may be used under the terms of the Be Sample Code License. -*/ - -// TypedList is a garden-variety of a type-safe template version of BList - -#ifndef __LIST_TEMPLATE__ -#define __LIST_TEMPLATE__ - -#ifndef _BE_H -#include -#endif - -#include - -class _PointerList : public BList { -public: - _PointerList(const _PointerList &list); - _PointerList(int32 itemsPerBlock = 20, bool owning = false); - virtual ~_PointerList(); - - typedef void *(* GenericEachFunction)(void *, void *); - typedef int (* GenericCompareFunction)(const void *, const void *); - void *EachElement(GenericEachFunction, void *); - - bool AddUnique(void *); - // return true if item added or already in the list - bool AddUnique(void *, GenericCompareFunction); - - bool Owning() const; -private: - const bool owning; -}; - -// TypedList - -// to be used as a list of pointers to objects; this class should contain -// pretty much no code, just stubs that do proper type conversion -// it uses BetterEachBList for all of it's functionality and provides a -// typed interface -template -class TypedList : public _PointerList { -public: - TypedList(int32 itemsPerBlock = 20, bool owning = false); - TypedList(const TypedList&); - virtual ~TypedList(); - - TypedList &operator=(const TypedList &); - - // iteration and sorting - typedef T (* EachFunction)(T, void *); - typedef const T (* ConstEachFunction)(const T, void *); - typedef int (* CompareFunction)(const T *, const T *); - - // adding and removing - bool AddItem(T); - bool AddItem(T, int32); - bool AddList(TypedList *); - bool AddList(TypedList *, int32); - bool AddUnique(T); - bool AddUnique(T, CompareFunction); - - bool RemoveItem(T); - T RemoveItem(int32); - T RemoveItemAt(int32); - // same as RemoveItem(int32), RemoveItem does not work when T is a scalar - - void MakeEmpty(); - - // item access - T ItemAt(int32) const; - T ItemAtFast(int32) const; - // does not do an index range check - - T FirstItem() const; - T LastItem() const; - - T Items() const; - - // misc. getters - int32 IndexOf(const T) const; - bool HasItem(const T) const; - bool IsEmpty() const; - int32 CountItems() const; - - - T EachElement(EachFunction, void *); - const T EachElement(ConstEachFunction, void *) const; - // Do for each are obsoleted by this list, possibly add - // them for convenience - void SortItems(CompareFunction); - bool ReplaceItem(int32 index, T item); - bool SwapItems(int32 a, int32 b); - bool MoveItem(int32 from, int32 to); - -private: - friend class ParseArray; -}; - -template -TypedList::TypedList(int32 itemsPerBlock, bool owning) - : _PointerList(itemsPerBlock, owning) -{ -} - -template -TypedList::TypedList(const TypedList &list) - : _PointerList(list) -{ - ASSERT(!list.Owning()); - // copying owned lists does not work yet -} - -template -TypedList::~TypedList() -{ - if (Owning()) - // have to nuke elements first - MakeEmpty(); -} - -template -TypedList & -TypedList::operator=(const TypedList &from) -{ - ASSERT(!from.Owning()); - // copying owned lists does not work yet - - return (TypedList &)BList::operator=(from); -} - -template -bool -TypedList::AddItem(T item) -{ - return _PointerList::AddItem(item); -} - -template -bool -TypedList::AddItem(T item, int32 atIndex) -{ - return _PointerList::AddItem(item, atIndex); -} - -template -bool -TypedList::AddList(TypedList *newItems) -{ - return _PointerList::AddList(newItems); -} - -template -bool -TypedList::AddList(TypedList *newItems, int32 atIndex) -{ - return _PointerList::AddList(newItems, atIndex); -} - -template -bool -TypedList::AddUnique(T item) -{ - return _PointerList::AddUnique(item); -} - -template -bool -TypedList::AddUnique(T item, CompareFunction function) -{ - return _PointerList::AddUnique(item, (GenericCompareFunction)function); -} - - -template -bool -TypedList::RemoveItem(T item) -{ - bool result = _PointerList::RemoveItem(item); - - if (result && Owning()) { - delete item; - } - - return result; -} - -template -T -TypedList::RemoveItem(int32 index) -{ - return (T)_PointerList::RemoveItem(index); -} - -template -T -TypedList::RemoveItemAt(int32 index) -{ - return (T)_PointerList::RemoveItem(index); -} - -template -T -TypedList::ItemAt(int32 index) const -{ - return (T)_PointerList::ItemAt(index); -} - -template -T -TypedList::ItemAtFast(int32 index) const -{ - return (T)_PointerList::ItemAtFast(index); -} - -template -int32 -TypedList::IndexOf(const T item) const -{ - return _PointerList::IndexOf(item); -} - -template -T -TypedList::FirstItem() const -{ - return (T)_PointerList::FirstItem(); -} - -template -T -TypedList::LastItem() const -{ - return (T)_PointerList::LastItem(); -} - -template -bool -TypedList::HasItem(const T item) const -{ - return _PointerList::HasItem(item); -} - -template -bool -TypedList::IsEmpty() const -{ - return _PointerList::IsEmpty(); -} - -template -int32 -TypedList::CountItems() const -{ - return _PointerList::CountItems(); -} - -template -void -TypedList::MakeEmpty() -{ - if (Owning()) { - int32 numElements = CountItems(); - - for (int32 count = 0; count < numElements; count++) - // this is probably not the most efficient, but - // is relatively indepenent of BList implementation - // details - RemoveItem(LastItem()); - } - _PointerList::MakeEmpty(); -} - -template -T -TypedList::EachElement(EachFunction func, void *params) -{ - return (T)_PointerList::EachElement((GenericEachFunction)func, params); -} - - -template -const T -TypedList::EachElement(ConstEachFunction func, void *params) const -{ - return (const T) - const_cast *>(this)->_PointerList::EachElement( - (GenericEachFunction)func, params); -} - - -template -T -TypedList::Items() const -{ - return (T)_PointerList::Items(); -} - -template -void -TypedList::SortItems(CompareFunction function) -{ - ASSERT(sizeof(T) == sizeof(void *)); - _PointerList::SortItems((GenericCompareFunction)function); -} - -template -bool TypedList::ReplaceItem(int32 index, T item) -{ - return _PointerList::ReplaceItem(index, (void *)item); -} - -template -bool TypedList::SwapItems(int32 a, int32 b) -{ - return _PointerList::SwapItems(a, b); -} - -template -bool TypedList::MoveItem(int32 from, int32 to) -{ - return _PointerList::MoveItem(from, to); -} - - -#endif