/********************************************************** Project: ralf_tracker -------- ------------ Version : 0.3a (alpha) 9 April 96 for BeOS 1.1d7 Sample wrapper around the Marc Espie's "tracker 3.19". Please feel free to reuse that code, as either a sample code for programing onto the BeBox or to add a more robust interface with nice features. Once I get another version of "tracker" from Marc Espie which uses something else that K&R formating, I will suppress the tracker_lib.so. This library is here because I can't mix C K&R code and C++ code in the same project with CodeWarior. There is no copyright on this code. You can modify it, destroy it, reuse it or simply trash it. If you reuse it, please mention my name somewhere. If you did something beautifull, please send me a copy. I'd like to see "be-demos" like there was "amiga-demos". Raphael MOLL, moll@linux.utc.fr Disclaimer : there is no link between this code and my work at MIPSYS, France. ***********************************************************/ //#include #include #include #include #include #include //------------------------------------------------------ char *strdup(const char *s); extern "C" { void setup_play_track(long freq, int stereo); void close_play_track(void); void play_track(char *filename); extern void (*gBeAudioPlayBuffer)(unsigned char *buffer, long length); extern int gBeAudioNextModule; extern int gBeAudioQuitModule; // these functions and flags should not be used any more (obsolete) int tracker_main(int _argc, char **_argv); extern long gBeAudioBufSize; extern void (*gBeAudioExit)(void); extern int gBeAudioNextModule; extern int gBeAudioQuitModule; } //------------------------------------------------------ #define BOOL unsigned char #define ULONG unsigned long #define LONG signed long #define UBYTE unsigned char #define USHORT unsigned short int #define SHORT signed short int #define DOUBLE double #define K_BACKGROUND_GRAY 220,220,220 //#define K_BACKGROUND_GRAY 144,144,144 #define K_ELECTRO_GRAY 88,88,88 #define K_ELECTRO_GREEN 0,153,0 #define K_MSG_PLAY 'Play' #define K_MSG_STOP 'Stop' #define K_MSG_NEXT 'Next' #define K_MSG_QUIT 'Quit' #define K_MSG_LOAD 'Load' #define K_MSG_SAVE 'Save' #define K_MSG_RAND 'Rand' #define K_MSG_ALFA 'Alfa' #define K_MSG_ABOUT 'Abot' //------------------------------------------------------ // debug stuff FILE *gDevSerial4 = NULL; void dprintf(char *format, ...); #undef K_ENABLE_LOG #define OPEN_LOG() gDevSerial4=fopen("/dev/serial4", "wt"); #define CLOSE_LOG() if(gDevSerial4) fclose(gDevSerial4); //------------------------------------------------------ //**************** struct SBufferItem //**************** { UBYTE *data; long length; }; //**************** class CFileItem //**************** #pragma mark CFileItem { public: CFileItem(void); ~CFileItem(void); char *mDisplayName; char *mFileName; BOOL mIsPlaying; ULONG mOrder; }; //************************************* class CFileList : public BListView //************************************* #pragma mark CFileList { public: CFileList(BRect frame, char *name, ULONG resizeMode=B_FOLLOW_LEFT|B_FOLLOW_TOP, ULONG flags=B_WILL_DRAW|B_FRAME_EVENTS); ~CFileList(void); bool MessageDropped(BMessage *msg, BPoint point, BPoint offset); }; //**************************** class CBackView : public BView //**************************** #pragma mark CBackView { public: CBackView(BRect frame, const char *name, ULONG resizeMode=B_FOLLOW_LEFT|B_FOLLOW_TOP, ULONG flags=B_WILL_DRAW) :BView(frame,name,resizeMode,flags) {}; ~CBackView(void) {}; void AttachedToWindow(void) {Window()->Lock(); SetViewColor(K_BACKGROUND_GRAY); Window()->Unlock();} }; //********************************* class CElectrogramme : public BView //********************************* #pragma mark CElectrogramme { public: CElectrogramme(BRect frame, const char *name, BOOL rightChannel, ULONG resizeMode=B_FOLLOW_LEFT|B_FOLLOW_TOP, ULONG flags=B_WILL_DRAW|B_PULSE_NEEDED|B_FRAME_EVENTS); ~CElectrogramme(void); void AttachedToWindow(void); void Draw(BRect r); void Pulse(void); void FrameResized(float width, float height); ULONG mAllocWidth; // alloc size of the array SHORT *mValue; BOOL mRightChannel; }; //************************************* class CTrackerWin : public BWindow //************************************* #pragma mark CTrackerWin { public: CTrackerWin(void); void MessageReceived(BMessage *msg); //bool FilterMessageDropped(BMessage *msg, BPoint point, BView **target); bool QuitRequested(void); void setPlayNames(char *displayName, char *fileName); CFileList *mFileList; BScrollView *mFileScroll; BStringView *mDisplayName; BStringView *mFileName; CElectrogramme *mElectroLeft; CElectrogramme *mElectroRight; }; //*********************************** class CTrackerLooper : public BLooper //*********************************** #pragma mark CTrackerLooper { public: CTrackerLooper(long priority); ~CTrackerLooper(void); void MessageReceived(BMessage *msg); BOOL QuitRequested(void); BOOL mIsPlaying; }; //************************************* class CTrackerApp : public BApplication //************************************* #pragma mark CTrackerApp { public: CTrackerApp(ulong sign); ~CTrackerApp(void); //thread_id Run(void); void ReadyToRun(void); void MessageReceived(BMessage *msg); bool QuitRequested(void); void RefsReceived(BMessage *msg); void createAppMenu(void); void uglyAboutBox(void); CTrackerLooper *mTrackerLooper; CTrackerWin *mWindow; BAudioSubscriber *mPlayer; BLocker mBufferLock; BList mBufferList; // a list of SBufferItem ptrs to be played BList mFileList; // a list of CFileItem ptrs to be selected BPopUpMenu *mMainMenu; ULONG mInstantRightVolume, mInstantLeftVolume; void addFileToList(record_ref ref); void addDirectoryToList(record_ref ref); void playList(void); void playNext(void); void stopPlay(void); static long trackerTask(void *data); static void trackerPlayBuffer(UBYTE *buffer, long length); static void trackerFastExit(void); static bool trackerStreamPlay(void *user, char *buffer, long count); }; //-------------------------------------------------------------------------------- #pragma mark - #ifdef __STRDUP_WAS_NOT_DEFINED_IN_BEOS_11DR6_ //************************************* char *strdup(const char *s) //************************************* // these loosy DR6 headers doesn't contains strdup ! { if (!s) return NULL; char *s2 = new char[strlen(s)+1]; strcpy(s2,s); return s2; } #endif /******************************************************************************/ void dprintf(char *format, ...) /******************************************************************************/ { va_list va; if (!gDevSerial4) return; va_start(va, format); vfprintf(gDevSerial4, format, va); va_end(va); } /* of dprintf */ //-------------------------------------------------------------------------------- #pragma mark - //************************ CFileItem::CFileItem(void) //************************ { mDisplayName = NULL; mFileName = NULL; mIsPlaying = FALSE; mOrder = FALSE; } //************************* CFileItem::~CFileItem(void) //************************* { if (mDisplayName) delete mDisplayName; if (mFileName) delete mFileName; } //-------------------------------------------------------------------------------- #pragma mark - //************************************* CFileList::CFileList(BRect frame, char *name, ULONG resizeMode, ULONG flags) :BListView(frame,name,resizeMode,flags) //************************************* { } //************************************* CFileList::~CFileList() //************************************* { } //************************************* bool CFileList::MessageDropped(BMessage *msg, BPoint point, BPoint offset) //************************************* { if (msg->HasRef("refs")) { msg->what = B_REFS_RECEIVED; be_app->RefsReceived(msg); return FALSE; } return TRUE; } //-------------------------------------------------------------------------------- #pragma mark - //******************************** CElectrogramme::CElectrogramme(BRect frame, const char *name, BOOL rightChannel, ULONG resizeMode, ULONG flags) :BView(frame, name, resizeMode, flags|B_PULSE_NEEDED) //******************************** { mRightChannel = rightChannel; mAllocWidth = max(200,frame.Width()); mValue = new SHORT[mAllocWidth]; if (!mValue) mAllocWidth = 0; else memset(mValue, 0, sizeof(SHORT)*mAllocWidth); } //******************************** CElectrogramme::~CElectrogramme(void) //******************************** { if (mValue) delete mValue; mAllocWidth = 0; } //***************************************** void CElectrogramme::AttachedToWindow(void) //***************************************** { if (Window() && Window()->Lock()) { SetViewColor(K_ELECTRO_GRAY); Window()->Unlock(); } } //******************************** void CElectrogramme::Pulse(void) //******************************** { if (Window() && Window()->Lock()) { Draw(Bounds()); Window()->Unlock(); } } //******************************** void CElectrogramme::Draw(BRect r) //******************************** // be sure this is not efficient at all. Ou presque. { register ULONG nbuf; register ULONG w,h; register ULONG i; rgb_color backgroundColor = {K_ELECTRO_GRAY}; rgb_color liveColor = {K_ELECTRO_GREEN}; register CTrackerApp *app = (CTrackerApp *)be_app; register SBufferItem *item; if (!Window() || !Window()->Lock()) return; w = min(Bounds().Width(), mAllocWidth); h = Bounds().Height(); // first eraase the current data buffer memset(mValue, 0, w*sizeof(SHORT)); app->mBufferLock.Lock(); register SHORT *val = mValue; register DOUBLE haut= (DOUBLE)h/2/16.0/32768.0; for(i=0, nbuf=0; imBufferList.ItemAt(nbuf); if (item && item->data) { register ULONG j; register SHORT *ptr = (SHORT *)item->data; if (mRightChannel) ptr++; for(j=0; j<2048 && imBufferLock.Unlock(); // first erase old chart SetHighColor(backgroundColor); FillRect(r); // second draw new chart if (w>0) { BeginLineArray(w); //for(i=0; iUnlock(); } //********************************************************** void CElectrogramme::FrameResized(float width, float height) //********************************************************** { ULONG w=width; if (!Window() || !Window()->Lock()) return; if (w > mAllocWidth) { SHORT *newPtr = new SHORT[w]; if (newPtr) { memset(newPtr, 0, w*sizeof(SHORT)); if (mValue) { memcpy(newPtr, mValue, mAllocWidth*sizeof(SHORT)); delete mValue; } mValue = newPtr; mAllocWidth = w; } } Window()->Unlock(); } //-------------------------------------------------------------------------------- #pragma mark - //******************************** CTrackerWin::CTrackerWin(void) :BWindow(BRect(100,100,100+450,100+230), "R'alf Tracker 0.3a", B_TITLED_WINDOW, B_NOT_RESIZABLE|B_NOT_ZOOMABLE) //******************************** { BButton *button; ULONG x1=5, x2=145, x3=170, x4=445, x5=170, x6=250, x7=255, x8=335, x9=340, x10=390, x11=395, x12=445; ULONG y1=5, y2=225, y3=180, y4=200, y5=205, y6=225; // background CBackView *back = new CBackView(BRect(x1-5,y1-5,x4+5,y2+5), "", B_FOLLOW_ALL, B_WILL_DRAW); if (back) AddChild(back); else return; // things are getting harder... // file scroll list mFileList = new CFileList(BRect(x1,y1, x2,y2), "", B_FOLLOW_LEFT|B_FOLLOW_TOP_BOTTOM); mFileList->SetInvocationMessage(new BMessage(K_MSG_PLAY)); mFileScroll = new BScrollView("fileScroll", mFileList, B_FOLLOW_LEFT|B_FOLLOW_TOP_BOTTOM, 0, FALSE, TRUE); back->AddChild(mFileScroll); // stack of buttons button = new BButton(BRect(x5, y3, x6, y4), "", "Load list", new BMessage(K_MSG_LOAD), B_FOLLOW_BOTTOM); back->AddChild(button); button = new BButton(BRect(x7, y3, x8, y4), "", "Alphabetize", new BMessage(K_MSG_ALFA), B_FOLLOW_BOTTOM); back->AddChild(button); button = new BButton(BRect(x9, y3, x10, y4), "", "Play", new BMessage(K_MSG_PLAY), B_FOLLOW_BOTTOM); back->AddChild(button); button = new BButton(BRect(x11,y3, x12, y4), "", "Stop", new BMessage(K_MSG_STOP), B_FOLLOW_BOTTOM); back->AddChild(button); button = new BButton(BRect(x5, y5, x6, y6), "", "Save list", new BMessage(K_MSG_SAVE), B_FOLLOW_BOTTOM); back->AddChild(button); button = new BButton(BRect(x7, y5, x8, y6), "", "Randomize", new BMessage(K_MSG_RAND), B_FOLLOW_BOTTOM); back->AddChild(button); button = new BButton(BRect(x9, y5, x10, y6), "", "Next", new BMessage(K_MSG_NEXT), B_FOLLOW_BOTTOM); back->AddChild(button); button = new BButton(BRect(x11,y5, x12, y6), "", "Quit", new BMessage(K_MSG_QUIT), B_FOLLOW_BOTTOM); back->AddChild(button); // strings mDisplayName = new BStringView(BRect(x3, 5, x4, 5+13), "", "", B_FOLLOW_LEFT_RIGHT|B_FOLLOW_TOP); mFileName = new BStringView(BRect(x3, 25, x4, 25+13), "", "", B_FOLLOW_LEFT_RIGHT|B_FOLLOW_TOP); back->AddChild(mDisplayName); back->AddChild(mFileName); // elctrogramme mElectroLeft = new CElectrogramme(BRect(x3,45,x4,45+60), "", FALSE, B_FOLLOW_LEFT_RIGHT|B_FOLLOW_TOP); mElectroRight = new CElectrogramme(BRect(x3,110,x4,110+60), "", TRUE, B_FOLLOW_LEFT_RIGHT|B_FOLLOW_TOP); back->AddChild(mElectroLeft); back->AddChild(mElectroRight); SetPulseRate(60); } //******************************** void CTrackerWin::MessageReceived(BMessage *msg) //******************************** { switch(msg->what) { case K_MSG_PLAY: case K_MSG_STOP: case K_MSG_NEXT: case K_MSG_QUIT: case K_MSG_LOAD: case K_MSG_SAVE: case K_MSG_RAND: case K_MSG_ALFA: msg = DetachCurrentMessage(); be_app->PostMessage(msg); break; default: BWindow::MessageReceived(msg); } } //******************************** bool CTrackerWin::QuitRequested(void) //******************************** { be_app->PostMessage(B_QUIT_REQUESTED); return TRUE; } //******************************** void CTrackerWin::setPlayNames(char *display, char *file) //******************************** { Lock(); mDisplayName->SetText(display); mFileName->SetText(file); Unlock(); } //------------------------------------------------------ #pragma mark - //******************************** CTrackerApp::CTrackerApp(ulong sign) : BApplication(sign) //******************************** { mTrackerLooper = NULL; mWindow = NULL; mPlayer = NULL; mInstantRightVolume = NULL; mInstantLeftVolume = NULL; } //******************************** CTrackerApp::~CTrackerApp(void) //******************************** { long i,n; dprintf("deleting audio subscriber\n"); if (mPlayer) delete mPlayer; mPlayer = NULL; dprintf("delete tracker task\n"); if (mTrackerLooper) mTrackerLooper->Quit(); dprintf("Freing buffers..."); mBufferLock.Lock(); n = mBufferList.CountItems(); dprintf("Number of buffers in the list : %d\n", n); for(i = 0; i < n; i++) { SBufferItem *item = (SBufferItem *)mBufferList.ItemAt(i); if (!item) continue; if (item->data) delete item->data; delete item; } mBufferLock.Unlock(); dprintf("End of destructor of CTrackerApp\n"); } //********************************************** void CTrackerApp::MessageReceived(BMessage *msg) //********************************************** { switch(msg->what) { case K_MSG_PLAY: playList(); break; case K_MSG_NEXT: playNext(); case K_MSG_STOP: stopPlay(); break; case K_MSG_LOAD: case K_MSG_SAVE: case K_MSG_RAND: case K_MSG_ALFA: break; case K_MSG_QUIT: gBeAudioNextModule = TRUE; gBeAudioQuitModule = TRUE; PostMessage(B_QUIT_REQUESTED); break; case K_MSG_ABOUT: uglyAboutBox(); break;; default: // dprintf... break; } } //******************************************* void CTrackerApp::RefsReceived(BMessage *msg) //******************************************* { BOOL succeed = FALSE; ULONG type, i; LONG count; record_ref item; if (!msg) return; msg->GetInfo("refs", &type, &count); for(i = 0; i < count; i++) { item = msg->FindRef("refs", i); if (item.database >= 0 && item.record >= 0) if (does_ref_conform(item, "File")) addFileToList(item); else if (does_ref_conform(item, "Folder")) addDirectoryToList(item); } } //******************************** bool CTrackerApp::QuitRequested(void) //******************************** { if (mTrackerLooper) return mTrackerLooper->QuitRequested(); return TRUE; } #ifdef NO_RUN //******************************** thread_id CTrackerApp::Run(void) //******************************** { thread_id retVal = BApplication::Run(); return retVal; } #endif //******************************** void CTrackerApp::ReadyToRun(void) //******************************** { // create the playing thread mTrackerLooper = new CTrackerLooper(B_REAL_TIME_PRIORITY); // create the window mWindow = new CTrackerWin; if (mWindow) mWindow->Show(); createAppMenu(); // create the audio subscriber mPlayer = new BAudioSubscriber("TrackerPlayer"); if (mPlayer) { long error; error = mPlayer->Subscribe(B_DAC_STREAM,B_INVISIBLE_SUBSCRIBER_ID,TRUE); error = mPlayer->SetDACSampleInfo(2, 2, B_BIG_ENDIAN, B_LINEAR_SAMPLES); error = mPlayer->SetSamplingRate(44100); long bufSize, bufCount, subCount; BOOL isRunning; subscriber_id clique; error = mPlayer->GetStreamParameters(&bufSize, &bufCount, &isRunning, &subCount, &clique); error = mPlayer->EnterStream(NULL, FALSE, NULL, trackerStreamPlay, NULL, TRUE); } } //*********************************** void CTrackerApp::createAppMenu(void) //*********************************** { BMenuItem *item; mMainMenu = new BPopUpMenu("", FALSE, FALSE); if (!mMainMenu) return; item = new BMenuItem("About...", new BMessage(K_MSG_ABOUT)); mMainMenu->AddItem(item); mMainMenu->AddSeparatorItem(); item = new BMenuItem("Load list...", new BMessage(K_MSG_LOAD), 'O'); mMainMenu->AddItem(item); item = new BMenuItem("Save list...", new BMessage(K_MSG_SAVE), 'S'); mMainMenu->AddItem(item); item = new BMenuItem("Alphabetize", new BMessage(K_MSG_ALFA), 'A'); mMainMenu->AddItem(item); item = new BMenuItem("Randomize", new BMessage(K_MSG_RAND), 'R'); mMainMenu->AddItem(item); mMainMenu->AddSeparatorItem(); item = new BMenuItem("Play", new BMessage(K_MSG_PLAY), 'P'); mMainMenu->AddItem(item); item = new BMenuItem("Next", new BMessage(K_MSG_NEXT), 'N'); mMainMenu->AddItem(item); item = new BMenuItem("Stop", new BMessage(K_MSG_STOP), 'S'); mMainMenu->AddItem(item); mMainMenu->AddSeparatorItem(); item = new BMenuItem("Quit", new BMessage(K_MSG_QUIT), 'Q'); mMainMenu->AddItem(item); SetMainMenu(mMainMenu); } //*********************************** void CTrackerApp::uglyAboutBox(void) //*********************************** { BAlert *about; about = new BAlert( "R'alf Tracker", "R'alf Tracker 0.3alpha\n\n" "A simple interface wrapped around Marc Espie's tracker player 3.19.\n\n" "Freeware by Raphael MOLL (moll@linux.utc.fr)", "OK"); if (about) about->Go(); } // end of uglyAboutBox //------------------------------------------------------ #pragma mark - //******************************** void CTrackerApp::addFileToList(record_ref ref) //******************************** { if (does_ref_conform(ref, "Folder")) { addDirectoryToList(ref); return; } if (!mWindow || !mWindow->mFileList) return; // and why does CodeWarior 8 refuses to call _register_auto_objects here ? // this is the brute force answer ! BFile *file = new BFile; BDirectory *dir = new BDirectory; BDirectory *dir2 = new BDirectory; if (!file || !dir || !dir2) return; // create the file instance... file->SetRef(ref); // create a new file item for the list CFileItem *item = new CFileItem(); if (!item) return; // critical. Should not occur. // extract the name to be displayed item->mDisplayName = new char[256]; file->GetName(item->mDisplayName); // check if that name already exists in the list... ULONG i,n; n = mFileList.CountItems(); for(i=0;imDisplayName && strcmp(item2->mDisplayName, item->mDisplayName) == 0) { // then remove the old item mFileList.RemoveItem(item2); mWindow->mFileList->RemoveItem(item2->mDisplayName); delete item2; } } // extract the directory path LONG error; char s1[512]=""; char s2[512]=""; file->GetName(s2); error = file->GetParent(dir); while(error == B_NO_ERROR) { dir->GetName(s1); if (strlen(s2)) { strcat(s1, "/"); strcat(s1, s2); } strcpy(s2, s1); error = dir->GetParent(dir2); if (error == B_NO_ERROR) dir->SetRef(dir2->Record()->Ref()); } strcpy(s1, "/"); strcat(s1, s2); strcpy(s2, s1); item->mFileName = strdup(s2); mFileList.AddItem(item); // add the item to the list of the app mWindow->mFileList->AddItem(item->mDisplayName); // add the name to be displayed mWindow->mFileList->Select(mWindow->mFileList->CountItems()-1); delete file; delete dir; delete dir2; } //******************************** void CTrackerApp::addDirectoryToList(record_ref ref) //******************************** { if (does_ref_conform(ref, "File")) { addFileToList(ref); return; } // and why does CodeWarior 8 refuses to call _register_auto_objects here ? BFile *file = new BFile; BDirectory *dir = new BDirectory; BDirectory *dir2 = new BDirectory; long i,n; long error; if (!file || !dir || !dir2) return; dir->SetRef(ref); // first load every file n = dir->CountFiles(); for(i=0; iGetFile(i, file); if (error == B_NO_ERROR) addFileToList(file->Record()->Ref()); } // then load every sub directory n = dir->CountDirectories(); for(i=0; iGetDirectory(i, dir2); if (error == B_NO_ERROR) addDirectoryToList(dir2->Record()->Ref()); } delete file; delete dir; delete dir2; } //------------------------------------------------------ #pragma mark - //******************************** void CTrackerApp::playList(void) //******************************** { ULONG index = mWindow->mFileList->CurrentSelection(); CFileItem *item; stopPlay(); item = (CFileItem *)mFileList.ItemAt(index); if (item && item->mFileName && item->mDisplayName) { BMessage *msg = new BMessage(K_MSG_PLAY); msg->AddString("filename", item->mFileName); msg->AddString("displayname", item->mDisplayName); mTrackerLooper->PostMessage(msg); } } //******************************** void CTrackerApp::playNext(void) //******************************** { ULONG index; index = mWindow->mFileList->CurrentSelection()+1; if (index >= mWindow->mFileList->CountItems()) index = 0; mWindow->mFileList->Select(index); playList(); } //******************************** void CTrackerApp::stopPlay(void) //******************************** { if (mTrackerLooper->mIsPlaying) { gBeAudioNextModule = TRUE; gBeAudioQuitModule = TRUE; } } //------------------------------------------------------ #pragma mark - //******************************** void CTrackerApp::trackerFastExit(void) //******************************** { dprintf("Fast exit from Tracker Task requested\n"); be_app->PostMessage(B_QUIT_REQUESTED); } //******************************** void CTrackerApp::trackerPlayBuffer(UBYTE *buffer, long length) //******************************** { CTrackerApp *app = (CTrackerApp *)be_app; SBufferItem *item; long n; //dprintf("play buffer : length %8d, ptr %p\n", length, buffer); item = new SBufferItem; if (!item) return; // can't alloc item item->data = new UBYTE[length]; item->length = length; memcpy(item->data, buffer, length); app->mBufferLock.Lock(); app->mBufferList.AddItem(item); n = app->mBufferList.CountItems(); app->mBufferLock.Unlock(); // each buffer of 4096 bytes takes approximately 23 ms to play. // if we have more than 50 buffer, give enougth time to suppress 30 buffers // from the list. if (n > 50) snooze(23000*30); } //******************************** bool CTrackerApp::trackerStreamPlay(void *user, char *buffer, long count) //******************************** { CTrackerApp *app = (CTrackerApp *)be_app; SBufferItem *item; long n; app->mBufferLock.Lock(); item = (SBufferItem *)app->mBufferList.RemoveItem(0L); n = app->mBufferList.CountItems(); app->mBufferLock.Unlock(); if (item) { if (item->data) { //dprintf("buffer %08p, count %6d, data %08p, length %6d, items %d\n", buffer, count,item->data, item->length,n); memcpy(buffer, item->data, min(count, item->length)); delete item->data; } delete item; } return TRUE; } //------------------------------------------------------ #pragma mark - //******************************************* CTrackerLooper::CTrackerLooper(long priority) :BLooper("player", priority) //******************************************* { dprintf("Tracker Task launched\n"); gBeAudioBufSize = 4096; gBeAudioPlayBuffer = CTrackerApp::trackerPlayBuffer; gBeAudioExit = CTrackerApp::trackerFastExit; mIsPlaying = FALSE; setup_play_track(FALSE, TRUE); Run(); // launch the thread and run separately... } //*********************************** CTrackerLooper::~CTrackerLooper(void) //*********************************** { gBeAudioNextModule = TRUE; gBeAudioQuitModule = TRUE; mIsPlaying = FALSE; close_play_track(); } //************************************** BOOL CTrackerLooper::QuitRequested(void) //************************************** { gBeAudioNextModule = TRUE; gBeAudioQuitModule = TRUE; mIsPlaying = FALSE; return TRUE; } //************************************************* void CTrackerLooper::MessageReceived(BMessage *msg) //************************************************* { if (msg && !mIsPlaying) { CTrackerApp *app = (CTrackerApp *)be_app; mIsPlaying = TRUE; gBeAudioNextModule = FALSE; gBeAudioQuitModule = FALSE; char displayname[256] = "Playing "; strcat(displayname, (char *)msg->FindString("displayname")); char *filename = (char *)msg->FindString("filename"); app->mWindow->setPlayNames(displayname, filename); play_track(filename); app->mWindow->setPlayNames("Stopped", ""); mIsPlaying = FALSE; if (!gBeAudioQuitModule) app->PostMessage(K_MSG_NEXT); } } //------------------------------------------------------ #pragma mark - //****************************** void main(int argc, char **argv) //****************************** { #ifdef K_ENABLE_LOG OPEN_LOG(); #endif CTrackerApp *theApp; theApp = new CTrackerApp('Trak'); if (!theApp) return; theApp->Run(); delete theApp; CLOSE_LOG(); } //------------------------------------------------------