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