I didn't feel like working on the app_server today. 'Hope Sikosis doesn't mind. :D
Definitely a work in progress, but it'll play CDs at the moment. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@13267 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
c641898150
commit
238e9fd71b
451
src/apps/cdplayer/CDButton.cpp
Normal file
451
src/apps/cdplayer/CDButton.cpp
Normal file
@ -0,0 +1,451 @@
|
||||
// Copyright 1992-1999, Be Incorporated, All Rights Reserved.
|
||||
// This file may be used under the terms of the Be Sample Code License.
|
||||
//
|
||||
// send comments/suggestions/feedback to pavel@be.com
|
||||
//
|
||||
|
||||
#include <Alert.h>
|
||||
#include <Application.h>
|
||||
#include <Bitmap.h>
|
||||
#include <Box.h>
|
||||
#include <Button.h>
|
||||
#include <Debug.h>
|
||||
#include <Deskbar.h>
|
||||
#include <Dragger.h>
|
||||
#include <Entry.h>
|
||||
#include <MenuItem.h>
|
||||
#include <PopUpMenu.h>
|
||||
#include <Roster.h>
|
||||
#include <Window.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "CDButton.h"
|
||||
#include "DrawButton.h"
|
||||
#include <TranslationUtils.h>
|
||||
|
||||
enum
|
||||
{
|
||||
M_STOP='mstp',
|
||||
M_PLAY,
|
||||
M_NEXT_TRACK,
|
||||
M_PREV_TRACK,
|
||||
M_FFWD,
|
||||
M_REWIND,
|
||||
M_EJECT,
|
||||
M_SAVE,
|
||||
M_SHUFFLE,
|
||||
M_REPEAT,
|
||||
M_SET_VOLUME,
|
||||
M_SET_CD_TITLE
|
||||
};
|
||||
|
||||
CDButton::CDButton(BRect frame, const char *name, uint32 resizeMask, uint32 flags)
|
||||
: BView(frame, name, resizeMask, flags)
|
||||
{
|
||||
SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
|
||||
engine = new CDEngine(CDEngine::FindCDPlayerDevice());
|
||||
|
||||
BuildGUI();
|
||||
|
||||
fCDState = engine->PlayStateWatcher()->GetState();
|
||||
|
||||
if(fCDState == kNoCD)
|
||||
{
|
||||
fStop->SetEnabled(false);
|
||||
fPlay->SetEnabled(false);
|
||||
fNextTrack->SetEnabled(false);
|
||||
fPrevTrack->SetEnabled(false);
|
||||
fFastFwd->SetEnabled(false);
|
||||
fRewind->SetEnabled(false);
|
||||
fSave->SetEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
CDButton::~CDButton()
|
||||
{
|
||||
delete engine;
|
||||
}
|
||||
|
||||
void CDButton::BuildGUI(void)
|
||||
{
|
||||
fCDTitle = new BTextControl( BRect(5,5,230,30), "CDTitle","","",new BMessage(M_SET_CD_TITLE));
|
||||
AddChild(fCDTitle);
|
||||
fCDTitle->SetDivider(0);
|
||||
fCDTitle->TextView()->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
|
||||
|
||||
BBox *box = new BBox(BRect(0,0,75,20),"TrackBox");
|
||||
box->MoveTo(fCDTitle->Frame().right + 15, 5);
|
||||
AddChild(box);
|
||||
|
||||
BView *view = new BView( box->Bounds().InsetByCopy(2,2), "view",B_FOLLOW_NONE,B_WILL_DRAW);
|
||||
view->SetViewColor(0,0,0);
|
||||
box->AddChild(view);
|
||||
|
||||
fTrackNumber = new BStringView( view->Bounds(),"TrackNumber","Track: --");
|
||||
view->AddChild(fTrackNumber);
|
||||
fTrackNumber->SetAlignment(B_ALIGN_CENTER);
|
||||
fTrackNumber->SetHighColor(0,255,0);
|
||||
fTrackNumber->SetFont(be_bold_font);
|
||||
|
||||
fVolume = new BSlider( BRect(0,0,75,30), "VolumeSlider", "Volume", new BMessage(M_SET_VOLUME),0,100);
|
||||
fVolume->MoveTo(5, Bounds().bottom - 10 - fVolume->Frame().Height());
|
||||
AddChild(fVolume);
|
||||
fVolume->SetEnabled(false);
|
||||
|
||||
fStop = new DrawButton( BRect(0,0,1,1), "Stop", BTranslationUtils::GetBitmap('PNG ',"stop_up"),
|
||||
BTranslationUtils::GetBitmap('PNG ',"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->SetDisabled(BTranslationUtils::GetBitmap('PNG ',"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('PNG ',"play_up"),
|
||||
BTranslationUtils::GetBitmap('PNG ',"play_down"), new BMessage(M_PLAY),
|
||||
B_FOLLOW_BOTTOM, B_WILL_DRAW);
|
||||
fPlay->ResizeToPreferred();
|
||||
fPlay->MoveTo(fStop->Frame().right + 2, Bounds().bottom - 5 - fPlay->Frame().Height());
|
||||
fPlay->SetDisabled(BTranslationUtils::GetBitmap('PNG ',"play_disabled"));
|
||||
AddChild(fPlay);
|
||||
|
||||
fPrevTrack = new DrawButton( BRect(0,0,1,1), "PrevTrack", BTranslationUtils::GetBitmap('PNG ',"prev_up"),
|
||||
BTranslationUtils::GetBitmap('PNG ',"prev_down"), new BMessage(M_PREV_TRACK),
|
||||
B_FOLLOW_BOTTOM, B_WILL_DRAW);
|
||||
fPrevTrack->ResizeToPreferred();
|
||||
fPrevTrack->MoveTo(fPlay->Frame().right + 10, Bounds().bottom - 5 - fPrevTrack->Frame().Height());
|
||||
fPrevTrack->SetDisabled(BTranslationUtils::GetBitmap('PNG ',"prev_disabled"));
|
||||
AddChild(fPrevTrack);
|
||||
|
||||
fNextTrack = new DrawButton( BRect(0,0,1,1), "NextTrack", BTranslationUtils::GetBitmap('PNG ',"next_up"),
|
||||
BTranslationUtils::GetBitmap('PNG ',"next_down"), new BMessage(M_NEXT_TRACK),
|
||||
B_FOLLOW_BOTTOM, B_WILL_DRAW);
|
||||
fNextTrack->ResizeToPreferred();
|
||||
fNextTrack->MoveTo(fPrevTrack->Frame().right + 2, Bounds().bottom - 5 - fNextTrack->Frame().Height());
|
||||
fNextTrack->SetDisabled(BTranslationUtils::GetBitmap('PNG ',"next_disabled"));
|
||||
AddChild(fNextTrack);
|
||||
|
||||
// TODO: Fast Forward and Rewind are special buttons. Implement as two-state buttons
|
||||
fRewind = new DrawButton( BRect(0,0,1,1), "Rewind", BTranslationUtils::GetBitmap('PNG ',"rew_up"),
|
||||
BTranslationUtils::GetBitmap('PNG ',"rew_down"), new BMessage(M_PREV_TRACK),
|
||||
B_FOLLOW_BOTTOM, B_WILL_DRAW);
|
||||
fRewind->ResizeToPreferred();
|
||||
fRewind->MoveTo(fNextTrack->Frame().right + 10, Bounds().bottom - 5 - fRewind->Frame().Height());
|
||||
fRewind->SetDisabled(BTranslationUtils::GetBitmap('PNG ',"rew_disabled"));
|
||||
AddChild(fRewind);
|
||||
|
||||
fFastFwd = new DrawButton( BRect(0,0,1,1), "FastFwd", BTranslationUtils::GetBitmap('PNG ',"ffwd_up"),
|
||||
BTranslationUtils::GetBitmap('PNG ',"ffwd_down"), new BMessage(M_NEXT_TRACK),
|
||||
B_FOLLOW_BOTTOM, B_WILL_DRAW);
|
||||
fFastFwd->ResizeToPreferred();
|
||||
fFastFwd->MoveTo(fRewind->Frame().right + 2, Bounds().bottom - 5 - fFastFwd->Frame().Height());
|
||||
fFastFwd->SetDisabled(BTranslationUtils::GetBitmap('PNG ',"ffwd_disabled"));
|
||||
AddChild(fFastFwd);
|
||||
|
||||
fEject = new DrawButton( BRect(0,0,1,1), "Eject", BTranslationUtils::GetBitmap('PNG ',"eject_up"),
|
||||
BTranslationUtils::GetBitmap('PNG ',"eject_down"), new BMessage(M_EJECT),
|
||||
B_FOLLOW_BOTTOM, B_WILL_DRAW);
|
||||
fEject->ResizeToPreferred();
|
||||
fEject->MoveTo(fFastFwd->Frame().right + 20, Bounds().bottom - 5 - fEject->Frame().Height());
|
||||
fEject->SetDisabled(BTranslationUtils::GetBitmap('PNG ',"eject_disabled"));
|
||||
AddChild(fEject);
|
||||
|
||||
fSave = new DrawButton( BRect(0,0,1,1), "Save", BTranslationUtils::GetBitmap('PNG ',"save_up"),
|
||||
BTranslationUtils::GetBitmap('PNG ',"save_down"), new BMessage(M_SAVE),
|
||||
B_FOLLOW_BOTTOM, B_WILL_DRAW);
|
||||
fSave->ResizeToPreferred();
|
||||
fSave->MoveTo(fEject->Frame().right + 20, Bounds().bottom - 5 - fSave->Frame().Height());
|
||||
fSave->SetDisabled(BTranslationUtils::GetBitmap('PNG ',"save_disabled"));
|
||||
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('PNG ',"shuffle_up"),
|
||||
BTranslationUtils::GetBitmap('PNG ',"shuffle_down"), new BMessage(M_SHUFFLE),
|
||||
B_FOLLOW_BOTTOM, B_WILL_DRAW);
|
||||
fShuffle->ResizeToPreferred();
|
||||
fShuffle->MoveTo(fSave->Frame().right + 2, Bounds().bottom - 5 - fShuffle->Frame().Height());
|
||||
fShuffle->SetDisabled(BTranslationUtils::GetBitmap('PNG ',"shuffle_disabled"));
|
||||
AddChild(fShuffle);
|
||||
fShuffle->SetEnabled(false);
|
||||
|
||||
fRepeat = new DrawButton( BRect(0,0,1,1), "Repeat", BTranslationUtils::GetBitmap('PNG ',"repeat_up"),
|
||||
BTranslationUtils::GetBitmap('PNG ',"repeat_down"), new BMessage(M_REPEAT),
|
||||
B_FOLLOW_BOTTOM, B_WILL_DRAW);
|
||||
fRepeat->ResizeToPreferred();
|
||||
fRepeat->MoveTo(fShuffle->Frame().right + 2, Bounds().bottom - 5 - fRepeat->Frame().Height());
|
||||
fRepeat->SetDisabled(BTranslationUtils::GetBitmap('PNG ',"repeat_disabled"));
|
||||
AddChild(fRepeat);
|
||||
fRepeat->SetEnabled(false);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
CDButton::MessageReceived(BMessage *message)
|
||||
{
|
||||
switch (message->what)
|
||||
{
|
||||
case M_SET_VOLUME:
|
||||
{
|
||||
// TODO: Implement
|
||||
break;
|
||||
}
|
||||
case M_STOP:
|
||||
{
|
||||
engine->Stop();
|
||||
break;
|
||||
}
|
||||
case M_PLAY:
|
||||
{
|
||||
engine->PlayOrPause();
|
||||
break;
|
||||
}
|
||||
case M_NEXT_TRACK:
|
||||
{
|
||||
engine->SkipOneForward();
|
||||
break;
|
||||
}
|
||||
case M_PREV_TRACK:
|
||||
{
|
||||
engine->SkipOneBackward();
|
||||
break;
|
||||
}
|
||||
case M_FFWD:
|
||||
{
|
||||
// TODO: Implement
|
||||
break;
|
||||
}
|
||||
case M_REWIND:
|
||||
{
|
||||
// TODO: Implement
|
||||
break;
|
||||
}
|
||||
case M_EJECT:
|
||||
{
|
||||
engine->Eject();
|
||||
break;
|
||||
}
|
||||
case M_SAVE:
|
||||
{
|
||||
// TODO: Implement
|
||||
break;
|
||||
}
|
||||
case M_SHUFFLE:
|
||||
{
|
||||
// TODO: Implement
|
||||
break;
|
||||
}
|
||||
case M_REPEAT:
|
||||
{
|
||||
// TODO: Implement
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
|
||||
if (!Observer::HandleObservingMessages(message))
|
||||
{
|
||||
// just support observing messages
|
||||
BView::MessageReceived(message);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CDButton::NoticeChange(Notifier *notifier)
|
||||
{
|
||||
// debugger("");
|
||||
|
||||
PlayState *ps;
|
||||
TrackState *trs;
|
||||
TimeState *tms;
|
||||
CDContentWatcher *ccw;
|
||||
|
||||
ps = dynamic_cast<PlayState *>(notifier);
|
||||
trs = dynamic_cast<TrackState *>(notifier);
|
||||
tms = dynamic_cast<TimeState *>(notifier);
|
||||
ccw = dynamic_cast<CDContentWatcher *>(notifier);
|
||||
|
||||
if(ps)
|
||||
{
|
||||
switch(ps->GetState())
|
||||
{
|
||||
case kNoCD:
|
||||
{
|
||||
if(fStop->IsEnabled())
|
||||
{
|
||||
fStop->SetEnabled(false);
|
||||
fPlay->SetEnabled(false);
|
||||
fNextTrack->SetEnabled(false);
|
||||
fPrevTrack->SetEnabled(false);
|
||||
fFastFwd->SetEnabled(false);
|
||||
fRewind->SetEnabled(false);
|
||||
fSave->SetEnabled(false);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case kStopped:
|
||||
{
|
||||
if(!fStop->IsEnabled())
|
||||
{
|
||||
fStop->SetEnabled(true);
|
||||
fPlay->SetEnabled(true);
|
||||
fNextTrack->SetEnabled(true);
|
||||
fPrevTrack->SetEnabled(true);
|
||||
fFastFwd->SetEnabled(true);
|
||||
fRewind->SetEnabled(true);
|
||||
fSave->SetEnabled(true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case kPaused:
|
||||
{
|
||||
// TODO: Set play button to Pause
|
||||
if(!fStop->IsEnabled())
|
||||
{
|
||||
fStop->SetEnabled(true);
|
||||
fPlay->SetEnabled(true);
|
||||
fNextTrack->SetEnabled(true);
|
||||
fPrevTrack->SetEnabled(true);
|
||||
fFastFwd->SetEnabled(true);
|
||||
fRewind->SetEnabled(true);
|
||||
fSave->SetEnabled(true);
|
||||
}
|
||||
UpdateTrackInfo();
|
||||
break;
|
||||
}
|
||||
case kPlaying:
|
||||
{
|
||||
if(!fStop->IsEnabled())
|
||||
{
|
||||
fStop->SetEnabled(true);
|
||||
fPlay->SetEnabled(true);
|
||||
fNextTrack->SetEnabled(true);
|
||||
fPrevTrack->SetEnabled(true);
|
||||
fFastFwd->SetEnabled(true);
|
||||
fRewind->SetEnabled(true);
|
||||
fSave->SetEnabled(true);
|
||||
}
|
||||
UpdateTrackInfo();
|
||||
break;
|
||||
}
|
||||
case kSkipping:
|
||||
{
|
||||
if(!fStop->IsEnabled())
|
||||
{
|
||||
fStop->SetEnabled(true);
|
||||
fPlay->SetEnabled(true);
|
||||
fNextTrack->SetEnabled(true);
|
||||
fPrevTrack->SetEnabled(true);
|
||||
fFastFwd->SetEnabled(true);
|
||||
fRewind->SetEnabled(true);
|
||||
fSave->SetEnabled(true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
if(trs)
|
||||
{
|
||||
UpdateTrackInfo();
|
||||
// TODO: Update track count indicator
|
||||
}
|
||||
else
|
||||
if(tms)
|
||||
{
|
||||
}
|
||||
else
|
||||
if(ccw)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CDButton::UpdateTrackInfo(void)
|
||||
{
|
||||
|
||||
fCurrentTrack=engine->TrackStateWatcher()->GetTrack();
|
||||
fTrackCount=engine->TrackStateWatcher()->GetNumTracks();
|
||||
|
||||
if(fCurrentTrack < 1)
|
||||
{
|
||||
char string[255];
|
||||
sprintf(string,"Track: %ld",fCurrentTrack);
|
||||
fTrackNumber->SetText(string);
|
||||
}
|
||||
else
|
||||
fTrackNumber->SetText("Track: --");
|
||||
}
|
||||
|
||||
void
|
||||
CDButton::AttachedToWindow()
|
||||
{
|
||||
// start observing
|
||||
engine->AttachedToLooper(Window());
|
||||
StartObserving(engine->TrackStateWatcher());
|
||||
StartObserving(engine->PlayStateWatcher());
|
||||
|
||||
fVolume->SetTarget(this);
|
||||
fStop->SetTarget(this);
|
||||
fPlay->SetTarget(this);
|
||||
fNextTrack->SetTarget(this);
|
||||
fPrevTrack->SetTarget(this);
|
||||
fFastFwd->SetTarget(this);
|
||||
fRewind->SetTarget(this);
|
||||
fEject->SetTarget(this);
|
||||
fSave->SetTarget(this);
|
||||
fShuffle->SetTarget(this);
|
||||
fRepeat->SetTarget(this);
|
||||
}
|
||||
|
||||
void
|
||||
CDButton::Pulse()
|
||||
{
|
||||
engine->DoPulse();
|
||||
}
|
||||
|
||||
class CDButtonWindow : public BWindow
|
||||
{
|
||||
public:
|
||||
CDButtonWindow(void);
|
||||
bool QuitRequested(void);
|
||||
};
|
||||
|
||||
CDButtonWindow::CDButtonWindow(void)
|
||||
: BWindow(BRect (100, 100, 610, 400), "CD Player", B_TITLED_WINDOW, 0)
|
||||
{
|
||||
}
|
||||
|
||||
bool CDButtonWindow::QuitRequested(void)
|
||||
{
|
||||
be_app->PostMessage(B_QUIT_REQUESTED);
|
||||
return true;
|
||||
}
|
||||
|
||||
CDButtonApplication::CDButtonApplication()
|
||||
: BApplication("application/x-vnd.Be-CDPlayer")
|
||||
{
|
||||
BWindow *window = new CDButtonWindow();
|
||||
|
||||
BView *button = new CDButton(window->Bounds(), "CD");
|
||||
window->AddChild(button);
|
||||
window->Show();
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main(int, char **argv)
|
||||
{
|
||||
(new CDButtonApplication())->Run();
|
||||
|
||||
return 0;
|
||||
}
|
72
src/apps/cdplayer/CDButton.h
Normal file
72
src/apps/cdplayer/CDButton.h
Normal file
@ -0,0 +1,72 @@
|
||||
/*
|
||||
Copyright 1999, Be Incorporated. All Rights Reserved.
|
||||
This file may be used under the terms of the Be Sample Code License.
|
||||
*/
|
||||
// This defines the replicant button
|
||||
|
||||
#ifndef __CD_BUTTON__
|
||||
#define __CD_BUTTON__
|
||||
|
||||
#include <Application.h>
|
||||
#include <View.h>
|
||||
#include <Window.h>
|
||||
#include <View.h>
|
||||
#include <Button.h>
|
||||
#include <Slider.h>
|
||||
#include <TextControl.h>
|
||||
#include <StringView.h>
|
||||
|
||||
#include "Observer.h"
|
||||
#include "CDEngine.h"
|
||||
|
||||
class DrawButton;
|
||||
|
||||
class CDButton : public BView, private Observer
|
||||
{
|
||||
public:
|
||||
CDButton(BRect frame, const char *name, uint32 resizeMask = B_FOLLOW_ALL,
|
||||
uint32 flags = B_WILL_DRAW | B_NAVIGABLE | B_PULSE_NEEDED);
|
||||
|
||||
virtual ~CDButton();
|
||||
|
||||
void BuildGUI(void);
|
||||
|
||||
// misc BView overrides
|
||||
virtual void AttachedToWindow();
|
||||
|
||||
virtual void Pulse();
|
||||
|
||||
virtual void MessageReceived(BMessage *);
|
||||
|
||||
// observing overrides
|
||||
virtual BHandler *RecipientHandler() const
|
||||
{ return (BHandler *)this; }
|
||||
|
||||
virtual void NoticeChange(Notifier *);
|
||||
|
||||
private:
|
||||
void UpdateTrackInfo(void);
|
||||
|
||||
CDEngine *engine;
|
||||
|
||||
DrawButton *fStop, *fPlay, *fNextTrack, *fPrevTrack;
|
||||
DrawButton *fFastFwd, *fRewind, *fEject, *fSave, *fShuffle, *fRepeat;
|
||||
|
||||
BSlider *fVolume;
|
||||
|
||||
BTextControl *fCDTitle;
|
||||
BStringView *fTrackNumber;
|
||||
|
||||
CDState fCDState;
|
||||
int32 fTrackCount, fCurrentTrack;
|
||||
};
|
||||
|
||||
|
||||
class CDButtonApplication : public BApplication
|
||||
{
|
||||
public:
|
||||
CDButtonApplication();
|
||||
};
|
||||
|
||||
|
||||
#endif
|
583
src/apps/cdplayer/CDDBSupport.cpp
Normal file
583
src/apps/cdplayer/CDDBSupport.cpp
Normal file
@ -0,0 +1,583 @@
|
||||
// Copyright 1992-2000, Be Incorporated, All Rights Reserved.
|
||||
// This file may be used under the terms of the Be Sample Code License.
|
||||
//
|
||||
// send comments/suggestions/feedback to pavel@be.com
|
||||
//
|
||||
|
||||
#include "CDDBSupport.h"
|
||||
|
||||
#include <Debug.h>
|
||||
#include <Directory.h>
|
||||
#include <Entry.h>
|
||||
#include <File.h>
|
||||
#include <FindDirectory.h>
|
||||
#include <NetAddress.h>
|
||||
#include <Path.h>
|
||||
#include <Query.h>
|
||||
#include <Volume.h>
|
||||
#include <VolumeRoster.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <fs_index.h>
|
||||
#include <netdb.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
// some glue
|
||||
|
||||
template <class InitCheckable>
|
||||
void
|
||||
InitCheck(InitCheckable *item)
|
||||
{
|
||||
if (!item)
|
||||
throw B_ERROR;
|
||||
status_t error = item->InitCheck();
|
||||
if (error != B_OK)
|
||||
throw error;
|
||||
}
|
||||
|
||||
inline void
|
||||
ThrowOnError(status_t error)
|
||||
{
|
||||
if (error != B_OK)
|
||||
throw error;
|
||||
}
|
||||
|
||||
inline void
|
||||
ThrowIfNotSize(ssize_t size)
|
||||
{
|
||||
if (size < 0)
|
||||
throw (status_t)size;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
CDDBQuery::CDDBQuery(const char *server, int32 port, bool log)
|
||||
: log(log),
|
||||
serverName(server),
|
||||
port(port),
|
||||
connected(false),
|
||||
discID(-1),
|
||||
state(kInitial)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
CDDBQuery::SetToSite(const char *server, int32 port)
|
||||
{
|
||||
Disconnect();
|
||||
serverName = server;
|
||||
port = port;
|
||||
state = kInitial;
|
||||
}
|
||||
|
||||
void
|
||||
CDDBQuery::SetToCD(const scsi_toc *toc)
|
||||
{
|
||||
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,
|
||||
tmpDiscIDStr);
|
||||
|
||||
if (discID == tmpDiscID && discLength == tmpDiscLength && numTracks == tmpNumTracks
|
||||
&& frameOffsetString == frameOffsetString)
|
||||
return;
|
||||
|
||||
discID = tmpDiscID;
|
||||
discLength = tmpDiscLength;
|
||||
numTracks = tmpNumTracks;
|
||||
frameOffsetString = tmpFrameOffsetString;
|
||||
discIDStr = tmpDiscIDStr;
|
||||
}
|
||||
|
||||
// ToDo:
|
||||
// add interrupting here
|
||||
|
||||
result = B_OK;
|
||||
state = kReading;
|
||||
thread = spawn_thread(&CDDBQuery::LookupBinder, "CDDBLookup", B_NORMAL_PRIORITY, this);
|
||||
if (thread >= 0)
|
||||
resume_thread(thread);
|
||||
else {
|
||||
state = kError;
|
||||
result = thread;
|
||||
}
|
||||
}
|
||||
|
||||
const int kTerminatingSignal = SIGINT; // SIGCONT;
|
||||
|
||||
static void
|
||||
DoNothing(int)
|
||||
{
|
||||
}
|
||||
|
||||
int32
|
||||
CDDBQuery::LookupBinder(void *castToThis)
|
||||
{
|
||||
CDDBQuery *query = (CDDBQuery *)castToThis;
|
||||
|
||||
BFile file;
|
||||
entry_ref ref;
|
||||
bool newFile = false;
|
||||
|
||||
try {
|
||||
signal(kTerminatingSignal, DoNothing);
|
||||
|
||||
if (!query->FindOrCreateContentFileForDisk(&file, &ref, query->discID)) {
|
||||
// new content file, read it in from the server
|
||||
Connector connection(query);
|
||||
query->ReadFromServer(&file);
|
||||
file.Seek(0, SEEK_SET);
|
||||
newFile = true;
|
||||
}
|
||||
query->ParseResult(&file);
|
||||
|
||||
query->state = kDone;
|
||||
query->thread = -1;
|
||||
query->result = B_OK;
|
||||
|
||||
if (newFile) {
|
||||
BString newTitle(query->title);
|
||||
int32 length = newTitle.Length();
|
||||
for (int32 index = 0; index < length; index++) {
|
||||
if (newTitle[index] == '/' || newTitle[index] == ':')
|
||||
newTitle[index] = '-';
|
||||
}
|
||||
|
||||
file.Sync();
|
||||
BEntry entry(&ref);
|
||||
entry.Rename(newTitle.String(), false);
|
||||
}
|
||||
|
||||
} catch (status_t error) {
|
||||
query->state = kError;
|
||||
query->result = error;
|
||||
|
||||
// the cached file is messed up, remove it
|
||||
BEntry entry(&ref);
|
||||
BPath path;
|
||||
entry.GetPath(&path);
|
||||
printf("removing bad CD content file %s\n", path.Path());
|
||||
entry.Remove();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
const char *
|
||||
CDDBQuery::GetToken(const char *stream, BString &result)
|
||||
{
|
||||
result = "";
|
||||
while (*stream && *stream <= ' ')
|
||||
stream++;
|
||||
while (*stream && *stream > ' ')
|
||||
result += *stream++;
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
CDDBQuery::GetSites(bool (*eachFunc)(const char *site, int port, const char *latitude,
|
||||
const char *longitude, const char *description, void *state), void *passThru)
|
||||
{
|
||||
// ToDo:
|
||||
// add interrupting here
|
||||
|
||||
Connector connection(this);
|
||||
BString tmp;
|
||||
|
||||
tmp = "sites\n";
|
||||
if (log)
|
||||
printf(">%s", tmp.String());
|
||||
|
||||
ThrowIfNotSize( socket.Send(tmp.String(), tmp.Length()) );
|
||||
ReadLine(tmp);
|
||||
|
||||
if (tmp.FindFirst("210") == -1)
|
||||
throw (status_t)B_ERROR;
|
||||
|
||||
for (;;) {
|
||||
BString site;
|
||||
int32 sitePort;
|
||||
BString latitude;
|
||||
BString longitude;
|
||||
BString description;
|
||||
|
||||
ReadLine(tmp);
|
||||
if (tmp == ".")
|
||||
break;
|
||||
const char *scanner = tmp.String();
|
||||
|
||||
scanner = GetToken(scanner, site);
|
||||
BString portString;
|
||||
scanner = GetToken(scanner, portString);
|
||||
sitePort = atoi(portString.String());
|
||||
scanner = GetToken(scanner, latitude);
|
||||
scanner = GetToken(scanner, longitude);
|
||||
description = scanner;
|
||||
|
||||
if (eachFunc(site.String(), sitePort, latitude.String(), longitude.String(),
|
||||
description.String(), passThru))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
CDDBQuery::GetTitles(BString *resultingTitle, vector<BString> *tracks, bigtime_t timeout)
|
||||
{
|
||||
bigtime_t deadline = system_time() + timeout;
|
||||
while (state == kReading) {
|
||||
snooze(50000);
|
||||
if (system_time() > deadline)
|
||||
break;
|
||||
}
|
||||
if (state != kDone)
|
||||
return false;
|
||||
|
||||
if (resultingTitle)
|
||||
*resultingTitle = title;
|
||||
|
||||
if (tracks)
|
||||
*tracks = trackNames;
|
||||
return true;
|
||||
}
|
||||
|
||||
static int32
|
||||
cddb_sum(int n)
|
||||
{
|
||||
char buf[12];
|
||||
int32 ret = 0;
|
||||
|
||||
sprintf(buf, "%u", n);
|
||||
for (const char *p = buf; *p != '\0'; p++)
|
||||
ret += (*p - '0');
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct ConvertedToc {
|
||||
int32 min;
|
||||
int32 sec;
|
||||
int32 frame;
|
||||
};
|
||||
|
||||
int32
|
||||
CDDBQuery::GetDiscID(const scsi_toc *toc)
|
||||
{
|
||||
int32 tmpDiscID;
|
||||
int32 tmpDiscLength;
|
||||
int32 tmpNumTracks;
|
||||
BString tmpFrameOffsetString;
|
||||
BString tmpDiscIDStr;
|
||||
|
||||
GetDiscID(toc, tmpDiscID, tmpNumTracks, tmpDiscLength, tmpFrameOffsetString,
|
||||
tmpDiscIDStr);
|
||||
|
||||
return tmpDiscID;
|
||||
}
|
||||
|
||||
void
|
||||
CDDBQuery::GetDiscID(const scsi_toc *toc, int32 &id, int32 &numTracks,
|
||||
int32 &length, BString &frameOffsetsString, BString &discIDString)
|
||||
{
|
||||
ConvertedToc tocData[100];
|
||||
|
||||
// figure out the disc ID
|
||||
for (int index = 0; index < 100; index++) {
|
||||
tocData[index].min = toc->toc_data[9 + 8*index];
|
||||
tocData[index].sec = toc->toc_data[10 + 8*index];
|
||||
tocData[index].frame = toc->toc_data[11 + 8*index];
|
||||
}
|
||||
numTracks = toc->toc_data[3] - toc->toc_data[2] + 1;
|
||||
|
||||
int32 sum1 = 0;
|
||||
int32 sum2 = 0;
|
||||
for (int index = 0; index < numTracks; index++) {
|
||||
sum1 += cddb_sum((tocData[index].min * 60) + tocData[index].sec);
|
||||
// the following is probably running over too far
|
||||
sum2 += (tocData[index + 1].min * 60 + tocData[index + 1].sec) -
|
||||
(tocData[index].min * 60 + tocData[index].sec);
|
||||
}
|
||||
id = ((sum1 % 0xff) << 24) + (sum2 << 8) + numTracks;
|
||||
discIDString = "";
|
||||
|
||||
sprintf(discIDString.LockBuffer(10), "%08lx", id);
|
||||
discIDString.UnlockBuffer();
|
||||
|
||||
// compute the total length of the CD.
|
||||
length = tocData[numTracks].min * 60 + tocData[numTracks].sec;
|
||||
|
||||
for (int index = 0; index < numTracks; index++)
|
||||
frameOffsetsString << tocData[index].min * 4500 + tocData[index].sec * 75
|
||||
+ tocData[index].frame << ' ';
|
||||
}
|
||||
|
||||
void
|
||||
CDDBQuery::ReadFromServer(BDataIO *stream)
|
||||
{
|
||||
// Format the query
|
||||
BString query;
|
||||
query << "cddb query " << discIDStr << ' ' << numTracks << ' '
|
||||
// Add frame offsets
|
||||
<< frameOffsetString << ' '
|
||||
// Finish it off with the total CD length.
|
||||
<< discLength << '\n';
|
||||
|
||||
if (log)
|
||||
printf(">%s", query.String());
|
||||
|
||||
// Send it off.
|
||||
ThrowIfNotSize( socket.Send(query.String(), query.Length()) );
|
||||
|
||||
BString tmp;
|
||||
ReadLine(tmp);
|
||||
if (tmp.FindFirst("200") != 0)
|
||||
return;
|
||||
|
||||
BString category;
|
||||
GetToken(tmp.String() + 3, category);
|
||||
if (!category.Length())
|
||||
category = "misc";
|
||||
|
||||
query = "";
|
||||
query << "cddb read " << category << ' ' << discIDStr << '\n' ;
|
||||
ThrowIfNotSize( socket.Send(query.String(), query.Length()) );
|
||||
|
||||
for (;;) {
|
||||
BString tmp;
|
||||
ReadLine(tmp);
|
||||
tmp += '\n';
|
||||
ThrowIfNotSize( stream->Write(tmp.String(), tmp.Length()) );
|
||||
if (tmp == "." || tmp == ".\n")
|
||||
break;
|
||||
}
|
||||
state = kDone;
|
||||
}
|
||||
|
||||
void
|
||||
CDDBQuery::ParseResult(BDataIO *source)
|
||||
{
|
||||
title = "";
|
||||
trackNames.clear();
|
||||
for (;;) {
|
||||
BString tmp;
|
||||
ReadLine(source, tmp);
|
||||
if (tmp == ".")
|
||||
break;
|
||||
|
||||
if (tmp == "")
|
||||
throw (status_t)B_ERROR;
|
||||
|
||||
if (tmp.FindFirst("DTITLE=") == 0)
|
||||
title = tmp.String() + sizeof("DTITLE");
|
||||
else if (tmp.FindFirst("TTITLE") == 0) {
|
||||
int32 afterIndex = tmp.FindFirst('=');
|
||||
if (afterIndex > 0) {
|
||||
BString trackName(tmp.String() + afterIndex + 1);
|
||||
trackNames.push_back(trackName);
|
||||
}
|
||||
}
|
||||
}
|
||||
state = kDone;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
CDDBQuery::Connect()
|
||||
{
|
||||
BNetAddress address(serverName.String(), port);
|
||||
InitCheck(&address);
|
||||
|
||||
ThrowOnError( socket.Connect(address) );
|
||||
connected = true;
|
||||
|
||||
BString tmp;
|
||||
ReadLine(tmp);
|
||||
IdentifySelf();
|
||||
}
|
||||
|
||||
bool
|
||||
CDDBQuery::IsConnected() const
|
||||
{
|
||||
return connected;
|
||||
}
|
||||
|
||||
void
|
||||
CDDBQuery::Disconnect()
|
||||
{
|
||||
socket.Close();
|
||||
connected = false;
|
||||
}
|
||||
|
||||
void
|
||||
CDDBQuery::ReadLine(BString &buffer)
|
||||
{
|
||||
buffer = "";
|
||||
char ch;
|
||||
for (;;) {
|
||||
if (socket.Receive(&ch, 1) <= 0)
|
||||
break;
|
||||
if (ch >= ' ')
|
||||
buffer += ch;
|
||||
if (ch == '\n')
|
||||
break;
|
||||
}
|
||||
if (log)
|
||||
printf("<%s\n", buffer.String());
|
||||
}
|
||||
|
||||
void
|
||||
CDDBQuery::ReadLine(BDataIO *stream, BString &buffer)
|
||||
{
|
||||
// this is super-lame, should use better buffering
|
||||
// ToDo:
|
||||
// redo using LockBuffer, growing the buffer by 2k and reading into it
|
||||
|
||||
buffer = "";
|
||||
char ch;
|
||||
for (;;) {
|
||||
ssize_t result = stream->Read(&ch, 1);
|
||||
|
||||
if (result < 0)
|
||||
// read error
|
||||
throw (status_t)result;
|
||||
if (result == 0)
|
||||
break;
|
||||
if (ch >= ' ')
|
||||
buffer += ch;
|
||||
if (ch == '\n')
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
CDDBQuery::IdentifySelf()
|
||||
{
|
||||
char username[256];
|
||||
if (!getusername(username,256))
|
||||
strcpy(username, "unknown");
|
||||
|
||||
char hostname[MAXHOSTNAMELEN + 1];
|
||||
if (gethostname(hostname, MAXHOSTNAMELEN) == -1)
|
||||
strcpy(hostname, "unknown");
|
||||
|
||||
BString tmp;
|
||||
tmp << "cddb hello " << username << " " << hostname << " CDButton v1.0\n";
|
||||
|
||||
if (log)
|
||||
printf(">%s", tmp.String());
|
||||
ThrowIfNotSize( socket.Send(tmp.String(), tmp.Length()) );
|
||||
|
||||
ReadLine(tmp);
|
||||
}
|
||||
|
||||
bool
|
||||
CDDBQuery::FindOrCreateContentFileForDisk(BFile *file, entry_ref *fileRef, int32 discID)
|
||||
{
|
||||
BString predicate;
|
||||
predicate << "cddb:discID == " << discID;
|
||||
entry_ref ref;
|
||||
|
||||
BVolumeRoster roster;
|
||||
BVolume volume;
|
||||
roster.Rewind();
|
||||
while (roster.GetNextVolume(&volume) == B_OK) {
|
||||
if (volume.IsReadOnly() || !volume.IsPersistent()
|
||||
|| !volume.KnowsAttr() || !volume.KnowsQuery())
|
||||
continue;
|
||||
|
||||
// make sure the volume we are looking at is indexed right
|
||||
fs_create_index(volume.Device(), "cddb:discID", B_INT32_TYPE, 0);
|
||||
|
||||
BQuery query;
|
||||
query.SetVolume(&volume);
|
||||
query.SetPredicate(predicate.String());
|
||||
if (query.Fetch() != B_OK)
|
||||
continue;
|
||||
|
||||
while (query.GetNextRef(&ref) == B_OK) {
|
||||
// we have one already, return
|
||||
file->SetTo(&ref, O_RDONLY);
|
||||
*fileRef = ref;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
BPath path;
|
||||
ThrowOnError( find_directory(B_USER_SETTINGS_DIRECTORY, &path, true) );
|
||||
path.Append("CDContentFiles");
|
||||
ThrowOnError( create_directory(path.Path(), 0755) );
|
||||
|
||||
BDirectory dir(path.Path());
|
||||
BString name("CDContent");
|
||||
for (int32 index = 0; ;index++) {
|
||||
if (dir.CreateFile(name.String(), file, true) != B_FILE_EXISTS) {
|
||||
BEntry entry(&dir, name.String());
|
||||
entry.GetRef(fileRef);
|
||||
file->WriteAttr("cddb:discID", B_INT32_TYPE, 0, &discID, sizeof(int32));
|
||||
break;
|
||||
}
|
||||
name = "CDContent";
|
||||
name << index;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
bool
|
||||
PrintSite(const char *site, int port, const char *latitude,
|
||||
const char *longitude, const char *description, void *)
|
||||
{
|
||||
printf("server:%s port:%d latitude:%s longitude:%s description: %s\n",
|
||||
site, port, latitude, longitude, description);
|
||||
return false;
|
||||
}
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
try {
|
||||
CDDBQuery query("us.cddb.com", 888, true);
|
||||
// query.GetSites(&PrintSite, NULL);
|
||||
|
||||
int32 device = CDEngine::FindCDPlayerDevice();
|
||||
if (!device) {
|
||||
printf("no device %s\n", strerror(device));
|
||||
return 0;
|
||||
}
|
||||
CDEngine engine(device);
|
||||
scsi_toc toc;
|
||||
engine.GetToc(&toc);
|
||||
|
||||
query.SetToCD(&toc);
|
||||
|
||||
BString title;
|
||||
vector<BString> trackTitles;
|
||||
query.GetTitles(title, trackTitles, 10000000);
|
||||
|
||||
printf("CD Title:%s\n", title.String());
|
||||
int32 index = 0;
|
||||
for (vector<BString>::iterator iterator = trackTitles.begin();
|
||||
iterator != trackTitles.end(); index++, iterator++)
|
||||
printf("%d: %s\n", index, (*iterator).String());
|
||||
|
||||
} catch(status_t error) {
|
||||
printf("error %s\n", strerror(error));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
107
src/apps/cdplayer/CDDBSupport.h
Normal file
107
src/apps/cdplayer/CDDBSupport.h
Normal file
@ -0,0 +1,107 @@
|
||||
#ifndef __CDDBSUPPORT__
|
||||
#define __CDDBSUPPORT__
|
||||
|
||||
#include <NetEndpoint.h>
|
||||
#include <String.h>
|
||||
#include <scsi.h>
|
||||
#include <vector>
|
||||
|
||||
|
||||
// based on Jukebox by Chip Paul
|
||||
|
||||
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 *);
|
||||
bool GetTitles(BString *title, vector<BString> *tracks, bigtime_t timeout);
|
||||
// title or tracks may be NULL if you are only interrested in one, not the other
|
||||
|
||||
bool Ready() const
|
||||
{ return state == kDone; }
|
||||
|
||||
int32 CurrentDiscID() const
|
||||
{ return discID; }
|
||||
|
||||
static int32 GetDiscID(const scsi_toc *);
|
||||
|
||||
private:
|
||||
|
||||
static void GetDiscID(const scsi_toc *, int32 &id, int32 &numTracks, int32 &length,
|
||||
BString &tmpFrameOffsetString, BString &discIDString);
|
||||
|
||||
void Connect();
|
||||
void Disconnect();
|
||||
bool IsConnected() const;
|
||||
|
||||
static int32 LookupBinder(void *);
|
||||
|
||||
class Connector {
|
||||
public:
|
||||
Connector(CDDBQuery *client)
|
||||
: client(client),
|
||||
wasConnected(client->IsConnected())
|
||||
{
|
||||
if (!wasConnected)
|
||||
client->Connect();
|
||||
}
|
||||
|
||||
~Connector()
|
||||
{
|
||||
if (!wasConnected)
|
||||
client->Disconnect();
|
||||
}
|
||||
|
||||
private:
|
||||
CDDBQuery *client;
|
||||
bool wasConnected;
|
||||
};
|
||||
|
||||
bool FindOrCreateContentFileForDisk(BFile *file, entry_ref *ref, int32 discID);
|
||||
|
||||
void ReadFromServer(BDataIO *);
|
||||
void ParseResult(BDataIO *);
|
||||
|
||||
void ReadLine(BString &);
|
||||
static void ReadLine(BDataIO *, BString &);
|
||||
void IdentifySelf();
|
||||
|
||||
const char *GetToken(const char *, BString &);
|
||||
|
||||
bool log;
|
||||
|
||||
// connection description
|
||||
BString serverName;
|
||||
BNetEndpoint socket;
|
||||
int32 port;
|
||||
bool connected;
|
||||
|
||||
// disc identification
|
||||
int32 discID;
|
||||
int32 discLength;
|
||||
int32 numTracks;
|
||||
BString frameOffsetString;
|
||||
BString discIDStr;
|
||||
|
||||
// cached retrieved data
|
||||
enum State {
|
||||
kInitial,
|
||||
kReading,
|
||||
kDone,
|
||||
kInterrupting,
|
||||
kError
|
||||
};
|
||||
|
||||
thread_id thread;
|
||||
State state;
|
||||
BString title;
|
||||
vector<BString> trackNames;
|
||||
status_t result;
|
||||
|
||||
friend class Connector;
|
||||
};
|
||||
|
||||
#endif
|
607
src/apps/cdplayer/CDEngine.cpp
Normal file
607
src/apps/cdplayer/CDEngine.cpp
Normal file
@ -0,0 +1,607 @@
|
||||
/*
|
||||
Copyright 1999, Be Incorporated. All Rights Reserved.
|
||||
This file may be used under the terms of the Be Sample Code License.
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <Debug.h>
|
||||
#include <Entry.h>
|
||||
#include <Directory.h>
|
||||
#include <Path.h>
|
||||
#include <errno.h>
|
||||
#include "scsi.h"
|
||||
#include "CDEngine.h"
|
||||
|
||||
PeriodicWatcher::PeriodicWatcher(int devicefd)
|
||||
: Notifier(),
|
||||
devicefd(devicefd)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
PeriodicWatcher::PeriodicWatcher(BMessage *)
|
||||
: devicefd(-1)
|
||||
{
|
||||
// not implemented yet
|
||||
PRINT(("under construction"));
|
||||
}
|
||||
|
||||
BHandler *
|
||||
PeriodicWatcher::RecipientHandler() const
|
||||
{
|
||||
return engine;
|
||||
}
|
||||
|
||||
void
|
||||
PeriodicWatcher::DoPulse()
|
||||
{
|
||||
// control the period here
|
||||
if (UpdateState())
|
||||
Notify();
|
||||
}
|
||||
|
||||
void
|
||||
PeriodicWatcher::UpdateNow()
|
||||
{
|
||||
UpdateState();
|
||||
}
|
||||
|
||||
|
||||
PlayState::PlayState(int devicefd)
|
||||
: PeriodicWatcher(devicefd),
|
||||
oldState(kNoCD)
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
PlayState::UpdateState()
|
||||
{
|
||||
// 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
|
||||
PlayState::GetState() const
|
||||
{
|
||||
return oldState;
|
||||
}
|
||||
|
||||
bool
|
||||
PlayState::CurrentState(CDState newState)
|
||||
{
|
||||
if (newState != oldState) {
|
||||
oldState = newState;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
TrackState::TrackState(int devicefd)
|
||||
: PeriodicWatcher(devicefd),
|
||||
currentTrack(0)
|
||||
{
|
||||
}
|
||||
|
||||
int32
|
||||
TrackState::GetTrack() const
|
||||
{
|
||||
return currentTrack;
|
||||
}
|
||||
|
||||
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]);
|
||||
}
|
||||
|
||||
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];
|
||||
}
|
||||
|
||||
bool
|
||||
TrackState::CurrentState(int32 track)
|
||||
{
|
||||
if (track != currentTrack) {
|
||||
currentTrack = track;
|
||||
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
|
||||
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);
|
||||
|
||||
status_t result = ioctl(devicefd, B_SCSI_GET_POSITION, &pos);
|
||||
|
||||
if (result != B_NO_ERROR)
|
||||
return CurrentState(-1, -1);
|
||||
else if ((!pos.position[1]) || (pos.position[1] >= 0x13) ||
|
||||
((pos.position[1] == 0x12) && (!pos.position[6])))
|
||||
return CurrentState(0, 0);
|
||||
else
|
||||
return CurrentState(pos.position[9], pos.position[10]);
|
||||
}
|
||||
|
||||
bool
|
||||
TimeState::CurrentState(int32 minutes, int32 seconds)
|
||||
{
|
||||
if (minutes == oldMinutes && seconds == oldSeconds)
|
||||
return false;
|
||||
oldMinutes = minutes;
|
||||
oldSeconds = seconds;
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
TimeState::GetTime(int32 &minutes, int32 &seconds) const
|
||||
{
|
||||
minutes = oldMinutes;
|
||||
seconds = oldSeconds;
|
||||
}
|
||||
|
||||
|
||||
CDContentWatcher::CDContentWatcher(int devicefd)
|
||||
: PeriodicWatcher(devicefd),
|
||||
cddbQuery("us.cddb.com", 888, true),
|
||||
discID(-1),
|
||||
wasReady(false)
|
||||
{
|
||||
}
|
||||
|
||||
CDContentWatcher::CDContentWatcher(BMessage *message)
|
||||
: PeriodicWatcher(message),
|
||||
cddbQuery("us.cddb.com", 888, true),
|
||||
discID(-1),
|
||||
wasReady(false)
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
CDContentWatcher::GetContent(BString *title, vector<BString> *tracks)
|
||||
{
|
||||
return cddbQuery.GetTitles(title, tracks, 1000000);
|
||||
}
|
||||
|
||||
bool
|
||||
CDContentWatcher::UpdateState()
|
||||
{
|
||||
bool newReady = false;
|
||||
bool newDiscID = -1;
|
||||
if (engine->PlayStateWatcher()->GetState() != kNoCD) {
|
||||
scsi_toc toc;
|
||||
ioctl(devicefd, B_SCSI_GET_TOC, &toc);
|
||||
newDiscID = cddbQuery.GetDiscID(&toc);
|
||||
if (discID != newDiscID)
|
||||
cddbQuery.SetToCD(&toc);
|
||||
}
|
||||
|
||||
bool result = newReady != cddbQuery.Ready() && newDiscID != discID;
|
||||
newReady = cddbQuery.Ready();
|
||||
newDiscID = discID;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
CDEngine::CDEngine(int devicefd)
|
||||
: 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)
|
||||
{
|
||||
}
|
||||
|
||||
CDEngine::~CDEngine()
|
||||
{
|
||||
if(devicefd >= 0)
|
||||
close(devicefd);
|
||||
}
|
||||
|
||||
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::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;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CDEngine::Play()
|
||||
{
|
||||
// play the CD
|
||||
if (playState.GetState() == kNoCD) {
|
||||
// no CD available, bail out
|
||||
ioctl(devicefd, B_LOAD_MEDIA, 0, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
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) {
|
||||
PRINT(("error %s playing track\n", strerror(errno)));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CDEngine::PlayContinue()
|
||||
{
|
||||
// continue after a pause
|
||||
status_t result = ioctl(devicefd, B_SCSI_RESUME_AUDIO);
|
||||
if (result != B_NO_ERROR) {
|
||||
PRINT(("error %s resuming\n", strerror(errno)));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CDEngine::Stop()
|
||||
{
|
||||
// stop a playing CD
|
||||
status_t result = ioctl(devicefd, B_SCSI_STOP_AUDIO);
|
||||
if (result != B_NO_ERROR) {
|
||||
PRINT(("error %s stoping\n", strerror(errno)));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
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_NO_ERROR) {
|
||||
PRINT(("error %s ejecting\n", strerror(errno)));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CDEngine::SkipOneForward()
|
||||
{
|
||||
// skip forward by one track
|
||||
CDState state = playState.GetState();
|
||||
|
||||
if (state == kNoCD)
|
||||
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();
|
||||
}
|
||||
|
||||
void
|
||||
CDEngine::SkipOneBackward()
|
||||
{
|
||||
// skip backward by one track
|
||||
CDState state = playState.GetState();
|
||||
|
||||
if (state == kNoCD)
|
||||
return;
|
||||
|
||||
bool wasPaused = state == kPaused
|
||||
|| state == kStopped;
|
||||
|
||||
int32 track = trackState.GetTrack();
|
||||
|
||||
if (track > 1)
|
||||
track--;
|
||||
|
||||
SelectTrack(track);
|
||||
|
||||
if (wasPaused)
|
||||
// make sure we don't start playing if we were paused before
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
const bigtime_t kPulseRate = 500000;
|
||||
|
||||
void
|
||||
CDEngine::DoPulse()
|
||||
{
|
||||
// this is the CDEngine's hearbeat; 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)
|
||||
{
|
||||
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))
|
||||
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");
|
||||
}
|
||||
|
226
src/apps/cdplayer/CDEngine.h
Normal file
226
src/apps/cdplayer/CDEngine.h
Normal file
@ -0,0 +1,226 @@
|
||||
/*
|
||||
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 <Looper.h>
|
||||
#include <String.h>
|
||||
#include <View.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "Observer.h"
|
||||
#include "FunctionObjectMessage.h"
|
||||
#include "CDDBSupport.h"
|
||||
|
||||
class CDEngine;
|
||||
class PeriodicWatcher : public Notifier {
|
||||
// watcher sits somewhere were it can get pulses and makes sure
|
||||
// notices get sent if state changes
|
||||
public:
|
||||
PeriodicWatcher(int devicefd);
|
||||
PeriodicWatcher(BMessage *);
|
||||
|
||||
virtual ~PeriodicWatcher() {}
|
||||
|
||||
void DoPulse();
|
||||
void UpdateNow();
|
||||
|
||||
void AttachedToLooper(CDEngine *engine)
|
||||
{ this->engine = engine; }
|
||||
|
||||
virtual BHandler *RecipientHandler() const;
|
||||
|
||||
protected:
|
||||
virtual bool UpdateState() = 0;
|
||||
|
||||
int devicefd;
|
||||
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
|
||||
public:
|
||||
PlayState(int devicefd);
|
||||
PlayState(BMessage *message)
|
||||
: PeriodicWatcher(message)
|
||||
{}
|
||||
|
||||
CDState GetState() const;
|
||||
|
||||
private:
|
||||
bool UpdateState();
|
||||
bool CurrentState(CDState);
|
||||
CDState oldState;
|
||||
};
|
||||
|
||||
class TrackState : public PeriodicWatcher {
|
||||
// this watcher sends notices to observers that are interrested
|
||||
// about changes in the current track
|
||||
public:
|
||||
TrackState(int devicefd);
|
||||
TrackState(BMessage *message)
|
||||
: PeriodicWatcher(message)
|
||||
{}
|
||||
|
||||
int32 GetTrack() const;
|
||||
int32 GetNumTracks() const;
|
||||
|
||||
private:
|
||||
bool UpdateState();
|
||||
bool CurrentState(int32);
|
||||
int32 currentTrack;
|
||||
};
|
||||
|
||||
class TimeState : public PeriodicWatcher {
|
||||
// this watcher sends notices to observers that are interrested
|
||||
// about changes in the current time
|
||||
public:
|
||||
TimeState(int devicefd)
|
||||
: PeriodicWatcher(devicefd)
|
||||
{ }
|
||||
TimeState(BMessage *message)
|
||||
: PeriodicWatcher(message)
|
||||
{}
|
||||
|
||||
void GetTime(int32 &minutes, int32 &seconds) const;
|
||||
|
||||
private:
|
||||
bool UpdateState();
|
||||
bool CurrentState(int32 minutes, int32 seconds);
|
||||
int32 oldMinutes;
|
||||
int32 oldSeconds;
|
||||
};
|
||||
|
||||
class CDContentWatcher : public PeriodicWatcher {
|
||||
public:
|
||||
CDContentWatcher(int devicefd);
|
||||
CDContentWatcher(BMessage *message);
|
||||
|
||||
bool GetContent(BString *title, vector<BString> *tracks);
|
||||
|
||||
private:
|
||||
bool UpdateState();
|
||||
|
||||
CDDBQuery cddbQuery;
|
||||
int32 discID;
|
||||
bool wasReady;
|
||||
};
|
||||
|
||||
class VolumeState : public PeriodicWatcher {
|
||||
// this watcher sends notices to observers that are interrested
|
||||
// about changes in the current volume
|
||||
// currently not used yet
|
||||
public:
|
||||
VolumeState(int devicefd)
|
||||
: PeriodicWatcher(devicefd)
|
||||
{ }
|
||||
VolumeState(BMessage *message)
|
||||
: PeriodicWatcher(message)
|
||||
{}
|
||||
|
||||
bool UpdateState() { return true; }
|
||||
virtual void DoPulse() {}
|
||||
int32 GetVolume() const;
|
||||
};
|
||||
|
||||
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
|
||||
public:
|
||||
CDEngine(int devicefd);
|
||||
CDEngine(BMessage *);
|
||||
|
||||
virtual ~CDEngine();
|
||||
|
||||
// observing supprt
|
||||
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);
|
||||
|
||||
|
||||
TrackState *TrackStateWatcher()
|
||||
{ return &trackState; }
|
||||
// to find the current Track, you may call the GetTrack function
|
||||
// TrackState defines
|
||||
|
||||
PlayState *PlayStateWatcher()
|
||||
{ return &playState; }
|
||||
// to find the current play state, you may call the GetState function
|
||||
// PlayState 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; }
|
||||
|
||||
static int FindCDPlayerDevice();
|
||||
|
||||
private:
|
||||
int devicefd;
|
||||
|
||||
PlayState playState;
|
||||
TrackState trackState;
|
||||
TimeState timeState;
|
||||
VolumeState volumeState;
|
||||
CDContentWatcher contentWatcher;
|
||||
|
||||
bigtime_t lastPulse;
|
||||
};
|
||||
|
||||
|
||||
// some function object glue
|
||||
class CDEngineFunctorFactory : public FunctorFactoryCommon {
|
||||
public:
|
||||
static BMessage *NewFunctorMessage(void (CDEngine::*func)(),
|
||||
CDEngine *target)
|
||||
{
|
||||
PlainMemberFunctionObject<void (CDEngine::*)(),
|
||||
CDEngine> tmp(func, target);
|
||||
return NewMessage(&tmp);
|
||||
}
|
||||
|
||||
static BMessage *NewFunctorMessage(void (CDEngine::*func)(ulong),
|
||||
CDEngine *target, ulong param)
|
||||
{
|
||||
SingleParamMemberFunctionObject<void (CDEngine::*)(ulong),
|
||||
CDEngine, ulong> tmp(func, target, param);
|
||||
return NewMessage(&tmp);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#endif
|
@ -1,76 +0,0 @@
|
||||
/*
|
||||
|
||||
CDPlayer
|
||||
|
||||
Author: Sikosis
|
||||
|
||||
(C)2004 Haiku - http://haiku-os.org/
|
||||
|
||||
*/
|
||||
|
||||
// Includes ------------------------------------------------------------------------------------------ //
|
||||
#include <Alert.h>
|
||||
#include <Application.h>
|
||||
#include <Button.h>
|
||||
#include <Entry.h>
|
||||
#include <File.h>
|
||||
#include <FilePanel.h>
|
||||
#include <ListView.h>
|
||||
#include <Path.h>
|
||||
#include <Screen.h>
|
||||
#include <ScrollView.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <TextControl.h>
|
||||
#include <Window.h>
|
||||
#include <View.h>
|
||||
|
||||
#include "CDPlayer.h"
|
||||
#include "CDPlayerWindows.h"
|
||||
#include "CDPlayerViews.h"
|
||||
#include "CDPlayerConstants.h"
|
||||
// Constants ---------------------------------------------------------------------------------------- //
|
||||
|
||||
const char *APP_SIGNATURE = "application/x-vnd.Haiku.CDPlayer"; // Application Signature and Title
|
||||
|
||||
// -------------------------------------------------------------------------------------------------- //
|
||||
|
||||
CDPlayerWindow *ptrCDPlayerWindow;
|
||||
|
||||
// CDPlayer - Constructor
|
||||
CDPlayer::CDPlayer() : BApplication (APP_SIGNATURE)
|
||||
{
|
||||
// Default Window Size - Position doesn't matter as we centre the form to the current screen size
|
||||
BRect screenFrame = (BScreen(B_MAIN_SCREEN_ID).Frame());
|
||||
|
||||
float FormTopDefault = 0;
|
||||
float FormLeftDefault = 0;
|
||||
float FormWidthDefault = 500;
|
||||
float FormHeightDefault = 100;
|
||||
BRect CDPlayerWindowRect(FormTopDefault,FormLeftDefault,FormLeftDefault+FormWidthDefault,FormTopDefault+FormHeightDefault);
|
||||
|
||||
ptrCDPlayerWindow = new CDPlayerWindow(CDPlayerWindowRect);
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------------- //
|
||||
|
||||
// CDPlayer::MessageReceived -- handles incoming messages
|
||||
void CDPlayer::MessageReceived (BMessage *message)
|
||||
{
|
||||
switch(message->what)
|
||||
{
|
||||
default:
|
||||
BApplication::MessageReceived(message); // pass it along ...
|
||||
break;
|
||||
}
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------------- //
|
||||
|
||||
// CDPlayer Main
|
||||
int main(void)
|
||||
{
|
||||
CDPlayer theApp;
|
||||
theApp.Run();
|
||||
return 0;
|
||||
}
|
||||
// end --------------------------------------------------------------------------------------------- //
|
||||
|
@ -1,25 +0,0 @@
|
||||
/*
|
||||
|
||||
CDPlayer Header
|
||||
|
||||
Author: Sikosis
|
||||
|
||||
(C)2004 Haiku - http://haiku-os.org/
|
||||
|
||||
*/
|
||||
|
||||
#ifndef __CDPLAYER_H__
|
||||
#define __CDPLAYER_H__
|
||||
|
||||
extern const char *APP_SIGNATURE;
|
||||
|
||||
class CDPlayer : public BApplication
|
||||
{
|
||||
public:
|
||||
CDPlayer();
|
||||
virtual void MessageReceived(BMessage *message);
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
#endif
|
@ -1,8 +1,32 @@
|
||||
|
||||
resource(1, "BEOS:FILE_TYPES") message;
|
||||
resource(1, "BEOS:APP_FLAGS") #'APPF' $"00000000";
|
||||
|
||||
resource(101, "BEOS:L:STD_ICON") #'ICON' array
|
||||
{
|
||||
resource(1, "BEOS:APP_VERSION") #'APPV' array {
|
||||
$"00000000000000000100000001000000000000004344506C6179657200000000"
|
||||
$"0000000000000000000000000000000000000000000000000000000000000000"
|
||||
$"0000000000000000000000000000000000000000426173696320434420506C61"
|
||||
$"79657220666F72204861696B7500000000000000000000000000000000000000"
|
||||
$"0000000000000000000000000000000000000000000000000000000000000000"
|
||||
$"0000000000000000000000000000000000000000000000000000000000000000"
|
||||
$"0000000000000000000000000000000000000000000000000000000000000000"
|
||||
$"0000000000000000000000000000000000000000000000000000000000000000"
|
||||
$"0000000000000000000000000000000000000000000000000000000000000000"
|
||||
$"0000000000000000000000000000000000000000000000000000000000000000"
|
||||
$"0000000000000000000000000000000000000000000000000000000000000000"
|
||||
$"0000000000000000000000000000000000000000000000000000000000000000"
|
||||
$"0000000000000000000000000000000000000000000000000000000000000000"
|
||||
$"0000000000000000000000000000000000000000000000000000000000000000"
|
||||
$"0000000000000000000000000000000000000000000000000000000000000000"
|
||||
$"0000000000000000000000000000000000000000000000000000000000000000"
|
||||
$"0000000000000000000000000000000000000000000000000000000000000000"
|
||||
$"0000000000000000000000000000000000000000000000000000000000000000"
|
||||
$"0000000000000000000000000000000000000000000000000000000000000000"
|
||||
$"0000000000000000000000000000000000000000000000000000000000000000"
|
||||
$"0000000000000000000000000000000000000000000000000000000000000000"
|
||||
$"0000000000000000"
|
||||
};
|
||||
|
||||
resource(101, "BEOS:L:STD_ICON") #'ICON' array {
|
||||
$"FFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
|
||||
$"FFFFFFFFFFFFFFFFFF000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
|
||||
$"FFFFFFFFFFFFFFFFFFFF00F90000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
|
||||
@ -37,8 +61,7 @@ resource(101, "BEOS:L:STD_ICON") #'ICON' array
|
||||
$"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000E0F0FFFFFFFFFFFFFFFFFFFFFFFFF"
|
||||
};
|
||||
|
||||
resource(101, "BEOS:M:STD_ICON") #'MICN' array
|
||||
{
|
||||
resource(101, "BEOS:M:STD_ICON") #'MICN' array {
|
||||
$"FFFFFFFF000000FFFFFFFFFFFFFFFFFF"
|
||||
$"FFFFFFFFFF005D0000FFFFFFFFFFFFFF"
|
||||
$"FFFFFFFFFFFF007D7D0000FFFFFFFFFF"
|
||||
@ -59,30 +82,387 @@ resource(101, "BEOS:M:STD_ICON") #'MICN' array
|
||||
|
||||
resource(1, "BEOS:APP_SIG") #'MIMS' "application/x-vnd.Haiku.CDPlayer";
|
||||
|
||||
resource(1, "BEOS:APP_VERSION") #'APPV' array
|
||||
{
|
||||
$"00000000000000000100000001000000000000004344506C6179657200000000"
|
||||
$"0000000000000000000000000000000000000000000000000000000000000000"
|
||||
$"0000000000000000000000000000000000000000426173696320434420506C61"
|
||||
$"79657220666F72204861696B7500000000000000000000000000000000000000"
|
||||
$"0000000000000000000000000000000000000000000000000000000000000000"
|
||||
$"0000000000000000000000000000000000000000000000000000000000000000"
|
||||
$"0000000000000000000000000000000000000000000000000000000000000000"
|
||||
$"0000000000000000000000000000000000000000000000000000000000000000"
|
||||
$"0000000000000000000000000000000000000000000000000000000000000000"
|
||||
$"0000000000000000000000000000000000000000000000000000000000000000"
|
||||
$"0000000000000000000000000000000000000000000000000000000000000000"
|
||||
$"0000000000000000000000000000000000000000000000000000000000000000"
|
||||
$"0000000000000000000000000000000000000000000000000000000000000000"
|
||||
$"0000000000000000000000000000000000000000000000000000000000000000"
|
||||
$"0000000000000000000000000000000000000000000000000000000000000000"
|
||||
$"0000000000000000000000000000000000000000000000000000000000000000"
|
||||
$"0000000000000000000000000000000000000000000000000000000000000000"
|
||||
$"0000000000000000000000000000000000000000000000000000000000000000"
|
||||
$"0000000000000000000000000000000000000000000000000000000000000000"
|
||||
$"0000000000000000000000000000000000000000000000000000000000000000"
|
||||
$"0000000000000000000000000000000000000000000000000000000000000000"
|
||||
$"0000000000000000"
|
||||
resource(1, "BEOS:FILE_TYPES") message;
|
||||
|
||||
resource(1, "play_up") #'PNG ' array {
|
||||
$"89504E470D0A1A0A0000000D494844520000002300000013080000000148CFDB"
|
||||
$"BE000000096F464673000000000000000000DA2AB6CE00000009704859730000"
|
||||
$"0FA000000FA001A06A8C770000009549444154789C8591BB11C5200C04578C4A"
|
||||
$"51AD8E5FE0F22076074E79013F83E5E112E058A10324030492A4243901920122"
|
||||
$"448980E484C502351504104DCD0B8059E77A45AC151DAC32AD6343A60ED62695"
|
||||
$"EA88AF1EA84BAF7B367E613979B4335B9DE10DA765D065ED657C547D4AF2B521"
|
||||
$"8E53E1DE40230F94DB396FA5ABE1706E66B369F93AC7E9A69BFD17F3F1B7CAE1"
|
||||
$"6F3CF407D134242111EC44A10000000049454E44AE426082"
|
||||
};
|
||||
|
||||
resource(1, "BEOS:APP_FLAGS") #'APPF' $"00000000";
|
||||
resource(2, "play_down") #'PNG ' array {
|
||||
$"89504E470D0A1A0A0000000D49484452000000230000001308060000001AA3B4"
|
||||
$"F40000008D49444154789CCDD6C10904210C40D13F8B4DD84E4AB00E2BB038CB"
|
||||
$"B18DEC6109CC6D5123E69F151E6AC0075002A4AA24805AEB55486B0DE0870128"
|
||||
$"A55CC3589FDB8077D3181141444E58D64FE6046AFB9A3C516E6FC603E5FE8077"
|
||||
$"50A1A629FD5F3257EF7D79AF1B6607616D633C10D632C613614D634E20AC50D3"
|
||||
$"140AF3003AC6B8ED20E74C520DF1D103E00B489821B04B2C9C09000000004945"
|
||||
$"4E44AE426082"
|
||||
};
|
||||
|
||||
resource(3, "play_disabled") #'PNG ' array {
|
||||
$"89504E470D0A1A0A0000000D494844520000002300000013080000000148CFDB"
|
||||
$"BE000000096F464673000000000000000000DA2AB6CE00000009704859730000"
|
||||
$"0FA000000FA001A06A8C770000009B49444154789C8591BB15C4200C04473C95"
|
||||
$"7265509FE30BAE249571C4EEC0290ECCC760F9B109B08CD0029201946411C909"
|
||||
$"900C6832A2FC01C9098B00812AC975A2A97A01306B5CAB88A5A281451FBD46AB"
|
||||
$"C8D0C1EAA4500DF1D50235E97E8CC6374C27F77666B3D3BDEED40C3AADBD8CB7"
|
||||
$"AA5749DE17C4F653381650CF03D7ED9CB7D2D9703837B3D9B07C9CE374D3C5FE"
|
||||
$"8379F95B65F3376E3A010B1C24319A2F2A100000000049454E44AE426082"
|
||||
};
|
||||
|
||||
resource(4, "stop_up") #'PNG ' array {
|
||||
$"89504E470D0A1A0A0000000D49484452000000230000001308060000001AA3B4"
|
||||
$"F40000006E49444154789CEDD6310E80300840D18FE9517AD69EB27B6FD01507"
|
||||
$"63D481585D60E0CF0C2F0C04515525402242011863B8425A6B00070660CEE986"
|
||||
$"39DBBC01F7CAFBC8B35AEBD25CEFFD3326D46612639518ABC45825C6EAF305FE"
|
||||
$"7359570BB599509802D73FE19D00213E3D801DE2CC137C9B1F7C290000000049"
|
||||
$"454E44AE426082"
|
||||
};
|
||||
|
||||
resource(5, "stop_down") #'PNG ' array {
|
||||
$"89504E470D0A1A0A0000000D49484452000000230000001308060000001AA3B4"
|
||||
$"F40000007649444154789CEDD6B10DC0200C00C1276209D66104E6600286631C"
|
||||
$"D6708A285252A0401ABBF0D72E4E2E2C074030908810016AADAA90D61AC08501"
|
||||
$"28A5A861EE0E6DC0B3F83DF22EE7BC34D77BDFC698DA8C636639669663663966"
|
||||
$"D6F605FE73595733B519539800C81843DB414A892862E2D103E004602A1406AE"
|
||||
$"0663330000000049454E44AE426082"
|
||||
};
|
||||
|
||||
resource(6, "stop_disabled") #'PNG ' array {
|
||||
$"89504E470D0A1A0A0000000D49484452000000230000001308060000001AA3B4"
|
||||
$"F40000006F49444154789CEDD6310E80300840D18FE9B17ABE9EAC77E90DBAE2"
|
||||
$"608C3A10AB0B0CFC99E1858120AAAA0448442800630C57486B0DE0C000CC39DD"
|
||||
$"30679B37E05E791F79D67B5F9AABB57EC684DA4C62AC12639518ABC4587DBEC0"
|
||||
$"7F2EEB6AA136130A53E0FA27BC1320C4A707B0036170119C944D95F600000000"
|
||||
$"49454E44AE426082"
|
||||
};
|
||||
|
||||
resource(7, "next_up") #'PNG ' array {
|
||||
$"89504E470D0A1A0A0000000D494844520000002300000013080000000148CFDB"
|
||||
$"BE000000096F464673000000000000000000DA2AB6CE00000009704859730000"
|
||||
$"0FA000000FA001A06A8C770000009649444154789C858E3B1684300C03C73C1F"
|
||||
$"C567A5DE628FA7D4DC80365B04F221B0A84AEC9125CB000BC952B29C00CB0002"
|
||||
$"9900CB8950814E1504304F00217020A89C004C0717E574AF38CE45C469EC12A2"
|
||||
$"454D4666D54255BEEDE3E0B334F71817EDA24F21AD922E8CEAC6DB5F57D7B32C"
|
||||
$"6F2FC4FA75D85FA0D699525BC74B0FCCC83D3327F79FD144F9B49FE5B7842ECC"
|
||||
$"7AEBEDF50309A3288D19DE43630000000049454E44AE426082"
|
||||
};
|
||||
|
||||
resource(8, "next_down") #'PNG ' array {
|
||||
$"89504E470D0A1A0A0000000D494844520000002300000013080000000148CFDB"
|
||||
$"BE000000096F464673000000000000000000DA2AB6CE00000009704859730000"
|
||||
$"0FA000000FA001A06A8C770000009649444154789C858ECB1583400C03C73C37"
|
||||
$"410769232E813AA880E2544EDA2007F6C3624874F27AC792E090900C417B2313"
|
||||
$"608810C044D2EE0208810341E30460D5EF7DB62EAB621711F5F0941075B839B4"
|
||||
$"3D1749B2751917AFA91B8F71D1C2F094DF2BE9C2F45EDEDFBA5EB53EA9B4B13E"
|
||||
$"952FDA6687E50FD43B73D45699F4C08CDC3353B9DF8C12E5E93FCB6F8991353E"
|
||||
$"B7B727CD5FEB601F32B3AD1E6C0000000049454E44AE426082"
|
||||
};
|
||||
|
||||
resource(9, "next_disabled") #'PNG ' array {
|
||||
$"89504E470D0A1A0A0000000D494844520000002300000013080000000148CFDB"
|
||||
$"BE000000096F464673000000000000000000DA2AB6CE00000009704859730000"
|
||||
$"0FA000000FA001A06A8C770000009A49444154789C858EBB1584300C04473C95"
|
||||
$"4219AA8FF8822B4965E0980E487D01FE1B8E8D646B56BB120194E086C4004804"
|
||||
$"3438263B2031E006B09025310F1A00DC4001A77006207BE2D6EB74AB359D73F7"
|
||||
$"6C6C12BC464D46669542457A9CFDC767A987FB38F7EA9AF26B251B182B1BAD6F"
|
||||
$"1B5DCF9278BC10DB57E17C816A67AEDA96267B607AEE99C9DC7FC6264AA7FD2C"
|
||||
$"BD256C60B65B6FAB1F14962A7DEE40835F0000000049454E44AE426082"
|
||||
};
|
||||
|
||||
resource(10, "prev_up") #'PNG ' array {
|
||||
$"89504E470D0A1A0A0000000D494844520000002300000013080000000148CFDB"
|
||||
$"BE000000096F464673000000000000000000DA2AB6CE00000009704859730000"
|
||||
$"0FA000000FA001A06A8C770000009649444154789C858FB911C3300C04171A94"
|
||||
$"825A153B707960AC0E94D201FF67CC8B38C4DEE12011E022480812032011C0C1"
|
||||
$"C5018901F30401584500D100600E9A6789F3CE515246D945C9334BC6CCD720F6"
|
||||
$"4656D54255FABCE3C7A7D52F11BA44EAB22257F2E5279FD85CDE611767497C0E"
|
||||
$"C4FD55780F50BB02B0DCC0182A0F4C99FFCBD91333E35B6EDEB5E3749ACEAFC4"
|
||||
$"DCDB0EBD7E98BA296A78A62B700000000049454E44AE426082"
|
||||
};
|
||||
|
||||
resource(11, "prev_down") #'PNG ' array {
|
||||
$"89504E470D0A1A0A0000000D494844520000002300000013080000000148CFDB"
|
||||
$"BE000000096F464673000000000000000000DA2AB6CE00000009704859730000"
|
||||
$"0FA000000FA001A06A8C770000009949444154789C858FC115C3200C43BF792C"
|
||||
$"910DBA463D42E6C804194EE3748DF41008E0D04627B064498613423204D71F99"
|
||||
$"0043B80012004E87230BC005F9E212A06EA3BA8C789F240EEEC53455B2854C16"
|
||||
$"EDE019B6ADE3E0D5D52FF6F91697637CADA4DBA49CD8B6D4C91211F7D2C6F6AB"
|
||||
$"7CC1BE64581F44ED0AC04B0367A83C682AFFCF67AE881A4D75316BA6CB818D2F"
|
||||
$"00E333EDD061F902FBC91FF2833D9C250000000049454E44AE426082"
|
||||
};
|
||||
|
||||
resource(12, "prev_disabled") #'PNG ' array {
|
||||
$"89504E470D0A1A0A0000000D494844520000002300000013080000000148CFDB"
|
||||
$"BE000000096F464673000000000000000000DA2AB6CE00000009704859730000"
|
||||
$"0FA000000FA001A06A8C770000009C49444154789C858FB911C3300C04171A94"
|
||||
$"E232509F62072E096598B13A504A07FC9FB12EE2F0F68083440025B821310012"
|
||||
$"010D8EC917901870033800F0820088060037D0EC25CEBA84E529A35EC9C4C13D"
|
||||
$"05335F07B10FB2AA16AAD2EB1E3FDEAD7E19AFCB3A9DD7974AB6FCE4135BCA3A"
|
||||
$"ECE05912AF07E2FC28DC0F50BB02F0DCC0192A0F4CF1FFCDD91333635B6EDEB5"
|
||||
$"E37472E75762CE6D875E3FEE602ABACC9639B80000000049454E44AE426082"
|
||||
};
|
||||
|
||||
resource(13, "ffwd_up") #'PNG ' array {
|
||||
$"89504E470D0A1A0A0000000D494844520000002300000013080000000148CFDB"
|
||||
$"BE000000096F464673000000000000000000DA2AB6CE00000009704859730000"
|
||||
$"0FA000000FA001A06A8C770000009F49444154789C858F3B16843008452F1E96"
|
||||
$"92B55A4F31CB7BD6EEC0365324928F8EBE8243E0022F9601C8802C6F80650081"
|
||||
$"4C80E52D09800580140860BE01A5AF4289051012982A97CAEA5EC9EB3695D02E"
|
||||
$"941B257033C8556128E4FB31163ECBB4393E94CE003E1A50B3541CAA31F1AE95"
|
||||
$"EEDD4D3DC8F2FE42AC5F87E3050ACFA430D0B29979E006E6EC9E996E1905D55D"
|
||||
$"F3B13F6723F39700679D4B17FD00CCDC346454415F090000000049454E44AE42"
|
||||
$"6082"
|
||||
};
|
||||
|
||||
resource(14, "ffwd_down") #'PNG ' array {
|
||||
$"89504E470D0A1A0A0000000D494844520000002300000013080000000148CFDB"
|
||||
$"BE000000096F464673000000000000000000DA2AB6CE00000009704859730000"
|
||||
$"0FA000000FA001A06A8C770000009F49444154789C858FCB15C3300804073F35"
|
||||
$"E10ED24628C175B88214B7E5A40DE720097DE2441CF46019C1021132D40A9009"
|
||||
$"30E459DE0070BAB892001790C0C1111B2024B03AEFD98F2E522AD3949FB6A1EC"
|
||||
$"C88B6E3EDAC53AEC3C46E1B14D93E320AF0FA4D1809AA56C438D89BA285DDDFD"
|
||||
$"6A7EBE4C1BE7E286D79EE05840E1190F032D9B993FDCC0D46ECD74CB28A86E5B"
|
||||
$"1AFB7336323F0930DEB334C7FE0115B3282C4AE639D10000000049454E44AE42"
|
||||
$"6082"
|
||||
};
|
||||
|
||||
resource(15, "ffwd_disabled") #'PNG ' array {
|
||||
$"89504E470D0A1A0A0000000D494844520000002300000013080000000148CFDB"
|
||||
$"BE000000096F464673000000000000000000DA2AB6CE00000009704859730000"
|
||||
$"0FA000000FA001A06A8C77000000A849444154789C858FBB15844008452F1E4A"
|
||||
$"B10CEA33DE601BD85E28C389EDC0740CC6F9EAEA0B38C05CE08D4400E5072631"
|
||||
$"0012010D8EC90A480C6E004C007846004403E006283838C604186620EBC9CD69"
|
||||
$"75AB59CF6D9642BD906EA4C0CD2057154345BAED7DE3330D9BCB873C07D0DE80"
|
||||
$"554BC9A155A6D467A7A99BA90749DC5E88E5ABB0BF40C5335E0CD46C641EB88E"
|
||||
$"C9AF39B35BC60AD55CD3FE7DCC7AE62F01CA32B62E3A00C80630E7BA72D89A00"
|
||||
$"00000049454E44AE426082"
|
||||
};
|
||||
|
||||
resource(16, "rew_up") #'PNG ' array {
|
||||
$"89504E470D0A1A0A0000000D494844520000002300000013080000000148CFDB"
|
||||
$"BE000000096F464673000000000000000000DA2AB6CE00000009704859730000"
|
||||
$"0FA000000FA001A06A8C77000000A149444154789C8590311684200C447F7839"
|
||||
$"4ACE6ABD85C71B6B6F60CB160882ACEB14BCBCF09319B00C40066479032C0308"
|
||||
$"64022C6F10021200444500F3ADF484439466022101A6938BB2BA57785BA77254"
|
||||
$"876847B51F0799D50235F97E8C8D4FEAE703C0273BBFDB9328D150DF29CF93AE"
|
||||
$"A911AB5EFF64797F2196D5E17881AAFBA96819AEAA67E2473532CFC4C5A8DD6A"
|
||||
$"E2FA3C4FDC98B9FBDCAE7296C9FFAE2FF13F3064D77552650000000049454E44"
|
||||
$"AE426082"
|
||||
};
|
||||
|
||||
resource(17, "rew_down") #'PNG ' array {
|
||||
$"89504E470D0A1A0A0000000D494844520000002300000013080000000148CFDB"
|
||||
$"BE000000096F464673000000000000000000DA2AB6CE00000009704859730000"
|
||||
$"0FA000000FA001A06A8C77000000AA49444154789C8592BB0DC3300C441F052D"
|
||||
$"E12675D60847F01C9E20C3DD24A95C780DA7D0CFB26C9885209147DE2320A821"
|
||||
$"43ED01320186C0058454F1D6C11E53878B582B0184045899F7398ECEA958C729"
|
||||
$"1DC5C18F2E178DB6F31CB6CC7DE29DF1F3F8171007BB78B62790D01A4600D27A"
|
||||
$"52EB6AB2B52ED2F10CD0C6F2B0C3778A303F888A7B0EAFA80EFCD6B3C62F6EBD"
|
||||
$"E65ED134AA550DBA23CF9DAE67A6FB771919631BFC4F31FD01075828D428AF1D"
|
||||
$"AC0000000049454E44AE426082"
|
||||
};
|
||||
|
||||
resource(18, "rew_disabled") #'PNG ' array {
|
||||
$"89504E470D0A1A0A0000000D494844520000002300000013080000000148CFDB"
|
||||
$"BE000000096F464673000000000000000000DA2AB6CE00000009704859730000"
|
||||
$"0FA000000FA001A06A8C77000000AA49444154789C8590B911C3300C04171A94"
|
||||
$"A232509F62076EC0BDB00C3156074AE9007C45CBBA00830197B8232501281F30"
|
||||
$"49119004680C98EC80A408C180050042460044A3CF0C85E0C3050C3340F6CCAD"
|
||||
$"BEBAD7AA759D79290EA196623F5E64560D54A5C7390E5E397EB75E273BBDDAB3"
|
||||
$"E0D1BC94893FCFACDD1AB1E2F54F928E07627B2B9C0F5071CF0A3543EB7A26FC"
|
||||
$"E846E69E688CD5539BB83ECF1D3766EE3EB7EB946DF2BFEA0B7B823033032405"
|
||||
$"7B0000000049454E44AE426082"
|
||||
};
|
||||
|
||||
resource(19, "eject_up") #'PNG ' array {
|
||||
$"89504E470D0A1A0A0000000D494844520000002300000013080000000148CFDB"
|
||||
$"BE000000096F464673000000000000000000DA2AB6CE00000009704859730000"
|
||||
$"0FA000000FA001A06A8C770000008E49444154789C8D913116C4200805071F47"
|
||||
$"E1ACA953ECF1629D1B6C6B0A233ED164F737CA6704542900892C394BC9801440"
|
||||
$"339000AA490BA12100A22D59B3E6BB239E70F09679D26CA851CB58B0DEE503B9"
|
||||
$"F4FC8EC6DEFBC5765D7D80E7FE7AAF4774ACBB1A9185A49C6F6960FB28846BD8"
|
||||
$"54739AB00FFFC8184C509A91094A0B2442FFFC980ED1FA9994ED679D0B07B91C"
|
||||
$"F1A3B1DDDF0000000049454E44AE426082"
|
||||
};
|
||||
|
||||
resource(20, "eject_down") #'PNG ' array {
|
||||
$"89504E470D0A1A0A0000000D494844520000002300000013080000000148CFDB"
|
||||
$"BE000000096F464673000000000000000000DA2AB6CE00000009704859730000"
|
||||
$"0FA000000FA001A06A8C770000009049444154789C8591D111C3200C431F9C97"
|
||||
$"C8065DA31E217364820CE771B246FA110E834DAEFA010B5916000F0CB382B58A"
|
||||
$"62400570B292704BEFA800DA7736770CD60DDF7EA83A793C361AA801E5CE5C16"
|
||||
$"1DFB4C7C7C5E1CE7F000EFF3A5AD16197556A26411BA702C728F383781700D8D"
|
||||
$"EF98137AF8578D4212D52C49A2BA9044D1E2C71264AAD29500285CFF6CB61FF3"
|
||||
$"3B15C0D5E713DD0000000049454E44AE426082"
|
||||
};
|
||||
|
||||
resource(21, "eject_disabled") #'PNG ' array {
|
||||
$"89504E470D0A1A0A0000000D494844520000002300000013080000000148CFDB"
|
||||
$"BE000000096F464673000000000000000000DA2AB6CE00000009704859730000"
|
||||
$"0FA000000FA001A06A8C770000009149444154789C8D91BB11C4200C051746A5"
|
||||
$"5C19D4E7D8C195A43688DD81532E309F41C2F6BD04F4B44802420110B22642C9"
|
||||
$"402880642002D5A485D01080202D7965B5EF923DD1C1AA4F4FAA4E35AE326AAC"
|
||||
$"67F581BAE43867631FFD6CBBA131C07D7FA96BB28E0E572CB25028C7531AD8BE"
|
||||
$"02E61AEA6ABA09C7F0B78C8283A2471C14178885FEF93199A2F53309DB6B9D1F"
|
||||
$"5A8523B87099497F0000000049454E44AE426082"
|
||||
};
|
||||
|
||||
resource(22, "save_up") #'PNG ' array {
|
||||
$"89504E470D0A1A0A0000000D494844520000002300000013080000000148CFDB"
|
||||
$"BE000000096F464673000000000000000000DA2AB6CE00000009704859730000"
|
||||
$"0FA000000FA001A06A8C77000000AD49444154789CA5D0316EC4300C04C0A1E0"
|
||||
$"2AAF70A1EFE51BA953DCF32440A9EE07AE0E500ACB675C622306C2462477B15C"
|
||||
$"6D7448AA5A1395E84835D428885E650A13348F418198AA8126F4CECAFBB2750F"
|
||||
$"9B0A322890935F358DB7615EDB03D6413D0DED52F7E579B0C0E7AA943B7A3ED1"
|
||||
$"DE0CF49F9B68078EC6E254A78CCF9F79BE1F030B6FE0E336B16CEBBCBB0A6507"
|
||||
$"AE24748533BD4C7181A3C1DCE67FDD2A7904397B492BFAFB5F32B76F1913323C"
|
||||
$"2181DF6C0000000049454E44AE426082"
|
||||
};
|
||||
|
||||
resource(23, "save_down") #'PNG ' array {
|
||||
$"89504E470D0A1A0A0000000D494844520000002300000013080000000148CFDB"
|
||||
$"BE000000096F464673000000000000000000DA2AB6CE00000009704859730000"
|
||||
$"0FA000000FA001A06A8C77000000A549444154789CA590CB11C3200C449F189A"
|
||||
$"F08D63DA3025B80E5790E2E44E32E492369403E0908013CF642FE8B3B3BB0200"
|
||||
$"049D371C6C1428A6A2794504050790120DCC2BCDD60CC003776A75A3AA00B168"
|
||||
$"03B3A3832F6F02422E072CB17ED693D6653754804B568A06583CD0AE01EC7322"
|
||||
$"6990A80C0E75B41C3F0E2DACDF4FE03A79586A175FA964971DBAF738C3F16F9D"
|
||||
$"9CE09000420A7F79692C1F1968CF4278FC92999E50C526E88C462E9A00000000"
|
||||
$"49454E44AE426082"
|
||||
};
|
||||
|
||||
resource(24, "save_disabled") #'PNG ' array {
|
||||
$"89504E470D0A1A0A0000000D494844520000002300000013080000000148CFDB"
|
||||
$"BE000000096F464673000000000000000000DA2AB6CE00000009704859730000"
|
||||
$"0FA000000FA001A06A8C77000000B649444154789CA5D0BB6DC4301004D04781"
|
||||
$"A5B80C06EC84DD5C7C811B50270A18BA043370741D5C74802E10751F5B020478"
|
||||
$"13EE67767638618641D3DA4023CC18DAA8856F84B9A9242264B70E81109B3E1D"
|
||||
$"500A0BEEC79ADDA4CE820A127C0CFE44EC6FC6B4A41BA88D78087A525DAE8F83"
|
||||
$"09CE0B532D2875877B15507E77C6BCA1A837767952FFFC9EE6CBEE6C89D367E4"
|
||||
$"BA56F5A96A7CA53DE2D0114C7CABC6031819A63CFDEB56AADDC8C99B5BD16973"
|
||||
$"F7EB25BF0326ED2E5BFED7474F0000000049454E44AE426082"
|
||||
};
|
||||
|
||||
resource(25, "repeat_up") #'PNG ' array {
|
||||
$"89504E470D0A1A0A0000000D49484452000000230000001308030000015A7A74"
|
||||
$"5000000012504C5445FFFFFF000000E6E6E6DCDCDC6C6C6C008300BB001C5100"
|
||||
$"0000096F464673000000000000000000DA2AB6CE000000097048597300000FA0"
|
||||
$"00000FA001A06A8C770000007E49444154789CAD8F510EC0200843ADD5FB5F79"
|
||||
$"90AA1B62B264593FB6525E104A9148D0BFE4ACCDA9244CAB6D662026A80976A8"
|
||||
$"E9FDA39B16F31723448A21C2D49885A49255C930AC59A24334A8C31204889F93"
|
||||
$"6DC5B6BDEEC961E77A96E1320DE98CE7D3E8DDCE1283CC605562B6AD9F10FF66"
|
||||
$"4ED01DE5BBB29C696FC205B240065004A187160000000049454E44AE426082"
|
||||
};
|
||||
|
||||
resource(26, "repeat_down") #'PNG ' array {
|
||||
$"89504E470D0A1A0A0000000D49484452000000230000001308030000015A7A74"
|
||||
$"5000000012504C5445000000FFFFFF6C6C6CE6E6E6BEBEBE0083004C8424AC00"
|
||||
$"0000096F464673000000000000000000DA2AB6CE000000097048597300000FA0"
|
||||
$"00000FA001A06A8C770000007C49444154789CAD90510EC0200843CBACF7BFF2"
|
||||
$"40D40D313159D60F85478320E022413BF5EEB991963632CB4631245E04AB7851"
|
||||
$"B58F4688714584E86240F3B9DE4B92907591A15951E28B78A30A2508267E26CB"
|
||||
$"886579DDC866E6EBA022698DF041B5EA5AEE41F66066EE59A67E9BF8B767677A"
|
||||
$"50DE2BCB3CE524B9012C9D0763558616CC0000000049454E44AE426082"
|
||||
};
|
||||
|
||||
resource(27, "repeat_up_on") #'PNG ' array {
|
||||
$"89504E470D0A1A0A0000000D49484452000000230000001308030000015A7A74"
|
||||
$"5000000012504C5445FFFFFF000000E6E6E66C6C6CDCDCDC00FF00911226CA00"
|
||||
$"0000096F464673000000000000000000DA2AB6CE000000097048597300000FA0"
|
||||
$"00000FA001A06A8C770000007B49444154789CAD8FDB0EC0200843AD96FFFFE5"
|
||||
$"6110276262B2AC0F0AE5844B292612EC2FE9B9469612AA59D660202A58111458"
|
||||
$"B1D78F9187F02F5A88148305D7E885A49255C9D0ACA963875823813A08103F3B"
|
||||
$"DB8A6D9BDE9DC3CEF5A28674C63A1A227A9631C80C6666CCB6F50AF16FE604BD"
|
||||
$"56BE2BAB33ED263C9CF907A6D61A86EF0000000049454E44AE426082"
|
||||
};
|
||||
|
||||
resource(28, "repeat_down_on") #'PNG ' array {
|
||||
$"89504E470D0A1A0A0000000D49484452000000230000001308030000015A7A74"
|
||||
$"5000000012504C5445000000FFFFFF6C6C6CE6E6E6BEBEBE00FF00CF0E125600"
|
||||
$"0000096F464673000000000000000000DA2AB6CE000000097048597300000FA0"
|
||||
$"00000FA001A06A8C770000007C49444154789CAD90510EC0200843CBACF7BFF2"
|
||||
$"40D40D313159D60F85478320E022413BF5EEB991963632CB4631245E04AB7851"
|
||||
$"B58F4688714584E86240F3B9DE4B92907591A15951E28B78A30A2508267E26CB"
|
||||
$"886579DDC866E6EBA022698DF041B5EA5AEE41F66066EE59A67E9BF8B767677A"
|
||||
$"50DE2BCB3CE524B9012C9D0763558616CC0000000049454E44AE426082"
|
||||
};
|
||||
|
||||
resource(29, "repeat_disabled") #'PNG ' array {
|
||||
$"89504E470D0A1A0A0000000D494844520000002300000013080000000148CFDB"
|
||||
$"BE000000096F464673000000000000000000DA2AB6CE00000009704859730000"
|
||||
$"0FA000000FA001A06A8C77000000B749444154789C8D90BD15C3200C843FF254"
|
||||
$"658E8CA13A63A574ED22D3B8D618A18D37704B0AC008E2FCA841EF743A4E1712"
|
||||
$"8010310D290221011281134048D100AD634C330520483400BD111E05BB9CA8D5"
|
||||
$"BAB20BA6E57134C0401D5FF781E4E1080FB51B6A7BEBD6E9EB2C59482D0B2D10"
|
||||
$"9E4BAF38779E86133E2392459D45F9E2B5795E8F071B9C0198EE02FD194E76B3"
|
||||
$"85ABE6846AAC1D57B31DA5A4E828B5D54AE2E8AEF7FA97D3F218FC789D83843C"
|
||||
$"244C3FFF7A014CCF345764741A860000000049454E44AE426082"
|
||||
};
|
||||
|
||||
resource(30, "shuffle_up") #'PNG ' array {
|
||||
$"89504E470D0A1A0A0000000D49484452000000230000001308030000015A7A74"
|
||||
$"5000000012504C5445FFFFFF000000E6E6E66C6C6CDCDCDC0083001298103000"
|
||||
$"0000096F464673000000000000000000DA2AB6CE000000097048597300000FA0"
|
||||
$"00000FA001A06A8C770000008E49444154789C85925B16802008449DC4FD6F39"
|
||||
$"E46581E57C100EF720786A4D452C8F715E26113803C05F4758B0228DC8088D21"
|
||||
$"E19E5EA4DEAD5842CDEE8012D22559DABFA8555DE9BE9E9C81EC5061D4818C02"
|
||||
$"1B881D9845E1F86131A5CF66E6EBA08EBCC67BA73178AD7F46063B3132E064E0"
|
||||
$"3BC9EBFBABEB91EC2EAD58D9330DD830FE2B44D8311F77F5937003992A073AE8"
|
||||
$"E0FDC50000000049454E44AE426082"
|
||||
};
|
||||
|
||||
resource(31, "shuffle_down") #'PNG ' array {
|
||||
$"89504E470D0A1A0A0000000D49484452000000230000001308030000015A7A74"
|
||||
$"5000000012504C5445000000FFFFFF6C6C6CE6E6E6BEBEBE0083004C8424AC00"
|
||||
$"0000096F464673000000000000000000DA2AB6CE000000097048597300000FA0"
|
||||
$"00000FA001A06A8C770000008749444154789C85925B168020084487C4FD6F39"
|
||||
$"792847B09C0F8E0CD7800A30F1D08C2B0F5312F3B19021F222F775621248B9DD"
|
||||
$"DB846A298518430FD9528A8A50F5A47E2D391DD9E1C29803D8C63A86DC825BBC"
|
||||
$"9C9904539E7398F9B9A8515E63DFA9F7B1D63FA383DD181D509878D9B00FCE91"
|
||||
$"B2F7B28A97E7C9020E8CFF0A114ECC47AF7613BD278906D3979AD3BB00000000"
|
||||
$"49454E44AE426082"
|
||||
};
|
||||
|
||||
resource(32, "shuffle_up_on") #'PNG ' array {
|
||||
$"89504E470D0A1A0A0000000D49484452000000230000001308030000015A7A74"
|
||||
$"5000000012504C5445FFFFFF000000E6E6E66C6C6CDCDCDC00FF00911226CA00"
|
||||
$"0000096F464673000000000000000000DA2AB6CE000000097048597300000FA0"
|
||||
$"00000FA001A06A8C770000008E49444154789C85925B16802008449DC4FD6F39"
|
||||
$"E46581E57C100EF720786A4D452C8F715E26113803C05F4758B0228DC8088D21"
|
||||
$"E19E5EA4DEAD5842CDEE8012D22559DABFA8555DE9BE9E9C81EC5061D4818C02"
|
||||
$"1B881D9845E1F86131A5CF66E6EBA08EBCC67BA73178AD7F46063B3132E064E0"
|
||||
$"3BC9EBFBABEB91EC2EAD58D9330DD830FE2B44D8311F77F5937003992A073AE8"
|
||||
$"E0FDC50000000049454E44AE426082"
|
||||
};
|
||||
|
||||
resource(33, "shuffle_down_on") #'PNG ' array {
|
||||
$"89504E470D0A1A0A0000000D49484452000000230000001308030000015A7A74"
|
||||
$"5000000012504C5445000000FFFFFF6C6C6CE6E6E6BEBEBE00FF00CF0E125600"
|
||||
$"0000096F464673000000000000000000DA2AB6CE000000097048597300000FA0"
|
||||
$"00000FA001A06A8C770000008749444154789C85925B168020084487C4FD6F39"
|
||||
$"792847B09C0F8E0CD7800A30F1D08C2B0F5312F3B19021F222F775621248B9DD"
|
||||
$"DB846A298518430FD9528A8A50F5A47E2D391DD9E1C29803D8C63A86DC825BBC"
|
||||
$"9C9904539E7398F9B9A8515E63DFA9F7B1D63FA383DD181D509878D9B00FCE91"
|
||||
$"B2F7B28A97E7C9020E8CFF0A114ECC47AF7613BD278906D3979AD3BB00000000"
|
||||
$"49454E44AE426082"
|
||||
};
|
||||
|
||||
resource(34, "shuffle_disabled") #'PNG ' array {
|
||||
$"89504E470D0A1A0A0000000D494844520000002300000013080000000148CFDB"
|
||||
$"BE000000096F464673000000000000000000DA2AB6CE00000009704859730000"
|
||||
$"0FA000000FA001A06A8C77000000C449444154789C7D91B115C2301043BFFD3C"
|
||||
$"0A63A8661B56A0A4A66001D648AD31480B1BA43585ED042721AA2C9DDE597717"
|
||||
$"324062042200210369E6218F0058213F4156B50084548A5C09AFAA9DA2B131FC"
|
||||
$"68AD4B83758AF410440CD8002E8FB431ED610E34237DA6FEBFFBAAD300E13DF5"
|
||||
$"DA7D9D091218614018998885D112262217E29667D3792FF3677F9819B74782E9"
|
||||
$"6FD903676D36D4A3A63CF4D43922D86DFF06B743148A8B07C958AA2AA2D13A7D"
|
||||
$"BF43999EEF781065CBB29703877C394C0D3CBE855E4A1104D8C6E70000000049"
|
||||
$"454E44AE426082"
|
||||
};
|
||||
|
@ -1,22 +0,0 @@
|
||||
/*
|
||||
|
||||
CDPlayer Constants
|
||||
|
||||
Author: Sikosis
|
||||
|
||||
(C)2004 Haiku - http://haiku-os.org/
|
||||
|
||||
*/
|
||||
|
||||
#ifndef __CDPLAYERCONSTANTS_H__
|
||||
#define __CDPLAYERCONSTANTS_H__
|
||||
|
||||
// Pointers to BWindows
|
||||
extern CDPlayerWindow* ptrCDPlayerWindow;
|
||||
|
||||
// Product Name and Properties
|
||||
const char projtitle[]="CDPlayer";
|
||||
const char projversion[]="v0.1";
|
||||
const char projauthor[]="Sikosis";
|
||||
|
||||
#endif
|
@ -1,35 +0,0 @@
|
||||
/*
|
||||
|
||||
CDPlayer View
|
||||
|
||||
Author: Sikosis
|
||||
|
||||
(C)2004 Haiku - http://haiku-os.org/
|
||||
|
||||
*/
|
||||
|
||||
// Includes ------------------------------------------------------------------------------------------ //
|
||||
#include <Alert.h>
|
||||
#include <Application.h>
|
||||
#include <Screen.h>
|
||||
#include <stdio.h>
|
||||
#include <Window.h>
|
||||
#include <View.h>
|
||||
|
||||
#include "CDPlayerWindows.h"
|
||||
#include "CDPlayerViews.h"
|
||||
// -------------------------------------------------------------------------------------------------- //
|
||||
|
||||
// CDPlayerView - Constructor
|
||||
CDPlayerView::CDPlayerView (BRect frame) : BView (frame, "CDPlayerView", B_FOLLOW_ALL_SIDES, B_WILL_DRAW )
|
||||
{
|
||||
SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------------- //
|
||||
|
||||
void CDPlayerView::Draw(BRect /*updateRect*/)
|
||||
{
|
||||
BRect r;
|
||||
r = Bounds();
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------------- //
|
@ -1,24 +0,0 @@
|
||||
/*
|
||||
|
||||
CDPlayer Views Header
|
||||
|
||||
Author: Sikosis
|
||||
|
||||
(C)2004 Haiku - http://haiku-os.org/
|
||||
|
||||
*/
|
||||
|
||||
#ifndef __CDPlayerVIEWS_H__
|
||||
#define __CDPlayerVIEWS_H__
|
||||
|
||||
#include "CDPlayer.h"
|
||||
#include "CDPlayerWindows.h"
|
||||
|
||||
class CDPlayerView : public BView
|
||||
{
|
||||
public:
|
||||
CDPlayerView(BRect frame);
|
||||
virtual void Draw(BRect updateRect);
|
||||
};
|
||||
|
||||
#endif
|
@ -1,134 +0,0 @@
|
||||
/*
|
||||
|
||||
CDPlayerWindow
|
||||
|
||||
Author: Sikosis
|
||||
|
||||
(C)2004 Haiku - http://haiku-os.org/
|
||||
|
||||
*/
|
||||
|
||||
// Includes ------------------------------------------------------------------------------------------ //
|
||||
#include <Alert.h>
|
||||
#include <Application.h>
|
||||
#include <Button.h>
|
||||
#include <File.h>
|
||||
#include <FindDirectory.h>
|
||||
#include <Path.h>
|
||||
#include <Screen.h>
|
||||
#include <ScrollView.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <TextControl.h>
|
||||
#include <Window.h>
|
||||
#include <View.h>
|
||||
|
||||
#include "CDPlayer.h"
|
||||
#include "CDPlayerWindows.h"
|
||||
#include "CDPlayerViews.h"
|
||||
// -------------------------------------------------------------------------------------------------- //
|
||||
|
||||
// CenterWindowOnScreen -- Centers the BWindow to the Current Screen
|
||||
static void CenterWindowOnScreen(BWindow* w)
|
||||
{
|
||||
BRect screenFrame = (BScreen(B_MAIN_SCREEN_ID).Frame()); BPoint pt;
|
||||
pt.x = screenFrame.Width()/2 - w->Bounds().Width()/2;
|
||||
pt.y = screenFrame.Height()/2 - w->Bounds().Height()/2;
|
||||
|
||||
if (screenFrame.Contains(pt))
|
||||
w->MoveTo(pt);
|
||||
}
|
||||
// -------------------------------------------------------------------------------------------------- //
|
||||
|
||||
// CDPlayerWindow - Constructor
|
||||
CDPlayerWindow::CDPlayerWindow(BRect frame) : BWindow (frame, "CD Player", B_TITLED_WINDOW, B_NORMAL_WINDOW_FEEL , 0)
|
||||
{
|
||||
InitWindow();
|
||||
CenterWindowOnScreen(this);
|
||||
|
||||
// Load User Settings
|
||||
BPath path;
|
||||
find_directory(B_USER_SETTINGS_DIRECTORY,&path);
|
||||
path.Append("CDPlayer_Settings",true);
|
||||
BFile file(path.Path(),B_READ_ONLY);
|
||||
BMessage msg;
|
||||
msg.Unflatten(&file);
|
||||
LoadSettings (&msg);
|
||||
|
||||
Show();
|
||||
}
|
||||
// -------------------------------------------------------------------------------------------------- //
|
||||
|
||||
|
||||
// CDPlayerWindow - Destructor
|
||||
CDPlayerWindow::~CDPlayerWindow()
|
||||
{
|
||||
//exit(0); - this is bad i seem to remember someone telling me ...
|
||||
}
|
||||
// -------------------------------------------------------------------------------------------------- //
|
||||
|
||||
|
||||
// CDPlayerWindow::InitWindow -- Initialization Commands here
|
||||
void CDPlayerWindow::InitWindow(void)
|
||||
{
|
||||
BRect r;
|
||||
r = Bounds(); // the whole view
|
||||
|
||||
// Create the Views
|
||||
AddChild(ptrCDPlayerView = new CDPlayerView(r));
|
||||
}
|
||||
// -------------------------------------------------------------------------------------------------- //
|
||||
|
||||
|
||||
// CDPlayerWindow::QuitRequested -- Post a message to the app to quit
|
||||
bool CDPlayerWindow::QuitRequested()
|
||||
{
|
||||
SaveSettings();
|
||||
be_app->PostMessage(B_QUIT_REQUESTED);
|
||||
return true;
|
||||
}
|
||||
// -------------------------------------------------------------------------------------------------- //
|
||||
|
||||
|
||||
// CDPlayerWindow::LoadSettings -- Loads your current settings
|
||||
void CDPlayerWindow::LoadSettings(BMessage *msg)
|
||||
{
|
||||
BRect frame;
|
||||
|
||||
if (B_OK == msg->FindRect("windowframe",&frame)) {
|
||||
MoveTo(frame.left,frame.top);
|
||||
ResizeTo(frame.right-frame.left,frame.bottom-frame.top);
|
||||
}
|
||||
}
|
||||
// -------------------------------------------------------------------------------------------------- //
|
||||
|
||||
|
||||
// CDPlayerWindow::SaveSettings -- Saves the Users settings
|
||||
void CDPlayerWindow::SaveSettings(void)
|
||||
{
|
||||
BMessage msg;
|
||||
msg.AddRect("windowframe",Frame());
|
||||
|
||||
BPath path;
|
||||
status_t result = find_directory(B_USER_SETTINGS_DIRECTORY,&path);
|
||||
if (result == B_OK) {
|
||||
path.Append("CDPlayer_Settings",true);
|
||||
BFile file(path.Path(),B_READ_WRITE | B_CREATE_FILE | B_ERASE_FILE);
|
||||
msg.Flatten(&file);
|
||||
}
|
||||
}
|
||||
// -------------------------------------------------------------------------------------------------- //
|
||||
|
||||
|
||||
// CDPlayerWindow::MessageReceived -- receives messages
|
||||
void CDPlayerWindow::MessageReceived (BMessage *message)
|
||||
{
|
||||
switch(message->what)
|
||||
{
|
||||
default:
|
||||
BWindow::MessageReceived(message);
|
||||
break;
|
||||
}
|
||||
}
|
||||
// -------------------------------------------------------------------------------------------------- //
|
||||
|
@ -1,34 +0,0 @@
|
||||
/*
|
||||
|
||||
CDPlayer Windows Header
|
||||
|
||||
Author: Sikosis
|
||||
|
||||
(C)2004 Haiku - http://haiku-os.org/
|
||||
|
||||
*/
|
||||
|
||||
#ifndef __CDPLAYERWINDOWS_H__
|
||||
#define __CDPLAYERWINDOWS_H__
|
||||
|
||||
#include "CDPlayer.h"
|
||||
#include "CDPlayerViews.h"
|
||||
|
||||
class CDPlayerView;
|
||||
|
||||
class CDPlayerWindow : public BWindow
|
||||
{
|
||||
public:
|
||||
CDPlayerWindow(BRect frame);
|
||||
~CDPlayerWindow();
|
||||
virtual bool QuitRequested();
|
||||
virtual void MessageReceived(BMessage *message);
|
||||
private:
|
||||
void InitWindow(void);
|
||||
|
||||
void LoadSettings(BMessage *msg);
|
||||
void SaveSettings(void);
|
||||
CDPlayerView* ptrCDPlayerView;
|
||||
};
|
||||
|
||||
#endif
|
69
src/apps/cdplayer/DrawButton.cpp
Normal file
69
src/apps/cdplayer/DrawButton.cpp
Normal file
@ -0,0 +1,69 @@
|
||||
#include "DrawButton.h"
|
||||
|
||||
DrawButton::DrawButton(BRect frame, const char *name, BBitmap *up, BBitmap *down,
|
||||
BMessage *msg, int32 resize, int32 flags)
|
||||
: BButton(frame, name, "", msg, resize, flags)
|
||||
{
|
||||
fUp=up;
|
||||
fDown=down;
|
||||
fDisabled=NULL;
|
||||
}
|
||||
|
||||
DrawButton::~DrawButton(void)
|
||||
{
|
||||
}
|
||||
|
||||
void DrawButton::SetBitmaps(BBitmap *up, BBitmap *down)
|
||||
{
|
||||
delete fUp;
|
||||
delete fDown;
|
||||
|
||||
fUp=up;
|
||||
fDown=down;
|
||||
}
|
||||
|
||||
void DrawButton::SetDisabled(BBitmap *disabled)
|
||||
{
|
||||
delete fDisabled;
|
||||
|
||||
fDisabled=disabled;
|
||||
}
|
||||
|
||||
void DrawButton::Draw(BRect update)
|
||||
{
|
||||
if(!IsEnabled())
|
||||
{
|
||||
if(fDisabled)
|
||||
DrawBitmap(fDisabled, BPoint(0,0));
|
||||
else
|
||||
StrokeRect(Bounds());
|
||||
return;
|
||||
}
|
||||
|
||||
if(Value() == B_CONTROL_ON)
|
||||
{
|
||||
if(fDown)
|
||||
DrawBitmap(fDown, BPoint(0,0));
|
||||
else
|
||||
StrokeRect(Bounds());
|
||||
}
|
||||
else
|
||||
{
|
||||
if(fUp)
|
||||
DrawBitmap(fUp, BPoint(0,0));
|
||||
else
|
||||
StrokeRect(Bounds());
|
||||
}
|
||||
}
|
||||
|
||||
void DrawButton::ResizeToPreferred(void)
|
||||
{
|
||||
if(fUp)
|
||||
ResizeTo(fUp->Bounds().Width(),fUp->Bounds().Height());
|
||||
else
|
||||
if(fDown)
|
||||
ResizeTo(fDown->Bounds().Width(),fDown->Bounds().Height());
|
||||
else
|
||||
if(fDisabled)
|
||||
ResizeTo(fDisabled->Bounds().Width(),fDisabled->Bounds().Height());
|
||||
}
|
31
src/apps/cdplayer/DrawButton.h
Normal file
31
src/apps/cdplayer/DrawButton.h
Normal file
@ -0,0 +1,31 @@
|
||||
#ifndef _DRAW_BUTTON_H
|
||||
#define _DRAW_BUTTON_H
|
||||
|
||||
#include <Looper.h>
|
||||
#include <Application.h>
|
||||
#include <Window.h>
|
||||
#include <Button.h>
|
||||
#include <Bitmap.h>
|
||||
#include <Rect.h>
|
||||
|
||||
|
||||
class DrawButton : public BButton
|
||||
{
|
||||
public:
|
||||
DrawButton(BRect frame, const char *name, BBitmap *up, BBitmap *down,
|
||||
BMessage *msg, int32 resize, int32 flags);
|
||||
~DrawButton(void);
|
||||
|
||||
void Draw(BRect update);
|
||||
|
||||
void SetBitmaps(BBitmap *up, BBitmap *down);
|
||||
void ResizeToPreferred(void);
|
||||
void SetDisabled(BBitmap *disabled);
|
||||
|
||||
private:
|
||||
|
||||
BBitmap *fUp, *fDown, *fDisabled;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
50
src/apps/cdplayer/FunctionObjectMessage.cpp
Normal file
50
src/apps/cdplayer/FunctionObjectMessage.cpp
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
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 <Debug.h>
|
||||
#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;
|
||||
}
|
||||
|
73
src/apps/cdplayer/FunctionObjectMessage.h
Normal file
73
src/apps/cdplayer/FunctionObjectMessage.h
Normal file
@ -0,0 +1,73 @@
|
||||
/*
|
||||
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 <Message.h>
|
||||
#include <MessageFilter.h>
|
||||
#endif
|
||||
|
||||
class FunctionObject {
|
||||
public:
|
||||
virtual void operator()() = 0;
|
||||
virtual ~FunctionObject() {}
|
||||
virtual ulong Size() const = 0;
|
||||
};
|
||||
|
||||
template<class FT, class T>
|
||||
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 FT, class T, class P>
|
||||
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
|
@ -1,5 +1,13 @@
|
||||
SubDir OBOS_TOP src apps cdplayer ;
|
||||
|
||||
AddResources CDPlayer : CDPlayer.rdef ;
|
||||
App CDPlayer : CDPlayer.cpp CDPlayerWindow.cpp CDPlayerView.cpp ;
|
||||
LinkSharedOSLibs CDPlayer : be ;
|
||||
App CDPlayer :
|
||||
CDButton.cpp
|
||||
CDDBSupport.cpp
|
||||
CDEngine.cpp
|
||||
DrawButton.cpp
|
||||
FunctionObjectMessage.cpp
|
||||
Observer.cpp
|
||||
TypedList.cpp
|
||||
;
|
||||
LinkSharedOSLibs CDPlayer : be net netapi translation ;
|
||||
|
31
src/apps/cdplayer/LICENSE
Normal file
31
src/apps/cdplayer/LICENSE
Normal file
@ -0,0 +1,31 @@
|
||||
----------------------
|
||||
Be Sample Code License
|
||||
----------------------
|
||||
|
||||
Copyright 1991-1999, Be Incorporated.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions, and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions, and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. The name of the author may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
|
||||
TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
180
src/apps/cdplayer/Observer.cpp
Normal file
180
src/apps/cdplayer/Observer.cpp
Normal file
@ -0,0 +1,180 @@
|
||||
/*
|
||||
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 <Message.h>
|
||||
#include <Looper.h>
|
||||
#include <Debug.h>
|
||||
#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 *>(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;
|
||||
}
|
||||
}
|
98
src/apps/cdplayer/Observer.h
Normal file
98
src/apps/cdplayer/Observer.h
Normal file
@ -0,0 +1,98 @@
|
||||
/*
|
||||
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 <Handler.h>
|
||||
|
||||
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<NotifierListEntry *> 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<ObserverListEntry *> observerList;
|
||||
|
||||
friend class Observer;
|
||||
};
|
||||
|
||||
#endif
|
87
src/apps/cdplayer/TypedList.cpp
Normal file
87
src/apps/cdplayer/TypedList.cpp
Normal file
@ -0,0 +1,87 @@
|
||||
/*
|
||||
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 <Debug.h>
|
||||
#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);
|
||||
}
|
||||
|
326
src/apps/cdplayer/TypedList.h
Normal file
326
src/apps/cdplayer/TypedList.h
Normal file
@ -0,0 +1,326 @@
|
||||
/*
|
||||
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 <List.h>
|
||||
#endif
|
||||
|
||||
#include <Debug.h>
|
||||
|
||||
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 T>
|
||||
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<class T>
|
||||
TypedList<T>::TypedList(int32 itemsPerBlock, bool owning)
|
||||
: _PointerList(itemsPerBlock, owning)
|
||||
{
|
||||
}
|
||||
|
||||
template<class T>
|
||||
TypedList<T>::TypedList(const TypedList<T> &list)
|
||||
: _PointerList(list)
|
||||
{
|
||||
ASSERT(!list.Owning());
|
||||
// copying owned lists does not work yet
|
||||
}
|
||||
|
||||
template<class T>
|
||||
TypedList<T>::~TypedList()
|
||||
{
|
||||
if (Owning())
|
||||
// have to nuke elements first
|
||||
MakeEmpty();
|
||||
}
|
||||
|
||||
template<class T>
|
||||
TypedList<T> &
|
||||
TypedList<T>::operator=(const TypedList<T> &from)
|
||||
{
|
||||
ASSERT(!from.Owning());
|
||||
// copying owned lists does not work yet
|
||||
|
||||
return (TypedList<T> &)BList::operator=(from);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
bool
|
||||
TypedList<T>::AddItem(T item)
|
||||
{
|
||||
return _PointerList::AddItem(item);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
bool
|
||||
TypedList<T>::AddItem(T item, int32 atIndex)
|
||||
{
|
||||
return _PointerList::AddItem(item, atIndex);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
bool
|
||||
TypedList<T>::AddList(TypedList<T> *newItems)
|
||||
{
|
||||
return _PointerList::AddList(newItems);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
bool
|
||||
TypedList<T>::AddList(TypedList<T> *newItems, int32 atIndex)
|
||||
{
|
||||
return _PointerList::AddList(newItems, atIndex);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
bool
|
||||
TypedList<T>::AddUnique(T item)
|
||||
{
|
||||
return _PointerList::AddUnique(item);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
bool
|
||||
TypedList<T>::AddUnique(T item, CompareFunction function)
|
||||
{
|
||||
return _PointerList::AddUnique(item, (GenericCompareFunction)function);
|
||||
}
|
||||
|
||||
|
||||
template<class T>
|
||||
bool
|
||||
TypedList<T>::RemoveItem(T item)
|
||||
{
|
||||
bool result = _PointerList::RemoveItem(item);
|
||||
|
||||
if (result && Owning()) {
|
||||
delete item;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
T
|
||||
TypedList<T>::RemoveItem(int32 index)
|
||||
{
|
||||
return (T)_PointerList::RemoveItem(index);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
T
|
||||
TypedList<T>::RemoveItemAt(int32 index)
|
||||
{
|
||||
return (T)_PointerList::RemoveItem(index);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
T
|
||||
TypedList<T>::ItemAt(int32 index) const
|
||||
{
|
||||
return (T)_PointerList::ItemAt(index);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
T
|
||||
TypedList<T>::ItemAtFast(int32 index) const
|
||||
{
|
||||
return (T)_PointerList::ItemAtFast(index);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
int32
|
||||
TypedList<T>::IndexOf(const T item) const
|
||||
{
|
||||
return _PointerList::IndexOf(item);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
T
|
||||
TypedList<T>::FirstItem() const
|
||||
{
|
||||
return (T)_PointerList::FirstItem();
|
||||
}
|
||||
|
||||
template<class T>
|
||||
T
|
||||
TypedList<T>::LastItem() const
|
||||
{
|
||||
return (T)_PointerList::LastItem();
|
||||
}
|
||||
|
||||
template<class T>
|
||||
bool
|
||||
TypedList<T>::HasItem(const T item) const
|
||||
{
|
||||
return _PointerList::HasItem(item);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
bool
|
||||
TypedList<T>::IsEmpty() const
|
||||
{
|
||||
return _PointerList::IsEmpty();
|
||||
}
|
||||
|
||||
template<class T>
|
||||
int32
|
||||
TypedList<T>::CountItems() const
|
||||
{
|
||||
return _PointerList::CountItems();
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void
|
||||
TypedList<T>::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<class T>
|
||||
T
|
||||
TypedList<T>::EachElement(EachFunction func, void *params)
|
||||
{
|
||||
return (T)_PointerList::EachElement((GenericEachFunction)func, params);
|
||||
}
|
||||
|
||||
|
||||
template<class T>
|
||||
const T
|
||||
TypedList<T>::EachElement(ConstEachFunction func, void *params) const
|
||||
{
|
||||
return (const T)
|
||||
const_cast<TypedList<T> *>(this)->_PointerList::EachElement(
|
||||
(GenericEachFunction)func, params);
|
||||
}
|
||||
|
||||
|
||||
template<class T>
|
||||
T
|
||||
TypedList<T>::Items() const
|
||||
{
|
||||
return (T)_PointerList::Items();
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void
|
||||
TypedList<T>::SortItems(CompareFunction function)
|
||||
{
|
||||
ASSERT(sizeof(T) == sizeof(void *));
|
||||
_PointerList::SortItems((GenericCompareFunction)function);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
bool TypedList<T>::ReplaceItem(int32 index, T item)
|
||||
{
|
||||
return _PointerList::ReplaceItem(index, (void *)item);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
bool TypedList<T>::SwapItems(int32 a, int32 b)
|
||||
{
|
||||
return _PointerList::SwapItems(a, b);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
bool TypedList<T>::MoveItem(int32 from, int32 to)
|
||||
{
|
||||
return _PointerList::MoveItem(from, to);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user