Advertisement
Testaware

SCAL DLL v2.00

Oct 6th, 2020 (edited)
2,939
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PureBasic 123.61 KB | None | 0 0
  1. ; -------------------------------------------------------------------------------------
  2. ; SCAL v2.00 x86-64 DLL - Play-Library for multiple formats [1060 (x86) / 424 (x64)]
  3. ; -------------------------------------------------------------------------------------
  4. ; Peace/TST - 05.10.2020 / Purebasic 5.70
  5. ; https://testaware.wordpress.com
  6. ; -------------------------------------------------------------------------------------
  7. ; Note:  - x64: Doesn't support #C2D_MUSIC_[AMP,BAS,BMF,FCP,MED,S68,SID,TSR,V2M,YMP]
  8. ;        - x86: Install the AmpMaster_x86.dll to playback +626 rare formats
  9. ; -------------------------------------------------------------------------------------
  10.  
  11. EnableExplicit
  12.  
  13. #SCAL_VERSION  =  200   ; * 0.01 -> 2.00
  14.  
  15. XIncludeFile   "Include\i_scal.pbi"
  16.  
  17. Global   RS_SCAL.RS_SCAL
  18.  
  19. ;************************
  20. ;{ *** LIB-INCLUDES *** }
  21.  
  22. IncludePath "Include\"
  23. XIncludeFile   "minizip_include.pbi"
  24.  
  25. IncludePath "Include\MusicLibs\"
  26.  
  27. CompilerIf  #PB_Compiler_Processor  =  #PB_Processor_x86
  28.    ;Import  "winmm_x86.lib"   :  EndImport   ; not needed coz #C2D_MUSIC_MOD
  29.    Import   "dsound_x86.lib"  :  EndImport
  30.    CompilerIf  #IsSID
  31.       Import   "masm32_x86.lib"  :  EndImport
  32.    CompilerEndIf
  33. ;CompilerElse
  34.    ;Import  "winmm.lib" :  EndImport   ; not needed coz #C2D_MUSIC_MOD
  35. CompilerEndIf
  36.  
  37. UseOGGSoundDecoder()
  38. UseFLACSoundDecoder()
  39.  
  40. ;{ #C2D_MUSIC_MOD * Native PureBasic ModPlug Library * }
  41. ; *.669;*.ABC;*.AMF;*.AMS;*.DBM;*.DMF;*.FAR;*.IT;*.J2B;*.MDL;*.MED;*.MID;*.MOD;*.MT2;*.MTM;*.OKT;*.PAT;*.PSM;*.PTM;*.S3M;*.STM;*.ULT;*.UMX;*.WAV;*.XM;*.MMCMP;*.PP
  42. ;InitSound()
  43. ;}
  44. ;{ #C2D_MUSIC_MOV * Native PureBasic Movie Library * }
  45. ; *.MP3;*.WAV;*.WMA...
  46. ;InitMovie()
  47. ;}
  48. ;{ #C2D_MUSIC_FT2 * Thanx to Olav "8bitbubsy" for the opensource FT2PLAY v1.04 * }
  49. ; Copyright (c) 2016-2020, Olav "8bitbubsy" Sørensen
  50. ; https://16-bits.org
  51. ; https://pastebin.com/0TLkMm0A
  52. ; *.FT;*.MOD;*.STK;*.XM
  53. ;Import  "winmm.lib" :  EndImport
  54. CompilerIf  #PB_Compiler_Processor  =  #PB_Processor_x64
  55.    Import   "playFT2_x64.lib"
  56.       ft2play_Close()
  57.       ft2play_GetAmp()        ; 1..32
  58.       ft2play_GetMasterVol()  ; 0..256
  59.       ft2play_GetMixerTicks() ; returns the amount of milliseconds of mixed audio (not realtime)
  60.       ft2play_GetSongName()   ; max 20 chars (21 with '\0'), string is in code page 437
  61.       ft2play_PauseSong(flag)
  62.       ft2play_PlaySong(*moduleData, length, interpolation, volumeramping, freq)  ; returns 1 = playing or 0 = error
  63.       ft2play_SetAmp(factor)           ; 1..32
  64.       ft2play_SetInterpolation(flag)   ; true/false
  65.       ft2play_SetMasterVol(vol)        ; 0..256
  66.       ft2play_SetVolumeRamping(flag)   ; true/false
  67.       ft2play_TogglePause()
  68.    EndImport
  69. CompilerElse
  70.    ImportC  "playFT2_x86.lib"
  71.       ft2play_Close()                  As "_ft2play_Close"
  72.       ft2play_GetAmp()                 As "_ft2play_GetAmp"
  73.       ft2play_GetMasterVol()           As "_ft2play_GetMasterVol"
  74.       ft2play_GetMixerTicks()          As "_ft2play_GetMixerTicks"
  75.       ft2play_GetSongName()            As "_ft2play_GetSongName"
  76.       ft2play_PauseSong(flag)          As "_ft2play_PauseSong"
  77.       ft2play_PlaySong(*moduleData, length, interpolation, volumeramping, freq)  As "_ft2play_PlaySong"
  78.       ft2play_SetAmp(factor)           As "_ft2play_SetAmp"
  79.       ft2play_SetInterpolation(flag)   As "_ft2play_SetInterpolation"
  80.       ft2play_SetMasterVol(vol)        As "_ft2play_SetMasterVol"
  81.       ft2play_SetVolumeRamping(flag)   As "_ft2play_SetVolumeRamping"
  82.       ft2play_TogglePause()            As "_ft2play_TogglePause"
  83.    EndImport
  84. CompilerEndIf
  85. ;}
  86. ;{ #C2D_MUSIC_PT2 * Thanx to Olav "8bitbubsy" for the opensource PT2PLAY v1.60 * }
  87. ; https://16-bits.org
  88. ; https://pastebin.com/pg95YduC
  89. ; *.MOD
  90. #CIA_TEMPO_MODE      =  0
  91. #VBLANK_TEMPO_MODE   =  1
  92. ;Import  "winmm.lib" :  EndImport
  93. CompilerIf  #PB_Compiler_Processor  =  #PB_Processor_x64
  94.    Import   "playPT2_x64.lib"
  95.       pt2play_Close()
  96.       pt2play_GetMasterVol()  ; 0..256
  97.       pt2play_GetMixerTicks() ; returns the amount of milliseconds of mixed audio (not realtime)
  98.       pt2play_GetSongName()   ; max 20 chars (21 with '\0'), string is in code page 437
  99.       pt2play_PauseSong(flag) ; true/false
  100.       pt2play_PlaySong(*moduleData, length, tempoMode, freq)   ; returns 1 = playing or 0 = error
  101.       pt2play_SetMasterVol(vol)     ; 0..256
  102.       pt2play_SetStereoSep(percent) ; 0..100
  103.       pt2play_TogglePause()
  104.    EndImport
  105. CompilerElse
  106.    ImportC  "playPT2_x86.lib"
  107.       pt2play_Close()               As "_pt2play_Close"
  108.       pt2play_GetMasterVol()        As "_pt2play_GetMasterVol"
  109.       pt2play_GetMixerTicks()       As "_pt2play_GetMixerTicks"
  110.       pt2play_GetSongName()         As "_pt2play_GetSongName"
  111.       pt2play_PauseSong(flag)       As "_pt2play_PauseSong"
  112.       pt2play_PlaySong(*moduleData, length, tempoMode, freq)   As "_pt2play_PlaySong"
  113.       pt2play_SetMasterVol(vol)     As "_pt2play_SetMasterVol"
  114.       pt2play_SetStereoSep(percent) As "_pt2play_SetStereoSep"
  115.       pt2play_TogglePause()         As "_pt2play_TogglePause"
  116.    EndImport
  117. CompilerEndIf
  118. ;}
  119. ;{ #C2D_MUSIC_FC4 * Thanx to Olav "8bitbubsy" for the opensource FC14PLAY v1.29 * }
  120. ; https://16-bits.org
  121. ; https://pastebin.com/VHxZ58UC
  122. ; *.FC;*.FC13;*.FC14;*.FC3;*.FC4;*.FCM;*.SMOD
  123. ;Import  "winmm.lib" :  EndImport
  124. CompilerIf  #PB_Compiler_Processor  =  #PB_Processor_x64
  125.    Import   "playFC4_x64.lib"
  126.       fc14play_Close()
  127.       fc14play_GetMasterVol()
  128.       fc14play_GetMixerTicks()   ; returns the amount of milliseconds of mixed audio (not realtime)
  129.       fc14play_PauseSong(flag)   ; true/false
  130.       fc14play_PlaySong(*moduleData, length, freq) ; returns 1 = playing or 0 = error
  131.       fc14play_SetMasterVol(vol)       ; 0..256
  132.       fc14play_SetStereoSep(percent)   ; 0..100
  133.       fc14play_TogglePause()
  134.    EndImport
  135. CompilerElse
  136.    ImportC  "playFC4_x86.lib"
  137.       fc14play_Close()                 As "_fc14play_Close"
  138.       fc14play_GetMasterVol()          As "_fc14play_GetMasterVol"
  139.       fc14play_GetMixerTicks()         As "_fc14play_GetMixerTicks"
  140.       fc14play_PauseSong(flag)         As "_fc14play_PauseSong"
  141.       fc14play_PlaySong(*moduleData, length, freq) As "_fc14play_PlaySong"
  142.       fc14play_SetMasterVol(vol)       As "_fc14play_SetMasterVol"
  143.       fc14play_SetStereoSep(percent)   As "_fc14play_SetStereoSep"
  144.       fc14play_TogglePause()           As "_fc14play_TogglePause"
  145.    EndImport
  146. CompilerEndIf
  147. ;}
  148. ;{ #C2D_MUSIC_AHX * Thanx to Olav "8bitbubsy" for the opensource AHX1PLAY v0.27 * }
  149. ; https://16-bits.org
  150. ; https://pastebin.com/fqwadbj7
  151. ; *.AHX;*.THX
  152. ;Import  "winmm.lib" :  EndImport
  153. CompilerIf  #PB_Compiler_Processor  =  #PB_Processor_x64
  154.    Import   "playAHX_x64.lib"
  155.       ahx1play_PlaySong(*moduleData, length, subsong, freq) ; returns 1 = playing or 0 = error
  156.       ahx1play_GetSongName()                                ; max 64 chars (65 with '\0'), string is in latin1
  157.       ahx1play_Close()
  158.       ahx1play_PauseSong(flag)         ; true/false
  159.       ahx1play_TogglePause()
  160.       ahx1play_GetMixerTicks()         ; returns the amount of milliseconds of mixed audio (not realtime)
  161.       ahx1play_SetStereoSep(percent)   ; 0..100
  162.    EndImport
  163. CompilerElse
  164.    ImportC  "playAHX_x86.lib"
  165.       ahx1play_PlaySong(*moduleData, length, subsong, freq) As "_ahx1play_PlaySong"
  166.       ahx1play_GetSongName()           As "_ahx1play_GetSongName"
  167.       ahx1play_Close()                 As "_ahx1play_Close"
  168.       ahx1play_PauseSong(flag)         As "_ahx1play_PauseSong"
  169.       ahx1play_TogglePause()           As "_ahx1play_TogglePause"
  170.       ahx1play_GetMixerTicks()         As "_ahx1play_GetMixerTicks"
  171.       ahx1play_SetStereoSep(percent)   As "_ahx1play_SetStereoSep"
  172.    EndImport
  173. CompilerEndIf
  174. ;}
  175. ;{ #C2D_MUSIC_STM * Thanx to Olav "8bitbubsy" for the opensource STMPLAY v0.33 * }
  176. ; https://16-bits.org
  177. ; https://pastebin.com/ifXSCZ71
  178. ; *.STM
  179. ;Import  "winmm.lib" :  EndImport
  180. CompilerIf  #PB_Compiler_Processor  =  #PB_Processor_x64
  181.    Import   "playST2_x64.lib"
  182.       st23play_Close()
  183.       st23play_GetMasterVol()    ; 0..256
  184.       st23play_GetMixerTicks()   ; returns the amount of milliseconds of mixed audio (not realtime)
  185.       st23play_GetSongName()     ; max 20 chars (21 with '\0'), string is in code page 437
  186.       st23play_PauseSong(flag)   ; true/false
  187.       st23play_PlaySong(*moduleData, dataLength, useInterpolationFlag, audioFreq)   ; returns 1 = playing or 0 = error
  188.       st23play_SetInterpolation(flag)  ; true/false
  189.       st23play_SetMasterVol(vol)       ; 0..256
  190.       st23play_TogglePause()
  191.    EndImport
  192. CompilerElse
  193.    ImportC  "playST2_x86.lib"
  194.       st23play_Close()                 As "_st23play_Close"
  195.       st23play_GetMasterVol()          As "_st23play_GetMasterVol"
  196.       st23play_GetMixerTicks()         As "_st23play_GetMixerTicks"
  197.       st23play_GetSongName()           As "_st23play_GetSongName"
  198.       st23play_PauseSong(flag)         As "_st23play_PauseSong"
  199.       st23play_PlaySong(*moduleData, dataLength, useInterpolationFlag, audioFreq)   As "_st23play_PlaySong"
  200.       st23play_SetInterpolation(flag)  As "_st23play_SetInterpolation"
  201.       st23play_SetMasterVol(vol)       As "_st23play_SetMasterVol"
  202.       st23play_TogglePause()           As "_st23play_TogglePause"
  203.    EndImport
  204. CompilerEndIf
  205. ;}
  206. ;{ #C2D_MUSIC_S3M * Thanx to Olav "8bitbubsy" for the opensource ST3PLAY v0.91+ (x86) / v0.99 (x64) * }
  207. ; https://16-bits.org
  208. ; https://pastebin.com/AwRXZAw7
  209. ; *.S3M
  210. #SOUNDCARD_GUS    =  0  ;/* Default */
  211. #SOUNDCARD_SBPRO  =  1
  212. ;Import  "winmm.lib" :  EndImport
  213. CompilerIf  #PB_Compiler_Processor  =  #PB_Processor_x64
  214.    Import   "playST3_x64.lib"
  215.       st3play_Close()
  216.       st3play_GetMasterVol()  ; 0..256
  217.       st3play_GetMixerTicks() ; returns the amount of milliseconds of mixed audio (not realtime)
  218.       st3play_GetSongName()
  219.       st3play_PauseSong(flag) ; true/false
  220.       st3play_PlaySong(*moduleData, length, flag, type, freq)  ; returns 1 = playing or 0 = error
  221.       st3play_SetInterpolation(flag)   ; true/false
  222.       st3play_SetMasterVol(vol)        ; 0..256
  223.       st3play_TogglePause()
  224.    EndImport
  225. CompilerElse
  226.    ImportC  "playST3_x86.lib" ; ST3PLAY v0.91 last working for x86
  227.       st3play_Close()                  As "_st3play_Close"
  228.       st3play_GetMixerTicks()          As "_st3play_GetMixerTicks"
  229.       st3play_GetSongName()            As "_st3play_GetSongName"
  230.       st3play_PauseSong(flag)          As "_st3play_PauseSong"
  231.       st3play_PlaySong(*moduleData, length, flag, type, freq)  As "_st3play_PlaySong"
  232.       st3play_SetInterpolation(flag)   As "_st3play_SetInterpolation"
  233.       st3play_SetMasterVol(vol)        As "_st3play_SetMasterVol"
  234.       st3play_TogglePause()            As "_st3play_TogglePause"
  235.    EndImport
  236. CompilerEndIf
  237. ;}
  238. ;{ #C2D_MUSIC_V1M * Thanx to kb^farbrausch for the static libv2.lib v1.0 / Error * }
  239. ; *.V2M 1.0
  240. CompilerIf  #IsV1M
  241.    ;Import  "winmm.lib"    :  EndImport
  242.    ;Import  "dsound.lib"   :  EndImport
  243.    Import   "libv2_x86.lib"
  244.       ssClose()               As "_ssClose@0"
  245.       ssDoTick()              As "_ssDoTick@0"
  246.       ssFadeOut(milliseconds) As "_ssFadeOut@4"
  247.       ssGetTime()             As "_ssGetTime@0"
  248.       ssInit(*module, *hWnd)  As "_ssInit@8"
  249.       ssPlay()                As "_ssPlay@0"
  250.       ssStop()                As "_ssStop@0"
  251.    EndImport
  252. CompilerEndIf
  253. ;}
  254. ;{ #C2D_MUSIC_V2M * Thanx to kb^farbrausch for the static libv2simple.lib v1.5 * }
  255. ; *.V2M 1.5
  256. CompilerIf  #IsV2M
  257.    Prototype   DSIOCALLBACK(*param, *buf.FLOAT, length.l)
  258.    Prototype   PERCENTCALLBACK(percent.f)
  259.    ;Import  "dsound.lib"   :  EndImport
  260.    Import   "libv2simple_x86.lib"
  261.       V2MClose()                                As "_V2MClose@0"
  262.       V2MGetChannelVU(channel, *left, *right)   As "_V2MGetChannelVU@12"
  263.       V2MGetCurrentTime()                       As "_V2MGetCurrentTime@0"
  264.       V2MGetTotalTime()                         As "_V2MGetTotalTime@0"
  265.       V2MInit(*tune, samplerate, *hWnd)         As "_V2MInit@12"
  266.       V2MIsPlaying()                            As "_V2MIsPlaying@0"
  267.       V2MPlay(start=0)                          As "_V2MPlay@4"
  268.       V2MSaveAsWave(a.s, *b.PERCENTCALLBACK)    As "_V2MSaveAsWave@8"
  269.       V2MSetRepeat(status.b)                    As "_V2MSetRepeat@4"
  270.       V2MSetVUMode(mode)                        As "_V2MSetVUMode@4"
  271.       V2MStop(fade=0)                           As "_V2MStop@4"
  272.       ;initializes DirectSound output.
  273.       ;callback: your render callback function
  274.       ;parm: a pointer that'll be supplied to the function on every call
  275.       ;hWnd: window handle of your application (GetForegroundWindow() works quite well :)
  276.       dsInit(*callback.DSIOCALLBACK, *parm, *hWnd) As "_dsInit@12"
  277.       dsClose()               As "_dsClose@0"      ;shuts down DirectSound output
  278.       dsGetCurSmp()           As "_dsGetCurSmp@0"  ;gets sample-exact and latency compensated current play position
  279.       dsSetVolume(vol.f=1.0)  As "_dsSetVolume@4"  ;sets player volume (Default is 1.0)
  280.       ;forces rendering thread to update. On single-core CPUs it's a good idea to
  281.       ;call this once per frame (improves A/V sync And reduces any stuttering),
  282.       ;with more than one CPU it's pretty much useless.
  283.       dsTick() As "_dsTick@0"
  284.       ;lock And unlock the sound thread's thread sync lock. If you want to modify
  285.       ;any of your sound variables outside the render thread, encapsulate that part
  286.       ;of code in between these two functions.
  287.       dsLock()    As "_dsLock@0"
  288.       dsUnlock()  As "_dsUnlock@0"
  289.    EndImport
  290. CompilerEndIf
  291. ;}
  292. ;{ #C2D_MUSIC_XM2 * Thanx to Quantum for the FastTracker2 uFMOD static lib * }
  293. ; *.XM
  294. CompilerIf  #IsXM2
  295.    #XM_RESOURCE         =  0
  296.    #XM_MEMORY           =  1
  297.    #XM_FILE             =  2
  298.    #XM_NOLOOP           =  8
  299.    #XM_SUSPENDED        =  16
  300.    #uFMOD_MIN_VOL       =  0
  301.    #uFMOD_MAX_VOL       =  25
  302.    #uFMOD_DEFAULT_VOL   =  25
  303.    ;Import  "winmm.lib" :  EndImport
  304.    Import   "ufmod_x86.lib"
  305.       uFMOD_GetRowOrder()                       As "_uFMOD_GetRowOrder@0"  ;Returns the current order in hi-order word and row in low-order word
  306.       uFMOD_GetStats()                          As "_uFMOD_GetStats@0"     ;Returns the L RMS volume in hi-order word and R RMS in low-order word
  307.       uFMOD_GetTime()                           As "_uFMOD_GetTime@0"      ;Returns the time in milliseconds since the song was started
  308.       uFMOD_GetTitle()                          As "_uFMOD_GetTitle@0"     ;Returns the track's title
  309.       uFMOD_Jump2Pattern(pat)                   As "_uFMOD_Jump2Pattern@4" ;Jumps to the specified zero based pattern index
  310.       uFMOD_Pause()                             As "_uFMOD_Pause@0"        ;Pauses the currently playing song, if any
  311.       uFMOD_PlaySong(*lpXM, param=0, fdwSong=0) As "_uFMOD_PlaySong@12"    ;Starts playing an XM song, *lpXM -> 0 = Stopp song
  312.       uFMOD_Resume()                            As "_uFMOD_Resume@0"       ;Resumes the currently paused song, if any
  313.       uFMOD_SetVolume(vol)                      As "_uFMOD_SetVolume@4"    ;Sets global volume: 0 - 25
  314.    EndImport
  315. CompilerEndIf
  316. ;}
  317. ;{ #C2D_MUSIC_SID * Thanx to statmat for the titchysid_extras.lib * }
  318. ; *.SID
  319. CompilerIf  #IsSID
  320.    #SID_RESOURCE     =  0  ;Load SID file from a resource
  321.    #SID_MEMORY       =  1  ;Load SID file from provided memory
  322.    ;Options used in SIDOpen()
  323.    #SID_DEFAULT      =  1  ;Play Default subsong, as found in the PSID header
  324.    #SID_NON_DEFAULT  =  2  ;Play specified subsong
  325.    ;Import  "winmm.lib"    :  EndImport   ; Not really needed!
  326.    ;Import  "masm32_x86.lib"  :  EndImport
  327.    Import   "titchysid_extras_x86.lib"
  328.       SIDOpen(*mem, len, mode, options, subsong)   As "_SIDOpen@20"     ;Returns non-zero on success
  329.       SIDClose()                                   As "_SIDClose@0"     ;Close the SID library
  330.       SIDChangeSong(song)                          As "_SIDChangeSong@4";Change to another sub song in the currently playing SID file
  331.       SIDPause()                                   As "_SIDPause@0"     ;Pause the currently playing SID song
  332.       SIDPlay()                                    As "_SIDPlay@0"      ;Start the SID playback
  333.       SIDResume()                                  As "_SIDResume@0"    ;Resume playing the SID song after a pause
  334.       SIDStop()                                    As "_SIDStop@0"      ;Stop the SID playback
  335.    EndImport
  336. ;  Import   "titchysid_x86.lib"
  337. ;     SIDOpen(*mem, len, mode, options, subsong)   As "_SIDOpen@20"     ;Returns non-zero on success
  338. ;     SIDClose()                                   As "_SIDClose@0"     ;Close the SID library
  339. ;  EndImport
  340. CompilerEndIf
  341. ;}
  342. ;{ #C2D_MUSIC_TPT * Not official TINY PT2PLAY v1.60 * }
  343. CompilerIf  #PB_Compiler_Processor  =  #PB_Processor_x64
  344.    Import   "tinyPT2_x64.lib"
  345.       tinypt2play_Close()  As "pt2play_Close"
  346.       tinypt2play_PlaySong(*moduleData, length) As "pt2play_PlaySong"; returns 1 = playing or 0 = error
  347.    EndImport
  348. CompilerElse
  349.    ImportC  "tinyPT2_x86.lib"
  350.       tinypt2play_Close()  As "_pt2play_Close"
  351.       tinypt2play_PlaySong(*moduleData, length) As "_pt2play_PlaySong"
  352.    EndImport
  353. CompilerEndIf
  354. ;}
  355. ;{ #C2D_MUSIC_TFC * Not official TINY FC14PLAY v1.29 * }
  356.  
  357. ; https://16-bits.org
  358. ; https://pastebin.com/VHxZ58UC
  359.  
  360. ; *.FC;*.FC13;*.FC14;*.FC3;*.FC4;*.FCM;*.SMOD
  361.  
  362. ;Import  "winmm.lib" :  EndImport
  363.  
  364. CompilerIf  #PB_Compiler_Processor  =  #PB_Processor_x64
  365.    Import   "tinyFC4_x64.lib"
  366.       tinyfc14play_Close() As "fc14play_Close"
  367.       tinyfc14play_PlaySong(*moduleData, length)   As "fc14play_PlaySong"  ; returns 1 = playing or 0 = error
  368.    EndImport
  369. CompilerElse
  370.    ImportC  "tinyFC4_x86.lib"
  371.       tinyfc14play_Close() As "_fc14play_Close"
  372.       tinyfc14play_PlaySong(*moduleData, length)   As "_fc14play_PlaySong"
  373.    EndImport
  374. CompilerEndIf
  375. ;}
  376. ;{ #C2D_MUSIC_THX * Not official TINY AHX1PLAY v0.27 * }
  377.  
  378. ; https://16-bits.org
  379. ; https://pastebin.com/fqwadbj7
  380.  
  381. ; *.AHX;*.THX
  382.  
  383. ;Import  "winmm.lib" :  EndImport
  384.  
  385. CompilerIf  #PB_Compiler_Processor  =  #PB_Processor_x64
  386.    Import   "tinyAHX_x64.lib"
  387.       tinyahx1play_PlaySong(*moduleData, length, subsong)   As "ahx1play_PlaySong"  ; returns 1 = playing or 0 = error
  388.       tinyahx1play_Close() As "ahx1play_Close"
  389.    EndImport
  390. CompilerElse
  391.    ImportC  "tinyAHX_x86.lib"
  392.       tinyahx1play_PlaySong(*moduleData, length, subsong)   As "_ahx1play_PlaySong"
  393.       tinyahx1play_Close() As "_ahx1play_Close"
  394.    EndImport
  395. CompilerEndIf
  396.  
  397. ;}
  398. ;{ #C2D_MUSIC_TSR * Thanx to unknown? for the tsidreplay.lib * }
  399. ; *.SID
  400. CompilerIf  #IsTSR
  401.    ImportC  "tsidreplay_x86.lib"
  402.       sid_sound_server_replay_init(*mem, len, subsong)   As "_sid_sound_server_replay_init"
  403.       sid_sound_server_replay_play()                     As "_sid_sound_server_replay_play"
  404.       sid_sound_server_replay_stop()                     As "_sid_sound_server_replay_stop"
  405.    EndImport
  406. CompilerEndIf
  407. ;}
  408. ;{ #C2D_MUSIC_FCP * Thanx to SiRioKD for the tFCLIB.lib (FutureComposer 1.4) * }
  409. ; *.FC;*.FC4;*.FC14
  410. CompilerIf  #IsFCP
  411.    ;Import  "winmm.lib"    :  EndImport   ; Not really needed?
  412.    ;Import  "dsound.lib"   :  EndImport
  413.    Import   "tFCLIB_x86.lib"
  414.       FCp_Open(*hWnd)      As "_FCp_Open@4"
  415.       FCp_InitModule(*Ptr) As "_FCp_InitModule@4"
  416.       FCp_Start()          As "_FCp_Start@0"
  417.       FCp_Close()          As "_FCp_Close@0"
  418.    EndImport
  419. CompilerEndIf
  420. ;}
  421. ;{ #C2D_MUSIC_BAS * Thanx to Ghandi for the ripped bassmod.lib * }
  422. ; *.XM;*.IT;*.S3M;*.MOD;*.MTM;*.UMX
  423. CompilerIf  #IsBAS
  424.    #BASS_OK                 = 0   ; all is OK
  425.    #BASS_ERROR_MEM          = 1   ; memory error
  426.    #BASS_ERROR_FILEOPEN     = 2   ; can't open the file
  427.    #BASS_ERROR_DRIVER       = 3   ; can't find a free/valid driver
  428.    #BASS_ERROR_HANDLE       = 5   ; invalid handle
  429.    #BASS_ERROR_FORMAT       = 6   ; unsupported format
  430.    #BASS_ERROR_POSITION     = 7   ; invalid playback position
  431.    #BASS_ERROR_INIT         = 8   ; BASS_Init has not been successfully called
  432.    #BASS_ERROR_ALREADY      = 14  ; already initialized/loaded
  433.    #BASS_ERROR_ILLTYPE      = 19  ; an illegal type was specified
  434.    #BASS_ERROR_ILLPARAM     = 20  ; an illegal parameter was specified
  435.    #BASS_ERROR_DEVICE       = 23  ; illegal device number
  436.    #BASS_ERROR_NOPLAY       = 24  ; not playing
  437.    #BASS_ERROR_NOMUSIC      = 28  ; no MOD music has been loaded
  438.    #BASS_ERROR_NOSYNC       = 30  ; synchronizers have been disabled
  439.    #BASS_ERROR_NOTAVAIL     = 37  ; requested data is not available
  440.    #BASS_ERROR_DECODE       = 38  ; the channel is a "decoding channel"
  441.    #BASS_ERROR_FILEFORM     = 41  ; unsupported file format
  442.    #BASS_ERROR_UNKNOWN      = -1  ; some other mystery error
  443.  
  444.    ; Device setup flags
  445.    #BASS_DEVICE_8BITS       = 1   ; use 8 bit resolution, else 16 bit
  446.    #BASS_DEVICE_MONO        = 2   ; use mono, else stereo
  447.    #BASS_DEVICE_NOSYNC      = 16  ; disable synchronizers
  448.  
  449.    #BASS_MUSIC_RAMP         =       1  ; normal ramping
  450.    #BASS_MUSIC_RAMPS        =       2  ; sensitive ramping
  451.    #BASS_MUSIC_LOOP         =       4  ; loop music
  452.    #BASS_MUSIC_FT2MOD       =      16  ; play .MOD as FastTracker 2 does
  453.    #BASS_MUSIC_PT1MOD       =      32  ; play .MOD as ProTracker 1 does
  454.    #BASS_MUSIC_POSRESET     =     256  ; stop all notes when moving position
  455.    #BASS_MUSIC_SURROUND     =     512  ; surround sound
  456.    #BASS_MUSIC_SURROUND2    =    1024  ; surround sound (mode 2)
  457.    #BASS_MUSIC_STOPBACK     =    2048  ; stop the music on a backwards jump effect
  458.    #BASS_MUSIC_CALCLEN      =    8192  ; calculate playback length
  459.    #BASS_MUSIC_NONINTER     =   16384  ; non-interpolated mixing
  460.    #BASS_MUSIC_NOSAMPLE     = $400000  ; don't load the samples
  461.  
  462.    #BASS_UNICODE            = $80000000
  463.  
  464.    #BASS_SYNC_MUSICPOS      = 0
  465.    #BASS_SYNC_POS           = 0
  466.    #BASS_SYNC_MUSICINST     = 1
  467.    #BASS_SYNC_END           = 2
  468.    #BASS_SYNC_MUSICFX       = 3
  469.    #BASS_SYNC_ONETIME       = $80000000   ; FLAG: sync only once, else continuously
  470.  
  471.    ; BASSMOD_ChannelIsActive return values
  472.    #BASS_ACTIVE_STOPPED     = 0
  473.    #BASS_ACTIVE_PLAYING     = 1
  474.    #BASS_ACTIVE_PAUSED      = 3
  475.  
  476.    ;Import  "winmm.lib"    :  EndImport
  477.    Import   "bassmod_x86.lib"
  478.       BASSMOD_DllMain(*hInstance, fdwReason, lpvReserved)
  479.       BASSMOD_Free()
  480.       BASSMOD_GetVolume()
  481.       BASSMOD_Init(device=-1, freq=44100, flags=0)
  482.       BASSMOD_MusicFree()
  483.       BASSMOD_MusicGetLength(playlen)
  484.       BASSMOD_MusicGetName()
  485.       BASSMOD_MusicLoad(mem, *file, offset=#Null, length=#Null, flags=#BASS_MUSIC_LOOP|#BASS_MUSIC_POSRESET|#BASS_MUSIC_NONINTER|#BASS_MUSIC_CALCLEN) ;mem=#true -> Load from *memory
  486.       BASSMOD_MusicPause()
  487.       BASSMOD_MusicPlay()
  488.       BASSMOD_MusicSetPosition(pos) ; $FFFF0000 | Seconds (max. $0000FFFF)
  489.       BASSMOD_MusicSetVolume(chanins, volume)
  490.       BASSMOD_MusicStop()
  491.       BASSMOD_SetVolume(volume)
  492.    EndImport
  493. CompilerEndIf
  494. ;}
  495. ;{ #C2D_MUSIC_S68 * Thanx to benjihan for the MC68000 Amiga/Atari SC68 libsc68replay.lib * }
  496. ; http://sc68.atari.org/index.html
  497. ; *.SC68
  498. CompilerIf  #IsS68
  499.    #SC68Replay_MEMORY   =  0
  500.    #SC68Replay_FILE     =  1
  501.    ;Import  "winmm.lib" :  EndImport
  502.    ImportC  "libsc68replay_x86.lib"
  503.       sc68replay_Init(*Ptr, Size, Mode)   As "_sc68replay_Init"
  504.       sc68replay_Play()                   As "_sc68replay_Play"
  505.       sc68replay_Stop()                   As "_sc68replay_Stop"
  506.    EndImport
  507. CompilerEndIf
  508. ;}
  509. ;{ #C2D_MUSIC_BMF * Thanx to BeRo^farbraush for the BR404 Software Synthesizer libbr404.lib * }
  510. ; *.BRO
  511. CompilerIf  #IsBMF
  512.    Import   "libbr404_x86.lib"
  513.       SynthCreate(SampleRate, BufferSize, ThreadPlay, SoundOutput)   As "_SynthCreate@16" ; = int Track
  514.       SynthReadBMFSampleRate(*Ptr, Size)                             As "_SynthReadBMFSampleRate@8"
  515.       SynthReadBMF(Track, *Ptr, Size)                                As "_SynthReadBMF@12"
  516.       SynthPlay(Track)                                               As "_SynthPlay@4"
  517.       SynthSetLooping(Track, Looping)                                As "_SynthSetLooping@8"
  518.       SynthEnter(Track)                                              As "_SynthEnter@4"
  519.       SynthStop(Track)                                               As "_SynthStop@4"
  520.       SynthLeave(Track)                                              As "_SynthLeave@4"
  521.       SynthDestroy(Track)                                            As "_SynthDestroy@4"
  522.    EndImport
  523. CompilerEndIf
  524. ;}
  525. ;{ #C2D_MUSIC_MED * MEDPDLL static lib ripped by Peace^TST * }
  526. ; *.MED;*.MMD0;*.MMD1;*.MMD2;*.MMD3 (PP20)
  527. ;Import  "winmm.lib" :  EndImport
  528. ;Import  "dsound.lib":  EndImport
  529. CompilerIf  #IsMED
  530.    Import   "medpdll_x86.lib"
  531.       MEDPDLL_DllMain(*hinstDLL, fdwReason, lpvReserved) As "_MEDPDLL_DllMain@12"
  532.       MEDP_Initialize(*instance, *mainwindow)            As "__MEDP_Initialize@8"
  533.       MEDP_ChangeOption(option, newvalue)                As "__MEDP_ChangeOption@8"
  534.       MEDP_Load(*filename)                               As "__MEDP_Load@4"
  535.       MEDP_IsLoaded()                                    As "__MEDP_IsLoaded@0"
  536.       MEDP_Play()                                        As "__MEDP_Play@0"
  537.       MEDP_Stop()                                        As "__MEDP_Stop@0"
  538.       MEDP_Unload()                                      As "__MEDP_Unload@0"
  539.       MEDP_ModuleLength()                                As "__MEDP_ModuleLength@0"
  540.       MEDP_ModuleTime()                                  As "__MEDP_ModuleTime@0"
  541.       MEDP_PlayPosition()                                As "__MEDP_PlayPosition@0"
  542.       MEDP_SetPlayPosition(pos)                          As "__MEDP_SetPlayPosition@4"
  543.       MEDP_IsPlaying()                                   As "__MEDP_IsPlaying@0"
  544.       MEDP_ModuleName(*buffer, max)                      As "__MEDP_ModuleName@8"
  545.       MEDP_Release()                                     As "__MEDP_Release@0"
  546.    EndImport
  547. CompilerEndIf
  548. ;}
  549. ;{ #C2D_MUSIC_YMP * YmPluginDLL static lib ripped by Peace^TST * }
  550. ; *.YM
  551. CompilerIf  #IsYMP
  552.    Structure RS_ymMusicInfo_t
  553.       *pSongName
  554.       *pSongAuthor
  555.       *pSongComment
  556.       *pSongType
  557.       *pSongPlayer
  558.       musicTimeInSec.l
  559.       musicTimeInMs.l
  560.    EndStructure
  561.    ;Import  "winmm.lib" :  EndImport
  562.    Import   "YmPlugin_x86.lib"
  563.       YMPLUGIN_DllMain(*hinstDLL, fdwReason, lpvReserved)   As "_YMPLUGIN_DllMain@12"
  564.       YM_Close()                    As "__YM_Close@0"
  565.       YM_FFT()                      As "__YM_FFT@0"
  566.       YM_Get_Info(struct)           As "__YM_Get_Info@4"    ; RS_ymMusicInfo_t
  567.       YM_Init()                     As "__YM_Init@0"
  568.       YM_Open(*file, *memory, size) As "__YM_Open@12"       ; file (size=0) or memory (size <>0)
  569.       YM_Pause()                    As "__YM_Pause@0"
  570.       YM_Play()                     As "__YM_Play@0"
  571.       YM_Seek(seconds)              As "__YM_Seek@4"
  572.       YM_SetVolume(vol)             As "__YM_SetVolume@4"   ; 0..255
  573.       YM_Stop()                     As "__YM_Stop@0"
  574.    EndImport
  575. CompilerEndIf
  576. ;}
  577.  
  578. ;#C2D_MUSIC_WAV ; *.WAV
  579. ;#C2D_MUSIC_API ; *.WAV
  580. ;#C2D_MUSIC_OGG ; *.OGG
  581. ;#C2D_MUSIC_FLA ; *.FLAC
  582. ;#C2D_MUSIC_MCI ; *.MID;*.MP3;*.OGG;*.WMA...
  583.  
  584. ;}
  585. ;************************
  586.  
  587. Procedure   StrSize(Value.q, Flags=1)
  588.  
  589.    Protected   nSize.d
  590.  
  591.    Static   t$ ; return param MUST! global or static in dll
  592.  
  593.    If       Value >= 1099511627776
  594.       nSize =  Value /  1099511627776  :  t$ =  "TB"  ;Pow(1024,4)
  595.    ElseIf   Value >= 1073741824
  596.       nSize =  Value /  1073741824     :  t$ =  "GB"  ;Pow(1024,3)
  597.    ElseIf   Value >= 1048576
  598.       nSize =  Value /  1048576        :  t$ =  "MB"  ;Pow(1024,2)
  599.    ElseIf   Value >= 1024
  600.       nSize =  Value /  1024           :  t$ =  "KB"
  601.    Else  ; also negative size / no NbDecimals
  602.       t$ =  FormatNumber(Value, 0) + " Bytes"
  603.       ProcedureReturn   @t$
  604.    EndIf
  605.  
  606.    t$ =  FormatNumber(nSize, 2) + " " + t$
  607.  
  608.    If Flags
  609.       t$ +  " ("  +  FormatNumber(Value, 0)  +  " Bytes)"
  610.    EndIf
  611.  
  612.    ProcedureReturn   @t$
  613.  
  614.    ; *** Not working in PB x86 ***
  615.    ;  Static   *Memory
  616.    ;  If *Memory  =  #Null :  *Memory  =  AllocateMemory(128)  :  EndIf
  617.    ;  StrFormatByteSize_(Value, *Memory, 128)
  618.    ;  ProcedureReturn   PeekS(*Memory)
  619.  
  620. EndProcedure
  621. Procedure   StrAsc(*Memory)
  622.  
  623.    ; correct ascii or unicode strings
  624.  
  625.    Static   *Buffer
  626.  
  627.    If *Buffer
  628.       FreeMemory(*Buffer)
  629.       *Buffer  =  #Null
  630.    EndIf
  631.  
  632.    If *Memory
  633.       If RS_SCAL\StrFormat =  #PB_Ascii
  634.          ProcedureReturn   *Memory
  635.       Else
  636.          *Buffer  =  Ascii(PeekS(*Memory, -1, RS_SCAL\StrFormat))
  637.       EndIf
  638.    EndIf
  639.  
  640.    ProcedureReturn   *Buffer
  641.  
  642. EndProcedure
  643. Procedure$  StrTime(Time)
  644.  
  645.    ; Milliseconds to String: HH:MM:SS,TTT
  646.    ; Flags <> 0 => show rest ms
  647.  
  648.    Static   t$
  649.  
  650.    t$ =  RSet(StrU(Time  / 3600000),      2, "0")  +  ":"   +  ; HH:
  651.          RSet(StrU((Time / 60000) % 60),  2, "0")  +  ":"   +  ; MM:
  652.          RSet(StrU((Time / 1000)  % 60),  2, "0")              ; SS
  653.  
  654.    t$ +  ","   +  LSet(StrU(Time % 1000), 3, "0")  ; ,TTT
  655.  
  656.    ProcedureReturn   t$
  657.  
  658. ;  Protected   t$=Space(64)
  659. ;  StrFromTimeInterval_(@t$, 64, Time, 1000)
  660. ;  ProcedureReturn   t$
  661.  
  662. EndProcedure
  663.  
  664. ;*******************************
  665. ;- *** NetWork ? ***************
  666. CompilerIf  Defined(HTTP_QUERY_CONTENT_LENGTH,     #PB_Constant)  =  0
  667.    #HTTP_QUERY_CONTENT_LENGTH    =  $5
  668. CompilerEndIf
  669. CompilerIf  Defined(INTERNET_FLAG_RELOAD,          #PB_Constant)  =  0
  670.    #INTERNET_FLAG_RELOAD         =  $80000000
  671. CompilerEndIf
  672. CompilerIf  Defined(INTERNET_FLAG_NO_CACHE_WRITE,  #PB_Constant)  =  0
  673.    #INTERNET_FLAG_NO_CACHE_WRITE =  $4000000
  674. CompilerEndIf
  675.  
  676. Structure   RS_NetWork
  677.    *CallBack   ; @Procedure(Param)
  678.    *hInternet  ; iNetConnection
  679.    *hURL       ; iNetURL
  680.    BytesRead.i ; Buffered bytes
  681.    BytesSkip.i ; Skip bytes of "header"!
  682.    Length.i    ; Bytesize of url
  683. EndStructure
  684. Global   RS_NetWork.RS_NetWork
  685.  
  686. Procedure   NetWorkCallBack(*CallBack=0)
  687.    ; *CallBack = @Procedure(Param)
  688.    RS_NetWork\CallBack  =  *CallBack
  689. EndProcedure
  690. Procedure   NetWorkFree()     ; private
  691.  
  692.    With  RS_NetWork
  693.  
  694.       If \hInternet
  695.          InternetCloseHandle_(\hInternet)
  696.       EndIf
  697.  
  698.       ClearStructure(@RS_NetWork, RS_NetWork)
  699.  
  700.    EndWith
  701.  
  702. EndProcedure
  703. Procedure$  NetWorkUrl(Url$)  ; private
  704.  
  705.    ; Encode unsave characters (canonicalize)
  706.    ; https://www.ietf.org/rfc/rfc1738.txt
  707.  
  708.    Protected   *Memory.Character=@Url$, i
  709.  
  710.    Static   t$
  711.  
  712.    t$ =  #Null$
  713.  
  714.    While *Memory\c
  715.       Select   *Memory\c
  716.          Case  ',',' ','!','"','#','$','&','+',';','<','=','>','@','[','\',']','^','_','`','{','|','}','~',$27 ; not '-','%'
  717.            t$ +  "%"   +  Hex(*Memory\c)
  718.         Default
  719.            If *Memory\c   <> '\'   ; no "\/"
  720.               t$ +  Chr(*Memory\c)
  721.            EndIf
  722.      EndSelect
  723.      *Memory  +  SizeOf(Character)
  724.   Wend
  725.  
  726.   ; Canonicalize filename - else error when char + %
  727.   If StrStrI_(@t$, @"%")
  728.      For   i  =  $20   To $FF
  729.         Select   i
  730.            Case  $20 To $2F, $40 To $FF  ; no numbers
  731.               t$ =  ReplaceString(t$, "%" + Chr(i), "%25" + Chr(i), #PB_String_CaseSensitive)
  732.         EndSelect
  733.      Next
  734.   EndIf
  735.  
  736.   ProcedureReturn   t$
  737.  
  738. EndProcedure
  739. Procedure   NetWorkBytes(Length=4096)
  740.   ; Length (BytesToRead) = Number of bytes preloaded from Url$
  741.   If Length   >  #Null
  742.      RS_NetWork\BytesRead =  Length
  743.   EndIf
  744. EndProcedure
  745. Procedure   NetWorkInit(Url$) ; private
  746.  
  747.   ; Return:  Filesize(Url$) or #NULL -> Error
  748.  
  749.   If StrStrI_(@Url$, @"://") =  #Null :  ProcedureReturn   #Null :  EndIf
  750.  
  751.   Protected   *Memory, Length
  752.  
  753.   With  RS_NetWork
  754.  
  755.      NetWorkCallBack(RS_SCAL\CallBack)   ; always set callback!
  756.  
  757.      If \hInternet  <= #Null
  758.         \hInternet  =  InternetOpen_(@"SCAL/1.0", #INTERNET_OPEN_TYPE_PRECONFIG, 0, 0, 0)
  759.      EndIf
  760.  
  761.      \Length  =  #Null
  762.  
  763.      If \hInternet
  764.  
  765.         If \BytesRead  <= #Null
  766.            NetWorkBytes()
  767.         EndIf
  768.  
  769.         ; Encode unsave URL-Characters (canonicalize)
  770.         Url$     =  NetWorkUrl(Url$)
  771.         Length   =  1024  +  Len(Url$)   +  \BytesSkip  ; + space for query content
  772.         *Memory  =  AllocateMemory(Length * SizeOf(Character))
  773.         PokeS(*Memory, Url$)
  774.  
  775.         \hURL =  InternetOpenUrl_(\hInternet, *Memory, 0, 0, #INTERNET_FLAG_RELOAD|#INTERNET_FLAG_NO_CACHE_WRITE|#INTERNET_FLAG_NO_COOKIES, 0)
  776.  
  777.         If \hURL
  778.            If HttpQueryInfo_(\hURL, #HTTP_QUERY_CONTENT_LENGTH, *Memory, @Length, 0)
  779.               \Length  =  StrToInt_(*Memory)
  780.               If GetLastError_()   Or \Length  <= 0  ; Error?
  781.                  \Length  =  #Null
  782.               ElseIf   \BytesSkip  ; <- skip pseudoheader for deceive hoster?
  783.                  InternetReadFile_(\hURL, *Memory, \BytesSkip, @Length)
  784.                  \Length  -  Length
  785.               EndIf
  786.            EndIf
  787.         EndIf
  788.  
  789.         FreeMemory(*Memory)
  790.  
  791.      EndIf
  792.  
  793.      RS_SCAL\NetLength =  \Length  ; global length for SCAL_Struct()
  794.  
  795.      ProcedureReturn   \Length
  796.  
  797.   EndWith
  798.  
  799. EndProcedure
  800. Procedure   NetWorkLoad(Url$)
  801.  
  802.   ; Download Netfile to *Memory
  803.  
  804.   ; Return: Ptr to *Memory
  805.  
  806.   Protected   *Buffer, Length
  807.   Static   *Memory
  808.  
  809.   *Memory  =  #Null
  810.  
  811.   If NetWorkInit(Url$)
  812.  
  813.      With  RS_NetWork
  814.  
  815.         If \Length  >  #Null
  816.  
  817.            *Memory  =  AllocateMemory(\Length)
  818.            *Buffer  =  *Memory
  819.  
  820.            While InternetReadFile_(\hURL, *Buffer, \BytesRead, @Length)
  821.  
  822.               *Buffer  +  Length
  823.  
  824.               ;// If   *CallBack   And   CallFunctionFast(*CallBack, Percent)   :  Break :  EndIf
  825.               If \CallBack
  826.                  If CallFunctionFast(\CallBack, (100.0 / \Length) * (*Buffer - *Memory)) ; Abort?
  827.                     FreeMemory(*Memory)
  828.                     *Memory  =  #Null
  829.                     Break
  830.                  EndIf
  831.               Else
  832.                  Delay(1)
  833.               EndIf
  834.  
  835.               If (Length  <= #Null)   Or (*Buffer >= *Memory  +  \Length)
  836.                  Break
  837.               EndIf
  838.  
  839.            Wend
  840.  
  841.         EndIf
  842.  
  843.         InternetCloseHandle_(\hURL)
  844.  
  845.      EndWith
  846.  
  847.   EndIf
  848.  
  849.   If RS_NetWork\CallBack
  850.      CallFunctionFast(RS_NetWork\CallBack, 100)
  851.   EndIf
  852.  
  853.   ProcedureReturn   *Memory
  854.  
  855. EndProcedure
  856. Procedure   NetWorkSize(Url$)
  857.  
  858.   ; = size of url$
  859.  
  860.   If NetWorkInit(Url$)
  861.      InternetCloseHandle_(RS_NetWork\hURL)
  862.      ProcedureReturn   RS_NetWork\Length
  863.   EndIf
  864.  
  865. EndProcedure
  866. Procedure   NetWorkSkip(Length=0)
  867.   ; Length (skip bytes) of decive header chars
  868.   If Length   >= #Null
  869.      RS_NetWork\BytesSkip =  Length
  870.   EndIf
  871. EndProcedure
  872. Procedure   NetWorkDownload(Url$, File$)
  873.  
  874.   ; Return: Size of saved file, Error = #NULL
  875.  
  876.   If NetWorkInit(Url$) =  #Null :  ProcedureReturn   #Null :  EndIf
  877.  
  878.   Protected   *Memory, Length, hF
  879.   Protected   nSizeLoad, IsAbort
  880.  
  881.   Static   nSizeSave
  882.  
  883.   nSizeSave   =  #Null
  884.  
  885.   With  RS_NetWork
  886.  
  887.      If \Length  >  #Null
  888.  
  889.         *Memory  =  AllocateMemory(\BytesRead)
  890.  
  891.         hF =  CreateFile(#PB_Any, File$)
  892.  
  893.         If hF
  894.  
  895.            While InternetReadFile_(\hURL, *Memory, \BytesRead, @nSizeLoad)
  896.  
  897.               Length      =  WriteData(hF, *Memory, nSizeLoad)
  898.               nSizeSave   +  Length
  899.  
  900.               ;// If   *CallBack   And   CallFunctionFast(*CallBack, Percent)   :  Break :  EndIf
  901.               If \CallBack
  902.                  If CallFunctionFast(\CallBack, (100.0 / \Length) * nSizeSave)  ; %Percent (Abort?)
  903.                     IsAbort  =  #True
  904.                     Break
  905.                  EndIf
  906.               Else
  907.                  Delay(1)
  908.               EndIf
  909.  
  910.               If nSizeSave   >= \Length  Or Length   <  nSizeLoad   ; Length -> WriteError?
  911.                  Break
  912.               EndIf
  913.  
  914.            Wend
  915.  
  916.            FlushFileBuffers(hF)
  917.            CloseFile(hF)
  918.  
  919.         EndIf
  920.  
  921.         FreeMemory(*Memory)
  922.  
  923.      EndIf
  924.  
  925.      InternetCloseHandle_(\hURL)
  926.  
  927.   EndWith
  928.  
  929.   If IsAbort  ; aborted?
  930.      nSizeSave   =  #Null
  931.      DeleteFile_(@File$)
  932.   EndIf
  933.  
  934.   If RS_NetWork\CallBack
  935.      CallFunctionFast(RS_NetWork\CallBack, 100)
  936.   EndIf
  937.  
  938.   ProcedureReturn   nSizeSave
  939.  
  940. EndProcedure
  941. ;*******************************
  942.  
  943. Declare  SCAL_IsFormat(Mode, *Memory.Long, Length)
  944. Declare  SCAL_SetVolume(Percent)
  945.  
  946. Procedure   scal_Init()
  947.  
  948.   Static   IsInit
  949.  
  950.   If IsInit   :  ProcedureReturn   :  EndIf
  951.  
  952.   IsInit   =  1
  953.  
  954.   InitSound()
  955.  
  956.   CompilerIf  #IsMOV
  957.      InitMovie()
  958.   CompilerEndIf
  959.  
  960. EndProcedure
  961. Procedure   scal_Temp(Name$)
  962.  
  963.   ; Creates %TEMP%\Name$
  964.  
  965.   Protected   t$, Path$, i
  966.   Static   IsError
  967.  
  968.   If RS_SCAL\Temp$  :  ProcedureReturn   #True :  EndIf
  969.  
  970.   Path$    =  GetTemporaryDirectory()
  971.   IsError  =  #Null
  972.  
  973.   Repeat
  974.  
  975.      i  +  1
  976.  
  977.      t$ =  Trim(StringField(Name$, i, #PS$))
  978.  
  979.      If Len(t$)
  980.  
  981.         Path$ +  t$ +  #PS$
  982.  
  983.         If FileSize(Path$)   =  -1
  984.            If CreateDirectory(Path$)  =  #Null
  985.               IsError  =  1  :  Break ; ERROR - Can't create directory
  986.            EndIf
  987.         EndIf
  988.  
  989.      EndIf
  990.  
  991.   Until Len(t$)  =  0
  992.  
  993.   If IsError
  994.      RS_SCAL\Temp$  =  GetTemporaryDirectory()
  995.   Else
  996.      RS_SCAL\Temp$  =  Path$
  997.   EndIf
  998.  
  999.   IsError  !  1
  1000.  
  1001.   ProcedureReturn   IsError  ; true if ok
  1002.  
  1003. EndProcedure
  1004. Procedure   scal_Size(File$)
  1005.  
  1006.   Static   Length
  1007.  
  1008.   If StrStrI_(@File$, @"://")   ; Netfile?
  1009.      Length   =  NetWorkSize(File$)
  1010.      If Length   <  #Null :  Length   =  #Null :  EndIf
  1011.      ProcedureReturn   Length
  1012.   EndIf
  1013.  
  1014.   Length   =  FileSize(File$)
  1015.  
  1016.   If Length   <  #Null :  Length   =  #Null :  EndIf
  1017.  
  1018.   ProcedureReturn   Length
  1019.  
  1020. EndProcedure
  1021. Procedure$  scal_Case(a$, b$)
  1022.  
  1023.   ; canonicalize a$ like b$
  1024.  
  1025.   ; some server allows real upper/lower chars only.
  1026.   ; so we have to adapt the upper/lower chars!
  1027.  
  1028.   ; use it align char-cases of "MDAT.?" / "SMPL.?" files
  1029.  
  1030.   Protected   *a.Character   =  @a$
  1031.   Protected   *b.Character   =  @b$
  1032.  
  1033.   While *a\c  And   *b\c
  1034.      If *b\c  &  %0100000
  1035.         *a\c  |  %0100000
  1036.      Else
  1037.         *a\c  &  %1011111
  1038.      EndIf
  1039.      *a +  SizeOf(Character)
  1040.      *b +  SizeOf(Character)
  1041.   Wend
  1042.  
  1043.   ProcedureReturn   a$
  1044.  
  1045. EndProcedure
  1046. Procedure   scal_Copy(File$, Save$)
  1047.  
  1048.   ; Return:   #True = OK, #False = Error
  1049.  
  1050.   Static   IsError
  1051.  
  1052.   If StrStrI_(@File$, @"://")   ; Netfile?
  1053.      IsError  =  NetWorkDownload(File$, Save$)
  1054.      ProcedureReturn   IsError
  1055.   EndIf
  1056.  
  1057.   IsError  =  CopyFile_(@File$, @Save$, #False)
  1058.  
  1059.   ProcedureReturn   IsError
  1060.  
  1061. EndProcedure
  1062. Procedure   scal_Sufx(*Memory, Flags)
  1063.  
  1064.   ; Checks filename first for "*.mod" & second for "mod.*"
  1065.  
  1066.   ; Do NOT check with GetExtensionPart()
  1067.   ; Extension doesn't accept spaces, that's why we must use the stringfield-trick!
  1068.  
  1069.   ; Return:   ptr to semi-quoted extension ";MOD;" etc.
  1070.  
  1071.    Static   t$
  1072.  
  1073.    Protected   File$ =  GetFilePart(PeekS(*Memory, -1, RS_SCAL\StrFormat))
  1074.  
  1075.    If Flags ; MOD.* (like MDAT.*)
  1076.       t$ =  StringField(File$, 1, ".")
  1077.    Else     ; *.MOD (default)
  1078.       t$ =  Trim(PeekS(PathFindExtension_(@File$), -1), ".")   ;StringField(File$, CountString(File$, ".") + 1, ".")
  1079.    EndIf
  1080.  
  1081.    If Len(t$)  =  #Null Or Len(t$)  >  16 Or StrStrI_(@t$, @" ")  ; spaces in extension are NOT allowed!
  1082.       ProcedureReturn   #Null
  1083.    EndIf
  1084.  
  1085.    CharUpper_(@t$)
  1086.  
  1087.    t$ =  ";"   +  t$ +  ";"
  1088.  
  1089.    ProcedureReturn   @t$
  1090.  
  1091. EndProcedure
  1092. Procedure   scal_Down(URL$)
  1093.  
  1094.    ;- Download file + sfx-libs to temporary path
  1095.    ; Return:   <> 0 = OK
  1096.  
  1097.    Protected   File$, t$, i
  1098.  
  1099.    If StrStrI_(@URL$, @"://") =  #Null :  ProcedureReturn   #Null :  EndIf
  1100.  
  1101.    scal_Temp(#SCAL_TempPath$)
  1102.  
  1103.    File$ =  GetFilePart(URL$)
  1104.    For   i  =  $20   To $FF
  1105.       If StrStrI_(@File$, @"%")  =  #Null :  Break :  EndIf
  1106.       File$ =  ReplaceString(File$, "%" + Hex(i), Chr(i), #PB_String_NoCase)
  1107.    Next
  1108.    File$ =  RS_SCAL\Temp$  +  File$
  1109.  
  1110.    RS_SCAL\File$  =  File$
  1111.  
  1112.    ; *** Already downloaded?
  1113.    If scal_Size(URL$)   =  scal_Size(File$)
  1114.       ProcedureReturn   #True
  1115.    EndIf
  1116.  
  1117.    ; *** Download file to #SCAL_TempPath$
  1118.    If scal_Copy(URL$, File$)  =  0
  1119.       ProcedureReturn   #Null
  1120.    EndIf
  1121.  
  1122.    ; =======================================================
  1123.    ;{ *** Check for needed sfx-lib files on server (x86) ***
  1124.    CompilerIf  #IsAMP
  1125.    If StrStrI_(@File$, @"MDAT.")
  1126.  
  1127.       ; MDAT.* =  Amiga TFMX?          -  Needs the SMPL.* sfx-file! Download always with adapted chars
  1128.  
  1129.       t$ =  GetFilePart(URL$, #PB_FileSystem_NoExtension)
  1130.       t$ =  scal_Case("SMPL", t$)   ; adapt upper / lower chars
  1131.  
  1132.       PokeS(StrStrI_(@URL$, @"MDAT."), t$, -1, #PB_String_NoZero)
  1133.       PokeS(StrStrI_(@File$,@"MDAT."), t$, -1, #PB_String_NoZero)
  1134.       scal_Copy(URL$, File$)
  1135.  
  1136.    ElseIf   StrStrI_(PathFindExtension_(@File$), @".TFX")
  1137.  
  1138.       ; *.TFX  =  Amiga TFMX Clone?    -  Needs the *.SAM sfx-file!  Download always with adapted chars
  1139.  
  1140.       t$ =  GetExtensionPart(URL$)
  1141.       t$ =  "."   +  scal_Case("SAM", t$)
  1142.  
  1143.       PathRenameExtension_(@URL$,   @t$)
  1144.       PathRenameExtension_(@File$,  @t$)
  1145.       scal_Copy(URL$, File$)
  1146.  
  1147.    ElseIf   StrStrI_(PathFindExtension_(@File$), @".KDM")
  1148.  
  1149.       ; *.KDM  =  Ken's Digital Music? -  Needs the waves.kwv sfx-file!
  1150.  
  1151.       URL$  =  GetPathPart(URL$) +  "waves.kwv"
  1152.       File$ =  RS_SCAL\Temp$     +  "waves.kwv"
  1153.       If scal_Size(URL$)   <> scal_Size(File$)
  1154.          scal_Copy(URL$, File$)
  1155.       EndIf
  1156.  
  1157.    ElseIf   StrStrI_(@File$, @".MINI2SF")    Or ; =   Nintendo DS Sound?      -  Needs a tagged *.lib sfx-file
  1158.             StrStrI_(@File$, @".MINIDSF")    Or ; =   Dreamcast Sound?        -  Needs a tagged *.lib sfx-file
  1159.             StrStrI_(@File$, @".MINIGSF")    Or ; =   Gameboy Sound?          -  Needs a tagged *.lib sfx-file
  1160.             StrStrI_(@File$, @".MINIPSF")    Or ; =   Playstation Sound?      -  Needs almost a couple of tagged *.lib sfx-files
  1161.             StrStrI_(@File$, @".PSF")        Or ; =   Playstation Sound?      -  Courious yes/no tagged *.lib sfx-files
  1162.             StrStrI_(@File$, @".MINIPSF2")   Or ; =   Playstation2 Sound?     -  Needs a tagged *.lib sfx-file
  1163.             StrStrI_(@File$, @".MINIQSF")    Or ; =   Capcom Q-Sound?         -  Needs a tagged *.lib sfx-file
  1164.             StrStrI_(@File$, @".MINISNSF")   Or ; =   Super Nintendo Sound?   -  Needs a tagged *.lib sfx-file
  1165.             StrStrI_(@File$, @".MINISSF")    Or ; =   Saturn Sound?           -  Needs almost a couple of tagged *.lib sfx-files
  1166.             StrStrI_(@File$, @".SSF")        Or ; =   Saturn Sound?           -  Courious yes/no tagged *.lib sfx-files
  1167.             StrStrI_(@File$, @".MINIUSF")       ; =   Ultra64 Sound?          -  Needs a tagged *.lib sfx-file
  1168.  
  1169.       ; *** Hardcoded [TAG] check for all needed *.lib sfx-files ***
  1170.       ; (too bad, unfortunately there are occasionally incorrect named *.lib's on modland server)
  1171.       If ReadFile(0, File$)
  1172.          While Eof(0)   =  0
  1173.             t$ =  ReadString(0, #PB_Ascii)
  1174.             If StrStrI_(@t$, @"_lib")  And   StrStrI_(@t$, @"=")                 ; [Tag] & _lib=, _lib1=, _lib2=..
  1175.                t$ =  PeekS(CharLower_(StrStrI_(@t$, @"=") + SizeOf(Character)))  ; LCase(StringField(t$, 2, "="))
  1176.                If scal_Size(GetPathPart(URL$) + t$)   <> scal_Size(RS_SCAL\Temp$ + t$) ; Bad solution, but works for now
  1177.                   scal_Copy(GetPathPart(URL$) + t$, RS_SCAL\Temp$ + t$)
  1178.                EndIf
  1179.             EndIf
  1180.          Wend
  1181.          CloseFile(0)
  1182.       EndIf
  1183.  
  1184.    EndIf
  1185.    CompilerEndIf  ;}
  1186.    ; =======================================================
  1187.  
  1188.    ProcedureReturn   #True
  1189.  
  1190. EndProcedure
  1191.  
  1192. CompilerIf  #IsAMP   ; C:\Users\Public\Documents\AmpMaster\
  1193. PrototypeC  pAmp_Close()
  1194. PrototypeC  pAmp_CountAmpFormatsAll()
  1195. PrototypeC  pAmp_CountAmpPlayersAll()
  1196. PrototypeC  pAmp_CountSubSongs(*File.p-Ascii)
  1197. PrototypeC  pAmp_Free()
  1198. PrototypeC  pAmp_GetAmpFormatsStrAll()
  1199. PrototypeC  pAmp_GetAmpInDllsStrAll(*File.p-Ascii)
  1200. PrototypeC  pAmp_GetAmpInDllStr(*File.p-Ascii)
  1201. PrototypeC  pAmp_GetAmpInFormatStr(*InLib.p-Ascii)
  1202. PrototypeC  pAmp_GetError()
  1203. PrototypeC  pAmp_GetErrorStr(Error.i)
  1204. PrototypeC  pAmp_GetFileInfo(*File.p-Ascii, *Title, *Length)
  1205. PrototypeC  pAmp_GetInFlags(*InLib.p-Ascii)
  1206. PrototypeC  pAmp_GetInFormatStr()
  1207. PrototypeC  pAmp_GetInInfoStr()
  1208. PrototypeC  pAmp_GetOutInfoStr()
  1209. PrototypeC  pAmp_GetPercent()
  1210. PrototypeC  pAmp_GetPlayTime()
  1211. PrototypeC  pAmp_GetStopTime()
  1212. PrototypeC  pAmp_GetSubSong(*File.p-Ascii)
  1213. PrototypeC  pAmp_InAbout()
  1214. PrototypeC  pAmp_InConfig()
  1215. PrototypeC  pAmp_InfoBox(*File.p-Ascii)
  1216. PrototypeC  pAmp_Init()
  1217. PrototypeC  pAmp_MusicBox(*File.p-Ascii, Flags.i=1)
  1218. PrototypeC  pAmp_MusicGetLength(Flags.i=0)
  1219. PrototypeC  pAmp_MusicGetOutPosition()
  1220. PrototypeC  pAmp_MusicGetPosition()
  1221. PrototypeC  pAmp_MusicGetTitleStr()
  1222. PrototypeC  pAmp_MusicIsPlaying()
  1223. PrototypeC  pAmp_MusicIsSeekable()
  1224. PrototypeC  pAmp_MusicPause(Pause.i)
  1225. PrototypeC  pAmp_MusicPlay(*File.p-Ascii)
  1226. PrototypeC  pAmp_MusicSetPan(Pan.i)
  1227. PrototypeC  pAmp_MusicSetPosition(Milliseconds.i)
  1228. PrototypeC  pAmp_MusicSetVolume(Volume.i)
  1229. PrototypeC  pAmp_MusicStop()
  1230. PrototypeC  pAmp_Open()
  1231. PrototypeC  pAmp_OutAbout()
  1232. PrototypeC  pAmp_OutConfig()
  1233. PrototypeC  pAmp_Play(*File.p-Ascii, Volume.i=255)
  1234. PrototypeC  pAmp_QuickPlay(*File.p-Ascii, *Path.p-Ascii)
  1235. PrototypeC  pAmp_SetAmpPath(*Path.p-Ascii)
  1236. PrototypeC  pAmp_SetDefaultLength(Milliseconds.i=0)
  1237. PrototypeC  pAmp_SetInDll(*InLib.p-Ascii)
  1238. PrototypeC  pAmp_SetInPath(*Path.p-Ascii)
  1239. PrototypeC  pAmp_SetLength(Milliseconds.i)
  1240. PrototypeC  pAmp_SetOutDll(*OutLib.p-Ascii)
  1241. PrototypeC  pAmp_SetOutPath(*Path.p-Ascii)
  1242. PrototypeC  pAmp_SetSubSong(*File.p-Ascii, SubSong.i)
  1243. PrototypeC  pAmp_SetWindow(*Window)
  1244. PrototypeC  pAmp_VersionStr(Flags.i=0)
  1245.  
  1246. Structure   RS_Amp
  1247.    DLL.i
  1248.    IsPlay.i
  1249.    TimeLength.i
  1250.    TimeLoop.i
  1251.    File$
  1252.    CountSubSongs     .pAmp_CountSubSongs
  1253.    Play              .pAmp_Play
  1254.    Free              .pAmp_Free
  1255.    GetPlayTime       .pAmp_GetPlayTime
  1256.    GetInInfoStr      .pAmp_GetInInfoStr
  1257.    GetSubSong        .pAmp_GetSubSong
  1258.    MusicGetLength    .pAmp_MusicGetLength
  1259.    MusicGetTitle     .pAmp_MusicGetTitleStr
  1260.    MusicIsSeekable   .pAmp_MusicIsSeekable
  1261.    MusicPause        .pAmp_MusicPause
  1262.    MusicSetPosition  .pAmp_MusicSetPosition
  1263.    MusicSetVolume    .pAmp_MusicSetVolume
  1264.    SetAmpPath        .pAmp_SetAmpPath
  1265.    SetSubSong        .pAmp_SetSubSong
  1266. EndStructure
  1267. Global   RS_Amp.RS_Amp
  1268.  
  1269. ProcedureC  AmpMusicFree()
  1270.    With  RS_Amp
  1271.       If \DLL
  1272.          \Free()
  1273.          FreeLibrary_(\DLL)
  1274.          \DLL     =  #Null
  1275.          \IsPlay  =  #Null
  1276.       EndIf
  1277.    EndWith
  1278. EndProcedure
  1279. ProcedureC  AmpMusicInit(Path$=#Null$)
  1280.  
  1281.    ; Default path to AmpMaster -> "C:\Users\Public\Documents\AmpMaster\"
  1282.  
  1283.    If RS_Amp\DLL  :  ProcedureReturn   RS_Amp\DLL  :  EndIf
  1284.  
  1285.    Protected   t${#MAX_PATH}
  1286.  
  1287.    With  RS_Amp
  1288.  
  1289.       If Path$
  1290.  
  1291.          t$ =  Path$
  1292.  
  1293.       Else  ; C:\Users\Public\Documents\ + "AmpMaster\"
  1294.  
  1295.          SHGetFolderPath_(#Null, #CSIDL_COMMON_DOCUMENTS, #Null, #Null, @t$)
  1296.          PathAddBackslash_(@t$)
  1297.  
  1298.          t$ +  "AmpMaster\"
  1299.  
  1300.       EndIf
  1301.  
  1302.       t$ +  "AmpMaster_x86.dll"
  1303.  
  1304.       \DLL  =  LoadLibrary_(@t$)
  1305.  
  1306.       If \DLL
  1307.  
  1308.          \CountSubSongs    =  GetProcAddress_(\DLL, StrAsc(@"Amp_CountSubSongs"))
  1309.          \Play             =  GetProcAddress_(\DLL, StrAsc(@"Amp_Play"))
  1310.          \Free             =  GetProcAddress_(\DLL, StrAsc(@"Amp_Free"))
  1311.          \MusicGetLength   =  GetProcAddress_(\DLL, StrAsc(@"Amp_MusicGetLength"))
  1312.          \MusicGetTitle    =  GetProcAddress_(\DLL, StrAsc(@"Amp_MusicGetTitleStr"))
  1313.          \MusicPause       =  GetProcAddress_(\DLL, StrAsc(@"Amp_MusicPause"))
  1314.          \MusicIsSeekable  =  GetProcAddress_(\DLL, StrAsc(@"Amp_MusicIsSeekable"))
  1315.          \MusicSetPosition =  GetProcAddress_(\DLL, StrAsc(@"Amp_MusicSetPosition"))
  1316.          \MusicSetVolume   =  GetProcAddress_(\DLL, StrAsc(@"Amp_MusicSetVolume"))
  1317.          \GetPlayTime      =  GetProcAddress_(\DLL, StrAsc(@"Amp_GetPlayTime"))
  1318.          \GetInInfoStr     =  GetProcAddress_(\DLL, StrAsc(@"Amp_GetInInfoStr"))
  1319.          \GetSubSong       =  GetProcAddress_(\DLL, StrAsc(@"Amp_GetSubSong"))
  1320.          \SetAmpPath       =  GetProcAddress_(\DLL, StrAsc(@"Amp_SetAmpPath"))
  1321.          \SetSubSong       =  GetProcAddress_(\DLL, StrAsc(@"Amp_SetSubSong"))
  1322.  
  1323.          If Path$
  1324.             Path$ +  "AmpLibs\"  :  \SetAmpPath(StrAsc(@Path$))   ; set path of amplibs
  1325.          EndIf
  1326.  
  1327.       EndIf
  1328.  
  1329.       ProcedureReturn   \DLL
  1330.  
  1331.    EndWith
  1332.  
  1333. EndProcedure
  1334. ProcedureC  AmpMusicPlay(*Memory, SubSong=0)
  1335.  
  1336.    ; *Memory   =  Ptr to @Filename$ only!
  1337.    ; SubSong   =  Number of subsong to play (eg. SID)
  1338.  
  1339.    ; Return: #True = Music is playing or #False = Error!
  1340.  
  1341.    With  RS_Amp
  1342.  
  1343.       \IsPlay     =  #False
  1344.       \TimeLength =  #Null
  1345.       \TimeLoop   =  #Null
  1346.       \File$      =  PeekS(*Memory, -1, RS_SCAL\StrFormat)
  1347.  
  1348.       If AmpMusicInit()
  1349.  
  1350.          \Free()
  1351.  
  1352.          If SubSong  >  0
  1353.             \SetSubSong(StrAsc(@\File$), SubSong)
  1354.          EndIf
  1355.  
  1356.          If \Play(StrAsc(@\File$))  =  0
  1357.             \TimeLength =  \MusicGetLength()
  1358.             If \TimeLength <= 100   Or StrStrI_(@\File$, @".SID") Or StrStrI_(@\File$, @".PSID")   Or StrStrI_(@\File$, @".RSID")
  1359.                \TimeLength =  600000
  1360.             EndIf
  1361.             \TimeLoop   =  \TimeLength +  ElapsedMilliseconds()   +  50 ; <- Time to reset
  1362.             \IsPlay     =  #True
  1363.          EndIf
  1364.  
  1365.          ProcedureReturn   \IsPlay
  1366.  
  1367.       EndIf
  1368.  
  1369.    EndWith
  1370.  
  1371. EndProcedure
  1372. ProcedureC  AmpMusicStop()
  1373.    RS_Amp\Free()  :  RS_Amp\IsPlay  =  #False
  1374. EndProcedure
  1375. ProcedureC  AmpMusicLoop()
  1376.    If RS_Amp\IsPlay  And   ElapsedMilliseconds()   >  RS_Amp\TimeLoop
  1377.       ProcedureReturn   AmpMusicPlay(@RS_Amp\File$)
  1378.    EndIf
  1379. EndProcedure
  1380. ProcedureC  AmpMusicPosition()
  1381.    If RS_Amp\IsPlay
  1382.       ProcedureReturn   RS_Amp\GetPlayTime()
  1383.    EndIf
  1384. EndProcedure
  1385. ProcedureC  AmpMusicVolume(Volume)
  1386.    If RS_Amp\IsPlay
  1387.       ProcedureReturn   RS_Amp\MusicSetVolume(Volume)
  1388.    EndIf
  1389. EndProcedure
  1390. ProcedureC  AmpMusicTitle()
  1391.    If RS_Amp\IsPlay
  1392.       ProcedureReturn   RS_Amp\MusicGetTitle()
  1393.    EndIf
  1394. EndProcedure
  1395. ProcedureC  AmpCountSubSongs(*Memory)
  1396.    ProcedureReturn   RS_Amp\CountSubSongs(StrAsc(*Memory))
  1397. EndProcedure
  1398. ProcedureC  AmpMusicInfo()
  1399.    If RS_Amp\IsPlay
  1400.       ProcedureReturn   RS_Amp\GetInInfoStr()
  1401.    EndIf
  1402. EndProcedure
  1403. ProcedureC  AmpMusicLength()
  1404.    ProcedureReturn   RS_Amp\TimeLength
  1405. EndProcedure
  1406. ProcedureC  AmpMusicPause(Flags)
  1407.    If RS_Amp\IsPlay
  1408.       ProcedureReturn   RS_Amp\MusicPause(Flags)
  1409.    EndIf
  1410. EndProcedure
  1411. ProcedureC  AmpMusicIsSeekable()
  1412.    With  RS_Amp
  1413.       ProcedureReturn   \MusicIsSeekable()
  1414.    EndWith
  1415. EndProcedure
  1416. ProcedureC  AmpMusicSetPosition(Milliseconds)
  1417.    With  RS_Amp
  1418.       If \IsPlay  And   AmpMusicIsSeekable() And   ; no PSID/SID/RSID
  1419.          StrStrI_(@\File$, @".SID")    =  0  And
  1420.          StrStrI_(@\File$, @".PSID")   =  0  And
  1421.          StrStrI_(@\File$, @".RSID")   =  0
  1422.          ProcedureReturn   \MusicSetPosition(Milliseconds)
  1423.       EndIf
  1424.    EndWith
  1425. EndProcedure
  1426. CompilerEndIf
  1427.  
  1428. CompilerIf  #IsS68
  1429. ProcedureC  sc68_Play(*Memory, Length)
  1430.    With  RS_SCAL
  1431.  
  1432.       If Length
  1433.          \ID      =  sc68replay_Init(*Memory, Length, #SC68Replay_MEMORY)
  1434.          \Title$  =  PeekS(*Memory + $48, -1, #PB_Ascii)
  1435.       Else
  1436.          \ID   =  sc68replay_Init(StrAsc(*Memory), #Null, #SC68Replay_FILE)
  1437.       EndIf
  1438.  
  1439.       If \ID
  1440.          sc68replay_Play()
  1441.       EndIf
  1442.  
  1443.       ProcedureReturn   \ID
  1444.  
  1445.    EndWith
  1446. EndProcedure
  1447. ProcedureC  sc68_Free()
  1448.    If RS_SCAL\ID
  1449.       sc68replay_Stop()
  1450.    EndIf
  1451. EndProcedure
  1452. CompilerEndIf
  1453.  
  1454. Procedure   IsAmpMaster()
  1455.  
  1456.    CompilerIf  #IsAMP
  1457.  
  1458.       Static   t${#MAX_PATH}
  1459.  
  1460.       If Len(t$)  =  #Null
  1461.          SHGetFolderPath_(#Null, #CSIDL_COMMON_DOCUMENTS, #Null, #Null, @t$)
  1462.          PathAddBackslash_(@t$)
  1463.          t$ +  "AmpMaster"
  1464.       EndIf
  1465.  
  1466.       ProcedureReturn   Bool(FileSize(t$) =  -2)
  1467.  
  1468.    CompilerElse
  1469.  
  1470.       ProcedureReturn   #False
  1471.  
  1472.    CompilerEndIf
  1473.  
  1474. EndProcedure
  1475. Procedure   Default_Mode(*Memory.Long, Length)
  1476.  
  1477.    ; Autodetect #C2D_MUSIC_[mode]
  1478.  
  1479.    ; *Memory = Pointer to @Filename if Length = 0
  1480.    ; Checks file.extension ?.* and *.?
  1481.  
  1482.    ; Return: Default playback-mode or 0 = Error!
  1483.  
  1484.    Static   Mode
  1485.  
  1486.    Mode  =  #Null
  1487.  
  1488.    If Length   >  #Null ; *** Check memory for default mode (not to be confused with supported mode!) ***
  1489.  
  1490.       If       SCAL_IsFormat(#C2D_MUSIC_FT2, *Memory, Length)  :  Mode  =  #C2D_MUSIC_FT2 ; stabile Sound/Pro/Mod/FastTracker-Replay
  1491.       ElseIf   SCAL_IsFormat(#C2D_MUSIC_PT2, *Memory, Length)  :  Mode  =  #C2D_MUSIC_PT2 ; only Protracker 2.3d
  1492.       ElseIf   SCAL_IsFormat(#C2D_MUSIC_AHX, *Memory, Length)  :  Mode  =  #C2D_MUSIC_AHX
  1493.       ElseIf   SCAL_IsFormat(#C2D_MUSIC_FC4, *Memory, Length)  :  Mode  =  #C2D_MUSIC_FC4
  1494.       ElseIf   SCAL_IsFormat(#C2D_MUSIC_S3M, *Memory, Length)  :  Mode  =  #C2D_MUSIC_S3M
  1495.       ElseIf   SCAL_IsFormat(#C2D_MUSIC_STM, *Memory, Length)  :  Mode  =  #C2D_MUSIC_STM
  1496.       ElseIf   SCAL_IsFormat(#C2D_MUSIC_OGG, *Memory, Length)  :  Mode  =  #C2D_MUSIC_OGG
  1497.       ElseIf   SCAL_IsFormat(#C2D_MUSIC_FLA, *Memory, Length)  :  Mode  =  #C2D_MUSIC_FLA
  1498.       ElseIf   SCAL_IsFormat(#C2D_MUSIC_WAV, *Memory, Length)  :  Mode  =  #C2D_MUSIC_WAV
  1499.  
  1500.       CompilerIf  (#IsSID  +  #IsTSR)
  1501.       ElseIf   SCAL_IsFormat(#C2D_MUSIC_SID, *Memory, Length)  :  Mode  =  #C2D_MUSIC_SID
  1502.       CompilerEndIf
  1503.       CompilerIf  #IsYMP
  1504.       ElseIf   SCAL_IsFormat(#C2D_MUSIC_YMP, *Memory, Length)  :  Mode  =  #C2D_MUSIC_YMP
  1505.       CompilerEndIf
  1506.       CompilerIf  #IsBAS
  1507.       ElseIf   SCAL_IsFormat(#C2D_MUSIC_BAS, *Memory, Length)  :  Mode  =  #C2D_MUSIC_BAS
  1508.       CompilerEndIf
  1509.       CompilerIf  #IsBMF
  1510.       ElseIf   SCAL_IsFormat(#C2D_MUSIC_BMF, *Memory, Length)  :  Mode  =  #C2D_MUSIC_BMF
  1511.       CompilerEndIf
  1512.       CompilerIf  #IsS68
  1513.       ElseIf   SCAL_IsFormat(#C2D_MUSIC_S68, *Memory, Length)  :  Mode  =  #C2D_MUSIC_S68
  1514.       CompilerEndIf
  1515.       CompilerIf  (#IsV2M  +  #IsV1M)
  1516.       ElseIf   SCAL_IsFormat(#C2D_MUSIC_V2M, *Memory, Length)  :  Mode  =  #C2D_MUSIC_V2M
  1517.       CompilerEndIf
  1518.  
  1519.       Else  ; default memory mode
  1520.  
  1521.          Mode  =  #C2D_MUSIC_MOD
  1522.  
  1523.       EndIf
  1524.  
  1525.    Else  ; *** Checks file.extension ?.* and *.? ***
  1526.  
  1527.       Protected   *x, i
  1528.  
  1529.       For   i  =  0  To 1
  1530.  
  1531.          *x =  scal_Sufx(*Memory, i)   :  If *x =  #Null :  Continue :  EndIf
  1532.  
  1533.          If       StrStrI_(?l_FT2, *x) :  Mode  =  #C2D_MUSIC_FT2
  1534.          ElseIf   StrStrI_(?l_PT2, *x) :  Mode  =  #C2D_MUSIC_PT2
  1535.          ElseIf   StrStrI_(?l_S3M, *x) :  Mode  =  #C2D_MUSIC_S3M
  1536.          ElseIf   StrStrI_(?l_STM, *x) :  Mode  =  #C2D_MUSIC_STM
  1537.          ElseIf   StrStrI_(?l_AHX, *x) :  Mode  =  #C2D_MUSIC_AHX
  1538.          ElseIf   StrStrI_(?l_FC4, *x) :  Mode  =  #C2D_MUSIC_FC4
  1539.          ElseIf   StrStrI_(?l_WAV, *x) :  Mode  =  #C2D_MUSIC_WAV
  1540.          ElseIf   StrStrI_(?l_OGG, *x) :  Mode  =  #C2D_MUSIC_OGG
  1541.          ElseIf   StrStrI_(?l_FLA, *x) :  Mode  =  #C2D_MUSIC_FLA
  1542.  
  1543.          CompilerIf  #IsBAS
  1544.          ElseIf   StrStrI_(?l_BAS, *x) :  Mode  =  #C2D_MUSIC_BAS
  1545.          CompilerEndIf
  1546.          CompilerIf  #IsMED
  1547.          ElseIf   StrStrI_(?l_MED, *x) :  Mode  =  #C2D_MUSIC_MED
  1548.          CompilerEndIf
  1549.          CompilerIf  #IsSID
  1550.          ElseIf   StrStrI_(?l_SID, *x) :  Mode  =  #C2D_MUSIC_SID
  1551.          CompilerEndIf
  1552.          CompilerIf  #IsTSR
  1553.          ElseIf   StrStrI_(?l_SID, *x) :  Mode  =  #C2D_MUSIC_TSR
  1554.          CompilerEndIf
  1555.          CompilerIf  #IsYMP
  1556.          ElseIf   StrStrI_(?l_YMP, *x) :  Mode  =  #C2D_MUSIC_YMP
  1557.          CompilerEndIf
  1558.          CompilerIf  #IsS68
  1559.          ElseIf   StrStrI_(?l_SC68, *x):  Mode  =  #C2D_MUSIC_S68
  1560.          CompilerEndIf
  1561.          CompilerIf  #IsV2M
  1562.          ElseIf   StrStrI_(?l_V2M, *x)
  1563.             If IsAmpMaster()
  1564.                Mode  =  #C2D_MUSIC_AMP ; stabile v1.0/1.5 playback
  1565.             Else
  1566.                Mode  =  #C2D_MUSIC_V2M
  1567.             EndIf
  1568.          CompilerEndIf
  1569.          CompilerIf  #IsBMF
  1570.          ElseIf   StrStrI_(?l_BMF, *x) :  Mode  =  #C2D_MUSIC_BMF
  1571.          CompilerEndIf
  1572.  
  1573.          ElseIf   StrStrI_(?l_MCI, *x) :  Mode  =  #C2D_MUSIC_MCI
  1574.          ElseIf   StrStrI_(?l_MOD, *x) :  Mode  =  #C2D_MUSIC_MOD
  1575.  
  1576.          CompilerIf  #IsAMP   ; check at last, coz we don't know if ampmaster is installed?
  1577.          ElseIf   StrStrI_(?l_AMP, *x) :  Mode  =  #C2D_MUSIC_AMP
  1578.          CompilerEndIf
  1579.  
  1580.          EndIf
  1581.  
  1582.          If Mode  :  Break :  EndIf
  1583.  
  1584.          ;Mode =  #C2D_MUSIC_MCI ; pre-set as default
  1585.  
  1586.       Next
  1587.  
  1588.    EndIf
  1589.  
  1590.    ProcedureReturn   Mode
  1591.  
  1592. EndProcedure
  1593.  
  1594. ;- *** Functions ***************
  1595. ProcedureDLL   SCAL_AmpInstall(*URL)
  1596.  
  1597.    ; Only for Windows x86!
  1598.  
  1599.    ; *** ZIP ***
  1600.    ; https://testaware.files.wordpress.com/2020/08/ampmaster200824
  1601.  
  1602.    CompilerIf  #IsAMP
  1603.  
  1604.       scal_Temp(#SCAL_TempPath$) ; create temporary directory for all files
  1605.  
  1606.       Static   IsError
  1607.       Protected   URL$, File$, i, Count
  1608.  
  1609.       ; 2.5KB smaller than -> Install_Path$  =  GetUserDirectory(#PB_Directory_Public)
  1610.       Protected   Install_Path${#MAX_PATH}
  1611.       SHGetFolderPath_(#Null, #CSIDL_COMMON_DOCUMENTS, #Null, #Null, @Install_Path$)
  1612.       PathAddBackslash_(@Install_Path$)
  1613.  
  1614.       If *URL
  1615.          URL$  =  PeekS(*URL, -1, RS_SCAL\StrFormat)
  1616.       Else
  1617.          URL$  =  #SCAL_AmpMaster$  +  ".gif"
  1618.       EndIf
  1619.  
  1620.       If StrStrI_(@URL$, @"://")
  1621.  
  1622.          File$ =  RS_SCAL\Temp$ + GetFilePart(URL$, #PB_FileSystem_NoExtension) + ".zip"
  1623.  
  1624.          If StrStrI_(@URL$, @".GIF")
  1625.             NetWorkSkip(6) ; "GIF89a" -> ; skip to real Arc-Header (6 bytes)
  1626.          Else
  1627.             NetWorkSkip(#Null)
  1628.          EndIf
  1629.  
  1630.          IsError  =  Bool(NetWorkDownload(URL$, File$)=0)
  1631.  
  1632.       Else  ; unpack file-archive
  1633.  
  1634.          File$    =  URL$
  1635.          IsError  =  Bool(FileSize(File$)<=0)   ; file error?
  1636.  
  1637.       EndIf
  1638.  
  1639.       If IsError  =  0
  1640.  
  1641.          Count =  ZIP_GetFilesCount(File$)
  1642.  
  1643.          If Count
  1644.             For   i  =  1  To Count
  1645.                If ZIP_ExtractFile(File$, i, Install_Path$)
  1646.                   If RS_SCAL\CallBack  ; user proc?
  1647.                      If CallFunctionFast(RS_SCAL\CallBack, (100.0 / Count) * (i + 1))  ; 126 Files + 3 Folders
  1648.                         IsError  =  #True
  1649.                         Break
  1650.                      EndIf
  1651.                   EndIf
  1652.                Else
  1653.                   IsError  =  #True
  1654.                   Break
  1655.                EndIf
  1656.             Next
  1657.          Else
  1658.             IsError  =  #True
  1659.          EndIf
  1660.  
  1661.       Else
  1662.  
  1663.          IsError  =  #True
  1664.  
  1665.       EndIf
  1666.  
  1667.       If RS_SCAL\CallBack  :  CallFunctionFast(RS_SCAL\CallBack, 100)   :  EndIf ; user proc?
  1668.  
  1669.       ; *** #True = ALL correct unpacked, #False = ERROR!
  1670.       ProcedureReturn   Bool(IsError=0)
  1671.  
  1672.    CompilerElse
  1673.  
  1674.       If RS_SCAL\CallBack  :  CallFunctionFast(RS_SCAL\CallBack, 100)   :  EndIf ; user proc?
  1675.  
  1676.       ProcedureReturn   #False
  1677.  
  1678.    CompilerEndIf
  1679.  
  1680. EndProcedure
  1681. ProcedureDLL   SCAL_CallBack(*Proc)
  1682.    ; *proc = @Procedurename(Param)
  1683.    ; Param -> downloadstatus 0-100%
  1684.    RS_SCAL\CallBack  =  *Proc ; NetWorkCallBack()
  1685. EndProcedure
  1686. ProcedureDLL   SCAL_Download(*URL, *File, Skip, Flags)
  1687.  
  1688.    ; Return:   Bytesize of download or number of unpacked files
  1689.  
  1690.    Static   Count
  1691.    Protected   i, File$, Path$, URL$
  1692.  
  1693.    If *URL  =  #Null :  ProcedureReturn   #Null :  EndIf
  1694.  
  1695.    URL$  =  PeekS(*URL, -1, RS_SCAL\StrFormat)
  1696.    If StrStrI_(@URL$, @"://") =  #Null :  ProcedureReturn   #Null :  EndIf
  1697.  
  1698.    If *File =  #Null
  1699.       scal_Temp(#SCAL_TempPath$)
  1700.       File$ =  RS_SCAL\Temp$ + GetFilePart(URL$)
  1701.    Else
  1702.       File$ =  PeekS(*File, -1, RS_SCAL\StrFormat)
  1703.    EndIf
  1704.  
  1705.    ; *** already downloaded?
  1706.    Count =  scal_Size(File$)
  1707.    If scal_Size(URL$)   =  Count
  1708.       ProcedureReturn   Count
  1709.    EndIf
  1710.  
  1711.    NetWorkSkip(Skip)
  1712.  
  1713.    i  =  NetWorkDownload(URL$, File$)
  1714.  
  1715.    ; *** Unzip archive?
  1716.    If Flags And   i  >  #Null
  1717.  
  1718.       Count =  ZIP_GetFilesCount(File$)
  1719.  
  1720.       If Count
  1721.  
  1722.          Path$ =  GetPathPart(File$)
  1723.  
  1724.          For   i  =  1  To Count
  1725.             If ZIP_ExtractFile(File$, i, Path$)
  1726.                If RS_SCAL\CallBack  ; user proc?
  1727.                   If CallFunctionFast(RS_SCAL\CallBack, (100.0 / Count) * (i + 1))
  1728.                      Count =  i
  1729.                      Break
  1730.                   EndIf
  1731.                EndIf
  1732.             Else
  1733.                Count =  i
  1734.                Break
  1735.             EndIf
  1736.          Next
  1737.  
  1738.       Else
  1739.  
  1740.          Count =  i  ; bytesize if not packed
  1741.  
  1742.       EndIf
  1743.  
  1744.    Else
  1745.  
  1746.       Count =  i  ; bytesize
  1747.  
  1748.    EndIf
  1749.  
  1750.    If RS_SCAL\CallBack  :  CallFunctionFast(RS_SCAL\CallBack, 100)   :  EndIf ; user proc?
  1751.  
  1752.    ProcedureReturn   Count
  1753.  
  1754. EndProcedure
  1755. ProcedureDLL   SCAL_DownMemory(*URL, *Length.Integer)
  1756.  
  1757.    Static   *Memory
  1758.  
  1759.    If *Memory  >  #Null
  1760.       FreeMemory(*Memory)
  1761.       *Memory  =  #Null
  1762.    EndIf
  1763.  
  1764.    If *URL  <= #Null Or *Length  <= #Null :  ProcedureReturn   #Null :  EndIf
  1765.  
  1766.    *Memory  =  NetWorkLoad(PeekS(*URL, -1, RS_SCAL\StrFormat))
  1767.  
  1768.    If *Memory
  1769.       *Length\i   =  RS_NetWork\Length
  1770.    Else
  1771.       *Length\i   =  #Null
  1772.    EndIf
  1773.  
  1774.    ProcedureReturn   *Memory
  1775.  
  1776. EndProcedure
  1777. ProcedureDLL   SCAL_Formats(Mode, Flags)
  1778.  
  1779.    ; Mode:  #C2D_MUSIC_[MODE] =  Get info of supported formats by Mode
  1780.    ;        < min or > max    =  Get info of all supported formats by SCAL
  1781.  
  1782.    ; Flags: 0  =  Get number of supported formats
  1783.    ;        1  =  Get ptr to unicode formatstrings "AHX;MOD;MP3..."
  1784.  
  1785.    Static   Count
  1786.    Static   TotalMode$, TotalCount
  1787.  
  1788.    Protected   t$, *Memory.Character
  1789.  
  1790.    Select   Mode
  1791.       Case  #SCAL_MIN   To #SCAL_MAX
  1792.  
  1793.          ;{ Mode = #C2D_MUSIC_[MODE] - Calculate supported formats by Engine }
  1794.  
  1795.          Select   Mode
  1796.  
  1797.             Case  #C2D_MUSIC_AHX :  *Memory  =  ?l_AHX
  1798.  
  1799.             CompilerIf  #IsAMP
  1800.             Case  #C2D_MUSIC_AMP :  *Memory  =  ?l_AMP
  1801.             CompilerEndIf
  1802.  
  1803.             Case  #C2D_MUSIC_API :  *Memory  =  ?l_WAV
  1804.  
  1805.             CompilerIf  #IsBAS
  1806.             Case  #C2D_MUSIC_BAS :  *Memory  =  ?l_BAS
  1807.             CompilerEndIf
  1808.  
  1809.             CompilerIf  #IsBMF
  1810.             Case  #C2D_MUSIC_BMF :  *Memory  =  ?l_BMF
  1811.             CompilerEndIf
  1812.  
  1813.             Case  #C2D_MUSIC_FC4 :  *Memory  =  ?l_FC4
  1814.  
  1815.             CompilerIf  #IsFCP
  1816.             Case  #C2D_MUSIC_FCP :  *Memory  =  ?l_FCP
  1817.             CompilerEndIf
  1818.  
  1819.             Case  #C2D_MUSIC_FLA :  *Memory  =  ?l_FLA
  1820.  
  1821.             Case  #C2D_MUSIC_FT2 :  *Memory  =  ?l_FT2
  1822.  
  1823.             Case  #C2D_MUSIC_MCI :  *Memory  =  ?l_MCI
  1824.  
  1825.             CompilerIf  #IsMED
  1826.             Case  #C2D_MUSIC_MED :  *Memory  =  ?l_MED
  1827.             CompilerEndIf
  1828.  
  1829.             Case  #C2D_MUSIC_MOD :  *Memory  =  ?l_MOD
  1830.  
  1831.             CompilerIf  #IsMOV
  1832.             Case  #C2D_MUSIC_MOV :  *Memory  =  ?l_MCI
  1833.             CompilerEndIf
  1834.  
  1835.             Case  #C2D_MUSIC_OGG :  *Memory  =  ?l_OGG
  1836.  
  1837.             Case  #C2D_MUSIC_PT2 :  *Memory  =  ?l_PT2
  1838.  
  1839.             CompilerIf  #IsS68
  1840.             Case  #C2D_MUSIC_S68 :  *Memory  =  ?l_SC68
  1841.             CompilerEndIf
  1842.  
  1843.             CompilerIf  #IsSID
  1844.             Case  #C2D_MUSIC_SID :  *Memory  =  ?l_SID
  1845.             CompilerEndIf
  1846.  
  1847.             Case  #C2D_MUSIC_STM :  *Memory  =  ?l_STM
  1848.  
  1849.             Case  #C2D_MUSIC_S3M :  *Memory  =  ?l_S3M
  1850.  
  1851.             Case  #C2D_MUSIC_TFC :  *Memory  =  ?l_FC4
  1852.  
  1853.             Case  #C2D_MUSIC_THX :  *Memory  =  ?l_AHX
  1854.  
  1855.             Case  #C2D_MUSIC_TPT :  *Memory  =  ?l_PT2
  1856.  
  1857.             CompilerIf  #IsTSR
  1858.             Case  #C2D_MUSIC_TSR :  *Memory  =  ?l_SID
  1859.             CompilerEndIf
  1860.  
  1861.             CompilerIf  #IsV1M
  1862.             Case  #C2D_MUSIC_V1M :  *Memory  =  ?l_V2M
  1863.             CompilerEndIf
  1864.  
  1865.             CompilerIf  #IsV2M
  1866.             Case  #C2D_MUSIC_V2M :  *Memory  =  ?l_V2M
  1867.             CompilerEndIf
  1868.  
  1869.             Case  #C2D_MUSIC_WAV :  *Memory  =  ?l_WAV
  1870.  
  1871.             CompilerIf  #IsXM2
  1872.             Case  #C2D_MUSIC_XM2 :  *Memory  =  ?l_XM2
  1873.             CompilerEndIf
  1874.  
  1875.             CompilerIf  #IsYMP
  1876.             Case  #C2D_MUSIC_YMP :  *Memory  =  ?l_YMP
  1877.             CompilerEndIf
  1878.  
  1879.          EndSelect
  1880.  
  1881.          If Flags And   *Memory
  1882.             ProcedureReturn   *Memory  ; ptr to ;MOD;...
  1883.          EndIf
  1884.  
  1885.          If *Memory  ; count extensions?
  1886.             Count =  -2 ; first ";" + last ";" + #null
  1887.             While *Memory  >  SizeOf(Character)
  1888.                *Memory  =  StrStrI_(*Memory, @";") +  SizeOf(Character)
  1889.                Count +  1
  1890.             Wend
  1891.          Else
  1892.             Count =  #Null
  1893.          EndIf
  1894.  
  1895.          ProcedureReturn   Count
  1896.          ;}
  1897.  
  1898.       Default  ; -1
  1899.  
  1900.          ;{ Mode <= #Null - Calculate ALL supported formats once }
  1901.  
  1902.          If TotalCount
  1903.             If Flags ; String?
  1904.                ProcedureReturn   @TotalMode$
  1905.             EndIf
  1906.             ProcedureReturn   TotalCount
  1907.          EndIf
  1908.  
  1909.          Protected   NewMap   ExtMap.s()
  1910.          Protected   NewList  ExtList.s()
  1911.  
  1912.          *Memory  =  ?l_Start
  1913.          While *Memory  <  ?l_Finish
  1914.             If *Memory\c
  1915.                t$ =  PeekS(*Memory)
  1916.                TotalMode$  +  Trim(t$, ";")  +  ";"   :  *Memory  +  Len(t$)  *  SizeOf(Character)
  1917.             EndIf
  1918.             *Memory  +  SizeOf(Character) ; Null$
  1919.          Wend
  1920.  
  1921.          Repeat
  1922.             TotalCount  +  1  :  t$ =  StringField(TotalMode$, TotalCount, ";")  :  ExtMap(t$)
  1923.          Until Len(t$)  =  #Null
  1924.  
  1925.          ForEach  ExtMap()
  1926.             If MapKey(ExtMap())
  1927.                AddElement(ExtList())   :  ExtList()   =  MapKey(ExtMap())
  1928.             EndIf
  1929.          Next
  1930.  
  1931.          SortList(ExtList(), #PB_Sort_Ascending)
  1932.  
  1933.          TotalCount  =  ListSize(ExtList())
  1934.          TotalMode$  =  ";"   ; ";Format;"
  1935.          ForEach  ExtList()
  1936.             TotalMode$  +  ExtList()   +  ";"
  1937.          Next
  1938.  
  1939.          FreeMap(ExtMap())
  1940.          FreeList(ExtList())
  1941.  
  1942.          If Flags
  1943.             ProcedureReturn   @TotalMode$
  1944.          EndIf
  1945.  
  1946.          ProcedureReturn   TotalCount
  1947.          ;}
  1948.  
  1949.    EndSelect
  1950.  
  1951. EndProcedure
  1952. ProcedureDLL   SCAL_Free()
  1953.  
  1954.    Protected   StrFormat, Freq, *Proc
  1955.    Static   Volume=-1
  1956.  
  1957.    With  RS_SCAL
  1958.  
  1959.       If \ID   ; Is playing active?
  1960.          Select   \Mode
  1961.  
  1962.             Case  #C2D_MUSIC_AHX :  ahx1play_Close()
  1963.             Case  #C2D_MUSIC_API :  PlaySound_(#Null, #Null, #Null)
  1964.             Case  #C2D_MUSIC_FC4 :  fc14play_Close()
  1965.             Case  #C2D_MUSIC_FLA :  If IsSound(0)  :  FreeSound(0)   :  EndIf
  1966.             Case  #C2D_MUSIC_FT2 :  ft2play_Close()
  1967.             Case  #C2D_MUSIC_MCI :  mciSendString_(@"STOP 0", 0, 0, 0)  :  mciSendString_(@"CLOSE 0", 0, 0, 0)
  1968.             Case  #C2D_MUSIC_MOD :  If IsMusic(0)  :  FreeMusic(0)   :  EndIf
  1969.             Case  #C2D_MUSIC_OGG :  If IsSound(0)  :  FreeSound(0)   :  EndIf
  1970.             Case  #C2D_MUSIC_PT2 :  pt2play_Close()
  1971.             Case  #C2D_MUSIC_S3M :  st3play_Close()
  1972.             Case  #C2D_MUSIC_STM :  st23play_Close()
  1973.             Case  #C2D_MUSIC_TFC :  tinyfc14play_Close()
  1974.             Case  #C2D_MUSIC_THX :  tinyahx1play_Close()
  1975.             Case  #C2D_MUSIC_TPT :  tinypt2play_Close()
  1976.             Case  #C2D_MUSIC_WAV :  If IsSound(0)  :  FreeSound(0)   :  EndIf
  1977.  
  1978.             CompilerIf  #IsAMP
  1979.             Case  #C2D_MUSIC_AMP :  AmpMusicFree()
  1980.             CompilerEndIf
  1981.             CompilerIf  #IsBAS
  1982.             Case  #C2D_MUSIC_BAS
  1983.                BASSMOD_MusicStop()
  1984.                BASSMOD_MusicFree()
  1985.                BASSMOD_SetVolume(100)  ; restore digital volume!
  1986.                BASSMOD_Free()
  1987.             CompilerEndIf
  1988.             CompilerIf  #IsBMF
  1989.             Case  #C2D_MUSIC_BMF
  1990.                SynthEnter(\ID)
  1991.                SynthStop(\ID)
  1992.                SynthLeave(\ID)
  1993.                SynthDestroy(\ID)
  1994.             CompilerEndIf
  1995.             CompilerIf  #IsFCP
  1996.             Case  #C2D_MUSIC_FCP :  FCp_Close()
  1997.             CompilerEndIf
  1998.             CompilerIf  #IsMED
  1999.             Case  #C2D_MUSIC_MED
  2000.                MEDP_Stop()
  2001.                MEDP_Unload()
  2002.                MEDP_Release()
  2003.             CompilerEndIf
  2004.             CompilerIf  #IsMOV
  2005.             Case  #C2D_MUSIC_MOV
  2006.                If IsMovie(0)     :  FreeMovie(0)      :  EndIf
  2007.                If \WinID   And   IsWindow(\WinID)
  2008.                   CloseWindow(\WinID)
  2009.                EndIf
  2010.                \WinID   =  #Null
  2011.             CompilerEndIf
  2012.             CompilerIf  #IsS68
  2013.             Case  #C2D_MUSIC_S68 :  sc68_Free() ;sc68replay_Stop()
  2014.             CompilerEndIf
  2015.             CompilerIf  #IsSID
  2016.             Case  #C2D_MUSIC_SID :  SIDClose()
  2017.             CompilerEndIf
  2018.             CompilerIf  #IsTSR
  2019.             Case  #C2D_MUSIC_TSR :  sid_sound_server_replay_stop()
  2020.             CompilerEndIf
  2021.             CompilerIf  #IsV1M
  2022.             Case  #C2D_MUSIC_V1M
  2023.                ssStop()
  2024.                ssClose()
  2025.             CompilerEndIf
  2026.             CompilerIf  #IsV2M
  2027.             Case  #C2D_MUSIC_V2M
  2028.                If \IsPause =  0  ; remember: custom pause!
  2029.                   V2MStop()
  2030.                   dsClose()
  2031.                EndIf
  2032.             CompilerEndIf
  2033.             CompilerIf  #IsXM2
  2034.             Case  #C2D_MUSIC_XM2 :  uFMOD_PlaySong(#Null)
  2035.             CompilerEndIf
  2036.             CompilerIf  #IsYMP
  2037.             Case  #C2D_MUSIC_YMP
  2038.                YM_Stop()
  2039.                YM_Close()
  2040.             CompilerEndIf
  2041.  
  2042.          EndSelect
  2043.       EndIf
  2044.  
  2045.       ; Netfile downloaded?
  2046.       NetWorkFree()
  2047.  
  2048.       ; Intern temporary *buffer?
  2049.       If \IsAlloc And   \Memory
  2050.          FreeMemory(\Memory)
  2051.       EndIf
  2052.  
  2053.       ; AscII or Unicode?
  2054.       If \StrFormat  <= #Null
  2055.          \StrFormat  =  #PB_Unicode ; Default PeekS-Mode if *Memory = @File
  2056.       EndIf
  2057.  
  2058.       ; Set default frequency
  2059.       If \Freq <= #Null
  2060.          \Freq =  44100
  2061.       EndIf
  2062.  
  2063.       ; Set default volume (used in SCAL_Play)
  2064.       If Volume   <  #Null And   \Volume  <= #Null
  2065.          \Volume  =  100
  2066.       EndIf
  2067.  
  2068.       StrFormat   =  \StrFormat
  2069.       Freq        =  \Freq
  2070.       Volume      =  \Volume
  2071.       *Proc       =  \CallBack
  2072.  
  2073.       ClearStructure(@RS_SCAL, RS_SCAL)
  2074.  
  2075.       \Freq       =  Freq
  2076.       \StrFormat  =  StrFormat
  2077.       \Volume     =  Volume   ; -1
  2078.       \CallBack   =  *Proc
  2079.       \NetLength  =  #Null
  2080.  
  2081.       ; Generate *pointers (avoid *ptr=0 error)
  2082.       \File$      =  #Null$
  2083.       \Path$      =  #Null$
  2084.       \Time$      =  #Null$
  2085.       \Title$     =  #Null$
  2086.       \Tracker$   =  #Null$
  2087.  
  2088.    EndWith
  2089.  
  2090. EndProcedure
  2091. ProcedureDLL   SCAL_GetLength(Flags)
  2092.  
  2093.    ; Flags: 0  =  Get timelength in ms
  2094.    ;        1  =  Get ptr to unicode timestring "hh:mm:ss.ttt"
  2095.  
  2096.    ; RETURN: Time in ms or ptr to timestring - #NULL not playing or time not calcuable
  2097.  
  2098.    With  RS_SCAL
  2099.  
  2100.       If Flags
  2101.          If \Time
  2102.             \Time$   =  StrTime(\Time)
  2103.             \Time$   =  RTrim(\Time$, "0")
  2104.             \Time$   =  RTrim(\Time$, ",")
  2105.          Else
  2106.             \Time$   =  PeekS(?s_unknown) ; "?"
  2107.          EndIf
  2108.          ProcedureReturn   @\Time$
  2109.       EndIf
  2110.  
  2111.       ProcedureReturn   \Time
  2112.  
  2113.    EndWith
  2114.  
  2115. EndProcedure
  2116. ProcedureDLL   SCAL_GetMode(Flags)
  2117.  
  2118.    ; Flags: 0  =  Get #ID of playengine
  2119.    ;        1  =  Get *ptr to string char[3] of playengine
  2120.  
  2121.    Static   t$
  2122.  
  2123.    With  RS_SCAL
  2124.  
  2125.       If \ID   =  #Null ; do not check with <= 0
  2126.          If Flags
  2127.             ProcedureReturn   ?s_unknown
  2128.          EndIf
  2129.          ProcedureReturn   #Null
  2130.       EndIf
  2131.  
  2132.       If Flags
  2133.          t$ =  PeekS(PeekI(?mode + \Mode * SizeOf(Integer)))
  2134.          t$ =  StringField(t$, 1, "|")
  2135.          ProcedureReturn   @t$
  2136.          ;ProcedureReturn  (?s_Mode +  (\Mode   -  1) *  4  *  SizeOf(Character))   ; 4 = AHX + 0
  2137.       EndIf
  2138.  
  2139.       ProcedureReturn   \Mode
  2140.  
  2141.    EndWith
  2142.  
  2143. EndProcedure
  2144. ProcedureDLL   SCAL_GetPosition(Flags)
  2145.  
  2146.    ; Flags: 0  =  Get current playposition in ms
  2147.    ;        1  =  Get ptr to timestring (hh:mm:ss.ttt) of current playposition
  2148.  
  2149.    ; RETURN:   Playtime in ms or *ptr to timestring
  2150.  
  2151.    ; - remarked engines calculate a timeline not the real pos of mixerticks!
  2152.    ; - call GetPosition() also to loop song on end
  2153.  
  2154.    Static   Time, t${#MAX_PATH}
  2155.  
  2156.    With  RS_SCAL
  2157.  
  2158.       If \ID   =  #Null ; do not check with <= 0
  2159.          If Flags
  2160.             ProcedureReturn   ?s_unknown
  2161.          EndIf
  2162.          ProcedureReturn   #Null
  2163.       EndIf
  2164.  
  2165.       Select   \Mode
  2166.  
  2167.          ;Case #C2D_MUSIC_AHX :  Time  =  ahx1play_GetMixerTicks()
  2168.          ;Case #C2D_MUSIC_FC4 :  Time  =  fc14play_GetMixerTicks()
  2169.          ;Case #C2D_MUSIC_FT2 :  Time  =  ft2play_GetMixerTicks()
  2170.          ;Case #C2D_MUSIC_PT2 :  Time  =  pt2play_GetMixerTicks()
  2171.          ;Case #C2D_MUSIC_STM :  Time  =  st23play_GetMixerTicks()
  2172.          ;Case #C2D_MUSIC_S3M :  Time  =  st3play_GetMixerTicks()
  2173.  
  2174.          Case  #C2D_MUSIC_OGG, #C2D_MUSIC_FLA, #C2D_MUSIC_WAV
  2175.             Time  =  GetSoundPosition(0, #PB_Sound_Millisecond)
  2176.  
  2177.          Case  #C2D_MUSIC_MCI
  2178.             mciSendString_(@"STATUS 0 POSITION", @t$, #MAX_PATH, 0)
  2179.             StrToInt64Ex_(@t$, #Null, @Time)
  2180.  
  2181.          CompilerIf  #IsV2M
  2182.          Case  #C2D_MUSIC_V2M
  2183.             Time  =  V2MGetCurrentTime()
  2184.          CompilerEndIf
  2185.  
  2186.          CompilerIf  #IsXM2
  2187.          Case  #C2D_MUSIC_XM2
  2188.             Time  =  uFMOD_GetTime()
  2189.          CompilerEndIf
  2190.  
  2191.          CompilerIf  #IsAMP
  2192.          Case  #C2D_MUSIC_AMP
  2193.             Time  =  AmpMusicPosition()
  2194.             If Time  >= RS_Amp\TimeLength
  2195.                RS_Amp\TimeLoop   =  #Null
  2196.                AmpMusicLoop() ; reload file
  2197.                AmpMusicVolume(2.55 * RS_SCAL\Volume)
  2198.             EndIf
  2199.          CompilerEndIf
  2200.  
  2201.          Default
  2202.  
  2203.             Time  =  ElapsedMilliseconds()   -  \TimePlay
  2204.  
  2205.             ; reset time-position & loop media?
  2206.             If \Time And   Time  >= \Time
  2207.  
  2208.                Select   \Mode
  2209.                   Case  #C2D_MUSIC_YMP
  2210.                      CompilerIf  #IsYMP
  2211.                         ; time is -200 ms coz no loop on (real) end
  2212.                         ; some songs work, some not...
  2213.                         YM_Seek(0)
  2214.                      CompilerEndIf
  2215.                   Case  #C2D_MUSIC_MOV
  2216.                      CompilerIf  #IsMOV
  2217.                         MovieSeek(0, 0)
  2218.                      CompilerEndIf
  2219.                EndSelect
  2220.  
  2221.                Time        =  #Null
  2222.                \TimePlay   =  ElapsedMilliseconds()
  2223.  
  2224.             EndIf
  2225.  
  2226.       EndSelect
  2227.  
  2228.       If Time  <  #Null :  Time  =  #Null :  EndIf
  2229.  
  2230.       If Flags ; TimeString?
  2231.          \Time$   =  StrTime(Time)
  2232.          ProcedureReturn   @\Time$
  2233.       EndIf
  2234.  
  2235.       ProcedureReturn   Time
  2236.  
  2237.    EndWith
  2238.  
  2239. EndProcedure
  2240. ProcedureDLL   SCAL_GetSize(Flags)
  2241.  
  2242.    ; Flags: 0 = Integer, 1 = *StrSize
  2243.  
  2244.    With  RS_SCAL
  2245.  
  2246.       If \Length  <= #Null
  2247.          \Length  =  FileSize(\File$)
  2248.       EndIf
  2249.  
  2250.       If \Length  <  #Null
  2251.          \Length  =  #Null
  2252.       EndIf
  2253.  
  2254.       If Flags
  2255.          ProcedureReturn   StrSize(\Length)
  2256.       EndIf
  2257.  
  2258.       ProcedureReturn   \Length
  2259.  
  2260.    EndWith
  2261.  
  2262. EndProcedure
  2263. ProcedureDLL   SCAL_GetSubsongs()
  2264.    With  RS_SCAL
  2265.       ProcedureReturn   \Songs
  2266.    EndWith
  2267. EndProcedure
  2268. ProcedureDLL   SCAL_GetTitle()
  2269.    With  RS_SCAL
  2270.       ProcedureReturn   @\Title$
  2271.    EndWith
  2272. EndProcedure
  2273. ProcedureDLL   SCAL_GetTracker()
  2274.    With  RS_SCAL
  2275.       ProcedureReturn   @\Tracker$
  2276.    EndWith
  2277. EndProcedure
  2278. ProcedureDLL   SCAL_Info(Flags)
  2279.  
  2280.    Protected   t$, Title$="SCAL DLL v" + StrF(#SCAL_VERSION * 0.01, 2)
  2281.  
  2282.    CompilerIf  #IsX86
  2283.       Title$   +  " (x86)"
  2284.    CompilerElse
  2285.       Title$   +  " (x64)"
  2286.    CompilerEndIf
  2287.  
  2288.    With  RS_SCAL
  2289.  
  2290.       ; Sound playing?
  2291.       If \ID   <= #Null :  ProcedureReturn   #Null :  EndIf
  2292.  
  2293.       If \Length  <= #Null
  2294.          \Length  =  SCAL_GetSize(0)
  2295.       EndIf
  2296.  
  2297.       If \File$
  2298.          \File$   =  ReplaceString(\File$, "%20", " ")
  2299.          t$ +  "File:"  +  #TAB$ +  GetFilePart(\File$)  +  #LF$
  2300.          t$ +  "Path:"  +  #TAB$ +  GetPathPart(\File$)  +  #LF$
  2301.       EndIf
  2302.  
  2303.       If \Length        :  t$ +  "Size:"  +  #TAB$ +  PeekS(SCAL_GetSize(1))        +  #LF$  :  EndIf
  2304.  
  2305.       If t$ :  t$ +  #LF$  :  EndIf ; kosmetische Freizeile
  2306.  
  2307.       If \Title$        :  t$ +  "Title:" +  #TAB$ +  \Title$                       +  #LF$  :  EndIf ; PeekS(SCAL_GetTitle())
  2308.  
  2309.       If \Time >  #Null :  t$ +  "Time:"  +  #TAB$ +  PeekS(SCAL_GetLength(1))      +  #LF$  :  EndIf
  2310.  
  2311.       If \Songs   >  1
  2312.          t$ +  "Song:"  +  #TAB$ +  Str(\SubSong + \ZipSong) + "/" + Str(\Songs)    +  #LF$  ; Str(SCAL_GetSubsongs())
  2313.       EndIf
  2314.  
  2315.       t$ +  #LF$  ; kosmetische Freizeile
  2316.  
  2317.       If \Tracker$      :  t$ +  "Type:"  +  #TAB$ +  \Tracker$                     +  #LF$  :  EndIf ; PeekS(SCAL_GetTracker())
  2318.  
  2319.       t$ +  #LF$  +  "Mode:"  +  #TAB$ +  "#C2D_MUSIC_"  +  PeekS(SCAL_GetMode(1))  +  #LF$
  2320.  
  2321.       ProcedureReturn   MessageBox_(GetForegroundWindow_(), @t$, @Title$, Flags)
  2322.  
  2323.    EndWith
  2324.  
  2325. EndProcedure
  2326. ProcedureDLL   SCAL_IsFormat(Mode, *Memory.Long, Length)
  2327.  
  2328.    ; Tiny check file.extension ?.* and *.? or *Memoryblock
  2329.  
  2330.    ; *Memory   =  Pointer to @File or *Memory
  2331.    ; Length    =  Size of *Memory or 0 if *Memory = @File
  2332.  
  2333.    ; Return:   Mode or #NULL if not supported
  2334.  
  2335.    Static   Typ
  2336.  
  2337.    Typ   =  #Null
  2338.  
  2339.    If Length   <= #Null
  2340.  
  2341.       ;{ *File? }
  2342.  
  2343.       Protected   *x, i
  2344.  
  2345.       For   i  =  0  To 1
  2346.  
  2347.          *x =  scal_Sufx(*Memory, i)   :  If *x =  #Null :  Continue :  EndIf
  2348.  
  2349.          Select   Mode
  2350.          Case  #C2D_MUSIC_AHX, #C2D_MUSIC_THX   :  Typ   =  StrStrI_(?l_AHX, *x)
  2351.          Case  #C2D_MUSIC_FC4, #C2D_MUSIC_TFC   :  Typ   =  StrStrI_(?l_FC4, *x)
  2352.          Case  #C2D_MUSIC_PT2, #C2D_MUSIC_TPT   :  Typ   =  StrStrI_(?l_PT2, *x)
  2353.          Case  #C2D_MUSIC_API, #C2D_MUSIC_WAV   :  Typ   =  StrStrI_(?l_WAV, *x)
  2354.          Case  #C2D_MUSIC_MCI, #C2D_MUSIC_MOV   :  Typ   =  StrStrI_(?l_MCI, *x)
  2355.          Case  #C2D_MUSIC_FT2 :  Typ   =  StrStrI_(?l_FT2, *x)
  2356.          Case  #C2D_MUSIC_S3M :  Typ   =  StrStrI_(?l_S3M, *x)
  2357.          Case  #C2D_MUSIC_STM :  Typ   =  StrStrI_(?l_STM, *x)
  2358.          Case  #C2D_MUSIC_FLA :  Typ   =  StrStrI_(?l_FLA, *x)
  2359.          Case  #C2D_MUSIC_OGG :  Typ   =  StrStrI_(?l_OGG, *x)
  2360.          Case  #C2D_MUSIC_MOD :  Typ   =  StrStrI_(?l_MOD, *x)
  2361.  
  2362.          CompilerIf  #IsAMP
  2363.          Case  #C2D_MUSIC_AMP
  2364.             Typ   =  StrStrI_(?l_AMP, *x)
  2365.          CompilerEndIf
  2366.          CompilerIf  #IsBAS
  2367.          Case  #C2D_MUSIC_BAS
  2368.                Typ   =  StrStrI_(?l_BAS, *x)
  2369.          CompilerEndIf
  2370.          CompilerIf  #IsBMF
  2371.          Case  #C2D_MUSIC_BMF
  2372.             Typ   =  StrStrI_(?l_BMF, *x)
  2373.          CompilerEndIf
  2374.          CompilerIf  #IsMED
  2375.          Case  #C2D_MUSIC_MED
  2376.             Typ   =  StrStrI_(?l_MED, *x)
  2377.          CompilerEndIf
  2378.          CompilerIf  #IsFCP
  2379.          Case  #C2D_MUSIC_FCP
  2380.             Typ   =  StrStrI_(?l_FCP, *x)
  2381.          CompilerEndIf
  2382.          CompilerIf  #IsS68
  2383.          Case  #C2D_MUSIC_S68
  2384.             Typ   =  StrStrI_(?l_SC68, *x)
  2385.          CompilerEndIf
  2386.          CompilerIf  (#IsSID  +  #IsTSR)
  2387.          Case  #C2D_MUSIC_SID, #C2D_MUSIC_TSR
  2388.             Typ   =  StrStrI_(?l_SID, *x)
  2389.          CompilerEndIf
  2390.          CompilerIf  (#IsV1M  +  #IsV2M)
  2391.          Case  #C2D_MUSIC_V1M, #C2D_MUSIC_V2M
  2392.             Typ   =  StrStrI_(?l_V2M, *x)
  2393.          CompilerEndIf
  2394.          CompilerIf  #IsXM2
  2395.          Case  #C2D_MUSIC_XM2
  2396.             Typ   =  StrStrI_(?l_XM2, *x)
  2397.          CompilerEndIf
  2398.          CompilerIf  #IsYMP
  2399.          Case  #C2D_MUSIC_YMP
  2400.             Typ   =  StrStrI_(?l_YMP, *x)
  2401.          CompilerEndIf
  2402.  
  2403.          Default  ; < Min or > Max  -> search through all extensions (SCAL Mode)
  2404.  
  2405.             Typ   =  StrStrI_(SCAL_Formats(#Null, 1), *x)   ; fastest check on 2. call!
  2406.  
  2407.          EndSelect
  2408.  
  2409.          If Typ   >  0  :  Break :  EndIf
  2410.  
  2411.       Next
  2412.       ;}
  2413.  
  2414.    Else
  2415.  
  2416.       ;{ *Memory? }
  2417.  
  2418.       Protected   *ID_MOD.Long   =  *Memory  +  $438
  2419.       Protected   *ID_STM.Long   =  *Memory  +  $14
  2420.       Protected   *ID_S3M.Long   =  *Memory  +  $2C
  2421.       Protected   *ID_WAV.Long   =  *Memory  +  $8
  2422.       CompilerIf  #IsYMP
  2423.          Protected   *ID_YMP.Long   =  *Memory  +  $2
  2424.       CompilerEndIf
  2425.  
  2426.       Select   Mode
  2427.          Case  #C2D_MUSIC_PT2, #C2D_MUSIC_TPT
  2428.             Typ   =  Bool(*ID_MOD\l =  #ID_M_K_ Or
  2429.                           *ID_MOD\l =  #ID_MIKI Or
  2430.                           *ID_MOD\l =  #ID_MAKI Or
  2431.                           *ID_MOD\l =  #ID_N_T_)
  2432.  
  2433.          Case  #C2D_MUSIC_FT2
  2434.             Typ   =  Bool(*Memory\l =  #ID_XM)  +
  2435.                      Bool(*ID_MOD\l =  #ID_6CHN Or
  2436.                           *ID_MOD\l =  #ID_8CHN Or
  2437.                           *ID_MOD\l =  #ID_FLT4 Or
  2438.                           *ID_MOD\l =  #ID_FLT8 Or
  2439.                           *ID_MOD\l =  #ID_M_K_ Or
  2440.                           *ID_MOD\l =  #ID_MIKI Or
  2441.                           *ID_MOD\l =  #ID_MAKI Or
  2442.                           *ID_MOD\l =  #ID_N_T_)
  2443.  
  2444.          Case  #C2D_MUSIC_AHX, #C2D_MUSIC_THX
  2445.             Typ   =  Bool(*Memory\l =  #ID_AHX  Or
  2446.                           *Memory\l =  #ID_THX)
  2447.  
  2448.          Case  #C2D_MUSIC_FC4, #C2D_MUSIC_TFC
  2449.             Typ   =  Bool(*Memory\l =  #ID_SMOD Or
  2450.                           *Memory\l =  #ID_FC14)
  2451.  
  2452.          Case  #C2D_MUSIC_S3M
  2453.             Typ   =  Bool(*ID_S3M\l =  #ID_S3M)
  2454.  
  2455.          Case  #C2D_MUSIC_STM
  2456.             Typ   =  Bool(*ID_STM\l =  #ID_STM)
  2457.  
  2458.          Case  #C2D_MUSIC_OGG
  2459.             Typ   =  Bool(*Memory\l =  #ID_OGG)
  2460.  
  2461.          Case  #C2D_MUSIC_FLA
  2462.             Typ   =  Bool(*Memory\l =  #ID_FLAC)
  2463.  
  2464.          Case  #C2D_MUSIC_API, #C2D_MUSIC_WAV
  2465.             Typ   =  Bool(*Memory\l =  #ID_RIFF And
  2466.                           *ID_WAV\l =  #ID_WAVE)
  2467.  
  2468.          Case  #C2D_MUSIC_MOD
  2469.             Typ   =  Bool(*ID_MOD\l =  #ID_M_K_ Or
  2470.                           *ID_MOD\l =  #ID_MIKI Or
  2471.                           *ID_MOD\l =  #ID_MAKI Or
  2472.                           *ID_MOD\l =  #ID_N_T_ Or
  2473.                           *ID_MOD\l =  #ID_6CHN Or
  2474.                           *ID_MOD\l =  #ID_8CHN Or
  2475.                           *ID_MOD\l =  #ID_FLT4 Or
  2476.                           *ID_MOD\l =  #ID_FLT8)   +
  2477.                      Bool(*ID_S3M\l =  #ID_S3M)    +
  2478.                      Bool(*ID_STM\l =  #ID_STM)    +
  2479.                      Bool(*Memory\l =  #ID_XM   Or
  2480.                           *Memory\l =  #ID_IT   Or
  2481.                           *Memory\l =  #ID_UMX  Or
  2482.                           *Memory\l =  #ID_MTM  Or
  2483.                           *Memory\l =  #ID_MT20 Or
  2484.                           *Memory\l =  #ID_MMD0 Or
  2485.                           *Memory\l =  #ID_MMD1 Or
  2486.                           *Memory\l =  #ID_MMD2 Or
  2487.                           *Memory\l =  #ID_MMD3 Or
  2488.                           *Memory\l =  #ID_OKTA)   +
  2489.                      Bool(*Memory\l =  #ID_RIFF And
  2490.                           *ID_WAV\l =  #ID_WAVE)
  2491.  
  2492.          CompilerIf  #IsBAS
  2493.          Case  #C2D_MUSIC_BAS
  2494.             Typ   =  Bool(*Memory\l =  #ID_IT   Or
  2495.                           *Memory\l =  #ID_UMX  Or
  2496.                           *Memory\l =  #ID_MTM)    +
  2497.                      Bool(*Memory\l =  #ID_XM   Or
  2498.                           *ID_MOD\l =  #ID_6CHN Or
  2499.                           *ID_MOD\l =  #ID_8CHN Or
  2500.                           *ID_MOD\l =  #ID_FLT4 Or
  2501.                           *ID_MOD\l =  #ID_FLT8)   +
  2502.                      Bool(*ID_MOD\l =  #ID_M_K_ Or
  2503.                           *ID_MOD\l =  #ID_MIKI Or
  2504.                           *ID_MOD\l =  #ID_MAKI Or
  2505.                           *ID_MOD\l =  #ID_N_T_)   +
  2506.                      Bool(*ID_S3M\l =  #ID_S3M)
  2507.          CompilerEndIf
  2508.          CompilerIf  #IsBMF
  2509.          Case  #C2D_MUSIC_BMF
  2510.             Typ   =  Bool(*Memory\l =  #ID_BMF4)
  2511.          CompilerEndIf
  2512.          CompilerIf  #IsFCP
  2513.          Case  #C2D_MUSIC_FCP
  2514.             Typ   =  Bool(*Memory\l =  #ID_FC14)
  2515.          CompilerEndIf
  2516.          CompilerIf  #IsS68
  2517.          Case  #C2D_MUSIC_S68
  2518.             Typ   =  Bool(*Memory\l =  #ID_SC68)
  2519.          CompilerEndIf
  2520.          CompilerIf  (#IsSID  +  #IsTSR)
  2521.          Case  #C2D_MUSIC_SID, #C2D_MUSIC_TSR
  2522.             Typ   =  Bool(*Memory\l =  #ID_SID)
  2523.          CompilerEndIf
  2524.          CompilerIf  (#IsV2M  +  #IsV1M)
  2525.          Case  #C2D_MUSIC_V1M, #C2D_MUSIC_V2M
  2526.             Typ   =  Bool(*Memory\l =  #ID_V2M  Or
  2527.                           *Memory\l =  #ID_V2M6 Or
  2528.                           *Memory\l =  #ID_V2ME)
  2529.             ; Loosy but important v1.5 sanity check or... crash
  2530.             If Mode  =  #C2D_MUSIC_V2M And   PeekL(*Memory + Length - SizeOf(Long)) <> #Null
  2531.                Typ   =  #Null
  2532.             EndIf
  2533.          CompilerEndIf
  2534.          CompilerIf  #IsXM2
  2535.          Case  #C2D_MUSIC_XM2 :  Typ   =  Bool(*Memory\l =  #ID_XM)
  2536.          CompilerEndIf
  2537.          CompilerIf  #IsYMP
  2538.          Case  #C2D_MUSIC_YMP
  2539.             Typ   =  Bool(*ID_YMP\l =  #ID_LH5  Or
  2540.                           *Memory\l =  #ID_YM6I)
  2541.          CompilerEndIf
  2542.  
  2543.       EndSelect
  2544.       ;}
  2545.  
  2546.    EndIf
  2547.  
  2548.    ProcedureReturn   Bool(Typ > #Null)
  2549.  
  2550. EndProcedure
  2551. ProcedureDLL   SCAL_Pause(Flags)
  2552.  
  2553.    ; Flags: 1 = Pause, 0 = Resume
  2554.  
  2555.    ; Return: 1 = paused, 0 = unpaused or no pause possible by engine
  2556.  
  2557.    Static   Time
  2558.  
  2559.    With  RS_SCAL
  2560.  
  2561.       If \ID   =  #Null :  ProcedureReturn   #Null :  EndIf
  2562.  
  2563.       Flags =  Bool(Flags<>0)
  2564.  
  2565.       If \IsPause =  Flags :  ProcedureReturn   \IsPause :  EndIf
  2566.  
  2567.       \IsPause =  Flags
  2568.  
  2569.       Select   \Mode
  2570.  
  2571.          Case  #C2D_MUSIC_AHX
  2572.             ahx1play_PauseSong(\IsPause)
  2573.  
  2574.          CompilerIf  #IsAMP
  2575.          Case  #C2D_MUSIC_AMP
  2576.             AmpMusicPause(\IsPause)
  2577.          CompilerEndIf
  2578.  
  2579.          CompilerIf  #IsBAS
  2580.          Case  #C2D_MUSIC_BAS
  2581.             If \IsPause
  2582.                BASSMOD_MusicPause()
  2583.             Else
  2584.                BASSMOD_MusicPlay()
  2585.             EndIf
  2586.          CompilerEndIf
  2587.  
  2588.          CompilerIf  #IsBMF
  2589.          Case  #C2D_MUSIC_BMF
  2590.             If \IsPause
  2591.                SynthStop(\ID)
  2592.             Else
  2593.                SynthPlay(\ID)
  2594.             EndIf
  2595.          CompilerEndIf
  2596.  
  2597.          Case  #C2D_MUSIC_FC4
  2598.             fc14play_PauseSong(\IsPause)
  2599.  
  2600.          Case  #C2D_MUSIC_FLA, #C2D_MUSIC_OGG, #C2D_MUSIC_WAV
  2601.             If IsSound(0)
  2602.                If \IsPause
  2603.                   PauseSound(0)
  2604.                Else
  2605.                   ResumeSound(0)
  2606.                EndIf
  2607.             EndIf
  2608.  
  2609.          Case  #C2D_MUSIC_FT2
  2610.             ft2play_PauseSong(\IsPause)
  2611.  
  2612.          Case  #C2D_MUSIC_MCI
  2613.             If \IsPause
  2614.                mciSendString_(@"PAUSE 0", 0, 0, 0)
  2615.             Else
  2616.                mciSendString_(@"RESUME 0",   0, 0, 0)
  2617.             EndIf
  2618.  
  2619.          CompilerIf  #IsMED
  2620.          Case  #C2D_MUSIC_MED
  2621.             If \IsPause
  2622.                MEDP_Stop()
  2623.             Else
  2624.                MEDP_Play()
  2625.             EndIf
  2626.          CompilerEndIf
  2627.  
  2628.          Case  #C2D_MUSIC_MOD
  2629.             If \IsPause
  2630.                StopMusic(0)
  2631.             Else
  2632.                PlayMusic(0)
  2633.             EndIf
  2634.  
  2635.          CompilerIf  #IsMOV
  2636.          Case  #C2D_MUSIC_MOV
  2637.             If \IsPause
  2638.                PauseMovie(0)
  2639.             Else
  2640.                ResumeMovie(0)
  2641.             EndIf
  2642.          CompilerEndIf
  2643.  
  2644.          Case  #C2D_MUSIC_PT2
  2645.             pt2play_PauseSong(\IsPause)
  2646.  
  2647.          Case  #C2D_MUSIC_S3M
  2648.             st3play_PauseSong(\IsPause)
  2649.  
  2650.          CompilerIf  #IsSID
  2651.          Case  #C2D_MUSIC_SID
  2652.             If \IsPause
  2653.                SIDPause()
  2654.             Else
  2655.                SIDResume()
  2656.             EndIf
  2657.          CompilerEndIf
  2658.  
  2659.          Case  #C2D_MUSIC_STM
  2660.             st23play_PauseSong(\IsPause)
  2661.  
  2662.          CompilerIf  #IsV2M   ; Custom Pause
  2663.          Case  #C2D_MUSIC_V2M
  2664.             If \IsPause
  2665.                Time  =  V2MGetCurrentTime()
  2666.                V2MStop()
  2667.                dsClose()
  2668.             Else
  2669.                V2MInit(\Memory, \Freq, GetForegroundWindow_())
  2670.                V2MSetRepeat(1)
  2671.                dsSetVolume(0.01  *  \Volume)
  2672.                V2MPlay(Time)
  2673.             EndIf
  2674.          CompilerEndIf
  2675.  
  2676.          CompilerIf  #IsXM2
  2677.          Case  #C2D_MUSIC_XM2
  2678.             If \IsPause
  2679.                uFMOD_Pause()
  2680.             Else
  2681.                uFMOD_Resume()
  2682.             EndIf
  2683.          CompilerEndIf
  2684.  
  2685.          CompilerIf  #IsYMP
  2686.          Case  #C2D_MUSIC_YMP
  2687.             If \IsPause
  2688.                YM_Pause()
  2689.             Else
  2690.                YM_Play()
  2691.             EndIf
  2692.          CompilerEndIf
  2693.  
  2694.       Default
  2695.  
  2696.          ; #C2D_MUSIC_API, #C2D_MUSIC_FCP, #C2D_MUSIC_S68
  2697.          ; #C2D_MUSIC_SCA, #C2D_MUSIC_TFC, #C2D_MUSIC_THX
  2698.          ; #C2D_MUSIC_TPT, #C2D_MUSIC_TSR, #C2D_MUSIC_V1M
  2699.  
  2700.          \IsPause =  #Null
  2701.          ProcedureReturn   #Null
  2702.  
  2703.       EndSelect
  2704.  
  2705.       ; Timecorrection, coz some mixerticks do a simple timeline
  2706.       Select   \Mode
  2707.          Case  #C2D_MUSIC_AHX,
  2708.                #C2D_MUSIC_BAS,
  2709.                #C2D_MUSIC_BMF,
  2710.                #C2D_MUSIC_FC4,
  2711.                #C2D_MUSIC_FT2,
  2712.                #C2D_MUSIC_PT2,
  2713.                #C2D_MUSIC_MED,
  2714.                #C2D_MUSIC_MOD,
  2715.                #C2D_MUSIC_MOV,
  2716.                #C2D_MUSIC_S3M,
  2717.                #C2D_MUSIC_SID,
  2718.                #C2D_MUSIC_STM,
  2719.                #C2D_MUSIC_YMP
  2720.             If \IsPause
  2721.                Time  =  ElapsedMilliseconds()
  2722.             Else
  2723.                \TimePlay   +  ElapsedMilliseconds()   -  Time
  2724.             EndIf
  2725.       EndSelect
  2726.  
  2727.       ProcedureReturn   \IsPause
  2728.  
  2729.    EndWith
  2730.  
  2731. EndProcedure
  2732. ProcedureDLL   SCAL_Play(Mode, *Memory, Length, SubSong)
  2733.  
  2734.    ; Mode      =  -1 (autoset) or #C2D_MUSIC_[Mode]
  2735.    ; *Memory   =  Ptr to data or @Filename$
  2736.    ; Length    =  Size(End) of data or #Null (*Memory = @Filename$)
  2737.    ; SubSong   =  #Subsong to play (#AMP, #SID, #TSR)
  2738.  
  2739.    ; Return: #True = Music is playing or #False = Error!
  2740.  
  2741.    Protected   IsOK, IsAmp, i, t$, Path$, *x, MDAT$, SMPL$
  2742.    Static   File$ ; *Memory = temporary @File$
  2743.  
  2744.    SCAL_Free() ; always stop if playing
  2745.  
  2746.    With  RS_SCAL
  2747.  
  2748.       ; Check for not-supported engines (*)do NOT check with [SCA] here!
  2749.       If Mode  =  #C2D_MUSIC_V1M Or Mode  =  #C2D_MUSIC_S68
  2750.          ProcedureReturn   #Null
  2751.       EndIf
  2752.  
  2753.       ; Check if *Memory is a ptr to a @Filename
  2754.       If Length   <= #Null
  2755.          \File$   =  PeekS(*Memory, -1, \StrFormat)
  2756.       EndIf
  2757.  
  2758.       ; ==========================================================================
  2759.       ;{ Network file? ("http://...") *** also download all needed sfx-libs ***
  2760.       If Length   <= 0  And   StrStrI_(@\File$, @"://")
  2761.          If scal_Down(\File$)
  2762.             *Memory  =  @\File$
  2763.             Length   =  #Null
  2764.          Else
  2765.             SCAL_Free() :  ProcedureReturn   #Null
  2766.          EndIf
  2767.       EndIf
  2768.       ;}
  2769.       ; ==========================================================================
  2770.  
  2771.       ; ==========================================================================
  2772.       ;{ Check for zipped @File (Extension)
  2773.       If Length   <= #Null
  2774.  
  2775.          *x =  scal_Sufx(@\File$, 0)   ; ";ZIP;" etc.
  2776.  
  2777.          If *x And   StrStrI_(?l_ZIP, *x)
  2778.  
  2779.             scal_Temp(#SCAL_TempPath$)
  2780.  
  2781.             \ZipCount   =  ZIP_GetFilesCount(\File$)
  2782.  
  2783.             If \ZipCount   <= 2  ; Single zipped or TFMX (MDAT+SMPL)?
  2784.                i  =  1  ; First file in archive
  2785.             Else
  2786.                \IsZip   =  1  ; Playing subsongs from zip-archive (flag)
  2787.                ;\Songs  =  \ZipCount;
  2788.                \ZipSong =  SubSong  ; SongNumber of archive-file (for Info)
  2789.                i        =  SubSong  ; SongNumber of archive-file to unpack
  2790.                SubSong  =  #Null    ; No individual subsong when zipped archive
  2791.                If i  <= #Null :  i  =  1  :  EndIf
  2792.             EndIf
  2793.  
  2794.             t$ =  GetFilePart(ZIP_GetFileInfo(\File$, i))
  2795.  
  2796.             If Len(t$)  =  #Null :  SCAL_Free() :  ProcedureReturn   #Null :  EndIf
  2797.  
  2798.             CompilerIf  #IsAMP
  2799.                ; UnZIP always TFMX (almost same names for different songs/sample-banks (MDAT.ingame1...)
  2800.  
  2801.                *x =  PathFindExtension_(@t$)
  2802.  
  2803.                If StrStrI_(@t$, @"MDAT.") Or StrStrI_(@t$, @"SMPL.") Or ; TFMX
  2804.                   StrStrI_(*x,  @".TFX")  Or StrStrI_(*x,  @".SAM")  Or ; TFMX Custom
  2805.                   StrStrI_(*x,  @".KDM")  ; Ken's Digital Music (waves.kwv sfx-bank)
  2806.  
  2807.                   IsAMP =  #True
  2808.  
  2809.                   If ZIP_ExtractFile(\File$, i, \Temp$)  =  #False   ; Error?
  2810.                      SCAL_Free() :  ProcedureReturn   #Null
  2811.                   EndIf
  2812.  
  2813.                   If       StrStrI_(@t$, @"MDAT.") =  @t$   :  PokeS(@t$, "SMPL", -1, #PB_String_NoZero)
  2814.                   ElseIf   StrStrI_(@t$, @"SMPL.") =  @t$   :  PokeS(@t$, "MDAT", -1, #PB_String_NoZero)
  2815.                   ElseIf   StrStrI_(*x,  @".SAM")  :  PathRenameExtension_(@t$, @".TFX")  ; need the song.tfx
  2816.                   ElseIf   StrStrI_(*x,  @".TFX")  :  PathRenameExtension_(@t$, @".SAM")  ; need the sfx-file.sam
  2817.                   ElseIf   StrStrI_(*x,  @".KDM")  :  File$ =  t$ :  t$ =  "waves.kwv"    ; need kwv sfx-bank
  2818.                   EndIf
  2819.  
  2820.                   i  =  ZIP_GetFileNumber(\File$, t$)
  2821.  
  2822.                   If i  <= #Null Or ZIP_ExtractFile(\File$, i, \Temp$)  =  #False   ; Error?
  2823.                      SCAL_Free() :  ProcedureReturn   #Null
  2824.                   EndIf
  2825.  
  2826.                   ; Restore songname!
  2827.                   If       StrStrI_(@t$, @"SMPL.") =  @t$               :  PokeS(@t$, "MDAT", -1, #PB_String_NoZero)
  2828.                   ElseIf   StrStrI_(PathFindExtension_(@t$), @".SAM")   :  PathRenameExtension_(@t$, @".TFX")
  2829.                   ElseIf   StrStrI_(PathFindExtension_(@t$), @".KWV")   :  t$ =  File$
  2830.                   EndIf
  2831.  
  2832.                EndIf
  2833.             CompilerEndIf
  2834.  
  2835.             ; No AMP & Do not UnZip if already unzipped
  2836.             If IsAMP =  #Null And   FileSize(\Temp$ + t$)   <= #Null
  2837.                If ZIP_ExtractFile(\File$, i, \Temp$)  =  #False   ; Error?
  2838.                   SCAL_Free() :  ProcedureReturn   #Null
  2839.                EndIf
  2840.             EndIf
  2841.  
  2842.             ; Update to temporary unzipped filename
  2843.             \File$   =  \Temp$   +  t$
  2844.             \Title$  =  t$
  2845.             *Memory  =  @\File$
  2846.  
  2847.          EndIf
  2848.       EndIf
  2849.       ;}
  2850.       ; ==========================================================================
  2851.  
  2852.       ; ==========================================================================
  2853.       ;{ Check mode-flag (when own-call (*) [SCA] - change to default mode
  2854.       If Bool(Mode = #C2D_MUSIC_SCA Or Mode < #SCAL_MIN Or Mode > #SCAL_MAX)  ; (-1,0) .. Clamp(1 upto 29)
  2855.          If Length   >  #Null
  2856.             Mode  =  Default_Mode(*Memory, Length)
  2857.          Else
  2858.             Mode  =  Default_Mode(@\File$, #Null)
  2859.          EndIf
  2860.          If Mode  <= #Null
  2861.             SCAL_Free() :  ProcedureReturn   #Null
  2862.          EndIf
  2863.       EndIf
  2864.       ;}
  2865.       ; ==========================================================================
  2866.  
  2867.       ; ================================================================================
  2868.       ; Play from memory? Check if file-only mode -> reset to its default support-engine
  2869.       ; ================================================================================
  2870.       If Length   >  #Null
  2871.          Select   Mode  ; this can't play from memory
  2872.             Case  #C2D_MUSIC_AMP,
  2873.                   #C2D_MUSIC_MCI,
  2874.                   #C2D_MUSIC_MED,
  2875.                   #C2D_MUSIC_MOV
  2876.                Mode  =  Default_Mode(*Memory, Length)
  2877.          EndSelect
  2878.       EndIf
  2879.  
  2880.       \Mode =  Mode
  2881.  
  2882.       ; *** @File or *Memory?
  2883.       Select   \Mode
  2884.          Case  #C2D_MUSIC_AMP ; *Memory = @File (ascii)
  2885.          Case  #C2D_MUSIC_API ; *Memory & @File (ascii & utf8)
  2886.          Case  #C2D_MUSIC_BAS ; *Memory & @File (ascii)
  2887.          Case  #C2D_MUSIC_FLA ; *Memory & @File (ascii & utf8)
  2888.          Case  #C2D_MUSIC_MCI ; *Memory = @File (ascii & utf8)
  2889.          Case  #C2D_MUSIC_MED ; *Memory = @File (ascii)
  2890.          Case  #C2D_MUSIC_MOD ; *Memory & @File (ascii & utf8)
  2891.          Case  #C2D_MUSIC_MOV ; *Memory = @File (ascii & utf8)
  2892.          Case  #C2D_MUSIC_OGG ; *Memory & @File (ascii & utf8)
  2893.          Case  #C2D_MUSIC_S68 ; *Memory & @File (ascii)
  2894.          Case  #C2D_MUSIC_WAV ; *Memory & @File (ascii & utf8)
  2895.          Case  #C2D_MUSIC_XM2 ; *Memory & @File (ascii)
  2896.          Case  #C2D_MUSIC_YMP ; *Memory & @File (ascii)
  2897.  
  2898.          Default  ;{ Engines who supports *Memory only? }
  2899.  
  2900.             If Length   <= #Null
  2901.  
  2902.                If ReadFile(0, \File$)
  2903.                   Length   =  Lof(0)
  2904.                   If Length   >  0
  2905.                      \Memory  =  AllocateMemory(Length)
  2906.                      \IsAlloc =  Bool(\Memory>0)   ; flag to free temp *memory
  2907.                      If \IsAlloc
  2908.                         Length   =  ReadData(0, \Memory, Length)
  2909.                      Else
  2910.                         Length   =  #Null
  2911.                      EndIf
  2912.                   EndIf
  2913.                   CloseFile(0)
  2914.                EndIf
  2915.  
  2916.                If  Length  <= #Null
  2917.                   SCAL_Free() :  ProcedureReturn   #Null
  2918.                EndIf
  2919.  
  2920.                *Memory  =  \Memory
  2921.  
  2922.             EndIf
  2923.             ;}
  2924.  
  2925.       EndSelect
  2926.  
  2927.       If Length   >  *Memory  :  Length   -  *Memory  :  EndIf
  2928.  
  2929.       ; *** DEFAULTS ***
  2930.       \ID      =  #True ; ok by default
  2931.       \Memory  =  *Memory
  2932.       \Length  =  Length
  2933.       \SubSong =  SubSong
  2934.  
  2935.       ; *** Default name of Tracker- / Decoder ***
  2936.       If \Mode >= #SCAL_MIN   And   Mode <= #SCAL_MAX
  2937.          \Tracker$   =  StringField(PeekS(PeekI(?mode + \Mode * SizeOf(Integer))), 3, "|")
  2938.       EndIf
  2939.  
  2940.       ; =========================================================================
  2941.       ; Playback the music (na endlich...)
  2942.       ; =========================================================================
  2943.       Select   \Mode
  2944.  
  2945.          Case  #C2D_MUSIC_AHX ;{ *** Play AHX/THX (no HVL) (*Memory)
  2946.             ; http://lclevy.free.fr/exotica/ahx/ahxformat.txt
  2947.             \ID   =  ahx1play_PlaySong(\Memory, \Length, \SubSong - 1, \Freq)
  2948.             If \ID
  2949.                \Title$  =  PeekS(ahx1play_GetSongName(), -1, #PB_Ascii)
  2950.                If \Songs   =  #Null ; no zip archive?
  2951.                   \Songs   =  PeekB(\Memory  +  $D)   +  1
  2952.                EndIf
  2953.             EndIf
  2954.             ;}
  2955.  
  2956.          Case  #C2D_MUSIC_API ;{ *** Play API-Wave (*.WAV) (@File / *Memory)
  2957.             If \Length
  2958.                \ID   =  PlaySound_(\Memory, #Null, #SND_MEMORY|#SND_ASYNC|#SND_LOOP|#SND_NODEFAULT)   ; play from *Memory
  2959.             Else
  2960.                \ID   =  PlaySound_(\Memory, #Null, #SND_FILENAME|#SND_ASYNC|#SND_LOOP|#SND_NODEFAULT) ; play from file -> *Memory = @Filename$
  2961.             EndIf
  2962.             ;}
  2963.  
  2964.          Case  #C2D_MUSIC_FC4 ;{ *** Play FutureComposer 1..4 (FC) (*Memory)
  2965.             \ID   =  fc14play_PlaySong(\Memory, \Length, \Freq)
  2966.             If \ID   And   PeekL(\Memory) =  #ID_SMOD
  2967.                \Tracker$   +  " / SMOD"   ; 1.3
  2968.             EndIf
  2969.             ;}
  2970.  
  2971.          Case  #C2D_MUSIC_FLA ;{ *** Play native FLAC-decoder (*.FLAC) (@File / *Memory)
  2972.             scal_Init()
  2973.             If \Length
  2974.                \ID   =  CatchSound(0, \Memory, \Length)
  2975.             Else
  2976.                \ID   =  LoadSound(0, PeekS(\Memory))
  2977.             EndIf
  2978.             If \ID
  2979.                PlaySound(0, #PB_Sound_Loop)
  2980.                \Time =  SoundLength(0, #PB_Sound_Millisecond)
  2981.             EndIf
  2982.             ;}
  2983.  
  2984.          Case  #C2D_MUSIC_FT2 ;{ *** Play FastTracker I/II (FT/XM) & Amiga Tracker (MOD) (*Memory)
  2985.             \ID   =  ft2play_PlaySong(\Memory, \Length, 0, 1, \Freq)
  2986.             If \ID
  2987.                ft2play_SetAmp(18)
  2988.                If PeekL(\Memory) =  #ID_XM
  2989.                   \Title$     =  PeekS(\Memory + $11, 20, #PB_Ascii)
  2990.                Else
  2991.                   \Tracker$   +  " / Amiga Tracker"
  2992.                   \Title$     =  PeekS(\Memory, 20, #PB_Ascii)
  2993.                EndIf
  2994.             EndIf
  2995.             ;}
  2996.  
  2997.          Case  #C2D_MUSIC_MCI ;{ *** Play Systemfile (*.MP3;*.OGG;*.WAV;*.WMA...) (@File)
  2998.             ; https://www.vbarchiv.net/tipps/tipp_856-alles-ueber-das-multimedia-control-interface-mci-api.html
  2999.             t$ =  "OPEN " + #DQUOTE$ + PeekS(\Memory) + #DQUOTE$ + " TYPE MPEGVIDEO ALIAS 0"
  3000.             If mciSendString_(@t$, 0, 0, 0)  =  #S_OK
  3001.                t$ =  Space(#MAX_PATH)
  3002.                mciSendString_(@"SET 0 TIME FORMAT MILLISECONDS", 0, 0, 0)
  3003.                mciSendString_(@"PLAY 0 REPEAT", 0, 0, 0)
  3004.                mciSendString_(@"STATUS 0 LENGTH", @t$, #MAX_PATH, 0)
  3005.                \Time =  Val(t$)
  3006.             Else
  3007.                \ID   =  #False
  3008.             EndIf
  3009.             ;}
  3010.  
  3011.          Case  #C2D_MUSIC_MOD ;{ *** Play native Tracker (*.XM;*.IT;*.S3M;*.MOD;*.MTM;*.UMX;*.OKT;*.MED + PP20) (@File / *Memory)
  3012.             scal_Init()
  3013.             If \Length
  3014.                \ID   =  CatchMusic(0, \Memory, \Length)
  3015.             Else
  3016.                \ID   =  LoadMusic(0, PeekS(\Memory))
  3017.             EndIf
  3018.             If \ID
  3019.                PlayMusic(0)
  3020.             EndIf
  3021.             ;}
  3022.  
  3023.          Case  #C2D_MUSIC_MOV ;{ *** Play native Movie / Audio (same as MCI) (@File)
  3024.          CompilerIf  #IsMOV
  3025.             scal_Init()
  3026.             If LoadMovie(0, \File$)
  3027.                *Memory  =  GetForegroundWindow_()
  3028.                If MovieWidth(0)  >  0  ; 99 if portable
  3029.                   \WinID   =  OpenWindow(#PB_Any, 40, 40, MovieWidth(0), MovieHeight(0), GetFilePart(\File$), #PB_Window_Tool|#PB_Window_NoGadgets)
  3030.                   *Memory  =  WindowID(\WinID)
  3031.                EndIf
  3032.                If PlayMovie(0, *Memory)
  3033.                   \Time =  (MovieLength(0) / (MovieInfo(0, 0) + 1)) * 1000
  3034.                Else
  3035.                   \ID   =  #False
  3036.                EndIf
  3037.             Else
  3038.                \ID   =  #False
  3039.             EndIf
  3040.          CompilerElse
  3041.             \ID   =  #False
  3042.          CompilerEndIf
  3043.          ;}
  3044.  
  3045.          Case  #C2D_MUSIC_OGG ;{ *** Play native ogg-decoder (*.OGG) (@File / *Memory)
  3046.             scal_Init()
  3047.             If \Length
  3048.                \ID   =  CatchSound(0, \Memory, \Length)
  3049.             Else
  3050.                \ID   =  LoadSound(0, PeekS(\Memory))
  3051.             EndIf
  3052.             If \ID
  3053.                PlaySound(0, #PB_Sound_Loop)
  3054.                \Time =  SoundLength(0, #PB_Sound_Millisecond)
  3055.             EndIf
  3056.             ;}
  3057.  
  3058.          Case  #C2D_MUSIC_PT2 ;{ *** Play ProTracker 2.3D (MOD) (*Memory)
  3059.             If SCAL_IsFormat(#C2D_MUSIC_PT2, \Memory, \Length) ; check, coz pt2 crashes if an error;Default_Mode(\Memory, \Length)  =  #C2D_MUSIC_PT2
  3060.                \ID   =  pt2play_PlaySong(\Memory, \Length, #CIA_TEMPO_MODE, \Freq)
  3061.             Else
  3062.                \ID   =  #False
  3063.             EndIf
  3064.             If \ID
  3065.                \Title$  =  PeekS(pt2play_GetSongName(), -1, #PB_Ascii)
  3066.             EndIf
  3067.             ;}
  3068.  
  3069.          Case  #C2D_MUSIC_S3M ;{ *** Play ScreamTracker III (S3M) (*Memory)
  3070.             \ID   =  st3play_PlaySong(\Memory, \Length, 0, #SOUNDCARD_GUS, \Freq)
  3071.             If \ID
  3072.                \Title$  =  PeekS(st3play_GetSongName(), -1, #PB_Ascii)
  3073.             EndIf
  3074.             ;}
  3075.  
  3076.          Case  #C2D_MUSIC_STM ;{ *** Play Scream Tracker 2.3 (STM) (*Memory)
  3077.             \ID   =  st23play_PlaySong(\Memory, \Length, 0, \Freq)
  3078.             If \ID
  3079.                \Title$  =  PeekS(st23play_GetSongName(), -1, #PB_Ascii)
  3080.             EndIf
  3081.             ;}
  3082.  
  3083.          Case  #C2D_MUSIC_TPT ;{ +++ Tiny ProTracker 2.3D (MOD) (*Memory)
  3084.             If SCAL_IsFormat(#C2D_MUSIC_TPT, \Memory, \Length)
  3085.                \ID   =  tinypt2play_PlaySong(\Memory, \Length)
  3086.             EndIf
  3087.             If \ID
  3088.                \Title$  =  PeekS(\Memory, -1, #PB_Ascii)
  3089.             EndIf
  3090.             ;}
  3091.  
  3092.          Case  #C2D_MUSIC_TFC ;{ +++ Tiny FutureComposer 1..4 (FC) (*Memory)
  3093.             \ID   =  tinyfc14play_PlaySong(\Memory, \Length)
  3094.             If \ID   And   PeekL(\Memory) =  #ID_SMOD
  3095.                \Tracker$   +  " / SMOD"   ; 1.3
  3096.             EndIf
  3097.             ;}
  3098.  
  3099.          Case  #C2D_MUSIC_THX ;{ +++ Tiny AHX (no HVL) (*Memory)
  3100.             \ID   =  tinyahx1play_PlaySong(\Memory, \Length, \SubSong)
  3101.             ;}
  3102.  
  3103.          Case  #C2D_MUSIC_WAV ;{ *** Play native Wave-Decoder (*.WAV) (@File / *Memory)
  3104.             scal_Init()
  3105.             If \Length
  3106.                \ID   =  CatchSound(0, \Memory, \Length)
  3107.             Else
  3108.                \ID   =  LoadSound(0, PeekS(\Memory))
  3109.             EndIf
  3110.             If \ID
  3111.                PlaySound(0, #PB_Sound_Loop)
  3112.                \Time =  SoundLength(0, #PB_Sound_Millisecond)
  3113.             EndIf
  3114.          ;}
  3115.  
  3116.          CompilerIf  #IsAMP   ;{ *** x86 - Play AmpMaster Plugin (933+ formats) (@File)
  3117.          Case  #C2D_MUSIC_AMP
  3118.             If AmpMusicInit()
  3119.  
  3120.                ; Clone to temp & set Subsong - coz we will NOT change the original one by AmpMaster!
  3121.  
  3122.                scal_Temp(#SCAL_TempPath$) ; create temporary directory for all files
  3123.  
  3124.                Path$ =  GetPathPart(\File$)
  3125.                File$ =  GetFilePart(\File$)
  3126.  
  3127.                If StrStrI_(@File$, @"MDAT.")    ; *** MDAT.file ***
  3128.  
  3129.                   MDAT$ =  StringField(File$, 1, ".")
  3130.                   SMPL$ =  scal_Case("SMPL", MDAT$)   ; adapt upper/lower case
  3131.  
  3132.                   File$ =  StringField(File$, 2, ".") ; Filename (no extension)
  3133.  
  3134.                   ; path-check coz don't download again to temp if already downloaded
  3135.                   If (Path$   <> \Temp$)  And   scal_Size(\File$) <> scal_Size(\Temp$  + MDAT$ + File$)
  3136.                      scal_Copy(\File$,                      \Temp$ + MDAT$ + "." + File$)
  3137.                      scal_Copy(Path$ + SMPL$ + "." + File$, \Temp$ + SMPL$ + "." + File$)
  3138.                   EndIf
  3139.  
  3140.                   File$    =  \Temp$   +  MDAT$ +  "."   +  File$
  3141.                   \Memory  =  @File$
  3142.  
  3143.                   \Songs   =  AmpCountSubSongs(\Memory)
  3144.  
  3145.                ElseIf   StrStrI_(@File$, @".MDAT") ; *** file.MDAT (rare) ***
  3146.  
  3147.                   MDAT$ =  GetExtensionPart(File$)
  3148.                   SMPL$ =  scal_Case("SMPL", MDAT$)
  3149.  
  3150.                   PathRemoveExtension_(@File$)  ; no extension (MDAT)
  3151.  
  3152.                   If (Path$   <> \Temp$)  And   scal_Size(\File$) <> scal_Size(\Temp$  + MDAT$ + "." + File$)
  3153.                      scal_Copy(\File$,                      \Temp$ + MDAT$ + "." + File$)
  3154.                      scal_Copy(Path$ + File$ + "." + SMPL$, \Temp$ + SMPL$ + "." + File$)
  3155.                   EndIf
  3156.  
  3157.                   File$    =  \Temp$ + MDAT$ + "." + File$
  3158.                   \Memory  =  @File$
  3159.  
  3160.                   \Songs   =  AmpCountSubSongs(\Memory)
  3161.  
  3162.                ElseIf   StrStrI_(@File$, @".TFX")  ; *** file.TFX (MDAT Clone) ***
  3163.  
  3164.                   MDAT$ =  GetExtensionPart(File$)
  3165.                   SMPL$ =  scal_Case("SAM", MDAT$)
  3166.  
  3167.                   PathRemoveExtension_(@File$)  ; no extension (TFX)
  3168.  
  3169.                   If (Path$   <> \Temp$)  And   scal_Size(\File$) <> scal_Size(\Temp$ + File$ + "." + MDAT$)
  3170.                      scal_Copy(\File$,                      \Temp$ + File$ + "." + MDAT$)
  3171.                      scal_Copy(Path$ + File$ + "." + SMPL$, \Temp$ + File$ + "." + SMPL$)
  3172.                   EndIf
  3173.  
  3174.                   File$    =  \Temp$   +  File$ +  "." + MDAT$
  3175.                   \Memory  =  @File$
  3176.  
  3177.                   \Songs   =  AmpCountSubSongs(\Memory)
  3178.  
  3179.                ElseIf   StrStrI_(@File$, @".SID")  Or
  3180.                         StrStrI_(@File$, @".PSID") Or
  3181.                         StrStrI_(@File$, @".RSID") Or
  3182.                         StrStrI_(@File$, @".TFM")  Or
  3183.                         StrStrI_(@File$, @".TFMX") Or
  3184.                         StrStrI_(@File$, @".GBS")  Or
  3185.                         StrStrI_(@File$, @".NSF")  Or
  3186.                         StrStrI_(@File$, @".FRED") Or StrStrI_(@File$, @"FRED.")
  3187.  
  3188.                   File$    =  \Temp$   +  File$
  3189.                   \Memory  =  @File$
  3190.  
  3191.                   If (Path$   <> \Temp$)  And   scal_Size(File$)  <= #Null
  3192.                      scal_Copy(\File$, File$)
  3193.                   EndIf
  3194.  
  3195.                   \Songs   =  AmpCountSubSongs(\Memory)
  3196.  
  3197.                Else
  3198.  
  3199.                   \SubSong =  0
  3200.  
  3201.                EndIf
  3202.  
  3203.                \ID   =  AmpMusicPlay(\Memory, \SubSong)
  3204.  
  3205.                If \ID
  3206.                   \File$      =  PeekS(\Memory, -1, \StrFormat)
  3207.                   \Time       =  AmpMusicLength()
  3208.                   \Title$     =  PeekS(AmpMusicTitle(),  -1, #PB_Ascii)
  3209.                   \Tracker$   =  PeekS(AmpMusicInfo(),   -1, #PB_Ascii)
  3210.                EndIf
  3211.  
  3212.             Else
  3213.  
  3214.                \ID   =  #False   ; Error!
  3215.  
  3216.             EndIf
  3217.  
  3218.          CompilerEndIf
  3219.          ;}
  3220.  
  3221.          CompilerIf  #IsBAS   ;{ *** x86 - Play Modules (*.XM;*.IT;*.S3M;*.MOD;*.MTM;*.UMX) (@File / *Memory)
  3222.          Case  #C2D_MUSIC_BAS
  3223.             ; http://www.users.on.net/~jtlim/ImpulseTracker/
  3224.  
  3225.             BASSMOD_DllMain(GetModuleHandle_(#Null), #DLL_PROCESS_ATTACH, #Null)
  3226.  
  3227.             \ID   =  BASSMOD_Init(-1, \Freq, #Null)
  3228.  
  3229.             If \ID
  3230.  
  3231.                If \Length  ; play from *memory?
  3232.                   IsOK  =  BASSMOD_MusicLoad(#True, \Memory, 0, \Length)
  3233.                   Select   PeekL(\Memory)
  3234.                      Case  #ID_IT
  3235.                         \Tracker$   +  " / Impulse Tracker 2.14"
  3236.                      Case  #ID_UMX
  3237.                         \Tracker$   +  " / UMX Container"
  3238.                      Case  #ID_MTM
  3239.                         \Tracker$   +  " / Multi Tracker"
  3240.                      Case  #ID_XM
  3241.                         \Tracker$   +  " / Fast Tracker II"
  3242.                   EndSelect
  3243.                Else  ; play from file
  3244.                   \File$   =  PeekS(\Memory, -1, \StrFormat)
  3245.                   IsOK     =  BASSMOD_MusicLoad(#False, StrAsc(\Memory))
  3246.                EndIf
  3247.  
  3248.                If IsOK  And   BASSMOD_MusicPlay()
  3249.                   ;\Time      =  BASSMOD_MusicGetLength(1)  /  176.4 ; = 44100
  3250.                   \Time    =  BASSMOD_MusicGetLength(1)  /  (\Freq   /  250.0)   ; / 2 * 125 BPM
  3251.                   *Memory  =  BASSMOD_MusicGetName()
  3252.                   If *Memory
  3253.                      \Title$  =  PeekS(*Memory, -1, #PB_Ascii)
  3254.                   EndIf
  3255.                Else
  3256.                   \ID   =  #Null ; Error!
  3257.                EndIf
  3258.  
  3259.             EndIf
  3260.          CompilerEndIf
  3261.          ;}
  3262.  
  3263.          CompilerIf  #IsBMF   ;{ *** x86 - Play BeroTracker04 (*.BMF) (*Memory)
  3264.          Case  #C2D_MUSIC_BMF
  3265.             \ID   =  SynthCreate(SynthReadBMFSampleRate(\Memory, \Length), 2048, 1, 1)
  3266.             If \ID
  3267.                SynthReadBMF(\ID, \Memory, \Length)
  3268.                SynthPlay(\ID)
  3269.                SynthSetLooping(\ID, 1)
  3270.             EndIf
  3271.          CompilerEndIf
  3272.          ;}
  3273.  
  3274.          CompilerIf  #IsFCP   ;{ *** x86 - Play FutureComposer 1.4 (*.FC;*.FC14;*.FC4) (*Memory)
  3275.          Case  #C2D_MUSIC_FCP
  3276.             FCp_Open(GetForegroundWindow_())
  3277.             FCp_InitModule(\Memory)
  3278.             FCp_Start()
  3279.          CompilerEndIf
  3280.          ;}
  3281.  
  3282.          CompilerIf  #IsMED   ;{ *** x86 - Play OctaMED (*.MED;*.MMD0;*.MMD1;*.MMD2;*.MMD3;*.MOD + PP20) (@File)
  3283.          Case  #C2D_MUSIC_MED
  3284.             MEDPDLL_DllMain(GetModuleHandle_(#Null), #DLL_PROCESS_ATTACH, #Null)
  3285.             MEDP_Initialize(#Null, GetForegroundWindow_())
  3286.             If MEDP_Load(StrAsc(\Memory)) ; *Memory = always @Filename$
  3287.                If MEDP_IsLoaded()
  3288.                   t$ =  Space(100)
  3289.                   MEDP_Play()
  3290.                   MEDP_ModuleName(@t$, 100)
  3291.                   \Title$  =  PeekS(@t$, -1, #PB_Ascii)
  3292.                   \Time    =  Abs(MEDP_ModuleTime())  *  0.001 ; micro- to milliseconds (dear Andreas - it's buggy)
  3293.                Else
  3294.                   \ID   =  #False
  3295.                EndIf
  3296.             Else
  3297.                \ID   =  #False
  3298.             EndIf
  3299.          CompilerEndIf
  3300.          ;}
  3301.  
  3302.          CompilerIf  #IsS68   ;{ *** x86 - Play SC68 MC68000 Amiga/Atari (*.SC68;*.SNDH + GZIP) (@File / *Memory)
  3303.          Case  #C2D_MUSIC_S68
  3304.             \ID   =  sc68_Play(\Memory, \Length)
  3305.          CompilerEndIf
  3306.          ;}
  3307.  
  3308.          CompilerIf  #IsSID   ;{ *** x86 - Play C64 (*.SID) (*Memory) (need masm32.lib)
  3309.          Case  #C2D_MUSIC_SID
  3310.             If \SubSong
  3311.                \ID   =  SIDOpen(\Memory, \Length, #SID_MEMORY, #SID_NON_DEFAULT, \SubSong)
  3312.             Else
  3313.                \ID   =  SIDOpen(\Memory, \Length, #SID_MEMORY, #SID_DEFAULT, #Null)
  3314.             EndIf
  3315.             If \ID
  3316.                \Title$     =  PeekS(\Memory + $16, -1, #PB_Ascii)
  3317.                If \Songs   =  #Null
  3318.                   \Songs   =  PeekW(\Memory + $E)
  3319.                   \Songs   =  UINT16(\Songs)
  3320.                EndIf
  3321.             EndIf
  3322.          CompilerEndIf
  3323.          ;}
  3324.  
  3325.          CompilerIf  #IsTSR   ;{ *** x86 - Play C64 (*.SID) (*Memory) (no masm32.lib)
  3326.          Case  #C2D_MUSIC_TSR
  3327.             \Title$     =  PeekS(\Memory + $16, -1, #PB_Ascii)
  3328.             If \Songs   =  #Null
  3329.                \Songs      =  PeekW(\Memory + $E)
  3330.                \Songs      =  UINT16(\Songs)
  3331.             EndIf
  3332.             sid_sound_server_replay_init(\Memory, \Length, \SubSong)
  3333.             sid_sound_server_replay_play()
  3334.          CompilerEndIf
  3335.          ;}
  3336.  
  3337.          CompilerIf  #IsV1M   ;{ *** x86 - Play LibV2 1.0 (*.V2M) (*Memory)
  3338.          Case  #C2D_MUSIC_V1M
  3339.             \ID   =  ssInit(\Memory, GetForegroundWindow_())
  3340.             If \ID
  3341.                ssPlay()
  3342.                ssDoTick()
  3343.             EndIf
  3344.          CompilerEndIf
  3345.          ;}
  3346.  
  3347.          CompilerIf  #IsV2M   ;{ *** x86 - Play LibV2 1.5 (*.V2M) (*Memory)
  3348.          Case  #C2D_MUSIC_V2M
  3349.             \ID   =  V2MInit(\Memory, \Freq, GetForegroundWindow_())
  3350.             If \ID
  3351.                V2MSetRepeat(1)
  3352.                V2MPlay()
  3353.                \Time =  V2MGetTotalTime()
  3354.             EndIf
  3355.          CompilerEndIf
  3356.          ;}
  3357.  
  3358.          CompilerIf  #IsXM2   ;{ *** x86 - Play FastTracker II (*.XM) (@File / *Memory)
  3359.          Case  #C2D_MUSIC_XM2
  3360.             If \Length
  3361.                uFMOD_PlaySong(\Memory, \Length, #XM_MEMORY)       ; *memory
  3362.             Else
  3363.                uFMOD_PlaySong(StrAsc(\Memory), #Null, #XM_FILE)   ; @file
  3364.             EndIf
  3365.             \Title$     =  PeekS(uFMOD_GetTitle(), -1, #PB_Ascii)
  3366.          CompilerEndIf
  3367.          ;}
  3368.  
  3369.          CompilerIf  #IsYMP   ;{ *** x86 - Play Atari (*.YM) (@File / *Memory)
  3370.          Case  #C2D_MUSIC_YMP
  3371.             Protected   *RS_ymMusicInfo_t.RS_ymMusicInfo_t  =  AllocateStructure(RS_ymMusicInfo_t)
  3372.  
  3373.             YMPLUGIN_DllMain(GetModuleHandle_(#Null), #DLL_PROCESS_ATTACH, #Null)
  3374.             YM_Init()
  3375.  
  3376.             If \Length  >  0
  3377.                YM_Open(#Null, \Memory, \Length)
  3378.             Else
  3379.                YM_Open(StrAsc(@\File$), #Null, #Null)
  3380.             EndIf
  3381.  
  3382.             YM_Play()
  3383.             YM_Get_Info(*RS_ymMusicInfo_t)
  3384.  
  3385.             \Tracker$   +  " / " +  Trim(PeekS(*RS_ymMusicInfo_t\pSongPlayer, -1, #PB_Ascii), ".") +  " ("  +  PeekS(*RS_ymMusicInfo_t\pSongType, -1, #PB_Ascii)  +  ")"
  3386.             \Title$     =  PeekS(*RS_ymMusicInfo_t\pSongName, -1, #PB_Ascii)
  3387.             \Time       =  *RS_ymMusicInfo_t\musicTimeInSec *  1000  -  200   ; -200 ms coz no loop on (real) end
  3388.  
  3389.             FreeStructure(*RS_ymMusicInfo_t)
  3390.  
  3391.          CompilerEndIf
  3392.          ;}
  3393.  
  3394.          Default
  3395.  
  3396.             \ID   =  #False   ; unknown or play x86 on x64?
  3397.  
  3398.       EndSelect
  3399.  
  3400.       If \ID
  3401.  
  3402.          SCAL_SetVolume(\Volume)
  3403.  
  3404.          If \IsZip   ; restore subsongs from zip-archive?
  3405.             \Songs   =  \ZipCount
  3406.             \SubSong =  \ZipSong
  3407.          EndIf
  3408.  
  3409.          \TimePlay   =  ElapsedMilliseconds()
  3410.  
  3411.       Else
  3412.          SCAL_Free()
  3413.       EndIf
  3414.  
  3415.       ProcedureReturn   \ID
  3416.  
  3417.    EndWith
  3418.  
  3419. EndProcedure
  3420. ProcedureDLL   SCAL_Seek(Position, Flags)
  3421.  
  3422.    ; Position = ms or 0-100%
  3423.    ; Flags = 0 -> seek in ms, 1 -> seek in percent
  3424.  
  3425.    ; Remember: \TimePlay   =  ElapsedMilliseconds()   -  Position
  3426.  
  3427.    Protected   t$
  3428.  
  3429.    With  RS_SCAL
  3430.  
  3431.       ; Playing?
  3432.       If \ID   =  #Null :  ProcedureReturn   #Null :  EndIf
  3433.  
  3434.       If Flags ; Percent?
  3435.          If Position <  0  Or Position >  100
  3436.             Position =  #Null
  3437.          EndIf
  3438.       ElseIf   Position <  0  Or Position >  \Time    ; Milliseconds!
  3439.          Position =  #Null
  3440.       EndIf
  3441.  
  3442.       If Flags ; convert % to ms
  3443.          Position =  \Time *  0.01  *  Position
  3444.       EndIf
  3445.  
  3446.       Select   \Mode
  3447.          Case  #C2D_MUSIC_OGG, #C2D_MUSIC_FLA, #C2D_MUSIC_WAV
  3448.             If IsSound(0)
  3449.                SetSoundPosition(0, Position, #PB_Sound_Millisecond)
  3450.             EndIf
  3451.  
  3452.          Case  #C2D_MUSIC_MCI
  3453.             t$ =  "SEEK 0 TO " + Str(Position)
  3454.             mciSendString_(@t$, 0, 0, 0)
  3455.             mciSendString_(@"PLAY 0 REPEAT", 0, 0, 0)
  3456.  
  3457.          CompilerIf  #IsAMP
  3458.          Case  #C2D_MUSIC_AMP
  3459.             AmpMusicSetPosition(Position)
  3460.          CompilerEndIf
  3461.  
  3462.          CompilerIf  #IsBAS
  3463.          Case  #C2D_MUSIC_BAS
  3464.             \TimePlay   =  ElapsedMilliseconds()   -  Position
  3465.             Position =  $FFFF0000   |  (Position   /  1000)
  3466.             BASSMOD_MusicSetPosition(Position)
  3467.          CompilerEndIf
  3468.  
  3469.          CompilerIf  #IsMED   ; Error
  3470. ;        Case  #C2D_MUSIC_MED
  3471. ;           If Flags ; only percent (coz unknown / buggy? ticks)
  3472. ;              \TimePlay   =  ElapsedMilliseconds()   -  Position
  3473. ;              Position    =  Abs(MEDP_ModuleLength())   *  0.01  *  Position
  3474. ;              MEDP_SetPlayPosition(Position)
  3475. ;           EndIf
  3476.          CompilerEndIf
  3477.  
  3478.          CompilerIf  #IsV2M
  3479.          Case  #C2D_MUSIC_V2M
  3480.             V2MStop()
  3481.             dsClose()
  3482.             V2MInit(\Memory, \Freq, GetForegroundWindow_())
  3483.             V2MSetRepeat(1)
  3484.             dsSetVolume(0.01  *  \Volume)
  3485.             V2MPlay(Position)
  3486.          CompilerEndIf
  3487.  
  3488.          CompilerIf  #IsYMP
  3489.          Case  #C2D_MUSIC_YMP
  3490.             \TimePlay   =  ElapsedMilliseconds()   -  Position
  3491.             Position /  1000
  3492.             YM_Seek(Position)
  3493.          CompilerEndIf
  3494.  
  3495.       EndSelect
  3496.  
  3497.    EndWith
  3498.  
  3499. EndProcedure
  3500. ProcedureDLL   SCAL_SetFreq(Freq)
  3501.    If Freq  <= #Null
  3502.       Freq  =  44100
  3503.    EndIf
  3504.    RS_SCAL\Freq   =  Freq
  3505. EndProcedure
  3506. ProcedureDLL   SCAL_SetString(Format)
  3507.  
  3508.    ; Set stringformat to AscII, UTF8, Unicode
  3509.  
  3510.    ; Format:   ASCII =  1 or #PB_Ascii (24)
  3511.    ;           UTF8  =  3
  3512.    ;           UNICODE  =  any other number (default)
  3513.  
  3514.    ; Tipp = SizeOf(Character))
  3515.  
  3516.    With  RS_SCAL
  3517.       Select   Format
  3518.          Case  1, #PB_Ascii
  3519.             \StrFormat  =  #PB_Ascii
  3520.          Case  3; #PB_UTF8
  3521.             \StrFormat  =  #PB_UTF8
  3522.          Default
  3523.             \StrFormat  =  #PB_Unicode
  3524.       EndSelect
  3525.    EndWith
  3526.  
  3527. EndProcedure
  3528. ProcedureDLL   SCAL_SetVolume(Percent)
  3529.  
  3530.    Protected   t$
  3531.  
  3532.    With  RS_SCAL
  3533.  
  3534.       If Percent  <  0
  3535.          Percent  =  0
  3536.       ElseIf   Percent  >  100
  3537.          Percent  =  100
  3538.       EndIf
  3539.  
  3540.       \Volume  =  Percent
  3541.  
  3542.       ; Playing?
  3543.       If \ID   =  #Null :  ProcedureReturn   :  EndIf
  3544.  
  3545.       Select   \Mode
  3546.          Case  #C2D_MUSIC_FT2 :  ft2play_SetMasterVol(2.56  *  \Volume)
  3547.          Case  #C2D_MUSIC_PT2 :  pt2play_SetMasterVol(2.56  *  \Volume)
  3548.          Case  #C2D_MUSIC_FC4 :  fc14play_SetMasterVol(2.56 *  \Volume)
  3549.          Case  #C2D_MUSIC_STM :  st23play_SetMasterVol(2.56 *  \Volume)
  3550.          Case  #C2D_MUSIC_S3M :  st3play_SetMasterVol(2.56  *  \Volume)
  3551.  
  3552.          Case  #C2D_MUSIC_MCI
  3553.             t$ =  "SETAUDIO 0 VOLUME TO " + Str(10 * \Volume)
  3554.             mciSendString_(@t$, 0, 0, 0)  ; 0 - 1000
  3555.  
  3556.          Case  #C2D_MUSIC_MOD :  MusicVolume(0, \Volume)
  3557.          Case  #C2D_MUSIC_MOV :  MovieAudio(0,  \Volume, 0)
  3558.  
  3559.          Case  #C2D_MUSIC_FLA, #C2D_MUSIC_OGG, #C2D_MUSIC_WAV
  3560.             SoundVolume(0, \Volume)
  3561.  
  3562.          CompilerIf  #IsAMP
  3563.          Case  #C2D_MUSIC_AMP
  3564.             AmpMusicVolume(2.55  *  \Volume)
  3565.          CompilerEndIf
  3566.  
  3567.          CompilerIf  #IsBAS
  3568.          Case  #C2D_MUSIC_BAS
  3569.             BASSMOD_SetVolume(\Volume)
  3570.          CompilerEndIf
  3571.  
  3572.          CompilerIf  #IsV2M
  3573.          Case  #C2D_MUSIC_V2M
  3574.             dsSetVolume(0.01  *  \Volume)
  3575.          CompilerEndIf
  3576.  
  3577.          CompilerIf  #IsXM2
  3578.          Case  #C2D_MUSIC_XM2
  3579.             uFMOD_SetVolume(0.25 *  \Volume)
  3580.          CompilerEndIf
  3581.  
  3582.          CompilerIf  #IsYMP
  3583.          Case  #C2D_MUSIC_YMP
  3584.             YM_SetVolume(2.55 *  \Volume)
  3585.          CompilerEndIf
  3586.  
  3587.       EndSelect
  3588.  
  3589.    EndWith
  3590.  
  3591. EndProcedure
  3592. ProcedureDLL   SCAL_Struct()
  3593.  
  3594.    ; creates temporary directory for all files
  3595.    ; define RS_SCAL\Temp$ even if not exist
  3596.  
  3597.    ; Return: private *structure
  3598.  
  3599.    scal_Temp(#SCAL_TempPath$)
  3600.  
  3601.    ProcedureReturn   @RS_SCAL
  3602.  
  3603. EndProcedure
  3604. ProcedureDLL   SCAL_Table(Mode)
  3605.  
  3606.    ; Mode = #C2D_MUSIC_[ID]
  3607.  
  3608.    ; Return:   ptr to infostring or table
  3609.  
  3610.    Static   *Memory.Integer
  3611.  
  3612.    *Memory  =  ?mode
  3613.  
  3614.    If Mode >= #Null  And   Mode <= #SCAL_MAX
  3615.       *Memory  +  Mode  *  SizeOf(Integer)
  3616.       ProcedureReturn   *Memory\i
  3617.    EndIf
  3618.  
  3619.    ProcedureReturn   *Memory
  3620.  
  3621. EndProcedure
  3622. ProcedureDLL   SCAL_Version()
  3623.    ; 100 = 1.00
  3624.    ProcedureReturn   #SCAL_VERSION
  3625. EndProcedure
  3626.  
  3627. DataSection
  3628.  
  3629.    IncludePath "Include\"
  3630.  
  3631.    l_Start: ; Compare extensions
  3632.  
  3633.    l_AHX:   :  IncludeFile "i_AHX.pbi"
  3634.    l_FC4:   :  IncludeFile "i_FC4.pbi"
  3635.    l_FLA:   :  IncludeFile "i_FLA.pbi"
  3636.    l_FT2:   :  IncludeFile "i_FT2.pbi"
  3637.    l_MOD:   :  IncludeFile "i_MOD.pbi"
  3638.    l_OGG:   :  IncludeFile "i_OGG.pbi"
  3639.    l_PT2:   :  IncludeFile "i_PT2.pbi"
  3640.    l_S3M:   :  IncludeFile "i_S3M.pbi"
  3641.    l_STM:   :  IncludeFile "i_STM.pbi"
  3642.    l_API:   ; same as wav
  3643.    l_WAV:   :  IncludeFile "i_WAV.pbi"
  3644.    l_MOV:   ; same as mci
  3645.    l_MCI:   :  IncludeFile "i_MCI.pbi"
  3646.  
  3647.    CompilerIf  #IsAMP
  3648.    l_AMP:   :  IncludeFile "i_AMP.pbi"
  3649.    CompilerEndIf
  3650.    CompilerIf  #IsBAS
  3651.    l_BAS:   :  IncludeFile "i_BAS.pbi"
  3652.    CompilerEndIf
  3653.    CompilerIf  #IsBMF
  3654.    l_BMF:   :  IncludeFile "i_BMF.pbi"
  3655.    CompilerEndIf
  3656.    CompilerIf  #IsFCP
  3657.    l_FCP:   :  IncludeFile "i_FCP.pbi"
  3658.    CompilerEndIf
  3659.    CompilerIf  #IsMED
  3660.    l_MED:   :  IncludeFile "i_MED.pbi"
  3661.    CompilerEndIf
  3662.    CompilerIf  #IsS68
  3663.    l_SC68:  :  IncludeFile "i_S68.pbi"
  3664.    CompilerEndIf
  3665.    CompilerIf  (#IsSID  +  #IsTSR)
  3666.    l_TSR:   ; same as sid
  3667.    l_SID:   :  IncludeFile "i_SID.pbi"
  3668.    CompilerEndIf
  3669.    CompilerIf  (#IsV1M  +  #IsV2M)
  3670.    l_V1M:   ; same as v2m
  3671.    l_V2M:   :  IncludeFile "i_V2M.pbi"
  3672.    CompilerEndIf
  3673.    CompilerIf  #IsXM2
  3674.    l_XM2:   :  IncludeFile "i_XM2.pbi"
  3675.    CompilerEndIf
  3676.    CompilerIf  #IsYMP
  3677.    l_YMP:   :  IncludeFile "i_YMP.pbi"
  3678.    CompilerEndIf
  3679.  
  3680.    l_ZIP:   :  IncludeFile "i_ZIP.pbi"
  3681.  
  3682.    l_Finish:   :  Data.l   #Null ; End of compare extensions
  3683.  
  3684.    ; Playengines: ID | Processor x86-64 | Trackerinfo/name -> never change order (same as #C2D_MUSIC_[ID])!
  3685.    mode: :  Data.i   ?m0,?m1,?m2,?m3,?m4,?m5,?m6,?m7,?m8,?m9,?m10,?m11,?m12,?m13,?m14,?m15,?m16,?m17,?m18,?m19,?m20,?m21,?m22,?m23,?m24,?m25,?m26,?m27,?m28,?m29
  3686.    m0:   :  Data.s   "AUTO|x86-64|Autodetect"
  3687.    m1:   :  Data.s   "AHX|x86-64|Amiga Abyss' Highest eXperience 1.00-1.27"
  3688.    m2:   :  Data.s   "AMP|x86|AmpMaster_x86.dll"
  3689.    m3:   :  Data.s   "API|x86-64|PlaySound Wave API"
  3690.    m4:   :  Data.s   "BAS|x86|BASSMOD 2.0"
  3691.    m5:   :  Data.s   "BMF|x86|BeRo 404 Tracker"
  3692.    m6:   :  Data.s   "FC4|x86-64|Amiga Future Composer 1.0-1.4"
  3693.    m7:   :  Data.s   "FCP|x86|Amiga Future Composer 1.4"
  3694.    m8:   :  Data.s   "FLA|x86-64|Pure Free Lossless Audio Codec"
  3695.    m9:   :  Data.s   "FT2|x86-64|FastTracker I / II"
  3696.    m10:  :  Data.s   "MCI|x86-64|Media Control Interface"
  3697.    m11:  :  Data.s   "MED|x86|Amiga OctaMED / MEDP 1.0"
  3698.    m12:  :  Data.s   "MOD|x86-64|Pure ModPlug Module"
  3699.    m13:  :  Data.s   "MOV|x86-64|Pure Movie Mediadecoder"
  3700.    m14:  :  Data.s   "OGG|x86-64|Pure OGG Vorbis Decoder"
  3701.    m15:  :  Data.s   "PT2|x86-64|Amiga ProTracker 2.3d"
  3702.    m16:  :  Data.s   "S3M|x86-64|ScreamTracker v3.21"
  3703.    m17:  :  Data.s   "S68|x86|SC68 MC68000 Amiga / Atari"
  3704.    m18:  :  Data.s   "SCA|x86-64|SCAL DLL"
  3705.    m19:  :  Data.s   "SID|x86|C64 TitchySid"
  3706.    m20:  :  Data.s   "STM|x86-64|ScreamTracker v2.2-2.3"
  3707.    m21:  :  Data.s   "TFC|x86-64|Tiny Future Composer 1.0-1.4"
  3708.    m22:  :  Data.s   "THX|x86-64|Tiny Abyss' Highest eXperience 1.00-1.27"
  3709.    m23:  :  Data.s   "TPT|x86-64|Tiny ProTracker 2.3d"
  3710.    m24:  :  Data.s   "TSR|x86|C64 Sid SoundServer"
  3711.    m25:  :  Data.s   "V1M|x86|Farbrausch V2 Synthesizer System v1.0"
  3712.    m26:  :  Data.s   "V2M|x86|Farbrausch V2 Synthesizer System v1.5"
  3713.    m27:  :  Data.s   "WAV|x86-64|Pure WAV Sound Decoder"
  3714.    m28:  :  Data.s   "XM2|x86|uFMOD FastTracker II"
  3715.    m29:  :  Data.s   "YMP|x86|Atari ST YM2149 (LZH-h0)"
  3716.  
  3717.    s_unknown:  :  Data.s   "?"
  3718.  
  3719. EndDataSection
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement