Updated the resource signature to match the app's signature

Utilize CDDB lookups
Use display controls look similar to LED panels on CD players
Window is resizable and controls respond appropriately
Added support to display elapsed time, both for the CD and the current track
Numerous little bugfixes


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@13294 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
DarkWyrm
2005-06-27 18:44:34 +00:00
parent 9f5ffc2c3c
commit 175c92ffb3
5 changed files with 400 additions and 103 deletions
+252 -49
View File
@@ -24,6 +24,9 @@
#include "CDButton.h" #include "CDButton.h"
#include "DrawButton.h" #include "DrawButton.h"
#include <TranslationUtils.h> #include <TranslationUtils.h>
#include <TranslatorFormats.h>
#include <TranslatorRoster.h>
#include <BitmapStream.h>
enum enum
{ {
@@ -42,9 +45,15 @@ enum
}; };
CDButton::CDButton(BRect frame, const char *name, uint32 resizeMask, uint32 flags) CDButton::CDButton(BRect frame, const char *name, uint32 resizeMask, uint32 flags)
: BView(frame, name, resizeMask, flags) : BView(frame, name, resizeMask, flags | B_FRAME_EVENTS)
{ {
// This will eventually one of a few preferences - to stop playing music
// when the app is closed
fStopOnQuit = false;
SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
// TODO: Support multiple CD drives
engine = new CDEngine(CDEngine::FindCDPlayerDevice()); engine = new CDEngine(CDEngine::FindCDPlayerDevice());
BuildGUI(); BuildGUI();
@@ -65,34 +74,69 @@ CDButton::CDButton(BRect frame, const char *name, uint32 resizeMask, uint32 flag
CDButton::~CDButton() CDButton::~CDButton()
{ {
if(fStopOnQuit)
engine->Stop();
delete engine; delete engine;
} }
void CDButton::BuildGUI(void) void CDButton::BuildGUI(void)
{ {
fCDTitle = new BTextControl( BRect(5,5,230,30), "CDTitle","","",new BMessage(M_SET_CD_TITLE)); BRect r(5,5,230,25);
AddChild(fCDTitle);
fCDTitle->SetDivider(0);
fCDTitle->TextView()->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
BBox *box = new BBox(BRect(0,0,75,20),"TrackBox"); // Assemble the CD Title box
box->MoveTo(fCDTitle->Frame().right + 15, 5); fCDBox = new BBox(r,"TrackBox");
AddChild(box); AddChild(fCDBox);
BView *view = new BView( box->Bounds().InsetByCopy(2,2), "view",B_FOLLOW_NONE,B_WILL_DRAW); BView *view = new BView( fCDBox->Bounds().InsetByCopy(2,2), "view",B_FOLLOW_ALL,B_WILL_DRAW);
view->SetViewColor(0,0,0); view->SetViewColor(20,20,20);
box->AddChild(view); fCDBox->AddChild(view);
fTrackNumber = new BStringView( view->Bounds(),"TrackNumber","Track: --"); fCDTitle = new BStringView(view->Bounds(),"CDTitle","");
view->AddChild(fTrackNumber); view->AddChild(fCDTitle);
fTrackNumber->SetAlignment(B_ALIGN_CENTER); fCDTitle->SetHighColor(200,200,200);
fTrackNumber->SetHighColor(0,255,0); fCDTitle->SetFont(be_bold_font);
fTrackNumber->SetFont(be_bold_font);
fVolume = new BSlider( BRect(0,0,75,30), "VolumeSlider", "Volume", new BMessage(M_SET_VOLUME),0,100); r.Set(fCDTitle->Frame().right + 15,5,Bounds().right - 5,25);
fTrackBox = new BBox(r,"TrackBox",B_FOLLOW_TOP);
AddChild(fTrackBox);
view = new BView( fTrackBox->Bounds().InsetByCopy(2,2), "view",B_FOLLOW_ALL,B_WILL_DRAW);
view->SetViewColor(0,34,7);
fTrackBox->AddChild(view);
fCurrentTrack = new BStringView( view->Bounds(),"TrackNumber","Track:",B_FOLLOW_ALL);
view->AddChild(fCurrentTrack);
fCurrentTrack->SetHighColor(40,230,40);
fCurrentTrack->SetFont(be_bold_font);
r.OffsetBy(0, r.Height() + 5);
fTimeBox = new BBox(r,"TimeBox",B_FOLLOW_LEFT_RIGHT);
AddChild(fTimeBox);
view = new BView( fTimeBox->Bounds().InsetByCopy(2,2), "view",B_FOLLOW_ALL,B_WILL_DRAW);
view->SetViewColor(0,7,34);
fTimeBox->AddChild(view);
r = view->Bounds();
r.right /= 2;
fTrackTime = new BStringView(r,"TrackTime","Track --:-- / --:--",B_FOLLOW_LEFT_RIGHT);
view->AddChild(fTrackTime);
fTrackTime->SetHighColor(120,120,255);
fTrackTime->SetFont(be_bold_font);
r.right = view->Bounds().right;
r.left = fTrackTime->Frame().right + 1;
fDiscTime = new BStringView(r,"DiscTime","Disc --:-- / --:--",B_FOLLOW_RIGHT);
view->AddChild(fDiscTime);
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()); fVolume->MoveTo(5, Bounds().bottom - 10 - fVolume->Frame().Height());
AddChild(fVolume); AddChild(fVolume);
fVolume->SetEnabled(false);
fStop = new DrawButton( BRect(0,0,1,1), "Stop", BTranslationUtils::GetBitmap('PNG ',"stop_up"), fStop = new DrawButton( BRect(0,0,1,1), "Stop", BTranslationUtils::GetBitmap('PNG ',"stop_up"),
BTranslationUtils::GetBitmap('PNG ',"stop_down"), new BMessage(M_STOP), BTranslationUtils::GetBitmap('PNG ',"stop_down"), new BMessage(M_STOP),
@@ -154,7 +198,7 @@ void CDButton::BuildGUI(void)
fSave = new DrawButton( BRect(0,0,1,1), "Save", BTranslationUtils::GetBitmap('PNG ',"save_up"), fSave = new DrawButton( BRect(0,0,1,1), "Save", BTranslationUtils::GetBitmap('PNG ',"save_up"),
BTranslationUtils::GetBitmap('PNG ',"save_down"), new BMessage(M_SAVE), BTranslationUtils::GetBitmap('PNG ',"save_down"), new BMessage(M_SAVE),
B_FOLLOW_BOTTOM, B_WILL_DRAW); B_FOLLOW_NONE, B_WILL_DRAW);
fSave->ResizeToPreferred(); fSave->ResizeToPreferred();
fSave->MoveTo(fEject->Frame().right + 20, Bounds().bottom - 5 - fSave->Frame().Height()); fSave->MoveTo(fEject->Frame().right + 20, Bounds().bottom - 5 - fSave->Frame().Height());
fSave->SetDisabled(BTranslationUtils::GetBitmap('PNG ',"save_disabled")); fSave->SetDisabled(BTranslationUtils::GetBitmap('PNG ',"save_disabled"));
@@ -164,7 +208,7 @@ void CDButton::BuildGUI(void)
// TODO: Shuffle and Repeat are special buttons. Implement as two-state buttons // TODO: Shuffle and Repeat are special buttons. Implement as two-state buttons
fShuffle = new DrawButton( BRect(0,0,1,1), "Shuffle", BTranslationUtils::GetBitmap('PNG ',"shuffle_up"), fShuffle = new DrawButton( BRect(0,0,1,1), "Shuffle", BTranslationUtils::GetBitmap('PNG ',"shuffle_up"),
BTranslationUtils::GetBitmap('PNG ',"shuffle_down"), new BMessage(M_SHUFFLE), BTranslationUtils::GetBitmap('PNG ',"shuffle_down"), new BMessage(M_SHUFFLE),
B_FOLLOW_BOTTOM, B_WILL_DRAW); B_FOLLOW_NONE, B_WILL_DRAW);
fShuffle->ResizeToPreferred(); fShuffle->ResizeToPreferred();
fShuffle->MoveTo(fSave->Frame().right + 2, Bounds().bottom - 5 - fShuffle->Frame().Height()); fShuffle->MoveTo(fSave->Frame().right + 2, Bounds().bottom - 5 - fShuffle->Frame().Height());
fShuffle->SetDisabled(BTranslationUtils::GetBitmap('PNG ',"shuffle_disabled")); fShuffle->SetDisabled(BTranslationUtils::GetBitmap('PNG ',"shuffle_disabled"));
@@ -173,7 +217,7 @@ void CDButton::BuildGUI(void)
fRepeat = new DrawButton( BRect(0,0,1,1), "Repeat", BTranslationUtils::GetBitmap('PNG ',"repeat_up"), fRepeat = new DrawButton( BRect(0,0,1,1), "Repeat", BTranslationUtils::GetBitmap('PNG ',"repeat_up"),
BTranslationUtils::GetBitmap('PNG ',"repeat_down"), new BMessage(M_REPEAT), BTranslationUtils::GetBitmap('PNG ',"repeat_down"), new BMessage(M_REPEAT),
B_FOLLOW_BOTTOM, B_WILL_DRAW); B_FOLLOW_NONE, B_WILL_DRAW);
fRepeat->ResizeToPreferred(); fRepeat->ResizeToPreferred();
fRepeat->MoveTo(fShuffle->Frame().right + 2, Bounds().bottom - 5 - fRepeat->Frame().Height()); fRepeat->MoveTo(fShuffle->Frame().right + 2, Bounds().bottom - 5 - fRepeat->Frame().Height());
fRepeat->SetDisabled(BTranslationUtils::GetBitmap('PNG ',"repeat_disabled")); fRepeat->SetDisabled(BTranslationUtils::GetBitmap('PNG ',"repeat_disabled"));
@@ -183,13 +227,72 @@ void CDButton::BuildGUI(void)
void void
CDButton::MessageReceived(BMessage *message) CDButton::MessageReceived(BMessage *msg)
{ {
switch (message->what) if(msg->WasDropped())
{
// We'll handle two types of drops: those from Tracker and those from ShowImage
if(msg->what==B_SIMPLE_DATA)
{
int32 actions;
if(msg->FindInt32("be:actions",&actions)==B_OK)
{
// ShowImage drop. This is a negotiated drag&drop, so send a reply
BMessage reply(B_COPY_TARGET), response;
reply.AddString("be:types","image/jpeg");
reply.AddString("be:types","image/png");
msg->SendReply(&reply,&response);
// now, we've gotten the response
if(response.what==B_MIME_DATA)
{
// Obtain and translate the received data
uint8 *imagedata;
ssize_t datasize;
// Try JPEG first
if(response.FindData("image/jpeg",B_MIME_DATA,(const void **)&imagedata,&datasize)!=B_OK)
{
// Try PNG next and piddle out if unsuccessful
if(response.FindData("image/png",B_PNG_FORMAT,(const void **)&imagedata,&datasize)!=B_OK)
return;
}
// Set up to decode into memory
BMemoryIO memio(imagedata,datasize);
BTranslatorRoster *roster=BTranslatorRoster::Default();
BBitmapStream bstream;
if(roster->Translate(&memio,NULL,NULL,&bstream, B_TRANSLATOR_BITMAP)==B_OK)
{
BBitmap *bmp;
if(bstream.DetachBitmap(&bmp)!=B_OK)
return;
SetBitmap(bmp);
}
}
return;
}
entry_ref ref;
if(msg->FindRef("refs",&ref)==B_OK)
{
// Tracker drop
BBitmap *bmp=BTranslationUtils::GetBitmap(&ref);
SetBitmap(bmp);
}
}
return;
}
switch (msg->what)
{ {
case M_SET_VOLUME: case M_SET_VOLUME:
{ {
// TODO: Implement // TODO: Implement
engine->SetVolume(fVolume->Value());
break; break;
} }
case M_STOP: case M_STOP:
@@ -245,10 +348,10 @@ CDButton::MessageReceived(BMessage *message)
default: default:
{ {
if (!Observer::HandleObservingMessages(message)) if (!Observer::HandleObservingMessages(msg))
{ {
// just support observing messages // just support observing messages
BView::MessageReceived(message); BView::MessageReceived(msg);
break; break;
} }
} }
@@ -258,17 +361,17 @@ CDButton::MessageReceived(BMessage *message)
void void
CDButton::NoticeChange(Notifier *notifier) CDButton::NoticeChange(Notifier *notifier)
{ {
// debugger("");
PlayState *ps; PlayState *ps;
TrackState *trs; TrackState *trs;
TimeState *tms; TimeState *tms;
CDContentWatcher *ccw; CDContentWatcher *ccw;
VolumeState *vs;
ps = dynamic_cast<PlayState *>(notifier); ps = dynamic_cast<PlayState *>(notifier);
trs = dynamic_cast<TrackState *>(notifier); trs = dynamic_cast<TrackState *>(notifier);
tms = dynamic_cast<TimeState *>(notifier); tms = dynamic_cast<TimeState *>(notifier);
ccw = dynamic_cast<CDContentWatcher *>(notifier); ccw = dynamic_cast<CDContentWatcher *>(notifier);
vs = dynamic_cast<VolumeState *>(notifier);
if(ps) if(ps)
{ {
@@ -286,6 +389,10 @@ CDButton::NoticeChange(Notifier *notifier)
fRewind->SetEnabled(false); fRewind->SetEnabled(false);
fSave->SetEnabled(false); fSave->SetEnabled(false);
} }
fCurrentTrack->SetText("Track: ");
fTrackTime->SetText("Track --:-- / --:--");
fDiscTime->SetText("Disc --:-- / --:--");
printf("Notification: No CD\n");
break; break;
} }
case kStopped: case kStopped:
@@ -300,6 +407,10 @@ CDButton::NoticeChange(Notifier *notifier)
fRewind->SetEnabled(true); fRewind->SetEnabled(true);
fSave->SetEnabled(true); fSave->SetEnabled(true);
} }
fCurrentTrack->SetText("Track: ");
fTrackTime->SetText("Track --:-- / --:--");
fDiscTime->SetText("Disc --:-- / --:--");
printf("Notification: CD Stopped\n");
break; break;
} }
case kPaused: case kPaused:
@@ -315,7 +426,7 @@ CDButton::NoticeChange(Notifier *notifier)
fRewind->SetEnabled(true); fRewind->SetEnabled(true);
fSave->SetEnabled(true); fSave->SetEnabled(true);
} }
UpdateTrackInfo(); printf("Notification: CD Paused\n");
break; break;
} }
case kPlaying: case kPlaying:
@@ -330,7 +441,7 @@ CDButton::NoticeChange(Notifier *notifier)
fRewind->SetEnabled(true); fRewind->SetEnabled(true);
fSave->SetEnabled(true); fSave->SetEnabled(true);
} }
UpdateTrackInfo(); printf("Notification: CD Playing\n");
break; break;
} }
case kSkipping: case kSkipping:
@@ -345,6 +456,7 @@ CDButton::NoticeChange(Notifier *notifier)
fRewind->SetEnabled(true); fRewind->SetEnabled(true);
fSave->SetEnabled(true); fSave->SetEnabled(true);
} }
printf("Notification: CD Skipping\n");
break; break;
} }
default: default:
@@ -356,34 +468,69 @@ CDButton::NoticeChange(Notifier *notifier)
else else
if(trs) if(trs)
{ {
UpdateTrackInfo(); UpdateCDInfo();
// TODO: Update track count indicator // TODO: Update track count indicator
} }
else else
if(tms) if(tms)
{ {
UpdateTimeInfo();
} }
else else
if(ccw) if(ccw)
{ {
UpdateCDInfo();
}
else
if(vs)
{
fVolume->SetValue(engine->VolumeStateWatcher()->GetVolume());
} }
} }
void void
CDButton::UpdateTrackInfo(void) CDButton::UpdateCDInfo(void)
{ {
BString CDName, currentTrackName;
fCurrentTrack=engine->TrackStateWatcher()->GetTrack(); vector<BString> trackNames;
fTrackCount=engine->TrackStateWatcher()->GetNumTracks();
if(fCurrentTrack < 1) int32 currentTrack = engine->TrackStateWatcher()->GetTrack();
engine->ContentWatcher()->GetContent(&CDName,&trackNames);
fCDTitle->SetText(CDName.String());
if(currentTrack > 0)
{ {
char string[255]; currentTrackName << "Track " << currentTrack << ": " << trackNames[ currentTrack - 1];
sprintf(string,"Track: %ld",fCurrentTrack); fCurrentTrack->SetText(currentTrackName.String());
fTrackNumber->SetText(string);
} }
else else
fTrackNumber->SetText("Track: --"); {
fCurrentTrack->SetText("Track:");
}
}
void
CDButton::UpdateTimeInfo(void)
{
int32 min,sec;
char string[1024];
engine->TimeStateWatcher()->GetDiscTime(min,sec);
if(min >= 0)
sprintf(string,"Disc %ld:%.2ld / --:--",min,sec);
else
sprintf(string,"Disc --:-- / --:--");
fDiscTime->SetText(string);
engine->TimeStateWatcher()->GetTrackTime(min,sec);
if(min >= 0)
sprintf(string,"Track %ld:%.2ld / --:--",min,sec);
else
sprintf(string,"Track --:-- / --:--");
fTrackTime->SetText(string);
} }
void void
@@ -393,6 +540,9 @@ CDButton::AttachedToWindow()
engine->AttachedToLooper(Window()); engine->AttachedToLooper(Window());
StartObserving(engine->TrackStateWatcher()); StartObserving(engine->TrackStateWatcher());
StartObserving(engine->PlayStateWatcher()); StartObserving(engine->PlayStateWatcher());
StartObserving(engine->ContentWatcher());
StartObserving(engine->TimeStateWatcher());
StartObserving(engine->VolumeStateWatcher());
fVolume->SetTarget(this); fVolume->SetTarget(this);
fStop->SetTarget(this); fStop->SetTarget(this);
@@ -407,12 +557,52 @@ CDButton::AttachedToWindow()
fRepeat->SetTarget(this); fRepeat->SetTarget(this);
} }
void
CDButton::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
// The boxes are laid out with 5 pixels between the window edge and each box.
// Additionally, 15 pixels of padding are between the two boxes themselves
float half = (new_width / 2);
fCDBox->ResizeTo( half - 7, fCDBox->Bounds().Height() );
fTrackBox->MoveTo(half + 8, fTrackBox->Frame().top);
fTrackBox->ResizeTo( Bounds().right - (half + 8) - 5, fTrackBox->Bounds().Height() );
fTimeBox->MoveTo(half + 8, fTimeBox->Frame().top);
fTimeBox->ResizeTo( Bounds().right - (half + 8) - 5, fTimeBox->Bounds().Height() );
fRepeat->MoveTo(new_width - fRepeat->Bounds().right - 5, fRepeat->Frame().top);
fShuffle->MoveTo(fRepeat->Frame().left - fShuffle->Bounds().Width() - 2, fShuffle->Frame().top);
fSave->MoveTo(fShuffle->Frame().left - fSave->Bounds().Width() - 2, fSave->Frame().top);
}
void void
CDButton::Pulse() CDButton::Pulse()
{ {
engine->DoPulse(); engine->DoPulse();
} }
void
CDButton::SetBitmap(BBitmap *bitmap)
{
if(!bitmap)
{
ClearViewBitmap();
return;
}
SetViewBitmap(bitmap);
fVolume->SetViewBitmap(bitmap);
fVolume->Invalidate();
Invalidate();
}
class CDButtonWindow : public BWindow class CDButtonWindow : public BWindow
{ {
public: public:
@@ -421,8 +611,14 @@ public:
}; };
CDButtonWindow::CDButtonWindow(void) CDButtonWindow::CDButtonWindow(void)
: BWindow(BRect (100, 100, 610, 400), "CD Player", B_TITLED_WINDOW, 0) : BWindow(BRect (100, 100, 610, 200), "CD Player", B_TITLED_WINDOW, B_NOT_V_RESIZABLE)
{ {
float wmin,wmax,hmin,hmax;
GetSizeLimits(&wmin,&wmax,&hmin,&hmax);
wmin=510;
hmin=100;
SetSizeLimits(wmin,wmax,hmin,hmax);
} }
bool CDButtonWindow::QuitRequested(void) bool CDButtonWindow::QuitRequested(void)
@@ -431,16 +627,23 @@ bool CDButtonWindow::QuitRequested(void)
return true; return true;
} }
CDButtonApplication::CDButtonApplication() CDButtonWindow *cdbwin;
: BApplication("application/x-vnd.Be-CDPlayer") CDButton *cdbutton;
{
BWindow *window = new CDButtonWindow();
BView *button = new CDButton(window->Bounds(), "CD");
window->AddChild(button);
window->Show();
}
CDButtonApplication::CDButtonApplication()
: BApplication("application/x-vnd.Haiku-CDPlayer")
{
// BWindow *window = new CDButtonWindow();
// BView *button = new CDButton(window->Bounds(), "CD");
/// window->AddChild(button);
// window->Show();
cdbwin = new CDButtonWindow();
cdbutton = new CDButton(cdbwin->Bounds(), "CD");
cdbwin->AddChild(cdbutton);
cdbwin->Show();
}
int int
main(int, char **argv) main(int, char **argv)
+15 -4
View File
@@ -35,6 +35,8 @@ public:
virtual void AttachedToWindow(); virtual void AttachedToWindow();
virtual void Pulse(); virtual void Pulse();
virtual void FrameResized(float new_width, float new_height);
virtual void MessageReceived(BMessage *); virtual void MessageReceived(BMessage *);
@@ -45,7 +47,11 @@ public:
virtual void NoticeChange(Notifier *); virtual void NoticeChange(Notifier *);
private: private:
void UpdateTrackInfo(void); void UpdateCDInfo(void);
void UpdateTimeInfo(void);
void SetBitmap(BBitmap *bitmap);
bool fStopOnQuit;
CDEngine *engine; CDEngine *engine;
@@ -54,11 +60,16 @@ private:
BSlider *fVolume; BSlider *fVolume;
BTextControl *fCDTitle; BStringView *fCDTitle;
BStringView *fTrackNumber; BStringView *fCurrentTrack;
BStringView *fTrackTime;
BStringView *fDiscTime;
BBox *fCDBox;
BBox *fTrackBox;
BBox *fTimeBox;
CDState fCDState; CDState fCDState;
int32 fTrackCount, fCurrentTrack;
}; };
+109 -37
View File
@@ -15,6 +15,8 @@
#include "scsi.h" #include "scsi.h"
#include "CDEngine.h" #include "CDEngine.h"
const bigtime_t kPulseRate = 500000;
PeriodicWatcher::PeriodicWatcher(int devicefd) PeriodicWatcher::PeriodicWatcher(int devicefd)
: Notifier(), : Notifier(),
devicefd(devicefd) devicefd(devicefd)
@@ -168,50 +170,67 @@ TimeState::UpdateState()
status_t media_status = B_DEV_NO_MEDIA; status_t media_status = B_DEV_NO_MEDIA;
ioctl(devicefd, B_GET_MEDIA_STATUS, &media_status, sizeof(media_status)); ioctl(devicefd, B_GET_MEDIA_STATUS, &media_status, sizeof(media_status));
if (media_status != B_NO_ERROR) if (media_status != B_NO_ERROR)
return CurrentState(-1, -1); return CurrentState(-1, -1, -1, -1);
status_t result = ioctl(devicefd, B_SCSI_GET_POSITION, &pos); status_t result = ioctl(devicefd, B_SCSI_GET_POSITION, &pos);
if (result != B_NO_ERROR) if (result != B_NO_ERROR)
return CurrentState(-1, -1); return CurrentState(-1, -1, -1, -1);
else if ((!pos.position[1]) || (pos.position[1] >= 0x13) || else
((pos.position[1] == 0x12) && (!pos.position[6]))) if ((!pos.position[1]) || (pos.position[1] >= 0x13) ||
return CurrentState(0, 0); ((pos.position[1] == 0x12) && (!pos.position[6])))
{
// 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);
}
else else
return CurrentState(pos.position[9], pos.position[10]); return CurrentState(pos.position[9], pos.position[10], pos.position[13], pos.position[14]);
} }
bool bool
TimeState::CurrentState(int32 minutes, int32 seconds) TimeState::CurrentState(int32 dmin, int32 dsec, int32 tmin, int32 tsec)
{ {
if (minutes == oldMinutes && seconds == oldSeconds) if (dmin == fDiscMinutes && dsec == fDiscSeconds)
return false; return false;
oldMinutes = minutes;
oldSeconds = seconds; fDiscMinutes = dmin;
fDiscSeconds = dsec;
fTrackMinutes = tmin;
fTrackSeconds = tsec;
return true; return true;
} }
void void
TimeState::GetTime(int32 &minutes, int32 &seconds) const TimeState::GetDiscTime(int32 &minutes, int32 &seconds) const
{ {
minutes = oldMinutes; minutes = fDiscMinutes;
seconds = oldSeconds; seconds = fDiscSeconds;
}
void
TimeState::GetTrackTime(int32 &minutes, int32 &seconds) const
{
minutes = fTrackMinutes;
seconds = fTrackSeconds;
} }
CDContentWatcher::CDContentWatcher(int devicefd) CDContentWatcher::CDContentWatcher(int devicefd)
: PeriodicWatcher(devicefd), : PeriodicWatcher(devicefd),
cddbQuery("us.cddb.com", 888, true), cddbQuery("us.freedb.org", 888, true),
discID(-1), discID(-1),
wasReady(false) fReady(false)
{ {
} }
CDContentWatcher::CDContentWatcher(BMessage *message) CDContentWatcher::CDContentWatcher(BMessage *message)
: PeriodicWatcher(message), : PeriodicWatcher(message),
cddbQuery("us.cddb.com", 888, true), cddbQuery("us.freedb.org", 888, true),
discID(-1), discID(-1),
wasReady(false) fReady(false)
{ {
} }
@@ -224,23 +243,61 @@ CDContentWatcher::GetContent(BString *title, vector<BString> *tracks)
bool bool
CDContentWatcher::UpdateState() CDContentWatcher::UpdateState()
{ {
bool newReady = false;
bool newDiscID = -1; bool newDiscID = -1;
if (engine->PlayStateWatcher()->GetState() != kNoCD) {
// 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
if (engine->PlayStateWatcher()->GetState() != kNoCD)
{
scsi_toc toc; scsi_toc toc;
ioctl(devicefd, B_SCSI_GET_TOC, &toc); ioctl(devicefd, B_SCSI_GET_TOC, &toc);
newDiscID = cddbQuery.GetDiscID(&toc); newDiscID = cddbQuery.GetDiscID(&toc);
if (discID != newDiscID)
cddbQuery.SetToCD(&toc); if (discID == newDiscID)
return false;
// We have changed CDs, so we are not ready until the CDDB lookup finishes
cddbQuery.SetToCD(&toc);
fReady=false;
}
// If the CD has changed and the CDDB query is ready, we set to true so that
// when UpdateState returns, a notification is sent
bool result = ( (fReady != cddbQuery.Ready()) && (newDiscID != discID) );
if(result)
{
fReady = true;
discID = newDiscID;
} }
bool result = newReady != cddbQuery.Ready() && newDiscID != discID;
newReady = cddbQuery.Ready();
newDiscID = discID;
return result; return result;
} }
VolumeState::VolumeState(int devicefd)
: PeriodicWatcher(devicefd),
fVolume(-1)
{
}
bool
VolumeState::UpdateState(void)
{
scsi_volume vol;
ioctl(devicefd, B_SCSI_GET_VOLUME, &vol);
if(vol.port0_volume == fVolume)
return false;
fVolume = vol.port0_volume;
return true;
}
int32
VolumeState::GetVolume(void) const
{
return fVolume;
}
CDEngine::CDEngine(int devicefd) CDEngine::CDEngine(int devicefd)
: BHandler("CDEngine"), : BHandler("CDEngine"),
devicefd(devicefd), devicefd(devicefd),
@@ -318,12 +375,13 @@ void
CDEngine::Play() CDEngine::Play()
{ {
// play the CD // play the CD
if (playState.GetState() == kNoCD) { if (playState.GetState() == kNoCD)
{
// no CD available, bail out // no CD available, bail out
ioctl(devicefd, B_LOAD_MEDIA, 0, 0); ioctl(devicefd, B_LOAD_MEDIA, 0, 0);
return; return;
} }
scsi_play_track track; scsi_play_track track;
track.start_track = 1; track.start_track = 1;
@@ -332,7 +390,8 @@ CDEngine::Play()
track.end_index = 1; track.end_index = 1;
status_t result = ioctl(devicefd, B_SCSI_PLAY_TRACK, &track); status_t result = ioctl(devicefd, B_SCSI_PLAY_TRACK, &track);
if (result != B_NO_ERROR) { if (result != B_NO_ERROR)
{
PRINT(("error %s playing track\n", strerror(errno))); PRINT(("error %s playing track\n", strerror(errno)));
return; return;
} }
@@ -343,7 +402,8 @@ CDEngine::PlayContinue()
{ {
// continue after a pause // continue after a pause
status_t result = ioctl(devicefd, B_SCSI_RESUME_AUDIO); status_t result = ioctl(devicefd, B_SCSI_RESUME_AUDIO);
if (result != B_NO_ERROR) { if (result != B_NO_ERROR)
{
PRINT(("error %s resuming\n", strerror(errno))); PRINT(("error %s resuming\n", strerror(errno)));
return; return;
} }
@@ -354,8 +414,9 @@ CDEngine::Stop()
{ {
// stop a playing CD // stop a playing CD
status_t result = ioctl(devicefd, B_SCSI_STOP_AUDIO); status_t result = ioctl(devicefd, B_SCSI_STOP_AUDIO);
if (result != B_NO_ERROR) { if (result != B_OK)
PRINT(("error %s stoping\n", strerror(errno))); {
PRINT(("error %s stopping\n", strerror(errno)));
return; return;
} }
} }
@@ -371,9 +432,10 @@ CDEngine::Eject()
// if door open, load the media, else eject the CD // if door open, load the media, else eject the CD
status_t result = ioctl(devicefd, status_t result = ioctl(devicefd,
media_status == B_DEV_DOOR_OPEN ? B_LOAD_MEDIA : B_EJECT_DEVICE); media_status == B_DEV_DOOR_OPEN ? B_LOAD_MEDIA : B_EJECT_DEVICE);
if (result != B_NO_ERROR) { if (result != B_OK)
{
PRINT(("error %s ejecting\n", strerror(errno))); PRINT(("error %s ejecting\n", strerror(errno)));
return; return;
} }
@@ -506,12 +568,22 @@ CDEngine::SelectTrack(int32 trackNumber)
} }
} }
const bigtime_t kPulseRate = 500000; 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);
}
void void
CDEngine::DoPulse() CDEngine::DoPulse()
{ {
// this is the CDEngine's hearbeat; Since it is a Notifier, it checks if // 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 // any values changed since the last hearbeat and sends notices to observers
bigtime_t time = system_time(); bigtime_t time = system_time();
+23 -12
View File
@@ -98,13 +98,18 @@ public:
: PeriodicWatcher(message) : PeriodicWatcher(message)
{} {}
void GetTime(int32 &minutes, int32 &seconds) const; void GetDiscTime(int32 &minutes, int32 &seconds) const;
void GetTrackTime(int32 &minutes, int32 &seconds) const;
private: private:
bool UpdateState(); bool UpdateState();
bool CurrentState(int32 minutes, int32 seconds); bool CurrentState(int32 dmin, int32 dsec, int32 tmin, int32 tsec);
int32 oldMinutes;
int32 oldSeconds; int32 fDiscMinutes;
int32 fDiscSeconds;
int32 fTrackMinutes;
int32 fTrackSeconds;
}; };
class CDContentWatcher : public PeriodicWatcher { class CDContentWatcher : public PeriodicWatcher {
@@ -119,24 +124,24 @@ private:
CDDBQuery cddbQuery; CDDBQuery cddbQuery;
int32 discID; int32 discID;
bool wasReady; bool fReady;
}; };
class VolumeState : public PeriodicWatcher { class VolumeState : public PeriodicWatcher {
// this watcher sends notices to observers that are interrested // this watcher sends notices to observers that are interested
// about changes in the current volume // about changes in the current volume
// currently not used yet // currently not used yet
public: public:
VolumeState(int devicefd) VolumeState(int devicefd);
: PeriodicWatcher(devicefd)
{ }
VolumeState(BMessage *message) VolumeState(BMessage *message)
: PeriodicWatcher(message) : PeriodicWatcher(message)
{} {}
bool UpdateState();
bool UpdateState() { return true; }
virtual void DoPulse() {}
int32 GetVolume() const; int32 GetVolume() const;
private:
int32 fVolume;
}; };
class CDEngine : public BHandler { class CDEngine : public BHandler {
@@ -168,6 +173,7 @@ public:
void StopSkipping(); void StopSkipping();
void SelectTrack(int32); void SelectTrack(int32);
void SetVolume(uint8 value);
TrackState *TrackStateWatcher() TrackState *TrackStateWatcher()
{ return &trackState; } { return &trackState; }
@@ -186,6 +192,11 @@ public:
CDContentWatcher *ContentWatcher() CDContentWatcher *ContentWatcher()
{ return &contentWatcher; } { return &contentWatcher; }
VolumeState *VolumeStateWatcher()
// to find the current location on the CD, you may call the GetVolume function
// VolumeState defines
{ return &volumeState; }
static int FindCDPlayerDevice(); static int FindCDPlayerDevice();
+1 -1
View File
@@ -80,7 +80,7 @@ resource(101, "BEOS:M:STD_ICON") #'MICN' array {
$"FFFFFFFFFFFF000000000EFFFFFFFFFF" $"FFFFFFFFFFFF000000000EFFFFFFFFFF"
}; };
resource(1, "BEOS:APP_SIG") #'MIMS' "application/x-vnd.Haiku.CDPlayer"; resource(1, "BEOS:APP_SIG") #'MIMS' "application/x-vnd.Haiku-CDPlayer";
resource(1, "BEOS:FILE_TYPES") message; resource(1, "BEOS:FILE_TYPES") message;