1 /*
2 TiMidity++ -- MIDI to WAVE converter and player
3 Copyright (C) 1999-2002 Masanao Izumo <mo@goice.co.jp>
4 Copyright (C) 1995 Tuukka Toivonen <tt@cgs.fi>
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
20 Macintosh interface for TiMidity
21 by T.Nogami <t-nogami@happy.email.ne.jp>
22
23 mac_main.c
24 */
25
26 #ifdef HAVE_CONFIG_H
27 #include "config.h"
28 #endif /* HAVE_CONFIG_H */
29 #include <Sound.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <Threads.h>
34
35 #include "timidity.h"
36 #include "common.h"
37 #include "instrum.h"
38 #include "playmidi.h"
39 #include "readmidi.h"
40 #include "output.h"
41 #include "controls.h"
42 #include "tables.h"
43 #include "wrd.h"
44 #ifdef SUPPORT_SOUNDSPEC
45 #include "soundspec.h"
46 #endif /* SUPPORT_SOUNDSPEC */
47 #include "recache.h"
48 #include "miditrace.h"
49 #include "aq.h"
50
51 #include "mac_main.h"
52 #include "mac_c.h"
53 #include "mac_util.h"
54
55 #ifdef MAC_USE_OMS
56 #include "OMS.h"
57 #include "mac_oms.h"
58 #endif
59
60 #define MAIN_INTERFACE /* non-static */
61 MAIN_INTERFACE void timidity_start_initialize(void);
62 MAIN_INTERFACE int timidity_pre_load_configuration(void);
63 MAIN_INTERFACE int timidity_post_load_configuration(void);
64 MAIN_INTERFACE void timidity_init_player(void);
65 MAIN_INTERFACE int timidity_play_main(int nfiles, char **files);
66 MAIN_INTERFACE void timidity_init_aq_buff(void);
67
68 extern char *wrdt_open_opts;
69
70 Boolean skin_f_repeat, gQuit, gBusy, gShuffle;
71 int mac_rc, skin_state=WAITING, mac_n_files, nPlaying;
72 long gStartTick;
73 double gSilentSec;
74 MidiFile fileList[LISTSIZE];
75 int evil_level;
76 int do_initial_filling;
77
78 #ifdef __MRC__
79 QDGlobals qd;
80 #endif
81
82 /*****************************************/
83
84 /* ************************************************** */
85
myHandleOAPP(AppleEvent *,AppleEvent *,long)86 static pascal OSErr myHandleOAPP(AppleEvent* /*theAppleEvent*/, AppleEvent* /*reply*/, long /*handlerRefCon*/)
87 {
88 return noErr;
89 }
90
myHandleODOC(AppleEvent * theAppleEvent,AppleEvent *,long)91 static pascal OSErr myHandleODOC(AppleEvent *theAppleEvent, AppleEvent* /*reply*/, long /*handlerRefCon*/)
92 {
93 int oldListEnd;
94 AEDescList docList;
95 AEKeyword keyword;
96 DescType returnedType;
97 FSSpec theFSSpec;
98 Size actualSize;
99 long itemsInList;
100 short index;
101 OSErr err;
102 KeyMap keys;
103
104 GetKeys(keys);
105 if( keys[1] & 0x00000004 )
106 if( mac_SetPlayOption()!=noErr ) return noErr; /* user cancel*/
107
108 if ( (err=AEGetParamDesc(theAppleEvent, keyDirectObject, typeAEList, &docList))!=0 )
109 return(err);
110
111 if ( (err=AECountItems(&docList, &itemsInList))!=0 )
112 return(err);
113
114 oldListEnd=mac_n_files;
115 for (index = 1; index <= itemsInList; index++) {
116 if ( (err=AEGetNthPtr(&docList, index, typeFSS, &keyword,
117 &returnedType, (Ptr) &theFSSpec, sizeof(FSSpec), &actualSize))!=0 )
118 return(err);
119 mac_add_fsspec(&theFSSpec);
120 //if( isArchiveFile(&theFSSpec) ){
121 // mac_add_archive_file(&theFSSpec);
122 //}else {
123 // mac_add_midi_file(&theFSSpec);
124 //}
125 }
126
127 if( gShuffle ) ShuffleList( oldListEnd, mac_n_files);
128 return noErr;
129 }
130
myHandleQUIT(AppleEvent *,AppleEvent *,long)131 static pascal OSErr myHandleQUIT(AppleEvent* /*theEvent*/, AppleEvent* /*reply*/, long /*refCon*/)
132 {
133 gQuit=true;
134 return noErr; /* don't ExitToShell() here, must return noErr */
135 }
136 /*******************************************************/
137
InitMenuBar()138 static void InitMenuBar()
139 {
140 MenuHandle synth;
141
142 SetMenuBar(GetNewMBar(128));
143 AppendResMenu(GetMenu(128),'DRVR');
144
145 synth= GetMenu(mSynth);
146 InsertMenu(synth, -1); //setup submenu
147 CheckItem(synth, iTiMidity & 0x0000FFFF, 1);
148
149 DrawMenuBar();
150 }
151
mac_init()152 static void mac_init()
153 {
154 long gestaltResponse;
155
156 InitGraf( &qd.thePort );
157 InitFonts();
158 FlushEvents( everyEvent,0 );
159 InitWindows();
160 InitMenus();
161 TEInit();
162 InitDialogs( 0 );
163 InitCursor();
164 MaxApplZone();
165 ReadDateTime( (unsigned long*)&qd.randSeed );
166
167 if( !((Gestalt(gestaltSystemVersion, &gestaltResponse)==noErr )
168 && gestaltResponse>=0x0750))
169 mac_ErrorExit("\pThis program can run on System 7.5 or later!");
170
171 if ((Gestalt(gestaltDragMgrAttr, &gestaltResponse) == noErr)
172 && (gestaltResponse & (1 << gestaltDragMgrPresent)))
173 gHasDragMgr=true;
174 else gHasDragMgr=false;
175
176 #if (__MC68K__ && __MC68881__)
177 if (!((Gestalt(gestaltFPUType, &gestaltResponse) == noErr)
178 && (gestaltResponse!=gestaltNoFPU )))
179 mac_ErrorExit("\pSorry, No FPU.");
180 #endif
181
182 AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
183 NewAEEventHandlerProc(myHandleOAPP), 0, false);
184 AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
185 NewAEEventHandlerProc(myHandleODOC), 0, false);
186 AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
187 NewAEEventHandlerProc(myHandleQUIT), 0, false);
188 InitMenuBar();
189 }
190
191 extern char *opt_aq_max_buff,*opt_aq_fill_buff;
main()192 int main()
193 {
194 int32 output_rate=DEFAULT_RATE;
195 int err;
196
197 mac_init();
198
199 nPlaying=mac_n_files=0; skin_state=WAITING;
200
201 mac_DefaultOption();
202 mac_GetPreference();
203
204 #ifdef MAC_INITIAL_FILLING
205 if(!opt_aq_max_buff)
206 opt_aq_max_buff = safe_strdup("0.0");
207 if(!opt_aq_fill_buff)
208 opt_aq_fill_buff = safe_strdup("100%");
209 #endif
210
211 timidity_start_initialize();
212 if((err = timidity_pre_load_configuration()) != 0)
213 return err;
214 err += timidity_post_load_configuration();
215 if( err )
216 {
217 //ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
218 // "Try %s -h for help", program_name);
219 return 1; /* problems with command line */
220 }
221
222 timidity_init_player();
223 wrdt=wrdt_list[0]; //dirty!!
224 wrdt_open_opts= "m";
225 timidity_play_main(0, NULL);
226 //CPU won't return from timidity_play_main
227 return 0;
228 }
229
StartPlay(void * threadParam)230 static pascal void *StartPlay(void *threadParam)
231 {
232 int rc;
233
234 //for( i=0; i<nfiles; i++)
235 {
236 skin_state=PLAYING; gBusy=true; DrawButton();
237 gCursorIsWatch=true; SetCursor(*GetCursor(watchCursor));
238 DisableItem(GetMenu(mFile), iSaveAs & 0x0000FFFF);
239 DisableItem(GetMenu(mFile), iPref & 0x0000FFFF);
240 rc=play_midi_file( fileList[nPlaying].filename );
241 gStartTick=0;
242 gBusy=true;
243 //theCmd.cmd=waitCmd;
244 //theCmd.param1=2000*gSilentSec;
245 //SndDoCommand(gSndCannel, &theCmd, 1);
246 EnableItem(GetMenu(mFile), iSaveAs & 0x0000FFFF);
247 EnableItem(GetMenu(mFile), iPref & 0x0000FFFF);
248 skin_state=(rc==RC_QUIT? STOP:WAITING);
249
250 if( rc==RC_REALLY_PREVIOUS && nPlaying>0)
251 nPlaying--;
252 else if(rc==RC_RESTART) /*noting*/;
253 else if(rc==RC_QUIT) /*noting*/;
254 else if(rc==RC_LOAD_FILE) /*noting*/;
255 else if(rc==RC_NEXT) nPlaying++;
256 else if(!skin_f_repeat) nPlaying++;
257 }
258 DrawButton();
259 if( gCursorIsWatch ){
260 InitCursor(); gCursorIsWatch=false;
261 }
262 return 0;
263 }
264
HandleNullEvent()265 static void HandleNullEvent()
266 {
267 YieldToAnyThread();
268 if( Button() ){DoVolume();}
269 if( skin_state==WAITING && mac_rc==RC_PREVIOUS && nPlaying>0)
270 {nPlaying--; mac_rc=0; }
271 if( skin_state==WAITING && nPlaying<mac_n_files )
272 {
273 NewThread(kCooperativeThread, StartPlay,
274 0, 0, kCreateIfNeeded, 0, 0);
275 }
276
277 #ifdef MAC_USE_OMS
278 mac_oms_doevent();
279 #endif
280 }
281
mac_HandleEvent(EventRecord * event)282 void mac_HandleEvent(EventRecord *event)
283 {
284 switch(event->what)
285 {
286 case nullEvent:
287 HandleNullEvent();
288 break;
289 case mouseDown:
290 HandleMouseDown(event);
291 break;
292 case keyDown:
293 if( event->modifiers&cmdKey )
294 {
295 mac_HandleMenuSelect(MenuKey(event->message&charCodeMask), event->modifiers);
296 HiliteMenu(0);
297 break;
298 }else{ //no command key
299 HandleSpecKeydownEvent( event->message, event->modifiers);
300 }
301 break;
302 case updateEvt:
303 BeginUpdate((WindowRef)event->message);
304 DoUpdate((WindowRef)event->message);
305 EndUpdate((WindowRef)event->message);
306 break;
307 case kHighLevelEvent:
308 AEProcessAppleEvent(event);
309 break;
310 default:
311 break;
312 }
313
314 }
315
mac_HandleControl()316 void mac_HandleControl()
317 {
318 SndCommand theCmd;
319
320 switch(mac_rc)
321 {
322 case RC_QUIT:
323 if( skin_state==PAUSE )
324 {
325 play_mode->acntl(PM_REQ_DISCARD,0);
326 theCmd.cmd=resumeCmd; SndDoImmediate(gSndCannel, &theCmd);
327 skin_state=PLAYING;
328 }
329 break;/*and wait ctl_read*/
330 case RC_NEXT:
331 if( skin_state==STOP )
332 { skin_state=WAITING; mac_rc=0; if( nPlaying<mac_n_files ) nPlaying++; }
333 else if( skin_state==WAITING )
334 { skin_state=WAITING; mac_rc=0; if( nPlaying<mac_n_files ) nPlaying++; }
335 else if( skin_state==PAUSE )
336 { mac_rc=RC_CONTINUE; mac_HandleControl(); mac_rc=RC_NEXT;}
337 break;
338 case RC_PREVIOUS:
339 if( skin_state==PAUSE ){ mac_rc=RC_CONTINUE; mac_HandleControl(); mac_rc=RC_PREVIOUS;}
340 else if( skin_state==STOP ) {skin_state=WAITING; if( nPlaying>0 ) nPlaying--; mac_rc=0; }
341 else if( skin_state==WAITING && nPlaying>0)
342 {nPlaying--; mac_rc=0; }
343 break; /*and wait ctl_read*/
344 case RC_FORWARD:
345 if( skin_state==STOP ){ skin_state=WAITING; mac_rc=0; }
346 else if( skin_state==PAUSE ){ mac_rc=RC_CONTINUE; mac_HandleControl(); }
347 break; /*and wait ctl_read*/
348 case RC_TOGGLE_PAUSE:
349 if( skin_state==PAUSE ){ theCmd.cmd=resumeCmd; SndDoImmediate(gSndCannel, &theCmd); skin_state=PLAYING;}
350 else if( skin_state==PLAYING ){theCmd.cmd=pauseCmd; SndDoImmediate(gSndCannel, &theCmd); skin_state=PAUSE;}
351 break;
352 case RC_RESTART:
353 break; /*and wait ctl_read*/
354 case RC_LOAD_FILE:
355 if( skin_state==PAUSE )
356 { mac_rc=RC_CONTINUE; mac_HandleControl(); mac_rc=RC_LOAD_FILE;}
357 skin_state=WAITING;
358 break;
359 /*case RC_PAUSE:
360 if( skin_state==PLAYING ){theCmd.cmd=pauseCmd; SndDoImmediate(gSndCannel, &theCmd); skin_state=PAUSE;}
361 break;*/
362 /*case RC_CONTINUE:
363 if( skin_state==PAUSE ){ theCmd.cmd=resumeCmd; SndDoImmediate(gSndCannel, &theCmd); skin_state=PLAYING;}
364 else if( skin_state==STOP ){ skin_state=WAITING; mac_rc=0; }
365 break;*/
366 case RC_REALLY_PREVIOUS:
367 break; /*and wait ctl_read*/
368 }
369 DrawButton();
370 }
371
372
373 /*******************************************/
374 #pragma mark -
375
376 extern PlayMode wave_play_mode;
377 extern PlayMode aiff_play_mode;
378 extern PlayMode mac_play_mode;
379 extern PlayMode mac_quicktime_play_mode;
380 extern PlayMode mac_oms_play_mode;
381
ConvertToAiffFile(void * threadParam)382 static pascal void *ConvertToAiffFile(void *threadParam)
383 {
384 OSErr err;
385 int tmp;
386 char newfile[256];
387 StandardFileReply stdReply;
388 Str255 fullPath;
389
390 #ifdef __MWERKS__
391 _fcreator='TVOD'; //Movie Player
392 _ftype='AIFF';
393 #endif
394 StandardGetFile(0, 0, 0, &stdReply);
395 if (stdReply.sfGood)
396 {
397 play_mode=&aiff_play_mode;
398 if( play_mode->open_output()==-1 ) return 0;
399 aq_setup();
400 tmp=skin_state;
401 skin_state=PLAYING;
402 err=GetFullPath( &stdReply.sfFile, fullPath);
403 if( err==noErr )
404 play_midi_file( p2cstr(fullPath) );
405 skin_state=tmp;
406 play_mode->close_output();
407 play_mode=&mac_play_mode;
408 aq_setup();
409 timidity_init_aq_buff();
410 p2cstrcpy(newfile, stdReply.sfFile.name); strcat(newfile,".aiff");
411 rename("output.aiff", newfile);
412 }
413 DrawButton();
414 return 0;
415 }
416
mac_AboutBox()417 static void mac_AboutBox()
418 {
419 short item;
420 DialogRef dialog, theDialog;
421 EventRecord event;
422
423 dialog=GetNewDialog(200,0,(WindowRef)-1);
424 if( dialog==0 ) return;
425 SetDialogDefaultItem(dialog, 1);
426
427 #ifdef __POWERPC__
428 #define TIMID_CPU "PPC"
429 #elif __MC68K__
430 #if __MC68881__
431 #define TIMID_CPU "68k+FPU"
432 #else
433 #define TIMID_CPU "68k"
434 #endif
435 #endif
436
437 ParamText("\p" TIMID_VERSION TIMID_CPU, "\p", "\p", "\p");
438
439 ShowWindow(dialog);
440 for(;;){
441 WaitNextEvent(everyEvent, &event, 10, 0);
442 if( ! IsDialogEvent(&event) ) continue;
443 if( StdFilterProc(dialog, &event, &item) ) /**/;
444 else DialogSelect(&event, &theDialog, &item);
445 if( theDialog!=dialog ) continue;
446 if( item==1 ) break;
447 YieldToAnyThread();
448 }
449 DisposeDialog(dialog);
450 }
451
CloseFrontWindow()452 static void CloseFrontWindow()
453 {
454 WindowRef window;
455 MacWindow *macwin;
456
457 window=FrontWindow();
458 if( ! window ) return;
459 macwin= (MacWindow*)GetWRefCon(window);
460 if( ! macwin ) return;
461 macwin->goaway(macwin);
462 }
463
mac_HandleMenuSelect(long select,short modifiers)464 void mac_HandleMenuSelect(long select, short modifiers)
465 {
466 StandardFileReply stdReply;
467 Str255 str;
468
469 switch(select)
470 {
471 case iAbout:
472 mac_AboutBox();
473 return;
474 case iOpen:
475 StandardGetFile(0, -1, 0, &stdReply);
476 if (stdReply.sfGood)
477 {
478 mac_add_fsspec(&stdReply.sfFile);
479 }
480 return;
481 case iClose:
482 CloseFrontWindow();
483 return;
484
485 case iLogWindow: SHOW_WINDOW(mac_LogWindow); return;
486 case iListWindow: SHOW_WINDOW(mac_ListWindow); return;
487 case iWrdWindow: SHOW_WINDOW(mac_WrdWindow); return;
488 case iDocWindow: SHOW_WINDOW(mac_DocWindow); return;
489 case iSpecWindow:
490 #ifdef SUPPORT_SOUNDSPEC
491 if(!mac_SpecWindow.show)
492 {
493 mac_SpecWindow.show=true;
494 open_soundspec();
495 soundspec_update_wave(NULL, 0);
496 }
497 SelectWindow(mac_SpecWindow.ref);
498 #endif /* SUPPORT_SOUNDSPEC */
499 return;
500 case iTraceWindow: SHOW_WINDOW(mac_TraceWindow); return;
501 case iSkinWindow: SHOW_WINDOW(mac_SkinWindow); return;
502 case iSaveAs:
503 NewThread(kCooperativeThread, ConvertToAiffFile,
504 0, 0, kCreateIfNeeded, 0, 0);
505 return;
506
507 case iPref: mac_SetPlayOption(); return;
508 case iQuit: Do_Quit(); return;
509
510 //Play menu
511 case iPlay: SKIN_ACTION_PLAY(); break;
512 case iStop: SKIN_ACTION_STOP(); break;
513 case iPause: SKIN_ACTION_PAUSE(); break;
514 case iPrev: SKIN_ACTION_PREV(); break;
515 case iNext: SKIN_ACTION_NEXT(); break;
516
517 //Synth menu
518 case iTiMidity:{
519 MenuHandle menu=GetMenu(mSynth);
520 CheckItem(menu, iTiMidity & 0x0000FFFF, 1);
521 CheckItem(menu, iQuickTime & 0x0000FFFF, 0);
522 CheckItem(menu, iOMS & 0x0000FFFF, 0);
523 play_mode=&mac_play_mode;
524 }
525 return;
526 case iQuickTime:{
527 MenuHandle menu=GetMenu(mSynth);
528
529 if( mac_quicktime_play_mode.fd==-1 ){ //not opened yet
530 if( mac_quicktime_play_mode.open_output()!=0 ){
531 SysBeep(0);
532 return; //can't open device
533 }
534 }
535 CheckItem(menu, iTiMidity & 0x0000FFFF, 0);
536 CheckItem(menu, iQuickTime & 0x0000FFFF, 1);
537 CheckItem(menu, iOMS & 0x0000FFFF, 0);
538 play_mode=&mac_quicktime_play_mode;
539 }
540 return;
541 #ifdef MAC_USE_OMS
542 case iOMS:{
543 MenuHandle menu=GetMenu(mSynth);
544
545 if( mac_oms_play_mode.fd==-1 || (modifiers & optionKey) ){
546 if( mac_oms_play_mode.open_output()!=0 ){
547 SysBeep(0);
548 return; //can't open device
549 }
550 }
551 CheckItem(menu, iTiMidity & 0x0000FFFF, 0);
552 CheckItem(menu, iQuickTime & 0x0000FFFF, 0);
553 CheckItem(menu, iOMS & 0x0000FFFF, 1);
554 play_mode=&mac_oms_play_mode;
555 }
556 return;
557 #endif
558 }
559
560 if( (select>>16)==mApple )
561 {
562 GetMenuItemText(GetMenu(mApple), select&0x0000FFFF, str);
563 OpenDeskAcc(str);
564 }
565 }
566
Do_Quit()567 void Do_Quit()
568 {
569 if( mac_play_mode.fd!=-1 )
570 mac_play_mode.close_output();
571 if( mac_quicktime_play_mode.fd!=-1 )
572 mac_quicktime_play_mode.close_output();
573 #ifdef MAC_USE_OMS
574 if( mac_oms_play_mode.fd!=-1 )
575 mac_oms_play_mode.close_output();
576 #endif
577 if( ctl )
578 ctl->close();
579
580 mac_SetPreference();
581
582 #ifdef MAC_USE_OMS
583 mac_oms_quit();
584 #endif
585
586 ExitToShell();
587 }
588
mac_ErrorExit(Str255 s)589 void mac_ErrorExit(Str255 s)
590 {
591 StopAlertMessage(s);
592 SndDisposeChannel(gSndCannel, 1); gSndCannel=0;
593 ExitToShell();
594 }
595
596 /* ****************************** */
597 #pragma mark -
598
ShuffleList(int start,int end)599 void ShuffleList(int start, int end)
600 {
601 int i, newFile;
602 MidiFile tmpItem;
603
604 for( i=start; i<end; i++){ /*Shuffle target is start..end-1*/
605 newFile= i+(end-i-1)*((32767+Random())/65535.0);
606 /*Random() returns between -32767 to 32767*/
607 tmpItem=fileList[newFile]; /*Swapping*/
608 fileList[newFile]=fileList[i];
609 fileList[i]=tmpItem;
610 //update list window
611 change_ListRow( i, &fileList[i]);
612 }
613 }
614
isMidiFilename(const char * fn)615 static int isMidiFilename(const char *fn)
616 {
617 char *p;
618
619 p= strrchr(fn, '.'); if( p==0 ) return 0;
620 if( strcasecmp(p, ".mid")==0 ||
621 strcasecmp(p, ".rcp")==0 ||
622 strcasecmp(p, ".r36")==0 ||
623 strcasecmp(p, ".g18")==0 ||
624 strcasecmp(p, ".g36")==0 ||
625 strcasecmp(p, ".kar")==0 ||
626 strcasecmp(p, ".mod")==0 ||
627 strcasecmp(p, ".gz")==0
628 ){
629 return 1;
630 }else{
631 return 0;
632 }
633 }
634
isArchiveFilename(const char * fn)635 static int isArchiveFilename(const char *fn)
636 {
637 char *p;
638
639 p= strrchr(fn, '.'); if( p==0 ) return 0;
640 if( strcasecmp(p, ".lzh")==0 ||
641 strcasecmp(p, ".zip")==0 ||
642 strcasecmp(p, ".tar")==0 ||
643 strcasecmp(p, ".gz")==0
644 ){
645 return 1;
646 }else{
647 return 0;
648 }
649 }
650
isBMPFilename(const char * fn)651 static int isBMPFilename(const char *fn)
652 {
653 char *p;
654
655 p= strrchr(fn, '.'); if( p==0 ) return 0;
656 if( strcasecmp(p, ".BMP")==0 ){
657 return 1;
658 }else{
659 return 0;
660 }
661 }
662
AddFolderFSSpec2PlayList(const FSSpec * spec)663 static void AddFolderFSSpec2PlayList(const FSSpec *spec)
664 {
665 CInfoPBRec cipb;
666 Str32 theString;
667 OSErr err = noErr;
668
669 BlockMoveData(spec->name, theString, spec->name[0]+1);
670
671 cipb.hFileInfo.ioCompletion = nil;
672 cipb.hFileInfo.ioFDirIndex = 0; /* this mean 'use ioNamePtr' */
673 cipb.hFileInfo.ioDirID = spec->parID;
674 cipb.hFileInfo.ioVRefNum = spec->vRefNum;
675 cipb.hFileInfo.ioNamePtr = (StringPtr)theString;
676
677 if( noErr==PBGetCatInfoSync(&cipb) )
678 AddFolder2PlayList(spec->vRefNum, cipb.hFileInfo.ioDirID);
679 }
680
mac_add_midi_file(const char * fullpath)681 static void mac_add_midi_file(const char *fullpath)
682 {
683 if( mac_n_files<LISTSIZE ) //not full
684 {
685 fileList[mac_n_files].filename= (char*)safe_malloc(strlen(fullpath)+1);
686 strcpy(fileList[mac_n_files].filename, fullpath);
687 if( skin_state==STOP ){ skin_state=WAITING; nPlaying=mac_n_files; }
688 add_ListWin(&fileList[mac_n_files]);
689 mac_n_files++;
690 }
691 }
692
mac_add_bmp_file(const char * fullpath)693 static void mac_add_bmp_file(const char *fullpath)
694 {
695 mac_SkinWindow.message(MW_SKIN_LOAD_BMP, (long)fullpath);
696 }
697
mac_add_nonarchive_file(const char * fullpath)698 static void mac_add_nonarchive_file(const char *fullpath)
699 {
700 if(isMidiFilename(fullpath)){
701 mac_add_midi_file(fullpath);
702 }else if(isBMPFilename(fullpath)){
703 mac_add_bmp_file(fullpath);
704 }else if( strtailcasecmp(fullpath, "viscolor.txt")==0 ){
705 read_viscolor(fullpath);
706 }
707 }
708
mac_add_archive_file(const char * fullpath)709 static void mac_add_archive_file(const char *fullpath)
710 {
711 if( mac_n_files<LISTSIZE ) /*not full*/
712 {
713 const char *arc_files[1];
714 char **new_files;
715 int nfiles=1,i;
716
717 //fileList[mac_n_files].filename= (char*)safe_malloc(fullpath[0]+1);
718 arc_files[0]= fullpath;
719
720 new_files = expand_file_archives((char **)arc_files, &nfiles);
721
722 for( i=0; i<nfiles; i++ ){
723 mac_add_nonarchive_file(new_files[i]);
724 }
725 if( arc_files!=new_files ) free(new_files);
726 }
727 }
728
mac_add_file(const char * fullpath)729 static void mac_add_file(const char *fullpath)
730 {
731 if( isArchiveFilename(fullpath) ){
732 mac_add_archive_file(fullpath);
733 }else{
734 mac_add_nonarchive_file(fullpath);
735 }
736 }
737
mac_add_fsspec(FSSpec * spec)738 void mac_add_fsspec( FSSpec *spec )
739 {
740 OSErr err;
741 FInfo fndrInfo;
742 Boolean targetIsFolder,wasAliased;
743
744 ResolveAliasFile(spec, true, &targetIsFolder, &wasAliased);
745
746 err= FSpGetFInfo(spec, &fndrInfo);
747
748 if( err ){
749 if( err==fnfErr ){
750 AddFolderFSSpec2PlayList(spec); // spec may be directory
751 return;
752 }else return;
753 }
754
755 //no error
756 { //spec is file, not folder or disk
757 Str255 fullpath;
758
759 GetFullPath(spec, fullpath);
760 p2cstr(fullpath);
761
762 if( fndrInfo.fdType=='Midi' ){
763 mac_add_midi_file((char*)fullpath);
764 }else{
765 mac_add_file((char*)fullpath);
766 }
767 }
768 }
769
AddHFS2PlayList(HFSFlavor * item)770 void AddHFS2PlayList(HFSFlavor* item)
771 {
772 if( item->fileType=='fold' || item->fileType=='disk')
773 AddFolderFSSpec2PlayList(&item->fileSpec);
774 //else if(item->fileType=='Midi'){}
775 else mac_add_fsspec(&item->fileSpec);
776 }
777
778 #define kDirFlag (1<<4)
779
AddFolder2PlayList(short vRefNum,long dirID)780 OSErr AddFolder2PlayList( short vRefNum, long dirID)
781 {
782 CInfoPBRec cipb;
783 Str32 theString;
784 StringPtr saveString;
785 short saveIndex;
786 OSErr err = noErr;
787
788 // initialize ourselves
789 cipb.hFileInfo.ioCompletion = nil;
790 cipb.hFileInfo.ioFDirIndex = 1;
791 cipb.hFileInfo.ioVRefNum = vRefNum;
792 cipb.hFileInfo.ioNamePtr = (StringPtr)theString;
793
794 while (err == noErr) {
795
796 // always reset directory id
797 cipb.hFileInfo.ioDirID = dirID;
798
799 // get the info for the next catalog item
800 err = PBGetCatInfoSync(&cipb);
801 if (err) goto exit;
802
803 // increment the count
804 cipb.hFileInfo.ioFDirIndex++;
805
806 // if we are a directory, recurse
807 if (cipb.hFileInfo.ioFlAttrib & kDirFlag) {
808
809 // save before recursing
810 saveIndex = cipb.hFileInfo.ioFDirIndex;
811 saveString = cipb.hFileInfo.ioNamePtr;
812
813 // recurse within the directory
814 err = AddFolder2PlayList( vRefNum, cipb.hFileInfo.ioDirID );
815
816 // restore after recursion
817 cipb.hFileInfo.ioFDirIndex = saveIndex;
818 cipb.hFileInfo.ioNamePtr = saveString;
819
820 } else { // we are a file
821
822 // call our scanProc if there is one specified
823 /*if (sp != nil)
824 err = (*sp)(cipbp, refCon);*/
825 FSSpec spec;
826 if(noErr==FSMakeFSSpec(vRefNum, dirID,
827 cipb.hFileInfo.ioNamePtr, &spec))
828 mac_add_fsspec(&spec);
829
830 }
831 }
832
833 exit:
834
835 // ignore fnfErr and afpAccessDenied errors since fnfErr is what we
836 // get when there are no more files left to scan, and afpAccessDenied
837 // can just ��happen�� depending on what we are scanning (ie: network
838 // volumes)
839 if ((err == fnfErr) || (err == afpAccessDenied)) return noErr;
840 else return err;
841 }
842
843 /*******************************************/
844 #pragma mark -
845
846
847