home *** CD-ROM | disk | FTP | other *** search
- /**********************************************************
-
- 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 <Be.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <stdarg.h>
- #include <string.h>
-
- #include <AudioSubscriber.h>
-
- //------------------------------------------------------
-
- 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; i<w; /* no inc */ )
- {
- item = (SBufferItem *)app->mBufferList.ItemAt(nbuf);
- if (item && item->data)
- {
- register ULONG j;
- register SHORT *ptr = (SHORT *)item->data;
- if (mRightChannel) ptr++;
- for(j=0; j<2048 && i<w; j+=32, ptr+=32, i++)
- {
- register LONG a;
- a = ptr[ 0];
- a += ptr[ 2];
- a += ptr[ 4];
- a += ptr[ 6];
- a += ptr[ 8];
- a += ptr[10];
- a += ptr[12];
- a += ptr[14];
- a += ptr[16];
- a += ptr[18];
- a += ptr[20];
- a += ptr[22];
- a += ptr[24];
- a += ptr[26];
- a += ptr[28];
- a += ptr[30];
- *(val++) = haut*a; // division par 16 dans 'haut'
- }
- }
- else break;
- nbuf++;
- }
-
- app->mBufferLock.Unlock();
-
- // first erase old chart
- SetHighColor(backgroundColor);
- FillRect(r);
-
- // second draw new chart
- if (w>0)
- {
- BeginLineArray(w);
- //for(i=0; i<w; i++)
- // AddLine(BPoint(i,mid), BPoint(i,mid-mValue[i]), liveColor);
- register ULONG mid=h/2;
- register ULONG end=w-1;
- register ULONG i2=1;
- register USHORT a=mid-mValue[0];
- for(i=0;i<end;i++,i2++)
- AddLine(BPoint(i,a), BPoint(i2,(a=mid-mValue[i2])), liveColor);
- }
- EndLineArray();
- Sync();
-
- Window()->Unlock();
- }
-
-
- //**********************************************************
- 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;i<n;i++)
- {
- CFileItem *item2 = (CFileItem *)mFileList.ItemAt(i);
- if (item2
- && item2->mDisplayName
- && 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; i<n; i++)
- {
- error = dir->GetFile(i, file);
- if (error == B_NO_ERROR) addFileToList(file->Record()->Ref());
- }
-
- // then load every sub directory
- n = dir->CountDirectories();
- for(i=0; i<n; i++)
- {
- error = dir->GetDirectory(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();
- }
-
- //------------------------------------------------------
-