REM > CDIcons+ REM © James Bursa, 2000 ON ERROR ON ERROR OFF: ERROR 0, REPORT$ + "(" + STR$ERL + "/" + STR$ERR + ")" CD_EMPTY = 0 CD_DATA = 1 CD_AUDIO = 2 MAX_TRACKS = 40 PROCcd_init PROCwimp_init PROCcddb_init PROCwimp_update PROCwimp_poll END REM******************************************************************************** REM CD handling REM******************************************************************************** REM check how many drives are connected and initialise cd data DEF PROCcd_init LOCAL drive%, number% SYS"CDFS_GetNumberOfDrives" TO cd_drives% IF cd_drives% = 0 THEN ERROR 1, "CDIcons+ cannot detect any CD drives connected to this computer" DIM cd_cb% 20, cd_b% 200 DIM cd_id%(cd_drives% - 1), cd_status%(cd_drives% - 1), cd_path$(cd_drives% - 1) FOR drive% = 0 TO cd_drives% - 1 cd_id%(drive%) = -1 NEXT ENDPROC REM******************************************************************************** REM convert a CDFS drive number to a CDFS control block in cd_cb% DEF PROCcd_device(drive%) LOCAL device% SYS"CDFS_ConvertDriveToDevice", drive% TO , device% cd_cb%!00 = device% AND 7 cd_cb%!04 = (device% >> 3) AND 3 cd_cb%!08 = (device% >> 5) AND 7 cd_cb%!12 = (device% >> 8) AND &ff cd_cb%!16 = device% >> 16 ENDPROC REM******************************************************************************** REM return a nearly unique number identifying the cd, 0 if none DEF FNcd_id(drive%) PROCcd_device(drive%) SYS"XCD_EnquireTrack", 0, cd_b%,,,,,, cd_cb% TO ;f% IF f% AND 1 THEN =0 SYS"CD_DiscUsed", 0, cd_b%,,,,,, cd_cb% =cd_b%!00 REM******************************************************************************** REM find out the type of cd and get information about it DEF PROCcd_update(drive%) LOCAL f% CASE cd_status%(drive%) OF WHEN CD_DATA: PROCclosedir(cd_path$(drive%)) SYS"OS_CLI", "CDFS:Dismount " + MID$(cd_path$(drive%), 7, LENcd_path$(drive%) - 8) WHEN CD_AUDIO: PROCcddb_finished(drive%) ENDCASE PROCcd_device(drive%) SYS"XCD_EnquireTrack", 1, cd_b%,,,,,, cd_cb% TO ;f% CASE TRUE OF WHEN (f% AND 1) = 1: cd_status%(drive%) = CD_EMPTY WHEN (cd_b%?04 AND 1) = 1: cd_status%(drive%) = CD_DATA SYS"OS_FSControl", 37, "CDFS::" + STR$drive%, cd_b%, 0, 0, 200 TO ,, cd_path$(drive%) PROCopendir(cd_path$(drive%)) OTHERWISE: cd_status%(drive%) = CD_AUDIO PROCcddb_query(drive%) ENDCASE ENDPROC REM******************************************************************************** REM call a CD_ swi DEF PROCcd_swi(drive%, swi%, r0%, r1%) PROCcd_device(drive%) SYS &41240 + swi%, r0%, r1%,,,,,, cd_cb% ENDPROC REM******************************************************************************** REM return a string suitable for displaying under the icon DEF FNcd_title(drive%) LOCAL title$ CASE cd_status%(drive%) OF WHEN CD_EMPTY: =STR$drive% WHEN CD_DATA : =MID$(cd_path$(drive%), 7, LENcd_path$(drive%) - 8) WHEN CD_AUDIO: title$ = FNcddb_title(drive%) IF title$ = "" THEN =STR$drive% ELSE =title$ ENDIF ENDCASE =STR$drive% REM******************************************************************************** REM return a string giving a suitable icon name for the drive DEF FNcd_icon(drive%) CASE cd_status%(drive%) OF WHEN CD_EMPTY: ="nocddisc" WHEN CD_DATA: ="cddisc" WHEN CD_AUDIO: ="acddisc" ENDCASE ="cddisc" REM******************************************************************************** DEF PROCcd_eject(drive%) PROCcd_swi(drive%, &7, 0, 0) ENDPROC REM******************************************************************************** DEF PROCcd_close(drive%) PROCcd_swi(drive%, &1b, 0, 0) ENDPROC REM******************************************************************************** DEF PROCcd_stop(drive%) PROCcd_swi(drive%, &12, 0, 0) ENDPROC REM******************************************************************************** DEF FNcd_tracks(drive%) PROCcd_device(drive%) SYS"CD_EnquireTrack", 0, cd_b%,,,,,, cd_cb% =cd_b%?1 REM******************************************************************************** DEF PROCcd_play(drive%, track%) PROCcd_device(drive%) SYS"CD_PlayTrack", track%, 255,,,,,, cd_cb% ENDPROC REM******************************************************************************** REM return playing track, 0 if not playing DEF FNcd_playingtrack(drive%) LOCAL status%, address%, tracks%, last% PROCcd_device(drive%) SYS"CD_AudioStatus",,,,,,,, cd_cb% TO status% IF status% <> 0 THEN =0 SYS"CD_EnquireAddress", 0,,,,,,, cd_cb% TO address% SYS"CD_EnquireTrack", 0, cd_b%,,,,,, cd_cb% tracks% = cd_b%?1 FOR track% = 1 TO tracks% SYS"CD_EnquireTrack", track%, cd_b%,,,,,, cd_cb% IF cd_b%!0 > address% THEN =track% - 1 NEXT =tracks% REM******************************************************************************** REM Wimp interaction REM******************************************************************************** REM initialise with the wimp DEF PROCwimp_init LOCAL drive%, data%, handle%, track% DIM b% 1023, menu% 28 + 24 * 4, tmenu% 28 + 24 * MAX_TRACKS b%!00 = &51bc1 b%!04 = 0 SYS"Wimp_Initialise", 310, &4b534154, "CDIcons+", b% TO , task% DIM iconbar_icon%(cd_drives% - 1), iconbar_data%(cd_drives% - 1) FOR drive% = 0 TO cd_drives% - 1 DIM data% 60 iconbar_icon%(drive%) = -1 iconbar_data%(drive%) = data% NEXT $(menu%) = "CDFS::?" menu%!12 = &00070207 menu%!16 = 200 menu%!20 = 44 menu%!24 = 0 menu%!(28 + 0 * 24 + 00) = 0 menu%!(28 + 0 * 24 + 04) = -1 menu%!(28 + 0 * 24 + 08) = &07000011 $(menu% + 28 + 0 * 24 + 12) = "Dismount" menu%!(28 + 1 * 24 + 00) = 0 menu%!(28 + 1 * 24 + 04) = -1 menu%!(28 + 1 * 24 + 08) = &07000011 $(menu% + 28 + 1 * 24 + 12) = "Eject" menu%!(28 + 2 * 24 + 00) = 0 menu%!(28 + 2 * 24 + 04) = -1 menu%!(28 + 2 * 24 + 08) = &07000011 $(menu% + 28 + 2 * 24 + 12) = "Close" menu%!(28 + 3 * 24 + 00) = &80 menu%!(28 + 3 * 24 + 04) = -1 menu%!(28 + 3 * 24 + 08) = &07000011 $(menu% + 28 + 3 * 24 + 12) = "Stop" tmenu%!12 = &00070008 tmenu%!16 = 500 tmenu%!20 = 44 tmenu%!24 = 0 FOR track% = 0 TO MAX_TRACKS - 1 tmenu%!(28 + track% * 24 + 04) = -1 NEXT ENDPROC REM******************************************************************************** REM handle wimp events DEF PROCwimp_poll LOCAL time%, reason% WHILE 1 SYS"OS_ReadMonotonicTime" TO time% SYS"Wimp_PollIdle", &3830, b%, time% + 50 TO reason% CASE reason% OF WHEN 0: PROCwimp_update WHEN 6: PROCwimp_click WHEN 9: PROCwimp_menu WHEN 17, 18: CASE b%!16 OF WHEN 0 : PROCquit WHEN &51bc1: PROCcddb_results ENDCASE ENDCASE ENDWHILE ENDPROC REM******************************************************************************** REM check for cd changes and update icons DEF PROCwimp_update LOCAL drive%, id% FOR drive% = 0 TO cd_drives% - 1 id% = FNcd_id(drive%) IF id% <> cd_id%(drive%) THEN PROCcd_update(drive%) PROCwimp_updateicon(drive%) cd_id%(drive%) = id% ENDIF NEXT ENDPROC REM******************************************************************************** REM handle mouse clicks DEF PROCwimp_click LOCAL drive%, path$ drive% = FNicon_to_drive(b%!16) IF b%!08 = 2 THEN menu_drive% = drive% menu_type% = menu% $(menu%) = "CDFS::" + STR$drive% IF cd_status%(drive%) = CD_DATA THEN menu%!(28 + 08) = &07000011 ELSE menu%!(28 + 08) = &07400011 ENDIF SYS"Wimp_CreateMenu",, menu%, b%!00 - 64, 272 ELSE CASE cd_status%(drive%) OF WHEN CD_EMPTY: IF b%!08 = 4 THEN PROCcd_eject(drive%) ELSE PROCcd_close(drive%) ENDIF WHEN CD_DATA: PROCopendir(cd_path$(drive%)) WHEN CD_AUDIO: PROCwimp_trackmenu(drive%) ENDCASE ENDIF ENDPROC REM******************************************************************************** DEF PROCwimp_trackmenu(drive%) LOCAL track%, title%, tracks%, playing% menu_drive% = drive% menu_type% = tmenu% title% = FNcddb_titleat(drive%) tracks% = FNcd_tracks(drive%) IF tracks% > MAX_TRACKS THEN tracks% = MAX_TRACKS IF title% = 0 THEN $(tmenu%) = "CDFS::" + STR$drive% FOR track% = 0 TO tracks% - 1 tmenu%!(28 + track% * 24 + 00) = 0 tmenu%!(28 + track% * 24 + 08) = &0b000011 $(tmenu% + 28 + track% * 24 + 12) = STR$(track% + 1) NEXT tmenu%!(28 + (tracks% - 1) * 24 + 00) = 1<<7 ELSE tmenu%!00 = title% tmenu%!04 = -1 tmenu%!08 = 0 FOR track% = 0 TO tracks% - 1 tmenu%!(28 + track% * 24 + 00) = 0 tmenu%!(28 + track% * 24 + 08) = &0b000111 tmenu%!(28 + track% * 24 + 12) = FNcddb_trackat(drive%, track% + 1) tmenu%!(28 + track% * 24 + 16) = -1 tmenu%!(28 + track% * 24 + 20) = 0 NEXT tmenu%!28 = 1<<8 tmenu%!(28 + (tracks% - 1) * 24 + 00) += 1<<7 ENDIF playing% = FNcd_playingtrack(drive%) IF playing% > 0 THEN tmenu%!(28 + (playing% - 1) * 24 + 00) += 1 SYS"Wimp_CreateMenu",, tmenu%, b%!00 - 80, 96 + 44 * tracks% ENDPROC REM******************************************************************************** REM handle menu selections DEF PROCwimp_menu SYS"Wimp_GetPointerInfo",, b% + 800 IF menu_type% = menu% THEN CASE b%!00 OF WHEN 0: PROCclosedir(cd_path$(menu_drive%)) SYS"OS_CLI", "CDFS:Dismount " + MID$(cd_path$(menu_drive%), 7, LENcd_path$(menu_drive%) - 8) WHEN 1: PROCcd_eject(menu_drive%) WHEN 2: PROCcd_close(menu_drive%) WHEN 3: PROCcd_stop(menu_drive%) ENDCASE ELSE PROCcd_play(menu_drive%, b%!00 + 1) ENDIF IF b%!808 = 1 THEN CASE menu_type% OF WHEN menu% : SYS"Wimp_CreateMenu",, menu% WHEN tmenu%: PROCwimp_trackmenu(menu_drive%) ENDCASE ENDIF ENDPROC REM******************************************************************************** DEF PROCwimp_updateicon(drive%) LOCAL icon% icon% = iconbar_icon%(drive%) iconbar_icon%(drive%) = FNwimp_createicon(drive%, FNcd_title(drive%), FNcd_icon(drive%), iconbar_data%(drive%)) IF icon% <> -1 THEN PROCwimp_deleteicon(icon%) ENDIF ENDPROC REM******************************************************************************** DEF FNwimp_createicon(number%, text$, sprite$, data%) LOCAL handle%, width% IF LENtext$ > 25 THEN text$ = LEFT$(text$, 24) + "Œ" SYS"Wimp_TextOp", 1, text$, 0 TO width% IF width% < 68 THEN width% = 68 $data% = text$ $(data% + 40) = "s" + sprite$ b%!800 = -5 b%!804 = 0 b%!808 = -16 b%!812 = width% b%!816 = 80 b%!820 = &1700310b b%!824 = data% b%!828 = data% + 40 b%!832 = 40 SYS"Wimp_CreateIcon", &78000000 + number%, b% + 800 TO handle% =handle% REM******************************************************************************** DEF PROCwimp_deleteicon(handle%) b%!800 = -2 b%!804 = handle% SYS"Wimp_DeleteIcon",, b% + 800 ENDPROC REM******************************************************************************** REM Reverse lookup functions REM******************************************************************************** DEF FNicon_to_drive(icon%) LOCAL drive% FOR drive% = 0 TO cd_drives% - 1 IF iconbar_icon%(drive%) = icon% THEN =drive% NEXT =0 REM******************************************************************************** DEF FNcddb_ref_to_drive(ref%) LOCAL drive% FOR drive% = 0 TO cd_drives% - 1 IF cddb_ref%(drive%) = ref% THEN =drive% NEXT =0 REM******************************************************************************** REM Filer messages REM******************************************************************************** DEF PROCopendir(dir$) PROCfiler(&400, dir$) ENDPROC REM******************************************************************************** DEF PROCclosedir(dir$) PROCfiler(&401, dir$) ENDPROC REM******************************************************************************** DEF PROCfiler(message%, dir$) b%!800 = 28 + ((LENdir$ DIV 4) + 1) * 4 b%!812 = 0 b%!816 = message% b%!820 = 37 b%!824 = 1 $(b% + 828) = dir$ + CHR$0 SYS"Wimp_SendMessage", 17, b% + 800, 0 ENDPROC REM******************************************************************************** REM AcornCD CDDB server communication REM******************************************************************************** REM initialise DEF PROCcddb_init DIM cddb_b% 40 DIM cddb_ref%(cd_drives% - 1), cddb_area%(cd_drives% - 1), cddb_areaid%(cd_drives% - 1) ENDPROC REM******************************************************************************** REM send a query to the server if possible DEF PROCcddb_query(drive%) LOCAL call%, found%, acorncd%, exists% call% = 0 found% = 0 WHILE (call% >= 0) AND (found% = 0) SYS"TaskManager_EnumerateTasks", call%, cddb_b%, 16 TO call% IF FNstring(cddb_b%!04) = "AcornCD" THEN found% = 1 acorncd% = cddb_b%!00 ENDIF ENDWHILE IF found% = 0 THEN SYS"XOS_ReadVarVal", "AcornCD$Dir", cddb_b%, -1 TO ,, exists% IF exists% = 0 THEN ENDPROC SYS"Wimp_StartTask", "Run .!Run" TO acorncd% ENDIF cddb_b%!00 = 28 cddb_b%!12 = 0 REM CDDB_Query cddb_b%!16 = &51bc0 cddb_b%!20 = 1 cddb_b%!24 = drive% SYS"Wimp_SendMessage", 17, cddb_b%, acorncd% cddb_ref%(drive%) = cd_b%!08 cddb_area%(drive%) = 0 cddb_areaid%(drive%) = 0 ENDPROC REM******************************************************************************** REM return the title of the cd if available DEF FNcddb_title(drive%) IF cddb_area%(drive%) = 0 THEN ="" =FNstring(cddb_area%(drive%)!04) REM******************************************************************************** DEF FNcddb_titleat(drive%) IF cddb_area%(drive%) = 0 THEN =0 =cddb_area%(drive%)!04 REM******************************************************************************** DEF FNcddb_trackat(drive%, track%) =!(cddb_area%(drive%) + 24 + (track% - 1) * 8) REM******************************************************************************** REM handle CDDB_QueryResults DEF PROCcddb_results LOCAL drive%, area% drive% = FNcddb_ref_to_drive(b%!12) CASE b%!20 OF WHEN 0, 3: cddb_area%(drive%) = b%!24 cddb_areaid%(drive%) = b%!28 PROCwimp_updateicon(drive%) ENDCASE ENDPROC REM******************************************************************************** DEF PROCcddb_finished(drive%) IF cddb_areaid%(drive%) = 0 THEN ENDPROC cddb_b%!00 = 28 cddb_b%!12 = 0 REM CDDB_FreeArea cddb_b%!16 = &51bc2 cddb_b%!20 = 0 cddb_b%!24 = cddb_areaid%(drive%) SYS"Wimp_SendMessage", 17, cddb_b%, 0 cddb_area%(drive%) = 0 cddb_areaid%(drive%) = 0 ENDPROC REM******************************************************************************** REM Useful functions REM******************************************************************************** DEF FNstring(a%) LOCAL s$ s$ = "" WHILE ?a% > 31 s$ += CHR$?a% a% += 1 ENDWHILE =s$ REM******************************************************************************** DEF PROCquit FOR drive% = 0 TO cd_drives% - 1 PROCcddb_finished(drive%) NEXT SYS"Wimp_CloseDown", task%, &4b534154 END ENDPROC REM********************************************************************************