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 86 static pascal OSErr myHandleOAPP(AppleEvent* /*theAppleEvent*/, AppleEvent* /*reply*/, long /*handlerRefCon*/) 87 { 88 return noErr; 89 } 90 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 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 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 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; 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 693 static void mac_add_bmp_file(const char *fullpath) 694 { 695 mac_SkinWindow.message(MW_SKIN_LOAD_BMP, (long)fullpath); 696 } 697 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 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 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 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 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 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