Testaware

SCAL DLL v2.03

Jan 20th, 2021
139
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. ; -------------------------------------------------------------------------------------
  2. ; SCAL v2.03 x86-64 DLL - Play-Library for multiple formats [1071 (x86) / 424 (x64)]
  3. ; -------------------------------------------------------------------------------------
  4. ; Peace/TST - 20.01.2021 / 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 +637 exotic formats
  9. ; -------------------------------------------------------------------------------------
  10.  
  11. EnableExplicit
  12.  
  13. #SCAL_VERSION  =  203   ; * 0.01 -> 2.03
  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.61 * }
  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.35 * }
  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 + % (s. "war at 33%.psid", "100%.mod"...)
  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_STATUS_CODE, *Memory, @Length, 0)
  779.               If StrToInt_(*Memory)   =  200
  780.  
  781.                  Length   =  MemorySize(*Memory)
  782.  
  783.                  If HttpQueryInfo_(\hURL, #HTTP_QUERY_CONTENT_LENGTH, *Memory, @Length, 0)
  784.  
  785.                     \Length  =  StrToInt_(*Memory)
  786.  
  787.                     If GetLastError_()   Or \Length  <= 0  ; Error?
  788.                        \Length  =  #Null
  789.                     ElseIf   \BytesSkip  ; <- skip pseudoheader for deceive hoster?
  790.                        InternetReadFile_(\hURL, *Memory, \BytesSkip, @Length)
  791.                        \Length  -  Length
  792.                     EndIf
  793.  
  794.                  EndIf
  795.  
  796.               EndIf
  797.            EndIf
  798.         EndIf
  799.  
  800.         FreeMemory(*Memory)
  801.  
  802.      EndIf
  803.  
  804.      RS_SCAL\NetLength =  \Length  ; global length for SCAL_Struct()
  805.  
  806.      ProcedureReturn   \Length
  807.  
  808.   EndWith
  809.  
  810. EndProcedure
  811. Procedure   NetWorkLoad(Url$)
  812.  
  813.   ; Download Netfile to *Memory
  814.  
  815.   ; Return: Ptr to *Memory
  816.  
  817.   Protected   *Buffer, Length
  818.   Static   *Memory
  819.  
  820.   *Memory  =  #Null
  821.  
  822.   If NetWorkInit(Url$)
  823.  
  824.      With  RS_NetWork
  825.  
  826.         If \Length  >  #Null
  827.  
  828.            *Memory  =  AllocateMemory(\Length)
  829.            *Buffer  =  *Memory
  830.  
  831.            While InternetReadFile_(\hURL, *Buffer, \BytesRead, @Length)
  832.  
  833.               *Buffer  +  Length
  834.  
  835.               ;// If   *CallBack   And   CallFunctionFast(*CallBack, Percent)   :  Break :  EndIf
  836.               If \CallBack
  837.                  If CallFunctionFast(\CallBack, (100.0 / \Length) * (*Buffer - *Memory)) ; Abort?
  838.                     FreeMemory(*Memory)
  839.                     *Memory  =  #Null
  840.                     Break
  841.                  EndIf
  842.               Else
  843.                  Delay(1)
  844.               EndIf
  845.  
  846.               If (Length  <= #Null)   Or (*Buffer >= *Memory  +  \Length)
  847.                  Break
  848.               EndIf
  849.  
  850.            Wend
  851.  
  852.         EndIf
  853.  
  854.         InternetCloseHandle_(\hURL)
  855.  
  856.      EndWith
  857.  
  858.   EndIf
  859.  
  860.   If RS_NetWork\CallBack
  861.      CallFunctionFast(RS_NetWork\CallBack, 100)
  862.   EndIf
  863.  
  864.   ProcedureReturn   *Memory
  865.  
  866. EndProcedure
  867. Procedure   NetWorkSize(Url$)
  868.  
  869.   ; = size of url$
  870.  
  871.   If NetWorkInit(Url$)
  872.      InternetCloseHandle_(RS_NetWork\hURL)
  873.      ProcedureReturn   RS_NetWork\Length
  874.   EndIf
  875.  
  876. EndProcedure
  877. Procedure   NetWorkSkip(Length=0)
  878.   ; Length (skip bytes) of decive header chars
  879.   If Length   >= #Null
  880.      RS_NetWork\BytesSkip =  Length
  881.   EndIf
  882. EndProcedure
  883. Procedure   NetWorkDownload(Url$, File$)
  884.  
  885.   ; Return: Size of saved file, Error = #NULL
  886.  
  887.   If NetWorkInit(Url$) =  #Null :  ProcedureReturn   #Null :  EndIf
  888.  
  889.   Protected   *Memory, Length, hF
  890.   Protected   nSizeLoad, IsAbort
  891.  
  892.   Static   nSizeSave
  893.  
  894.   nSizeSave   =  #Null
  895.  
  896.   With  RS_NetWork
  897.  
  898.      If \Length  >  #Null
  899.  
  900.         *Memory  =  AllocateMemory(\BytesRead)
  901.  
  902.         hF =  CreateFile(#PB_Any, File$)
  903.  
  904.         If hF
  905.  
  906.            While InternetReadFile_(\hURL, *Memory, \BytesRead, @nSizeLoad)
  907.  
  908.               Length      =  WriteData(hF, *Memory, nSizeLoad)
  909.               nSizeSave   +  Length
  910.  
  911.               ;// If   *CallBack   And   CallFunctionFast(*CallBack, Percent)   :  Break :  EndIf
  912.               If \CallBack
  913.                  If CallFunctionFast(\CallBack, (100.0 / \Length) * nSizeSave)  ; %Percent (Abort?)
  914.                     IsAbort  =  #True
  915.                     Break
  916.                  EndIf
  917.               Else
  918.                  Delay(1)
  919.               EndIf
  920.  
  921.               If nSizeSave   >= \Length  Or Length   <  nSizeLoad   ; Length -> WriteError?
  922.                  Break
  923.               EndIf
  924.  
  925.            Wend
  926.  
  927.            FlushFileBuffers(hF)
  928.            CloseFile(hF)
  929.  
  930.         EndIf
  931.  
  932.         FreeMemory(*Memory)
  933.  
  934.      EndIf
  935.  
  936.      InternetCloseHandle_(\hURL)
  937.  
  938.   EndWith
  939.  
  940.   If IsAbort  ; aborted?
  941.      nSizeSave   =  #Null
  942.      DeleteFile_(@File$)
  943.   EndIf
  944.  
  945.   If RS_NetWork\CallBack
  946.      CallFunctionFast(RS_NetWork\CallBack, 100)
  947.   EndIf
  948.  
  949.   ProcedureReturn   nSizeSave
  950.  
  951. EndProcedure
  952. ;*****************************
  953.  
  954. Declare  SCAL_IsFormat(Mode, *Memory.Long, Length)
  955. Declare  SCAL_SetVolume(Percent)
  956.  
  957. Procedure   scal_Init()
  958.  
  959.   Static   IsInit
  960.  
  961.   If IsInit   :  ProcedureReturn   :  EndIf
  962.  
  963.   IsInit   =  1
  964.  
  965.   InitSound()
  966.  
  967.   CompilerIf  #IsMOV
  968.      InitMovie()
  969.   CompilerEndIf
  970.  
  971. EndProcedure
  972. Procedure   scal_Temp(Name$)
  973.  
  974.   ; Creates %TEMP%\Name$
  975.  
  976.   Protected   t$, Path$, i
  977.   Static   IsError
  978.  
  979.   If RS_SCAL\Temp$  :  ProcedureReturn   #True :  EndIf
  980.  
  981.   Path$    =  GetTemporaryDirectory()
  982.   IsError  =  #Null
  983.  
  984.   Repeat
  985.  
  986.      i  +  1
  987.  
  988.      t$ =  Trim(StringField(Name$, i, #PS$))
  989.  
  990.      If Len(t$)
  991.  
  992.         Path$ +  t$ +  #PS$
  993.  
  994.         If FileSize(Path$)   =  -1
  995.            If CreateDirectory(Path$)  =  #Null
  996.               IsError  =  1  :  Break ; ERROR - Can't create directory
  997.            EndIf
  998.         EndIf
  999.  
  1000.      EndIf
  1001.  
  1002.   Until Len(t$)  =  0
  1003.  
  1004.   If IsError
  1005.      RS_SCAL\Temp$  =  GetTemporaryDirectory()
  1006.   Else
  1007.      RS_SCAL\Temp$  =  Path$
  1008.   EndIf
  1009.  
  1010.   IsError  !  1
  1011.  
  1012.   ProcedureReturn   IsError  ; true if ok
  1013.  
  1014. EndProcedure
  1015. Procedure   scal_Size(File$)
  1016.  
  1017.   Static   Length
  1018.  
  1019.   If StrStrI_(@File$, @"://")   ; Netfile?
  1020.      Length   =  NetWorkSize(File$)
  1021.      If Length   <  #Null :  Length   =  #Null :  EndIf
  1022.      ProcedureReturn   Length
  1023.   EndIf
  1024.  
  1025.   Length   =  FileSize(File$)
  1026.  
  1027.   If Length   <  #Null :  Length   =  #Null :  EndIf
  1028.  
  1029.   ProcedureReturn   Length
  1030.  
  1031. EndProcedure
  1032. Procedure$  scal_Case(a$, b$)
  1033.  
  1034.   ; canonicalize a$ like b$
  1035.  
  1036.   ; some server allows real upper/lower chars only.
  1037.   ; so we have to adapt the upper/lower chars!
  1038.  
  1039.   ; use it align char-cases of "MDAT.?" / "SMPL.?" files
  1040.  
  1041.   ; e.g.: scal_Case("smpl.Song", "MDAT.song") =  "SMPL.Song"
  1042.  
  1043.   Protected   *a.Character   =  @a$
  1044.   Protected   *b.Character   =  @b$
  1045.  
  1046.   While *a\c  And   *b\c
  1047.      If *b\c  &  %0100000
  1048.         *a\c  |  %0100000
  1049.      Else
  1050.         *a\c  &  %1011111
  1051.      EndIf
  1052.      *a +  SizeOf(Character)
  1053.      *b +  SizeOf(Character)
  1054.   Wend
  1055.  
  1056.   ProcedureReturn   a$
  1057.  
  1058. EndProcedure
  1059. Procedure   scal_Copy(File$, Save$)
  1060.  
  1061.   ; Return:   #True = OK, #False = Error
  1062.  
  1063.   Static   IsError
  1064.  
  1065.   If StrStrI_(@File$, @"://")   ; Netfile?
  1066.      IsError  =  NetWorkDownload(File$, Save$)
  1067.      ProcedureReturn   IsError
  1068.   EndIf
  1069.  
  1070.   IsError  =  CopyFile_(@File$, @Save$, #False)
  1071.  
  1072.   ProcedureReturn   IsError
  1073.  
  1074. EndProcedure
  1075. Procedure   scal_Sufx(*Memory, Flags)
  1076.  
  1077.   ; Checks filename first for "*.mod" & second for "mod.*"
  1078.  
  1079.   ; Do NOT check with GetExtensionPart()
  1080.   ; Extension doesn't accept spaces, that's why we must use the stringfield-trick!
  1081.  
  1082.   ; Return:   ptr to semi-quoted extension ";MOD;" etc.
  1083.  
  1084.    Static   t$
  1085.  
  1086.    Protected   File$ =  GetFilePart(PeekS(*Memory, -1, RS_SCAL\StrFormat))
  1087.  
  1088.    If Flags ; MOD.* (like MDAT.*)
  1089.       t$ =  StringField(File$, 1, ".")
  1090.    Else     ; *.MOD (default)
  1091.       t$ =  Trim(PeekS(PathFindExtension_(@File$), -1), ".")   ;StringField(File$, CountString(File$, ".") + 1, ".")
  1092.    EndIf
  1093.  
  1094.    If Len(t$)  =  #Null Or Len(t$)  >  16 Or StrStrI_(@t$, @" ")  ; spaces in extension are NOT allowed!
  1095.       ProcedureReturn   #Null
  1096.    EndIf
  1097.  
  1098.    CharUpper_(@t$)
  1099.  
  1100.    t$ =  ";"   +  t$ +  ";"
  1101.  
  1102.    ProcedureReturn   @t$
  1103.  
  1104. EndProcedure
  1105. Procedure   scal_Down(URL$)
  1106.  
  1107.    ;- Download file + sfx-libs to temporary path
  1108.    ; Return:   <> 0 = OK
  1109.  
  1110.    Protected   File$, t$, i
  1111.  
  1112.    If StrStrI_(@URL$, @"://") =  #Null :  ProcedureReturn   #Null :  EndIf
  1113.  
  1114.    scal_Temp(#SCAL_TempPath$)
  1115.  
  1116.    File$ =  GetFilePart(URL$)
  1117.    For   i  =  $20   To $FF
  1118.       If StrStrI_(@File$, @"%")  =  #Null :  Break :  EndIf
  1119.       File$ =  ReplaceString(File$, "%" + Hex(i), Chr(i), #PB_String_NoCase)
  1120.    Next
  1121.    File$ =  RS_SCAL\Temp$  +  File$
  1122.  
  1123.    RS_SCAL\File$  =  File$
  1124.  
  1125.    ; *** Already downloaded?
  1126.    If scal_Size(URL$)   =  scal_Size(File$)
  1127.       ProcedureReturn   #True
  1128.    EndIf
  1129.  
  1130.    ; *** Download file to #SCAL_TempPath$
  1131.    If scal_Copy(URL$, File$)  =  0
  1132.       ProcedureReturn   #Null
  1133.    EndIf
  1134.  
  1135.    ; =======================================================
  1136.    ;{ *** Check for needed sfx-lib files on server (x86) ***
  1137.    CompilerIf  #IsAMP
  1138.    If StrStrI_(@File$, @"MDAT.")
  1139.  
  1140.       ; MDAT.* =  Amiga TFMX?          -  Needs the SMPL.* sfx-file! Download always with adapted chars
  1141.  
  1142.       t$ =  GetFilePart(URL$, #PB_FileSystem_NoExtension)
  1143.       t$ =  scal_Case("SMPL", t$)   ; adapt upper / lower chars
  1144.  
  1145.       PokeS(StrStrI_(@URL$, @"MDAT."), t$, -1, #PB_String_NoZero)
  1146.       PokeS(StrStrI_(@File$,@"MDAT."), t$, -1, #PB_String_NoZero)
  1147.       scal_Copy(URL$, File$)
  1148.  
  1149.    ElseIf   StrStrI_(PathFindExtension_(@File$), @".TFX")
  1150.  
  1151.       ; *.TFX  =  Amiga TFMX Clone?    -  Needs the *.SAM sfx-file!  Download always with adapted chars
  1152.  
  1153.       t$ =  GetExtensionPart(URL$)
  1154.       t$ =  "."   +  scal_Case("SAM", t$)
  1155.  
  1156.       PathRenameExtension_(@URL$,   @t$)
  1157.       PathRenameExtension_(@File$,  @t$)
  1158.       scal_Copy(URL$, File$)
  1159.  
  1160.    ElseIf   StrStrI_(PathFindExtension_(@File$), @".KDM")
  1161.  
  1162.       ; *.KDM  =  Ken's Digital Music? -  Needs the waves.kwv sfx-file!
  1163.  
  1164.       URL$  =  GetPathPart(URL$) +  "waves.kwv"
  1165.       File$ =  RS_SCAL\Temp$     +  "waves.kwv"
  1166.       If scal_Size(URL$)   <> scal_Size(File$)
  1167.          scal_Copy(URL$, File$)
  1168.       EndIf
  1169.  
  1170.    ElseIf   StrStrI_(@File$, @".MINI2SF")    Or ; =   Nintendo DS Sound?      -  Needs a tagged *.lib sfx-file
  1171.             StrStrI_(@File$, @".MINIDSF")    Or ; =   Dreamcast Sound?        -  Needs a tagged *.lib sfx-file
  1172.             StrStrI_(@File$, @".MINIGSF")    Or ; =   Gameboy Sound?          -  Needs a tagged *.lib sfx-file
  1173.             StrStrI_(@File$, @".MINIPSF")    Or ; =   Playstation Sound?      -  Needs almost a couple of tagged *.lib sfx-files
  1174.             StrStrI_(@File$, @".PSF")        Or ; =   Playstation Sound?      -  Courious yes/no tagged *.lib sfx-files
  1175.             StrStrI_(@File$, @".MINIPSF2")   Or ; =   Playstation2 Sound?     -  Needs a tagged *.lib sfx-file
  1176.             StrStrI_(@File$, @".MINIQSF")    Or ; =   Capcom Q-Sound?         -  Needs a tagged *.lib sfx-file
  1177.             StrStrI_(@File$, @".MINISNSF")   Or ; =   Super Nintendo Sound?   -  Needs a tagged *.lib sfx-file
  1178.             StrStrI_(@File$, @".MINISSF")    Or ; =   Saturn Sound?           -  Needs almost a couple of tagged *.lib sfx-files
  1179.             StrStrI_(@File$, @".SSF")        Or ; =   Saturn Sound?           -  Courious yes/no tagged *.lib sfx-files
  1180.             StrStrI_(@File$, @".MINIUSF")       ; =   Ultra64 Sound?          -  Needs a tagged *.lib sfx-file
  1181.  
  1182.       ; *** Hardcoded [TAG] check for all needed *.lib sfx-files ***
  1183.       ; (too bad, unfortunately there are occasionally incorrect named *.lib's on modland server)
  1184.       If ReadFile(0, File$)
  1185.          While Eof(0)   =  0
  1186.             t$ =  ReadString(0, #PB_Ascii)
  1187.             If StrStrI_(@t$, @"_lib")  And   StrStrI_(@t$, @"=")                 ; [Tag] & _lib=, _lib1=, _lib2=..
  1188.                t$ =  PeekS(CharLower_(StrStrI_(@t$, @"=") + SizeOf(Character)))  ; LCase(StringField(t$, 2, "="))
  1189.                If scal_Size(GetPathPart(URL$) + t$)   <> scal_Size(RS_SCAL\Temp$ + t$) ; Bad solution, but works for now
  1190.                   scal_Copy(GetPathPart(URL$) + t$, RS_SCAL\Temp$ + t$)
  1191.                EndIf
  1192.             EndIf
  1193.          Wend
  1194.          CloseFile(0)
  1195.       EndIf
  1196.  
  1197.    EndIf
  1198.    CompilerEndIf  ;}
  1199.    ; =======================================================
  1200.  
  1201.    ProcedureReturn   #True
  1202.  
  1203. EndProcedure
  1204.  
  1205. CompilerIf  #IsAMP   ; C:\Users\Public\Documents\AmpMaster\
  1206. PrototypeC  pAmp_Close()
  1207. PrototypeC  pAmp_CountAmpFormatsAll()
  1208. PrototypeC  pAmp_CountAmpPlayersAll()
  1209. PrototypeC  pAmp_CountSubSongs(*File.p-Ascii)
  1210. PrototypeC  pAmp_Free()
  1211. PrototypeC  pAmp_GetAmpFormatsStrAll()
  1212. PrototypeC  pAmp_GetAmpInDllsStrAll(*File.p-Ascii)
  1213. PrototypeC  pAmp_GetAmpInDllStr(*File.p-Ascii)
  1214. PrototypeC  pAmp_GetAmpInFormatStr(*InLib.p-Ascii)
  1215. PrototypeC  pAmp_GetError()
  1216. PrototypeC  pAmp_GetErrorStr(Error.i)
  1217. PrototypeC  pAmp_GetFileInfo(*File.p-Ascii, *Title, *Length)
  1218. PrototypeC  pAmp_GetInFlags(*InLib.p-Ascii)
  1219. PrototypeC  pAmp_GetInFormatStr()
  1220. PrototypeC  pAmp_GetInInfoStr()
  1221. PrototypeC  pAmp_GetOutInfoStr()
  1222. PrototypeC  pAmp_GetPercent()
  1223. PrototypeC  pAmp_GetPlayTime()
  1224. PrototypeC  pAmp_GetStopTime()
  1225. PrototypeC  pAmp_GetSubSong(*File.p-Ascii)
  1226. PrototypeC  pAmp_InAbout()
  1227. PrototypeC  pAmp_InConfig()
  1228. PrototypeC  pAmp_InfoBox(*File.p-Ascii)
  1229. PrototypeC  pAmp_Init()
  1230. PrototypeC  pAmp_MusicBox(*File.p-Ascii, Flags.i=1)
  1231. PrototypeC  pAmp_MusicGetLength(Flags.i=0)
  1232. PrototypeC  pAmp_MusicGetOutPosition()
  1233. PrototypeC  pAmp_MusicGetPosition()
  1234. PrototypeC  pAmp_MusicGetTitleStr()
  1235. PrototypeC  pAmp_MusicIsPlaying()
  1236. PrototypeC  pAmp_MusicIsSeekable()
  1237. PrototypeC  pAmp_MusicPause(Pause.i)
  1238. PrototypeC  pAmp_MusicPlay(*File.p-Ascii)
  1239. PrototypeC  pAmp_MusicSetPan(Pan.i)
  1240. PrototypeC  pAmp_MusicSetPosition(Milliseconds.i)
  1241. PrototypeC  pAmp_MusicSetVolume(Volume.i)
  1242. PrototypeC  pAmp_MusicStop()
  1243. PrototypeC  pAmp_Open()
  1244. PrototypeC  pAmp_OutAbout()
  1245. PrototypeC  pAmp_OutConfig()
  1246. PrototypeC  pAmp_Play(*File.p-Ascii, Volume.i=255)
  1247. PrototypeC  pAmp_QuickPlay(*File.p-Ascii, *Path.p-Ascii)
  1248. PrototypeC  pAmp_SetAmpPath(*Path.p-Ascii)
  1249. PrototypeC  pAmp_SetDefaultLength(Milliseconds.i=0)
  1250. PrototypeC  pAmp_SetInDll(*InLib.p-Ascii)
  1251. PrototypeC  pAmp_SetInPath(*Path.p-Ascii)
  1252. PrototypeC  pAmp_SetLength(Milliseconds.i)
  1253. PrototypeC  pAmp_SetOutDll(*OutLib.p-Ascii)
  1254. PrototypeC  pAmp_SetOutPath(*Path.p-Ascii)
  1255. PrototypeC  pAmp_SetSubSong(*File.p-Ascii, SubSong.i)
  1256. PrototypeC  pAmp_SetWindow(*Window)
  1257. PrototypeC  pAmp_VersionStr(Flags.i=0)
  1258.  
  1259. Structure   RS_Amp
  1260.    DLL.i
  1261.    IsPlay.i
  1262.    TimeLength.i
  1263.    TimeLoop.i
  1264.    File$
  1265.    CountSubSongs     .pAmp_CountSubSongs
  1266.    Play              .pAmp_Play
  1267.    Free              .pAmp_Free
  1268.    GetPlayTime       .pAmp_GetPlayTime
  1269.    GetInInfoStr      .pAmp_GetInInfoStr
  1270.    GetSubSong        .pAmp_GetSubSong
  1271.    MusicGetLength    .pAmp_MusicGetLength
  1272.    MusicGetTitle     .pAmp_MusicGetTitleStr
  1273.    MusicIsSeekable   .pAmp_MusicIsSeekable
  1274.    MusicPause        .pAmp_MusicPause
  1275.    MusicSetPosition  .pAmp_MusicSetPosition
  1276.    MusicSetVolume    .pAmp_MusicSetVolume
  1277.    SetAmpPath        .pAmp_SetAmpPath
  1278.    SetSubSong        .pAmp_SetSubSong
  1279. EndStructure
  1280. Global   RS_Amp.RS_Amp
  1281.  
  1282. ProcedureC  AmpMusicFree()
  1283.    With  RS_Amp
  1284.       If \DLL
  1285.          \Free()
  1286.          FreeLibrary_(\DLL)
  1287.          \DLL     =  #Null
  1288.          \IsPlay  =  #Null
  1289.       EndIf
  1290.    EndWith
  1291. EndProcedure
  1292. ProcedureC  AmpMusicInit(Path$=#Null$)
  1293.  
  1294.    ; Default path to AmpMaster -> "C:\Users\Public\Documents\AmpMaster\"
  1295.  
  1296.    If RS_Amp\DLL  :  ProcedureReturn   RS_Amp\DLL  :  EndIf
  1297.  
  1298.    Protected   t${#MAX_PATH}
  1299.  
  1300.    With  RS_Amp
  1301.  
  1302.       If Path$
  1303.  
  1304.          t$ =  Path$
  1305.  
  1306.       Else  ; C:\Users\Public\Documents\ + "AmpMaster\"
  1307.  
  1308.          SHGetFolderPath_(#Null, #CSIDL_COMMON_DOCUMENTS, #Null, #Null, @t$)
  1309.          PathAddBackslash_(@t$)
  1310.  
  1311.          t$ +  "AmpMaster\"
  1312.  
  1313.       EndIf
  1314.  
  1315.       t$ +  "AmpMaster_x86.dll"
  1316.  
  1317.       \DLL  =  LoadLibrary_(@t$)
  1318.  
  1319.       If \DLL
  1320.  
  1321.          \CountSubSongs    =  GetProcAddress_(\DLL, StrAsc(@"Amp_CountSubSongs"))
  1322.          \Play             =  GetProcAddress_(\DLL, StrAsc(@"Amp_Play"))
  1323.          \Free             =  GetProcAddress_(\DLL, StrAsc(@"Amp_Free"))
  1324.          \MusicGetLength   =  GetProcAddress_(\DLL, StrAsc(@"Amp_MusicGetLength"))
  1325.          \MusicGetTitle    =  GetProcAddress_(\DLL, StrAsc(@"Amp_MusicGetTitleStr"))
  1326.          \MusicPause       =  GetProcAddress_(\DLL, StrAsc(@"Amp_MusicPause"))
  1327.          \MusicIsSeekable  =  GetProcAddress_(\DLL, StrAsc(@"Amp_MusicIsSeekable"))
  1328.          \MusicSetPosition =  GetProcAddress_(\DLL, StrAsc(@"Amp_MusicSetPosition"))
  1329.          \MusicSetVolume   =  GetProcAddress_(\DLL, StrAsc(@"Amp_MusicSetVolume"))
  1330.          \GetPlayTime      =  GetProcAddress_(\DLL, StrAsc(@"Amp_GetPlayTime"))
  1331.          \GetInInfoStr     =  GetProcAddress_(\DLL, StrAsc(@"Amp_GetInInfoStr"))
  1332.          \GetSubSong       =  GetProcAddress_(\DLL, StrAsc(@"Amp_GetSubSong"))
  1333.          \SetAmpPath       =  GetProcAddress_(\DLL, StrAsc(@"Amp_SetAmpPath"))
  1334.          \SetSubSong       =  GetProcAddress_(\DLL, StrAsc(@"Amp_SetSubSong"))
  1335.  
  1336.          If Path$
  1337.             Path$ +  "AmpLibs\"  :  \SetAmpPath(StrAsc(@Path$))   ; set path of amplibs
  1338.          EndIf
  1339.  
  1340.       EndIf
  1341.  
  1342.       ProcedureReturn   \DLL
  1343.  
  1344.    EndWith
  1345.  
  1346. EndProcedure
  1347. ProcedureC  AmpMusicPlay(*Memory, SubSong=0)
  1348.  
  1349.    ; *Memory   =  Ptr to @Filename$ only!
  1350.    ; SubSong   =  Number of subsong to play (eg. SID)
  1351.  
  1352.    ; Return: #True = Music is playing or #False = Error!
  1353.  
  1354.    With  RS_Amp
  1355.  
  1356.       \IsPlay     =  #False
  1357.       \TimeLength =  #Null
  1358.       \TimeLoop   =  #Null
  1359.       \File$      =  PeekS(*Memory, -1, RS_SCAL\StrFormat)
  1360.  
  1361.       If AmpMusicInit()
  1362.  
  1363.          \Free()
  1364.  
  1365.          If SubSong  >  0
  1366.             \SetSubSong(StrAsc(@\File$), SubSong)
  1367.          EndIf
  1368.  
  1369.          If \Play(StrAsc(@\File$))  =  0
  1370.             \TimeLength =  \MusicGetLength()
  1371.             If \TimeLength <= 100   Or StrStrI_(@\File$, @".SID") Or StrStrI_(@\File$, @".PSID")   Or StrStrI_(@\File$, @".RSID")
  1372.                \TimeLength =  600000
  1373.             EndIf
  1374.             \TimeLoop   =  \TimeLength +  ElapsedMilliseconds()   +  50 ; <- Time to reset
  1375.             \IsPlay     =  #True
  1376.          EndIf
  1377.  
  1378.          ProcedureReturn   \IsPlay
  1379.  
  1380.       EndIf
  1381.  
  1382.    EndWith
  1383.  
  1384. EndProcedure
  1385. ProcedureC  AmpMusicStop()
  1386.    RS_Amp\Free()  :  RS_Amp\IsPlay  =  #False
  1387. EndProcedure
  1388. ProcedureC  AmpMusicLoop()
  1389.    If RS_Amp\IsPlay  And   ElapsedMilliseconds()   >  RS_Amp\TimeLoop
  1390.       ProcedureReturn   AmpMusicPlay(@RS_Amp\File$)
  1391.    EndIf
  1392. EndProcedure
  1393. ProcedureC  AmpMusicPosition()
  1394.    If RS_Amp\IsPlay
  1395.       ProcedureReturn   RS_Amp\GetPlayTime()
  1396.    EndIf
  1397. EndProcedure
  1398. ProcedureC  AmpMusicVolume(Volume)
  1399.    If RS_Amp\IsPlay
  1400.       ProcedureReturn   RS_Amp\MusicSetVolume(Volume)
  1401.    EndIf
  1402. EndProcedure
  1403. ProcedureC  AmpMusicTitle()
  1404.    If RS_Amp\IsPlay
  1405.       ProcedureReturn   RS_Amp\MusicGetTitle()
  1406.    EndIf
  1407. EndProcedure
  1408. ProcedureC  AmpCountSubSongs(*Memory)
  1409.    ProcedureReturn   RS_Amp\CountSubSongs(StrAsc(*Memory))
  1410. EndProcedure
  1411. ProcedureC  AmpMusicInfo()
  1412.    If RS_Amp\IsPlay
  1413.       ProcedureReturn   RS_Amp\GetInInfoStr()
  1414.    EndIf
  1415. EndProcedure
  1416. ProcedureC  AmpMusicLength()
  1417.    ProcedureReturn   RS_Amp\TimeLength
  1418. EndProcedure
  1419. ProcedureC  AmpMusicPause(Flags)
  1420.    If RS_Amp\IsPlay
  1421.       ProcedureReturn   RS_Amp\MusicPause(Flags)
  1422.    EndIf
  1423. EndProcedure
  1424. ProcedureC  AmpMusicIsSeekable()
  1425.    With  RS_Amp
  1426.       ProcedureReturn   \MusicIsSeekable()
  1427.    EndWith
  1428. EndProcedure
  1429. ProcedureC  AmpMusicSetPosition(Milliseconds)
  1430.    With  RS_Amp
  1431.       If \IsPlay  And   AmpMusicIsSeekable() And   ; no PSID/SID/RSID
  1432.          StrStrI_(@\File$, @".SID")    =  0  And
  1433.          StrStrI_(@\File$, @".PSID")   =  0  And
  1434.          StrStrI_(@\File$, @".RSID")   =  0
  1435.          ProcedureReturn   \MusicSetPosition(Milliseconds)
  1436.       EndIf
  1437.    EndWith
  1438. EndProcedure
  1439. CompilerEndIf
  1440.  
  1441. CompilerIf  #IsS68
  1442. ProcedureC  sc68_Play(*Memory, Length)
  1443.    With  RS_SCAL
  1444.  
  1445.       If Length
  1446.          \Title$  =  PeekS(*Memory + $48, -1, #PB_Ascii)
  1447.          \ID      =  sc68replay_Init(*Memory, Length, #SC68Replay_MEMORY)
  1448.       Else
  1449.          \ID   =  sc68replay_Init(StrAsc(*Memory), #Null, #SC68Replay_FILE)
  1450.       EndIf
  1451.  
  1452.       If \ID
  1453.          sc68replay_Play()
  1454.       EndIf
  1455.  
  1456.       ProcedureReturn   \ID
  1457.  
  1458.    EndWith
  1459. EndProcedure
  1460. ProcedureC  sc68_Free()
  1461.    If RS_SCAL\ID
  1462.       sc68replay_Stop()
  1463.    EndIf
  1464. EndProcedure
  1465. CompilerEndIf
  1466.  
  1467. Procedure   IsAmpMaster()
  1468.  
  1469.    CompilerIf  #IsAMP
  1470.  
  1471.       Static   t${#MAX_PATH}
  1472.  
  1473.       If Len(t$)  =  #Null
  1474.          SHGetFolderPath_(#Null, #CSIDL_COMMON_DOCUMENTS, #Null, #Null, @t$)
  1475.          PathAddBackslash_(@t$)
  1476.          t$ +  "AmpMaster"
  1477.       EndIf
  1478.  
  1479.       ProcedureReturn   Bool(FileSize(t$) =  -2)
  1480.  
  1481.    CompilerElse
  1482.  
  1483.       ProcedureReturn   #False
  1484.  
  1485.    CompilerEndIf
  1486.  
  1487. EndProcedure
  1488. Procedure   Default_Mode(*Memory.Long, Length)
  1489.  
  1490.    ; Autodetect #C2D_MUSIC_[mode]
  1491.  
  1492.    ; *Memory = Pointer to @Filename if Length = 0
  1493.    ; Checks file.extension ?.* and *.?
  1494.  
  1495.    ; Return: Default playback-mode or 0 = Error!
  1496.  
  1497.    Static   Mode
  1498.  
  1499.    Mode  =  #Null
  1500.  
  1501.    If Length   >  #Null ; *** Check memory for default mode (not to be confused with supported mode!) ***
  1502.  
  1503.       If       SCAL_IsFormat(#C2D_MUSIC_FT2, *Memory, Length)  :  Mode  =  #C2D_MUSIC_FT2 ; stabile Sound/Pro/Mod/FastTracker-Replay
  1504.       ElseIf   SCAL_IsFormat(#C2D_MUSIC_PT2, *Memory, Length)  :  Mode  =  #C2D_MUSIC_PT2 ; only Protracker 2.3d
  1505.       ElseIf   SCAL_IsFormat(#C2D_MUSIC_AHX, *Memory, Length)  :  Mode  =  #C2D_MUSIC_AHX
  1506.       ElseIf   SCAL_IsFormat(#C2D_MUSIC_FC4, *Memory, Length)  :  Mode  =  #C2D_MUSIC_FC4
  1507.       ElseIf   SCAL_IsFormat(#C2D_MUSIC_S3M, *Memory, Length)  :  Mode  =  #C2D_MUSIC_S3M
  1508.       ElseIf   SCAL_IsFormat(#C2D_MUSIC_STM, *Memory, Length)  :  Mode  =  #C2D_MUSIC_STM
  1509.       ElseIf   SCAL_IsFormat(#C2D_MUSIC_OGG, *Memory, Length)  :  Mode  =  #C2D_MUSIC_OGG
  1510.       ElseIf   SCAL_IsFormat(#C2D_MUSIC_FLA, *Memory, Length)  :  Mode  =  #C2D_MUSIC_FLA
  1511.       ElseIf   SCAL_IsFormat(#C2D_MUSIC_WAV, *Memory, Length)  :  Mode  =  #C2D_MUSIC_WAV
  1512.  
  1513.       CompilerIf  (#IsSID  +  #IsTSR)
  1514.       ElseIf   SCAL_IsFormat(#C2D_MUSIC_SID, *Memory, Length)  :  Mode  =  #C2D_MUSIC_SID
  1515.       CompilerEndIf
  1516.       CompilerIf  #IsYMP
  1517.       ElseIf   SCAL_IsFormat(#C2D_MUSIC_YMP, *Memory, Length)  :  Mode  =  #C2D_MUSIC_YMP
  1518.       CompilerEndIf
  1519.       CompilerIf  #IsBAS
  1520.       ElseIf   SCAL_IsFormat(#C2D_MUSIC_BAS, *Memory, Length)  :  Mode  =  #C2D_MUSIC_BAS
  1521.       CompilerEndIf
  1522.       CompilerIf  #IsBMF
  1523.       ElseIf   SCAL_IsFormat(#C2D_MUSIC_BMF, *Memory, Length)  :  Mode  =  #C2D_MUSIC_BMF
  1524.       CompilerEndIf
  1525.       CompilerIf  #IsS68
  1526.       ElseIf   SCAL_IsFormat(#C2D_MUSIC_S68, *Memory, Length)  :  Mode  =  #C2D_MUSIC_S68
  1527.       CompilerEndIf
  1528.       CompilerIf  (#IsV2M  +  #IsV1M)
  1529.       ElseIf   SCAL_IsFormat(#C2D_MUSIC_V2M, *Memory, Length)  :  Mode  =  #C2D_MUSIC_V2M
  1530.       CompilerEndIf
  1531.  
  1532.       Else  ; default memory mode
  1533.  
  1534.          Mode  =  #C2D_MUSIC_MOD
  1535.  
  1536.       EndIf
  1537.  
  1538.    Else  ; *** Checks file.extension ?.* and *.? ***
  1539.  
  1540.       Protected   *x, i
  1541.  
  1542.       For   i  =  0  To 1
  1543.  
  1544.          *x =  scal_Sufx(*Memory, i)   :  If *x =  #Null :  Continue :  EndIf
  1545.  
  1546.          If       StrStrI_(?l_FT2, *x) :  Mode  =  #C2D_MUSIC_FT2
  1547.          ElseIf   StrStrI_(?l_PT2, *x) :  Mode  =  #C2D_MUSIC_PT2
  1548.          ElseIf   StrStrI_(?l_S3M, *x) :  Mode  =  #C2D_MUSIC_S3M
  1549.          ElseIf   StrStrI_(?l_STM, *x) :  Mode  =  #C2D_MUSIC_STM
  1550.          ElseIf   StrStrI_(?l_AHX, *x) :  Mode  =  #C2D_MUSIC_AHX
  1551.          ElseIf   StrStrI_(?l_FC4, *x) :  Mode  =  #C2D_MUSIC_FC4
  1552.          ElseIf   StrStrI_(?l_WAV, *x) :  Mode  =  #C2D_MUSIC_WAV
  1553.          ElseIf   StrStrI_(?l_OGG, *x) :  Mode  =  #C2D_MUSIC_OGG
  1554.          ElseIf   StrStrI_(?l_FLA, *x) :  Mode  =  #C2D_MUSIC_FLA
  1555.  
  1556.          CompilerIf  #IsBAS
  1557.          ElseIf   StrStrI_(?l_BAS, *x) :  Mode  =  #C2D_MUSIC_BAS
  1558.          CompilerEndIf
  1559.          CompilerIf  #IsMED
  1560.          ElseIf   StrStrI_(?l_MED, *x) :  Mode  =  #C2D_MUSIC_MED
  1561.          CompilerEndIf
  1562.          CompilerIf  #IsSID
  1563.          ElseIf   StrStrI_(?l_SID, *x) :  Mode  =  #C2D_MUSIC_SID
  1564.          CompilerEndIf
  1565.          CompilerIf  #IsTSR
  1566.          ElseIf   StrStrI_(?l_SID, *x) :  Mode  =  #C2D_MUSIC_TSR
  1567.          CompilerEndIf
  1568.          CompilerIf  #IsYMP
  1569.          ElseIf   StrStrI_(?l_YMP, *x) :  Mode  =  #C2D_MUSIC_YMP
  1570.          CompilerEndIf
  1571.          CompilerIf  #IsS68
  1572.          ElseIf   StrStrI_(?l_SC68, *x):  Mode  =  #C2D_MUSIC_S68
  1573.          CompilerEndIf
  1574.          CompilerIf  #IsV2M
  1575.          ElseIf   StrStrI_(?l_V2M, *x)
  1576.             If IsAmpMaster()
  1577.                Mode  =  #C2D_MUSIC_AMP ; stabile v1.0/1.5 playback
  1578.             Else
  1579.                Mode  =  #C2D_MUSIC_V2M
  1580.             EndIf
  1581.          CompilerEndIf
  1582.          CompilerIf  #IsBMF
  1583.          ElseIf   StrStrI_(?l_BMF, *x) :  Mode  =  #C2D_MUSIC_BMF
  1584.          CompilerEndIf
  1585.  
  1586.          ElseIf   StrStrI_(?l_MCI, *x) :  Mode  =  #C2D_MUSIC_MCI
  1587.          ElseIf   StrStrI_(?l_MOD, *x) :  Mode  =  #C2D_MUSIC_MOD
  1588.  
  1589.          CompilerIf  #IsAMP   ; check at last, coz we don't know if ampmaster is installed?
  1590.          ElseIf   StrStrI_(?l_AMP, *x) :  Mode  =  #C2D_MUSIC_AMP
  1591.          CompilerEndIf
  1592.  
  1593.          EndIf
  1594.  
  1595.          If Mode  :  Break :  EndIf
  1596.  
  1597.          ;Mode =  #C2D_MUSIC_MCI ; pre-set as default
  1598.  
  1599.       Next
  1600.  
  1601.    EndIf
  1602.  
  1603.    ProcedureReturn   Mode
  1604.  
  1605. EndProcedure
  1606.  
  1607. ;- *** Functions ***************
  1608. ProcedureDLL   SCAL_AmpInstall(*URL)
  1609.  
  1610.    ; Only for Windows x86!
  1611.  
  1612.    ; *** ZIP ***
  1613.    ; https://testaware.files.wordpress.com/2020/08/ampmaster200824
  1614.  
  1615.    CompilerIf  #IsAMP
  1616.  
  1617.       scal_Temp(#SCAL_TempPath$) ; create temporary directory for all files
  1618.  
  1619.       Static   IsError
  1620.       Protected   URL$, File$, i, Count
  1621.  
  1622.       ; 2.5KB smaller than -> Install_Path$  =  GetUserDirectory(#PB_Directory_Public)
  1623.       Protected   Install_Path${#MAX_PATH}
  1624.       SHGetFolderPath_(#Null, #CSIDL_COMMON_DOCUMENTS, #Null, #Null, @Install_Path$)
  1625.       PathAddBackslash_(@Install_Path$)
  1626.  
  1627.       If *URL
  1628.          URL$  =  PeekS(*URL, -1, RS_SCAL\StrFormat)
  1629.       Else
  1630.          URL$  =  #SCAL_AmpMaster$  +  ".gif"
  1631.       EndIf
  1632.  
  1633.       If StrStrI_(@URL$, @"://")
  1634.  
  1635.          File$ =  RS_SCAL\Temp$ + GetFilePart(URL$, #PB_FileSystem_NoExtension) + ".zip"
  1636.  
  1637.          If StrStrI_(@URL$, @".GIF")
  1638.             NetWorkSkip(6) ; "GIF89a" -> ; skip to real Arc-Header (6 bytes)
  1639.          Else
  1640.             NetWorkSkip(#Null)
  1641.          EndIf
  1642.  
  1643.          IsError  =  Bool(NetWorkDownload(URL$, File$)=0)
  1644.  
  1645.       Else  ; unpack file-archive
  1646.  
  1647.          File$    =  URL$
  1648.          IsError  =  Bool(FileSize(File$)<=0)   ; file error?
  1649.  
  1650.       EndIf
  1651.  
  1652.       If IsError  =  0
  1653.  
  1654.          Count =  ZIP_GetFilesCount(File$)
  1655.  
  1656.          If Count
  1657.             For   i  =  1  To Count
  1658.                If ZIP_ExtractFile(File$, i, Install_Path$)
  1659.                   If RS_SCAL\CallBack  ; user proc?
  1660.                      If CallFunctionFast(RS_SCAL\CallBack, (100.0 / Count) * (i + 1))  ; 126 Files + 3 Folders
  1661.                         IsError  =  #True
  1662.                         Break
  1663.                      EndIf
  1664.                   EndIf
  1665.                Else
  1666.                   IsError  =  #True
  1667.                   Break
  1668.                EndIf
  1669.             Next
  1670.          Else
  1671.             IsError  =  #True
  1672.          EndIf
  1673.  
  1674.       Else
  1675.  
  1676.          IsError  =  #True
  1677.  
  1678.       EndIf
  1679.  
  1680.       If RS_SCAL\CallBack  :  CallFunctionFast(RS_SCAL\CallBack, 100)   :  EndIf ; user proc?
  1681.  
  1682.       ; *** #True = ALL correct unpacked, #False = ERROR!
  1683.       ProcedureReturn   Bool(IsError=0)
  1684.  
  1685.    CompilerElse
  1686.  
  1687.       If RS_SCAL\CallBack  :  CallFunctionFast(RS_SCAL\CallBack, 100)   :  EndIf ; user proc?
  1688.  
  1689.       ProcedureReturn   #False
  1690.  
  1691.    CompilerEndIf
  1692.  
  1693. EndProcedure
  1694. ProcedureDLL   SCAL_CallBack(*Proc)
  1695.    ; *proc = @Procedurename(Param)
  1696.    ; Param -> downloadstatus 0-100%
  1697.    RS_SCAL\CallBack  =  *Proc ; NetWorkCallBack()
  1698. EndProcedure
  1699. ProcedureDLL   SCAL_Download(*URL, *File, Skip, Flags)
  1700.  
  1701.    ; Return:   Bytesize of download or number of unpacked files
  1702.  
  1703.    Static   Count
  1704.    Protected   i, File$, Path$, URL$
  1705.  
  1706.    If *URL  =  #Null :  ProcedureReturn   #Null :  EndIf
  1707.  
  1708.    URL$  =  PeekS(*URL, -1, RS_SCAL\StrFormat)
  1709.    If StrStrI_(@URL$, @"://") =  #Null :  ProcedureReturn   #Null :  EndIf
  1710.  
  1711.    If *File =  #Null
  1712.       scal_Temp(#SCAL_TempPath$)
  1713.       File$ =  RS_SCAL\Temp$ + GetFilePart(URL$)
  1714.    Else
  1715.       File$ =  PeekS(*File, -1, RS_SCAL\StrFormat)
  1716.    EndIf
  1717.  
  1718.    ; *** already downloaded?
  1719.    Count =  scal_Size(File$)
  1720.    If scal_Size(URL$)   =  Count
  1721.       ProcedureReturn   Count
  1722.    EndIf
  1723.  
  1724.    NetWorkSkip(Skip)
  1725.  
  1726.    i  =  NetWorkDownload(URL$, File$)
  1727.  
  1728.    ; *** Unzip archive?
  1729.    If Flags And   i  >  #Null
  1730.  
  1731.       Count =  ZIP_GetFilesCount(File$)
  1732.  
  1733.       If Count
  1734.  
  1735.          Path$ =  GetPathPart(File$)
  1736.  
  1737.          For   i  =  1  To Count
  1738.             If ZIP_ExtractFile(File$, i, Path$)
  1739.                If RS_SCAL\CallBack  ; user proc?
  1740.                   If CallFunctionFast(RS_SCAL\CallBack, (100.0 / Count) * (i + 1))
  1741.                      Count =  i
  1742.                      Break
  1743.                   EndIf
  1744.                EndIf
  1745.             Else
  1746.                Count =  i
  1747.                Break
  1748.             EndIf
  1749.          Next
  1750.  
  1751.       Else
  1752.  
  1753.          Count =  i  ; bytesize if not packed
  1754.  
  1755.       EndIf
  1756.  
  1757.    Else
  1758.  
  1759.       Count =  i  ; bytesize
  1760.  
  1761.    EndIf
  1762.  
  1763.    If RS_SCAL\CallBack  :  CallFunctionFast(RS_SCAL\CallBack, 100)   :  EndIf ; user proc?
  1764.  
  1765.    ProcedureReturn   Count
  1766.  
  1767. EndProcedure
  1768. ProcedureDLL   SCAL_DownMemory(*URL, *Length.Integer)
  1769.  
  1770.    Static   *Memory
  1771.  
  1772.    If *Memory  >  #Null
  1773.       FreeMemory(*Memory)
  1774.       *Memory  =  #Null
  1775.    EndIf
  1776.  
  1777.    If *URL  <= #Null Or *Length  <= #Null :  ProcedureReturn   #Null :  EndIf
  1778.  
  1779.    *Memory  =  NetWorkLoad(PeekS(*URL, -1, RS_SCAL\StrFormat))
  1780.  
  1781.    If *Memory
  1782.       *Length\i   =  RS_NetWork\Length
  1783.    Else
  1784.       *Length\i   =  #Null
  1785.    EndIf
  1786.  
  1787.    ProcedureReturn   *Memory
  1788.  
  1789. EndProcedure
  1790. ProcedureDLL   SCAL_Formats(Mode, Flags)
  1791.  
  1792.    ; Mode:  #C2D_MUSIC_[MODE] =  Get info of supported formats by Mode
  1793.    ;        < min or > max    =  Get info of all supported formats by SCAL
  1794.  
  1795.    ; Flags: 0  =  Get number of supported formats
  1796.    ;        1  =  Get ptr to unicode formatstrings "AHX;MOD;MP3..."
  1797.  
  1798.    Static   Count
  1799.    Static   TotalMode$, TotalCount
  1800.  
  1801.    Protected   t$, *Memory.Character
  1802.  
  1803.    Select   Mode
  1804.       Case  #SCAL_MIN   To #SCAL_MAX
  1805.  
  1806.          ;{ Mode = #C2D_MUSIC_[MODE] - Calculate supported formats by Engine }
  1807.  
  1808.          Select   Mode
  1809.  
  1810.             Case  #C2D_MUSIC_AHX :  *Memory  =  ?l_AHX
  1811.  
  1812.             CompilerIf  #IsAMP
  1813.             Case  #C2D_MUSIC_AMP :  *Memory  =  ?l_AMP
  1814.             CompilerEndIf
  1815.  
  1816.             Case  #C2D_MUSIC_API :  *Memory  =  ?l_WAV
  1817.  
  1818.             CompilerIf  #IsBAS
  1819.             Case  #C2D_MUSIC_BAS :  *Memory  =  ?l_BAS
  1820.             CompilerEndIf
  1821.  
  1822.             CompilerIf  #IsBMF
  1823.             Case  #C2D_MUSIC_BMF :  *Memory  =  ?l_BMF
  1824.             CompilerEndIf
  1825.  
  1826.             Case  #C2D_MUSIC_FC4 :  *Memory  =  ?l_FC4
  1827.  
  1828.             CompilerIf  #IsFCP
  1829.             Case  #C2D_MUSIC_FCP :  *Memory  =  ?l_FCP
  1830.             CompilerEndIf
  1831.  
  1832.             Case  #C2D_MUSIC_FLA :  *Memory  =  ?l_FLA
  1833.  
  1834.             Case  #C2D_MUSIC_FT2 :  *Memory  =  ?l_FT2
  1835.  
  1836.             Case  #C2D_MUSIC_MCI :  *Memory  =  ?l_MCI
  1837.  
  1838.             CompilerIf  #IsMED
  1839.             Case  #C2D_MUSIC_MED :  *Memory  =  ?l_MED
  1840.             CompilerEndIf
  1841.  
  1842.             Case  #C2D_MUSIC_MOD :  *Memory  =  ?l_MOD
  1843.  
  1844.             CompilerIf  #IsMOV
  1845.             Case  #C2D_MUSIC_MOV :  *Memory  =  ?l_MCI
  1846.             CompilerEndIf
  1847.  
  1848.             Case  #C2D_MUSIC_OGG :  *Memory  =  ?l_OGG
  1849.  
  1850.             Case  #C2D_MUSIC_PT2 :  *Memory  =  ?l_PT2
  1851.  
  1852.             CompilerIf  #IsS68
  1853.             Case  #C2D_MUSIC_S68 :  *Memory  =  ?l_SC68
  1854.             CompilerEndIf
  1855.  
  1856.             CompilerIf  #IsSID
  1857.             Case  #C2D_MUSIC_SID :  *Memory  =  ?l_SID
  1858.             CompilerEndIf
  1859.  
  1860.             Case  #C2D_MUSIC_STM :  *Memory  =  ?l_STM
  1861.  
  1862.             Case  #C2D_MUSIC_S3M :  *Memory  =  ?l_S3M
  1863.  
  1864.             Case  #C2D_MUSIC_TFC :  *Memory  =  ?l_FC4
  1865.  
  1866.             Case  #C2D_MUSIC_THX :  *Memory  =  ?l_AHX
  1867.  
  1868.             Case  #C2D_MUSIC_TPT :  *Memory  =  ?l_PT2
  1869.  
  1870.             CompilerIf  #IsTSR
  1871.             Case  #C2D_MUSIC_TSR :  *Memory  =  ?l_SID
  1872.             CompilerEndIf
  1873.  
  1874.             CompilerIf  #IsV1M
  1875.             Case  #C2D_MUSIC_V1M :  *Memory  =  ?l_V2M
  1876.             CompilerEndIf
  1877.  
  1878.             CompilerIf  #IsV2M
  1879.             Case  #C2D_MUSIC_V2M :  *Memory  =  ?l_V2M
  1880.             CompilerEndIf
  1881.  
  1882.             Case  #C2D_MUSIC_WAV :  *Memory  =  ?l_WAV
  1883.  
  1884.             CompilerIf  #IsXM2
  1885.             Case  #C2D_MUSIC_XM2 :  *Memory  =  ?l_XM2
  1886.             CompilerEndIf
  1887.  
  1888.             CompilerIf  #IsYMP
  1889.             Case  #C2D_MUSIC_YMP :  *Memory  =  ?l_YMP
  1890.             CompilerEndIf
  1891.  
  1892.          EndSelect
  1893.  
  1894.          If Flags And   *Memory
  1895.             ProcedureReturn   *Memory  ; ptr to ;MOD;...
  1896.          EndIf
  1897.  
  1898.          If *Memory  ; count extensions?
  1899.             Count =  -2 ; first ";" + last ";" + #null
  1900.             While *Memory  >  SizeOf(Character)
  1901.                *Memory  =  StrStrI_(*Memory, @";") +  SizeOf(Character)
  1902.                Count +  1
  1903.             Wend
  1904.          Else
  1905.             Count =  #Null
  1906.          EndIf
  1907.  
  1908.          ProcedureReturn   Count
  1909.          ;}
  1910.  
  1911.       Default  ; -1
  1912.  
  1913.          ;{ Mode <= #Null - Calculate ALL supported formats once }
  1914.  
  1915.          If TotalCount
  1916.             If Flags ; String?
  1917.                ProcedureReturn   @TotalMode$
  1918.             EndIf
  1919.             ProcedureReturn   TotalCount
  1920.          EndIf
  1921.  
  1922.          Protected   NewMap   ExtMap.s()
  1923.          Protected   NewList  ExtList.s()
  1924.  
  1925.          *Memory  =  ?l_Start
  1926.          While *Memory  <  ?l_Finish
  1927.             If *Memory\c
  1928.                t$ =  PeekS(*Memory)
  1929.                TotalMode$  +  Trim(t$, ";")  +  ";"   :  *Memory  +  Len(t$)  *  SizeOf(Character)
  1930.             EndIf
  1931.             *Memory  +  SizeOf(Character) ; Null$
  1932.          Wend
  1933.  
  1934.          Repeat
  1935.             TotalCount  +  1  :  t$ =  StringField(TotalMode$, TotalCount, ";")  :  ExtMap(t$)
  1936.          Until Len(t$)  =  #Null
  1937.  
  1938.          ForEach  ExtMap()
  1939.             If MapKey(ExtMap())
  1940.                AddElement(ExtList())   :  ExtList()   =  MapKey(ExtMap())
  1941.             EndIf
  1942.          Next
  1943.  
  1944.          SortList(ExtList(), #PB_Sort_Ascending)
  1945.  
  1946.          TotalCount  =  ListSize(ExtList())
  1947.          TotalMode$  =  ";"   ; ";Format;"
  1948.          ForEach  ExtList()
  1949.             TotalMode$  +  ExtList()   +  ";"
  1950.          Next
  1951.  
  1952.          FreeMap(ExtMap())
  1953.          FreeList(ExtList())
  1954.  
  1955.          If Flags
  1956.             ProcedureReturn   @TotalMode$
  1957.          EndIf
  1958.  
  1959.          ProcedureReturn   TotalCount
  1960.          ;}
  1961.  
  1962.    EndSelect
  1963.  
  1964. EndProcedure
  1965. ProcedureDLL   SCAL_Free()
  1966.  
  1967.    Protected   StrFormat, Freq, *Proc
  1968.    Static   Volume=-1
  1969.  
  1970.    With  RS_SCAL
  1971.  
  1972.       If \ID   ; Is playing active?
  1973.          Select   \Mode
  1974.  
  1975.             Case  #C2D_MUSIC_AHX :  ahx1play_Close()
  1976.             Case  #C2D_MUSIC_API :  PlaySound_(#Null, #Null, #Null)
  1977.             Case  #C2D_MUSIC_FC4 :  fc14play_Close()
  1978.             Case  #C2D_MUSIC_FLA :  If IsSound(0)  :  FreeSound(0)   :  EndIf
  1979.             Case  #C2D_MUSIC_FT2 :  ft2play_Close()
  1980.             Case  #C2D_MUSIC_MCI :  mciSendString_(@"STOP 0", 0, 0, 0)  :  mciSendString_(@"CLOSE 0", 0, 0, 0)
  1981.             Case  #C2D_MUSIC_MOD :  If IsMusic(0)  :  FreeMusic(0)   :  EndIf
  1982.             Case  #C2D_MUSIC_OGG :  If IsSound(0)  :  FreeSound(0)   :  EndIf
  1983.             Case  #C2D_MUSIC_PT2 :  pt2play_Close()
  1984.             Case  #C2D_MUSIC_S3M :  st3play_Close()
  1985.             Case  #C2D_MUSIC_STM :  st23play_Close()
  1986.             Case  #C2D_MUSIC_TFC :  tinyfc14play_Close()
  1987.             Case  #C2D_MUSIC_THX :  tinyahx1play_Close()
  1988.             Case  #C2D_MUSIC_TPT :  tinypt2play_Close()
  1989.             Case  #C2D_MUSIC_WAV :  If IsSound(0)  :  FreeSound(0)   :  EndIf
  1990.  
  1991.             CompilerIf  #IsAMP
  1992.             Case  #C2D_MUSIC_AMP :  AmpMusicFree()
  1993.             CompilerEndIf
  1994.             CompilerIf  #IsBAS
  1995.             Case  #C2D_MUSIC_BAS
  1996.                BASSMOD_MusicStop()
  1997.                BASSMOD_MusicFree()
  1998.                BASSMOD_SetVolume(100)  ; restore digital volume!
  1999.                BASSMOD_Free()
  2000.             CompilerEndIf
  2001.             CompilerIf  #IsBMF
  2002.             Case  #C2D_MUSIC_BMF
  2003.                SynthEnter(\ID)
  2004.                SynthStop(\ID)
  2005.                SynthLeave(\ID)
  2006.                SynthDestroy(\ID)
  2007.             CompilerEndIf
  2008.             CompilerIf  #IsFCP
  2009.             Case  #C2D_MUSIC_FCP :  FCp_Close()
  2010.             CompilerEndIf
  2011.             CompilerIf  #IsMED
  2012.             Case  #C2D_MUSIC_MED
  2013.                MEDP_Stop()
  2014.                MEDP_Unload()
  2015.                MEDP_Release()
  2016.             CompilerEndIf
  2017.             CompilerIf  #IsMOV
  2018.             Case  #C2D_MUSIC_MOV
  2019.                If IsMovie(0)     :  FreeMovie(0)      :  EndIf
  2020.                If \WinID   And   IsWindow(\WinID)
  2021.                   CloseWindow(\WinID)
  2022.                EndIf
  2023.                \WinID   =  #Null
  2024.             CompilerEndIf
  2025.             CompilerIf  #IsS68
  2026.             Case  #C2D_MUSIC_S68 :  sc68_Free() ;sc68replay_Stop()
  2027.             CompilerEndIf
  2028.             CompilerIf  #IsSID
  2029.             Case  #C2D_MUSIC_SID :  SIDClose()
  2030.             CompilerEndIf
  2031.             CompilerIf  #IsTSR
  2032.             Case  #C2D_MUSIC_TSR :  sid_sound_server_replay_stop()
  2033.             CompilerEndIf
  2034.             CompilerIf  #IsV1M
  2035.             Case  #C2D_MUSIC_V1M
  2036.                ssStop()
  2037.                ssClose()
  2038.             CompilerEndIf
  2039.             CompilerIf  #IsV2M
  2040.             Case  #C2D_MUSIC_V2M
  2041.                If \IsPause =  0  ; remember: custom pause!
  2042.                   V2MStop()
  2043.                   dsClose()
  2044.                EndIf
  2045.             CompilerEndIf
  2046.             CompilerIf  #IsXM2
  2047.             Case  #C2D_MUSIC_XM2 :  uFMOD_PlaySong(#Null)
  2048.             CompilerEndIf
  2049.             CompilerIf  #IsYMP
  2050.             Case  #C2D_MUSIC_YMP
  2051.                YM_Stop()
  2052.                YM_Close()
  2053.             CompilerEndIf
  2054.  
  2055.          EndSelect
  2056.       EndIf
  2057.  
  2058.       ; Netfile downloaded?
  2059.       NetWorkFree()
  2060.  
  2061.       ; Intern temporary *buffer?
  2062.       If \IsAlloc And   \Memory
  2063.          FreeMemory(\Memory)
  2064.       EndIf
  2065.  
  2066.       ; AscII or Unicode?
  2067.       If \StrFormat  <= #Null
  2068.          \StrFormat  =  #PB_Unicode ; Default PeekS-Mode if *Memory = @File
  2069.       EndIf
  2070.  
  2071.       ; Set default frequency
  2072.       If \Freq <= #Null
  2073.          \Freq =  44100
  2074.       EndIf
  2075.  
  2076.       ; Set default volume (used in SCAL_Play)
  2077.       If Volume   <  #Null And   \Volume  <= #Null
  2078.          \Volume  =  100
  2079.       EndIf
  2080.  
  2081.       StrFormat   =  \StrFormat
  2082.       Freq        =  \Freq
  2083.       Volume      =  \Volume
  2084.       *Proc       =  \CallBack
  2085.  
  2086.       ClearStructure(@RS_SCAL, RS_SCAL)
  2087.  
  2088.       \Freq       =  Freq
  2089.       \StrFormat  =  StrFormat
  2090.       \Volume     =  Volume   ; -1
  2091.       \CallBack   =  *Proc
  2092.       \NetLength  =  #Null
  2093.  
  2094.       ; Generate *pointers (avoid *ptr=0 error)
  2095.       \File$      =  #Null$
  2096.       \Path$      =  #Null$
  2097.       \Time$      =  #Null$
  2098.       \Title$     =  #Null$
  2099.       \Tracker$   =  #Null$
  2100.  
  2101.    EndWith
  2102.  
  2103. EndProcedure
  2104. ProcedureDLL   SCAL_GetLength(Flags)
  2105.  
  2106.    ; Flags: 0  =  Get timelength in ms
  2107.    ;        1  =  Get ptr to unicode timestring "hh:mm:ss.ttt"
  2108.  
  2109.    ; RETURN: Time in ms or ptr to timestring - #NULL not playing or time not calcuable
  2110.  
  2111.    With  RS_SCAL
  2112.  
  2113.       If Flags
  2114.          If \Time
  2115.             \Time$   =  StrTime(\Time)
  2116.             \Time$   =  RTrim(\Time$, "0")
  2117.             \Time$   =  RTrim(\Time$, ",")
  2118.          Else
  2119.             \Time$   =  PeekS(?s_unknown) ; "?"
  2120.          EndIf
  2121.          ProcedureReturn   @\Time$
  2122.       EndIf
  2123.  
  2124.       ProcedureReturn   \Time
  2125.  
  2126.    EndWith
  2127.  
  2128. EndProcedure
  2129. ProcedureDLL   SCAL_GetLink(*URL)
  2130.  
  2131.    ; Decode the real url of a hosted mediafile
  2132.  
  2133.    ; Return: Ptr to @filename / #NULL = Error
  2134.  
  2135.    Static   URL$
  2136.  
  2137.    Protected   Link$, t$, ID$, ID, *Start, *Finish
  2138.    Protected   hNET, hURL, Length
  2139.  
  2140.    URL$  =  #Null$
  2141.    Link$ =  PeekS(*URL, -1, RS_SCAL\StrFormat)  ; string to user-format
  2142.  
  2143.    ; ----------------------------
  2144.    ; *** Prepare access links ***
  2145.    ; ----------------------------
  2146.    If       StrStrI_(@Link$, @"://dein.tube/")
  2147.       ID =  #ID_DEINTUBE   :  ReplaceString(Link$, "/watch/", "/embed/", #PB_String_InPlace) ; embed -> shorter netload-datas
  2148.    ElseIf   StrStrI_(@Link$, @"://www.bitchute.com/")
  2149.       ID =  #ID_BITCHUTE   :  ReplaceString(Link$, "/video/", "/embed/", #PB_String_InPlace) ; embed -> shorter netload-datas
  2150.    ElseIf   StrStrI_(@Link$, @"://www.mediafire.com/file/")
  2151.       ID =  #ID_MEDIAFIRE
  2152.    ElseIf   StrStrI_(@Link$, @"://www.4shared.com/")
  2153.       ID =  #ID_4SHARED
  2154.    ElseIf   StrStrI_(@Link$, @"://www.gmx.net/")
  2155.       ID =  #ID_GMX
  2156.    ElseIf   StrStrI_(@Link$, @"://web.de/")
  2157.       ID =  #ID_WEBDE
  2158.    ElseIf   StrStrI_(@Link$, @"://www.t-online.de/tv/")
  2159.       ID =  #ID_TONLINE
  2160.    Else
  2161.       ProcedureReturn   #Null
  2162.    EndIf
  2163.  
  2164.    ; ---------------------------------
  2165.    ; *** Read full website of host ***
  2166.    ; ---------------------------------
  2167.    hNET = InternetOpen_(@"SCAL/1.0", #INTERNET_OPEN_TYPE_PRECONFIG, #Null, #Null, 0)
  2168.    If hNET  =  #Null :  ProcedureReturn   #Null :  EndIf ; error
  2169.  
  2170.    hURL = InternetOpenUrl_(hNET, @Link$, #Null, 0, #INTERNET_FLAG_PRAGMA_NOCACHE|#INTERNET_FLAG_KEEP_CONNECTION|#INTERNET_FLAG_NO_COOKIES, 0)
  2171.    If hURL  =  #Null :  InternetCloseHandle_(hNET) :  ProcedureReturn   #Null :  EndIf ; error
  2172.  
  2173.    *Start   =  AllocateMemory(#SIZE_SITEBUF)
  2174.  
  2175.    While InternetReadFile_(hURL, *Start, #SIZE_SITEBUF, @Length)  And   Length   >  #Null
  2176.       t$ +  PeekS(*Start, Length, #PB_Ascii)
  2177.    Wend
  2178.  
  2179.    FreeMemory(*Start)
  2180.  
  2181.    InternetCloseHandle_(hURL)
  2182.    InternetCloseHandle_(hNET)
  2183.  
  2184.    ; ------------------------------------
  2185.    ; *** Search for link ( & decode ) ***
  2186.    ; ------------------------------------
  2187.    *Start   =  @t$
  2188.    *Finish  =  *Start   +  Len(t$)  *  SizeOf(Character)
  2189.  
  2190.    Select   ID
  2191.  
  2192.       Case  #ID_BITCHUTE   ;{ *** www.bitchute.com *** }
  2193.  
  2194.          ID$   =  ~"<source src=\""
  2195.         *URL  =  StrStrI_(*Start, @ID$)
  2196.  
  2197.         If *URL
  2198.            *URL  =  StrStrI_(*URL, @"H") ; http
  2199.            URL$  =  PeekS(*URL, (StrStrI_(*URL, #DQUOTE$) - *URL) / SizeOf(Character))
  2200.         EndIf
  2201.         ;}
  2202.  
  2203.      Case  #ID_MEDIAFIRE  ;{ *** www.mediafire.com *** }
  2204.  
  2205.         ID$   =  "http://download"
  2206.         *URL  =  StrStrI_(*Start, @ID$)
  2207.  
  2208.         If *URL  =  #Null
  2209.            *URL  =  StrStrI_(*Start, @"https://download")
  2210.         EndIf
  2211.  
  2212.         If *URL
  2213.            URL$  =  PeekS(*URL, (StrStrI_(*URL, #DQUOTE$) - *URL) / SizeOf(Character))
  2214.         EndIf
  2215.         ;}
  2216.  
  2217.      Case  #ID_DEINTUBE   ;{ *** dein.tube (no donnersender anymore! coz Thorsten blop the videos) *** }
  2218.  
  2219.         ; !!dein.tube support embed dailymotion, but dm is not supported by edge!!
  2220.         *URL  =  StrStrI_(*Start, @"//www.dailymotion.com/embed/video/")
  2221.  
  2222.         If *URL
  2223.  
  2224.            URL$  =  "https:" +  PeekS(*URL, (StrStrI_(*URL, @"?") - *URL) / SizeOf(Character))
  2225.  
  2226.         Else
  2227.  
  2228.            ID$   =  "/upload/videos/"
  2229.  
  2230.            While *Start   <  *Finish
  2231.  
  2232.               *URL  =  StrStrI_(*Start, @ID$)
  2233.               If *URL  =  #Null :  URL$  =  #Null$   :  Break :  EndIf
  2234.  
  2235.               URL$  =  PeekS(*URL, (StrStrI_(*URL, #DQUOTE$) - *URL) / SizeOf(Character))
  2236.  
  2237.               ; must type/mp4 (no jpg, gif - don't test with extensionpart)
  2238.               If StrStrI_(@URL$, @".MP4")
  2239.  
  2240.                  ; remove parameter?
  2241.                  If StrStrI_(@URL$, @"?")
  2242.                     URL$  =  PeekS(*URL, (StrStrI_(*URL, @"?") - *URL) / SizeOf(Character))
  2243.                  EndIf
  2244.  
  2245.                  URL$  =  "https://cdn.dein.tube" +  URL$
  2246.  
  2247.                  Break
  2248.  
  2249.               EndIf
  2250.  
  2251.               *Start   =  *URL  +  SizeOf(Character)
  2252.  
  2253.            Wend
  2254.  
  2255.         EndIf
  2256.         ;}
  2257.  
  2258.      Case  #ID_4SHARED    ;{ *** www.4shared.com *** }
  2259.  
  2260.         If StrStrI_(@Link$, @"/MP3/") Or StrStrI_(@Link$, @"/music/")  ; *** MP3 full preview ***
  2261.  
  2262.            ID$   =  ~"data-cp-preview=\""
  2263.             *URL  =  StrStrI_(*Start, @ID$)
  2264.  
  2265.             If *URL
  2266.  
  2267.                *URL  +  Len(ID$) *  SizeOf(Character)
  2268.                URL$  =  PeekS(*URL, (StrStrI_(*URL, #DQUOTE$) - *URL) / SizeOf(Character))
  2269.  
  2270.                *URL  =  AllocateMemory(Len(URL$) * SizeOf(Character) * 2 + 64)
  2271.  
  2272.                ; decode link
  2273.                If Base64Decoder(URL$, *URL, MemorySize(*URL))
  2274.                   URL$  =  PeekS(*URL, -1, #PB_Ascii)
  2275.                Else
  2276.                   URL$  =  #Null$
  2277.                EndIf
  2278.  
  2279.                FreeMemory(*URL)
  2280.  
  2281.             EndIf
  2282.  
  2283.          ElseIf   StrStrI_(@Link$, @"/video/")  ; *** MP4 full preview ***
  2284.  
  2285.             *URL  =  StrStrI_(*Start, @"file: 'https://dc")
  2286.  
  2287.             If *URL
  2288.                *URL  =  StrStrI_(*URL, @"H") ; https://
  2289.                URL$  =  PeekS(*URL, (StrStrI_(*URL, @"'") - *URL) / SizeOf(Character))
  2290.             EndIf
  2291.  
  2292.          EndIf
  2293.          ;}
  2294.  
  2295.       Case  #ID_GMX,
  2296.             #ID_WEBDE      ;{ *** www.gmx.net / web.de (same stupid videos) *** }
  2297.  
  2298.          Select   ID
  2299.             Case  #ID_GMX     :  ID$   =  "'file': 'https://v.gmx.net/"
  2300.             Case  #ID_WEBDE   :  ID$   =  "'file': 'https://v.web.de/"
  2301.          EndSelect
  2302.  
  2303.          While *Start   <  *Finish
  2304.  
  2305.             *URL  =  StrStrI_(*Start, @ID$)
  2306.             If *URL  =  #Null :  Break :  EndIf
  2307.  
  2308.             *URL  =  StrStrI_(*URL, @"H")
  2309.             URL$  =  PeekS(*URL, (StrStrI_(*URL, @"'") - *URL) / SizeOf(Character))
  2310.  
  2311.             *Start   =  *URL  +  SizeOf(Character)
  2312.  
  2313.          Wend
  2314.          ;}
  2315.  
  2316.       Case  #ID_TONLINE    ;{ *** www.t-online.de *** }
  2317.  
  2318.          ID$   =  ~"source data-quality=\""
  2319.         *URL  =  StrStrI_(*Start, @ID$)
  2320.  
  2321.         If *URL
  2322.            *URL  =  StrStrI_(*URL, @"H")
  2323.            URL$  =  PeekS(*URL, (StrStrI_(*URL, #DQUOTE$) - *URL) / SizeOf(Character))
  2324.         EndIf
  2325.         ;}
  2326.  
  2327.   EndSelect
  2328.  
  2329.   t$ =  #Null$
  2330.  
  2331.   If Len(URL$)
  2332.      ProcedureReturn   @URL$
  2333.   EndIf
  2334.  
  2335.   ProcedureReturn   #Null
  2336.  
  2337. EndProcedure
  2338. ProcedureDLL   SCAL_GetMode(Flags)
  2339.  
  2340.   ; Flags: 0  =  Get #ID of playengine
  2341.   ;        1  =  Get *ptr to string char[3] of playengine
  2342.  
  2343.   Static   t$
  2344.  
  2345.   With  RS_SCAL
  2346.  
  2347.      If \ID   =  #Null ; do not check with <= 0
  2348.         If Flags
  2349.            ProcedureReturn   ?s_unknown
  2350.         EndIf
  2351.         ProcedureReturn   #Null
  2352.      EndIf
  2353.  
  2354.      If Flags
  2355.         t$ =  PeekS(PeekI(?mode + \Mode * SizeOf(Integer)))
  2356.         t$ =  StringField(t$, 1, "|")
  2357.         ProcedureReturn   @t$
  2358.         ;ProcedureReturn  (?s_Mode +  (\Mode   -  1) *  4  *  SizeOf(Character))   ; 4 = AHX + 0
  2359.      EndIf
  2360.  
  2361.      ProcedureReturn   \Mode
  2362.  
  2363.   EndWith
  2364.  
  2365. EndProcedure
  2366. ProcedureDLL   SCAL_GetPosition(Flags)
  2367.  
  2368.   ; Flags: 0  =  Get current playposition in ms
  2369.   ;        1  =  Get ptr to timestring (hh:mm:ss.ttt) of current playposition
  2370.  
  2371.   ; RETURN:   Playtime in ms or *ptr to timestring
  2372.  
  2373.   ; - remarked engines calculate a timeline not the real pos of mixerticks!
  2374.   ; - call GetPosition() also to loop song on end
  2375.  
  2376.   Static   Time, t${#MAX_PATH}
  2377.  
  2378.   With  RS_SCAL
  2379.  
  2380.      If \ID   =  #Null ; do not check with <= 0
  2381.         If Flags
  2382.            ProcedureReturn   ?s_unknown
  2383.         EndIf
  2384.         ProcedureReturn   #Null
  2385.      EndIf
  2386.  
  2387.      Select   \Mode
  2388.  
  2389.         ;Case #C2D_MUSIC_AHX :  Time  =  ahx1play_GetMixerTicks()
  2390.         ;Case #C2D_MUSIC_FC4 :  Time  =  fc14play_GetMixerTicks()
  2391.         ;Case #C2D_MUSIC_FT2 :  Time  =  ft2play_GetMixerTicks()
  2392.         ;Case #C2D_MUSIC_PT2 :  Time  =  pt2play_GetMixerTicks()
  2393.         ;Case #C2D_MUSIC_STM :  Time  =  st23play_GetMixerTicks()
  2394.         ;Case #C2D_MUSIC_S3M :  Time  =  st3play_GetMixerTicks()
  2395.  
  2396.         Case  #C2D_MUSIC_OGG, #C2D_MUSIC_FLA, #C2D_MUSIC_WAV
  2397.            Time  =  GetSoundPosition(0, #PB_Sound_Millisecond)
  2398.  
  2399.         Case  #C2D_MUSIC_MCI
  2400.            mciSendString_(@"STATUS 0 POSITION", @t$, #MAX_PATH, 0)
  2401.            StrToInt64Ex_(@t$, #Null, @Time)
  2402.  
  2403.         CompilerIf  #IsV2M
  2404.         Case  #C2D_MUSIC_V2M
  2405.            Time  =  V2MGetCurrentTime()
  2406.         CompilerEndIf
  2407.  
  2408.         CompilerIf  #IsXM2
  2409.         Case  #C2D_MUSIC_XM2
  2410.            Time  =  uFMOD_GetTime()
  2411.         CompilerEndIf
  2412.  
  2413.         CompilerIf  #IsAMP
  2414.         Case  #C2D_MUSIC_AMP
  2415.            Time  =  AmpMusicPosition()
  2416.            If Time  >= RS_Amp\TimeLength
  2417.               RS_Amp\TimeLoop   =  #Null
  2418.               AmpMusicLoop() ; reload file
  2419.               AmpMusicVolume(2.55 * RS_SCAL\Volume)
  2420.            EndIf
  2421.         CompilerEndIf
  2422.  
  2423.         Default
  2424.  
  2425.            Time  =  ElapsedMilliseconds()   -  \TimePlay
  2426.  
  2427.            ; reset time-position & loop media?
  2428.            If \Time And   Time  >= \Time
  2429.  
  2430.               Select   \Mode
  2431.                  Case  #C2D_MUSIC_YMP
  2432.                     CompilerIf  #IsYMP
  2433.                        ; time is -200 ms coz no loop on (real) end
  2434.                        ; some songs work, some not...
  2435.                        YM_Seek(0)
  2436.                     CompilerEndIf
  2437.                  Case  #C2D_MUSIC_MOV
  2438.                     CompilerIf  #IsMOV
  2439.                        MovieSeek(0, 0)
  2440.                     CompilerEndIf
  2441.               EndSelect
  2442.  
  2443.               Time        =  #Null
  2444.               \TimePlay   =  ElapsedMilliseconds()
  2445.  
  2446.            EndIf
  2447.  
  2448.      EndSelect
  2449.  
  2450.      If Time  <  #Null :  Time  =  #Null :  EndIf
  2451.  
  2452.      If Flags ; TimeString?
  2453.         \Time$   =  StrTime(Time)
  2454.         ProcedureReturn   @\Time$
  2455.      EndIf
  2456.  
  2457.      ProcedureReturn   Time
  2458.  
  2459.   EndWith
  2460.  
  2461. EndProcedure
  2462. ProcedureDLL   SCAL_GetSize(Flags)
  2463.  
  2464.   ; Flags: 0 = Integer, 1 = *StrSize
  2465.  
  2466.   With  RS_SCAL
  2467.  
  2468.      If \Length  <= #Null
  2469.         \Length  =  FileSize(\File$)
  2470.      EndIf
  2471.  
  2472.      If \Length  <  #Null
  2473.         \Length  =  #Null
  2474.      EndIf
  2475.  
  2476.      If Flags
  2477.         ProcedureReturn   StrSize(\Length)
  2478.      EndIf
  2479.  
  2480.      ProcedureReturn   \Length
  2481.  
  2482.   EndWith
  2483.  
  2484. EndProcedure
  2485. ProcedureDLL   SCAL_GetSubsongs()
  2486.   With  RS_SCAL
  2487.      ProcedureReturn   \Songs
  2488.   EndWith
  2489. EndProcedure
  2490. ProcedureDLL   SCAL_GetTitle()
  2491.   With  RS_SCAL
  2492.      ProcedureReturn   @\Title$
  2493.   EndWith
  2494. EndProcedure
  2495. ProcedureDLL   SCAL_GetTracker()
  2496.   With  RS_SCAL
  2497.      ProcedureReturn   @\Tracker$
  2498.   EndWith
  2499. EndProcedure
  2500. ProcedureDLL   SCAL_Info(Flags)
  2501.  
  2502.   Protected   t$, Title$="SCAL DLL v" + StrF(#SCAL_VERSION * 0.01, 2)
  2503.  
  2504.   CompilerIf  #IsX86
  2505.      Title$   +  " (x86)"
  2506.   CompilerElse
  2507.      Title$   +  " (x64)"
  2508.   CompilerEndIf
  2509.  
  2510.   With  RS_SCAL
  2511.  
  2512.      ; Sound playing?
  2513.      If \ID   <= #Null :  ProcedureReturn   #Null :  EndIf
  2514.  
  2515.      If \Length  <= #Null
  2516.         \Length  =  SCAL_GetSize(0)
  2517.      EndIf
  2518.  
  2519.      If \File$
  2520.         \File$   =  ReplaceString(\File$, "%20", " ")
  2521.         t$ +  "File:"  +  #TAB$ +  GetFilePart(\File$)  +  #LF$
  2522.         t$ +  "Path:"  +  #TAB$ +  GetPathPart(\File$)  +  #LF$
  2523.      EndIf
  2524.  
  2525.      If \Length        :  t$ +  "Size:"  +  #TAB$ +  PeekS(SCAL_GetSize(1))        +  #LF$  :  EndIf
  2526.  
  2527.      If t$ :  t$ +  #LF$  :  EndIf ; kosmetische Freizeile
  2528.  
  2529.      If \Title$        :  t$ +  "Title:" +  #TAB$ +  \Title$                       +  #LF$  :  EndIf ; PeekS(SCAL_GetTitle())
  2530.  
  2531.      If \Time >  #Null :  t$ +  "Time:"  +  #TAB$ +  PeekS(SCAL_GetLength(1))      +  #LF$  :  EndIf
  2532.  
  2533.      If \Songs   >  1
  2534.         t$ +  "Song:"  +  #TAB$ +  Str(\SubSong + \ZipSong) + "/" + Str(\Songs)    +  #LF$  ; Str(SCAL_GetSubsongs())
  2535.      EndIf
  2536.  
  2537.      t$ +  #LF$  ; kosmetische Freizeile
  2538.  
  2539.      If \Tracker$      :  t$ +  "Type:"  +  #TAB$ +  \Tracker$                     +  #LF$  :  EndIf ; PeekS(SCAL_GetTracker())
  2540.  
  2541.      t$ +  #LF$  +  "Mode:"  +  #TAB$ +  "#C2D_MUSIC_"  +  PeekS(SCAL_GetMode(1))  +  #LF$
  2542.  
  2543.      ProcedureReturn   MessageBox_(GetForegroundWindow_(), @t$, @Title$, Flags)
  2544.  
  2545.   EndWith
  2546.  
  2547. EndProcedure
  2548. ProcedureDLL   SCAL_IsFormat(Mode, *Memory.Long, Length)
  2549.  
  2550.   ; Tiny check file.extension ?.* and *.? or *Memoryblock
  2551.  
  2552.   ; *Memory   =  Pointer to @File or *Memory
  2553.   ; Length    =  Size of *Memory or 0 if *Memory = @File
  2554.  
  2555.   ; Return:   Mode or #NULL if not supported
  2556.  
  2557.   Static   Typ
  2558.  
  2559.   Typ   =  #Null
  2560.  
  2561.   If Length   <= #Null
  2562.  
  2563.      ;{ *File? }
  2564.  
  2565.      Protected   *x, i
  2566.  
  2567.      For   i  =  0  To 1
  2568.  
  2569.         *x =  scal_Sufx(*Memory, i)   :  If *x =  #Null :  Continue :  EndIf
  2570.  
  2571.         Select   Mode
  2572.         Case  #C2D_MUSIC_AHX, #C2D_MUSIC_THX   :  Typ   =  StrStrI_(?l_AHX, *x)
  2573.         Case  #C2D_MUSIC_FC4, #C2D_MUSIC_TFC   :  Typ   =  StrStrI_(?l_FC4, *x)
  2574.         Case  #C2D_MUSIC_PT2, #C2D_MUSIC_TPT   :  Typ   =  StrStrI_(?l_PT2, *x)
  2575.         Case  #C2D_MUSIC_API, #C2D_MUSIC_WAV   :  Typ   =  StrStrI_(?l_WAV, *x)
  2576.         Case  #C2D_MUSIC_MCI, #C2D_MUSIC_MOV   :  Typ   =  StrStrI_(?l_MCI, *x)
  2577.         Case  #C2D_MUSIC_FT2 :  Typ   =  StrStrI_(?l_FT2, *x)
  2578.         Case  #C2D_MUSIC_S3M :  Typ   =  StrStrI_(?l_S3M, *x)
  2579.         Case  #C2D_MUSIC_STM :  Typ   =  StrStrI_(?l_STM, *x)
  2580.         Case  #C2D_MUSIC_FLA :  Typ   =  StrStrI_(?l_FLA, *x)
  2581.         Case  #C2D_MUSIC_OGG :  Typ   =  StrStrI_(?l_OGG, *x)
  2582.         Case  #C2D_MUSIC_MOD :  Typ   =  StrStrI_(?l_MOD, *x)
  2583.  
  2584.         CompilerIf  #IsAMP
  2585.         Case  #C2D_MUSIC_AMP
  2586.            Typ   =  StrStrI_(?l_AMP, *x)
  2587.         CompilerEndIf
  2588.         CompilerIf  #IsBAS
  2589.         Case  #C2D_MUSIC_BAS
  2590.               Typ   =  StrStrI_(?l_BAS, *x)
  2591.         CompilerEndIf
  2592.         CompilerIf  #IsBMF
  2593.         Case  #C2D_MUSIC_BMF
  2594.            Typ   =  StrStrI_(?l_BMF, *x)
  2595.         CompilerEndIf
  2596.         CompilerIf  #IsMED
  2597.         Case  #C2D_MUSIC_MED
  2598.            Typ   =  StrStrI_(?l_MED, *x)
  2599.         CompilerEndIf
  2600.         CompilerIf  #IsFCP
  2601.         Case  #C2D_MUSIC_FCP
  2602.            Typ   =  StrStrI_(?l_FCP, *x)
  2603.         CompilerEndIf
  2604.         CompilerIf  #IsS68
  2605.         Case  #C2D_MUSIC_S68
  2606.            Typ   =  StrStrI_(?l_SC68, *x)
  2607.         CompilerEndIf
  2608.         CompilerIf  (#IsSID  +  #IsTSR)
  2609.         Case  #C2D_MUSIC_SID, #C2D_MUSIC_TSR
  2610.            Typ   =  StrStrI_(?l_SID, *x)
  2611.         CompilerEndIf
  2612.         CompilerIf  (#IsV1M  +  #IsV2M)
  2613.         Case  #C2D_MUSIC_V1M, #C2D_MUSIC_V2M
  2614.            Typ   =  StrStrI_(?l_V2M, *x)
  2615.         CompilerEndIf
  2616.         CompilerIf  #IsXM2
  2617.         Case  #C2D_MUSIC_XM2
  2618.            Typ   =  StrStrI_(?l_XM2, *x)
  2619.         CompilerEndIf
  2620.         CompilerIf  #IsYMP
  2621.         Case  #C2D_MUSIC_YMP
  2622.            Typ   =  StrStrI_(?l_YMP, *x)
  2623.         CompilerEndIf
  2624.  
  2625.         Default  ; < Min or > Max  -> search through all extensions (SCAL Mode)
  2626.  
  2627.            Typ   =  StrStrI_(SCAL_Formats(#Null, 1), *x)   ; fastest check on 2. call!
  2628.  
  2629.         EndSelect
  2630.  
  2631.         If Typ   >  0  :  Break :  EndIf
  2632.  
  2633.      Next
  2634.      ;}
  2635.  
  2636.   Else
  2637.  
  2638.      ;{ *Memory? }
  2639.  
  2640.      Protected   *ID_MOD.Long   =  *Memory  +  $438
  2641.      Protected   *ID_STM.Long   =  *Memory  +  $14
  2642.      Protected   *ID_S3M.Long   =  *Memory  +  $2C
  2643.      Protected   *ID_WAV.Long   =  *Memory  +  $8
  2644.      CompilerIf  #IsYMP
  2645.         Protected   *ID_YMP.Long   =  *Memory  +  $2
  2646.      CompilerEndIf
  2647.  
  2648.      Select   Mode
  2649.         Case  #C2D_MUSIC_PT2, #C2D_MUSIC_TPT
  2650.            Typ   =  Bool(*ID_MOD\l =  #ID_M_K_ Or
  2651.                          *ID_MOD\l =  #ID_MIKI Or
  2652.                          *ID_MOD\l =  #ID_MAKI Or
  2653.                          *ID_MOD\l =  #ID_N_T_)
  2654.  
  2655.         Case  #C2D_MUSIC_FT2
  2656.            Typ   =  Bool(*Memory\l =  #ID_XM)  +
  2657.                     Bool(*ID_MOD\l =  #ID_6CHN Or
  2658.                          *ID_MOD\l =  #ID_8CHN Or
  2659.                          *ID_MOD\l =  #ID_FLT4 Or
  2660.                          *ID_MOD\l =  #ID_FLT8 Or
  2661.                          *ID_MOD\l =  #ID_M_K_ Or
  2662.                          *ID_MOD\l =  #ID_MIKI Or
  2663.                          *ID_MOD\l =  #ID_MAKI Or
  2664.                          *ID_MOD\l =  #ID_N_T_)
  2665.  
  2666.         Case  #C2D_MUSIC_AHX, #C2D_MUSIC_THX
  2667.            Typ   =  Bool(*Memory\l =  #ID_AHX  Or
  2668.                          *Memory\l =  #ID_THX)
  2669.  
  2670.         Case  #C2D_MUSIC_FC4, #C2D_MUSIC_TFC
  2671.            Typ   =  Bool(*Memory\l =  #ID_SMOD Or
  2672.                          *Memory\l =  #ID_FC14)
  2673.  
  2674.         Case  #C2D_MUSIC_S3M
  2675.            Typ   =  Bool(*ID_S3M\l =  #ID_S3M)
  2676.  
  2677.         Case  #C2D_MUSIC_STM
  2678.            Typ   =  Bool(*ID_STM\l =  #ID_STM)
  2679.  
  2680.         Case  #C2D_MUSIC_OGG
  2681.            Typ   =  Bool(*Memory\l =  #ID_OGG)
  2682.  
  2683.         Case  #C2D_MUSIC_FLA
  2684.            Typ   =  Bool(*Memory\l =  #ID_FLAC)
  2685.  
  2686.         Case  #C2D_MUSIC_API, #C2D_MUSIC_WAV
  2687.            Typ   =  Bool(*Memory\l =  #ID_RIFF And
  2688.                          *ID_WAV\l =  #ID_WAVE)
  2689.  
  2690.         Case  #C2D_MUSIC_MOD
  2691.            Typ   =  Bool(*ID_MOD\l =  #ID_M_K_ Or
  2692.                          *ID_MOD\l =  #ID_MIKI Or
  2693.                          *ID_MOD\l =  #ID_MAKI Or
  2694.                          *ID_MOD\l =  #ID_N_T_ Or
  2695.                          *ID_MOD\l =  #ID_6CHN Or
  2696.                          *ID_MOD\l =  #ID_8CHN Or
  2697.                          *ID_MOD\l =  #ID_FLT4 Or
  2698.                          *ID_MOD\l =  #ID_FLT8)   +
  2699.                     Bool(*ID_S3M\l =  #ID_S3M)    +
  2700.                     Bool(*ID_STM\l =  #ID_STM)    +
  2701.                     Bool(*Memory\l =  #ID_XM   Or
  2702.                          *Memory\l =  #ID_IT   Or
  2703.                          *Memory\l =  #ID_UMX  Or
  2704.                          *Memory\l =  #ID_MTM  Or
  2705.                          *Memory\l =  #ID_MT20 Or
  2706.                          *Memory\l =  #ID_MMD0 Or
  2707.                          *Memory\l =  #ID_MMD1 Or
  2708.                          *Memory\l =  #ID_MMD2 Or
  2709.                          *Memory\l =  #ID_MMD3 Or
  2710.                          *Memory\l =  #ID_OKTA)   +
  2711.                     Bool(*Memory\l =  #ID_RIFF And
  2712.                          *ID_WAV\l =  #ID_WAVE)
  2713.  
  2714.         CompilerIf  #IsBAS
  2715.         Case  #C2D_MUSIC_BAS
  2716.            Typ   =  Bool(*Memory\l =  #ID_IT   Or
  2717.                          *Memory\l =  #ID_UMX  Or
  2718.                          *Memory\l =  #ID_MTM)    +
  2719.                     Bool(*Memory\l =  #ID_XM   Or
  2720.                          *ID_MOD\l =  #ID_6CHN Or
  2721.                          *ID_MOD\l =  #ID_8CHN Or
  2722.                          *ID_MOD\l =  #ID_FLT4 Or
  2723.                          *ID_MOD\l =  #ID_FLT8)   +
  2724.                     Bool(*ID_MOD\l =  #ID_M_K_ Or
  2725.                          *ID_MOD\l =  #ID_MIKI Or
  2726.                          *ID_MOD\l =  #ID_MAKI Or
  2727.                          *ID_MOD\l =  #ID_N_T_)   +
  2728.                     Bool(*ID_S3M\l =  #ID_S3M)
  2729.         CompilerEndIf
  2730.         CompilerIf  #IsBMF
  2731.         Case  #C2D_MUSIC_BMF
  2732.            Typ   =  Bool(*Memory\l =  #ID_BMF4)
  2733.         CompilerEndIf
  2734.         CompilerIf  #IsFCP
  2735.         Case  #C2D_MUSIC_FCP
  2736.            Typ   =  Bool(*Memory\l =  #ID_FC14)
  2737.         CompilerEndIf
  2738.         CompilerIf  #IsS68
  2739.         Case  #C2D_MUSIC_S68
  2740.            Typ   =  Bool(*Memory\l =  #ID_SC68)
  2741.         CompilerEndIf
  2742.         CompilerIf  (#IsSID  +  #IsTSR)
  2743.         Case  #C2D_MUSIC_SID, #C2D_MUSIC_TSR
  2744.            Typ   =  Bool(*Memory\l =  #ID_SID)
  2745.         CompilerEndIf
  2746.         CompilerIf  (#IsV2M  +  #IsV1M)
  2747.         Case  #C2D_MUSIC_V1M, #C2D_MUSIC_V2M
  2748.            Typ   =  Bool(*Memory\l =  #ID_V2M  Or
  2749.                          *Memory\l =  #ID_V2M6 Or
  2750.                          *Memory\l =  #ID_V2ME)
  2751.            ; Loosy but important v1.5 sanity check or... crash
  2752.            If Mode  =  #C2D_MUSIC_V2M And   PeekL(*Memory + Length - SizeOf(Long)) <> #Null
  2753.               Typ   =  #Null
  2754.            EndIf
  2755.         CompilerEndIf
  2756.         CompilerIf  #IsXM2
  2757.         Case  #C2D_MUSIC_XM2 :  Typ   =  Bool(*Memory\l =  #ID_XM)
  2758.         CompilerEndIf
  2759.         CompilerIf  #IsYMP
  2760.         Case  #C2D_MUSIC_YMP
  2761.            Typ   =  Bool(*ID_YMP\l =  #ID_LH5  Or
  2762.                          *Memory\l =  #ID_YM6I)
  2763.         CompilerEndIf
  2764.  
  2765.      EndSelect
  2766.      ;}
  2767.  
  2768.   EndIf
  2769.  
  2770.   ProcedureReturn   Bool(Typ > #Null)
  2771.  
  2772. EndProcedure
  2773. ProcedureDLL   SCAL_Pause(Flags)
  2774.  
  2775.   ; Flags: 1 = Pause, 0 = Resume
  2776.  
  2777.   ; Return: 1 = paused, 0 = unpaused or no pause possible by engine
  2778.  
  2779.   Static   Time
  2780.  
  2781.   With  RS_SCAL
  2782.  
  2783.      If \ID   =  #Null :  ProcedureReturn   #Null :  EndIf
  2784.  
  2785.      Flags =  Bool(Flags<>0)
  2786.  
  2787.      If \IsPause =  Flags :  ProcedureReturn   \IsPause :  EndIf
  2788.  
  2789.      \IsPause =  Flags
  2790.  
  2791.      Select   \Mode
  2792.  
  2793.         Case  #C2D_MUSIC_AHX
  2794.            ahx1play_PauseSong(\IsPause)
  2795.  
  2796.         CompilerIf  #IsAMP
  2797.         Case  #C2D_MUSIC_AMP
  2798.            AmpMusicPause(\IsPause)
  2799.         CompilerEndIf
  2800.  
  2801.         CompilerIf  #IsBAS
  2802.         Case  #C2D_MUSIC_BAS
  2803.            If \IsPause
  2804.               BASSMOD_MusicPause()
  2805.            Else
  2806.               BASSMOD_MusicPlay()
  2807.            EndIf
  2808.         CompilerEndIf
  2809.  
  2810.         CompilerIf  #IsBMF
  2811.         Case  #C2D_MUSIC_BMF
  2812.            If \IsPause
  2813.               SynthStop(\ID)
  2814.            Else
  2815.               SynthPlay(\ID)
  2816.            EndIf
  2817.         CompilerEndIf
  2818.  
  2819.         Case  #C2D_MUSIC_FC4
  2820.            fc14play_PauseSong(\IsPause)
  2821.  
  2822.         Case  #C2D_MUSIC_FLA, #C2D_MUSIC_OGG, #C2D_MUSIC_WAV
  2823.            If IsSound(0)
  2824.               If \IsPause
  2825.                  PauseSound(0)
  2826.               Else
  2827.                  ResumeSound(0)
  2828.               EndIf
  2829.            EndIf
  2830.  
  2831.         Case  #C2D_MUSIC_FT2
  2832.            ft2play_PauseSong(\IsPause)
  2833.  
  2834.         Case  #C2D_MUSIC_MCI
  2835.            If \IsPause
  2836.               mciSendString_(@"PAUSE 0", 0, 0, 0)
  2837.            Else
  2838.               mciSendString_(@"RESUME 0",   0, 0, 0)
  2839.            EndIf
  2840.  
  2841.         CompilerIf  #IsMED
  2842.         Case  #C2D_MUSIC_MED
  2843.            If \IsPause
  2844.               MEDP_Stop()
  2845.            Else
  2846.               MEDP_Play()
  2847.            EndIf
  2848.         CompilerEndIf
  2849.  
  2850.         Case  #C2D_MUSIC_MOD
  2851.            If \IsPause
  2852.               StopMusic(0)
  2853.            Else
  2854.               PlayMusic(0)
  2855.            EndIf
  2856.  
  2857.         CompilerIf  #IsMOV
  2858.         Case  #C2D_MUSIC_MOV
  2859.            If \IsPause
  2860.               PauseMovie(0)
  2861.            Else
  2862.               ResumeMovie(0)
  2863.            EndIf
  2864.         CompilerEndIf
  2865.  
  2866.         Case  #C2D_MUSIC_PT2
  2867.            pt2play_PauseSong(\IsPause)
  2868.  
  2869.         Case  #C2D_MUSIC_S3M
  2870.            st3play_PauseSong(\IsPause)
  2871.  
  2872.         CompilerIf  #IsSID
  2873.         Case  #C2D_MUSIC_SID
  2874.            If \IsPause
  2875.               SIDPause()
  2876.            Else
  2877.               SIDResume()
  2878.            EndIf
  2879.         CompilerEndIf
  2880.  
  2881.         Case  #C2D_MUSIC_STM
  2882.            st23play_PauseSong(\IsPause)
  2883.  
  2884.         CompilerIf  #IsV2M   ; Custom Pause
  2885.         Case  #C2D_MUSIC_V2M
  2886.            If \IsPause
  2887.               Time  =  V2MGetCurrentTime()
  2888.               V2MStop()
  2889.               dsClose()
  2890.            Else
  2891.               V2MInit(\Memory, \Freq, GetForegroundWindow_())
  2892.               V2MSetRepeat(1)
  2893.               dsSetVolume(0.01  *  \Volume)
  2894.               V2MPlay(Time)
  2895.            EndIf
  2896.         CompilerEndIf
  2897.  
  2898.         CompilerIf  #IsXM2
  2899.         Case  #C2D_MUSIC_XM2
  2900.            If \IsPause
  2901.               uFMOD_Pause()
  2902.            Else
  2903.               uFMOD_Resume()
  2904.            EndIf
  2905.         CompilerEndIf
  2906.  
  2907.         CompilerIf  #IsYMP
  2908.         Case  #C2D_MUSIC_YMP
  2909.            If \IsPause
  2910.               YM_Pause()
  2911.            Else
  2912.               YM_Play()
  2913.            EndIf
  2914.         CompilerEndIf
  2915.  
  2916.      Default
  2917.  
  2918.         ; #C2D_MUSIC_API, #C2D_MUSIC_FCP, #C2D_MUSIC_S68
  2919.         ; #C2D_MUSIC_SCA, #C2D_MUSIC_TFC, #C2D_MUSIC_THX
  2920.         ; #C2D_MUSIC_TPT, #C2D_MUSIC_TSR, #C2D_MUSIC_V1M
  2921.  
  2922.         \IsPause =  #Null
  2923.         ProcedureReturn   #Null
  2924.  
  2925.      EndSelect
  2926.  
  2927.      ; Timecorrection, coz some mixerticks do a simple timeline
  2928.      Select   \Mode
  2929.         Case  #C2D_MUSIC_AHX,
  2930.               #C2D_MUSIC_BAS,
  2931.               #C2D_MUSIC_BMF,
  2932.               #C2D_MUSIC_FC4,
  2933.               #C2D_MUSIC_FT2,
  2934.               #C2D_MUSIC_PT2,
  2935.               #C2D_MUSIC_MED,
  2936.               #C2D_MUSIC_MOD,
  2937.               #C2D_MUSIC_MOV,
  2938.               #C2D_MUSIC_S3M,
  2939.               #C2D_MUSIC_SID,
  2940.               #C2D_MUSIC_STM,
  2941.               #C2D_MUSIC_YMP
  2942.            If \IsPause
  2943.               Time  =  ElapsedMilliseconds()
  2944.            Else
  2945.               \TimePlay   +  ElapsedMilliseconds()   -  Time
  2946.            EndIf
  2947.      EndSelect
  2948.  
  2949.      ProcedureReturn   \IsPause
  2950.  
  2951.   EndWith
  2952.  
  2953. EndProcedure
  2954. ProcedureDLL   SCAL_Play(Mode, *Memory, Length, SubSong)
  2955.  
  2956.   ; Mode      =  -1 (autoset) or #C2D_MUSIC_[Mode]
  2957.   ; *Memory   =  Ptr to data or @Filename$
  2958.   ; Length    =  Size(End) of data or #Null (*Memory = @Filename$)
  2959.   ; SubSong   =  #Subsong to play (#AMP, #SID, #TSR)
  2960.  
  2961.   ; Return: #True = Music is playing or #False = Error!
  2962.  
  2963.   Protected   IsOK, IsAmp, i, t$, Path$, *x, MDAT$, SMPL$
  2964.   Static   File$ ; *Memory = temporary @File$
  2965.  
  2966.   SCAL_Free() ; always stop if playing
  2967.  
  2968.   With  RS_SCAL
  2969.  
  2970.      ; Check for not-supported engines (*)do NOT check with [SCA] here!
  2971.      If Mode  =  #C2D_MUSIC_V1M Or Mode  =  #C2D_MUSIC_S68
  2972.         ProcedureReturn   #Null
  2973.      EndIf
  2974.  
  2975.      ; Check if *Memory is a ptr to a @Filename
  2976.      If Length   <= #Null
  2977.         \File$   =  PeekS(*Memory, -1, \StrFormat)
  2978.      EndIf
  2979.  
  2980.      ; ==========================================================================
  2981.      ;{ Network file? ("http://...") *** also download all needed sfx-libs ***
  2982.      If Length   <= 0  And   StrStrI_(@\File$, @"://")
  2983.         If scal_Down(\File$)
  2984.            *Memory  =  @\File$  ; filename set in scal_down()
  2985.            Length   =  #Null
  2986.         Else
  2987.            SCAL_Free() :  ProcedureReturn   #Null
  2988.         EndIf
  2989.      EndIf
  2990.      ;}
  2991.      ; ==========================================================================
  2992.  
  2993.      ; ==========================================================================
  2994.      ;{ Check for zipped @File (Extension)
  2995.      If Length   <= #Null
  2996.  
  2997.         *x =  scal_Sufx(@\File$, 0)   ; ";ZIP;" etc.
  2998.  
  2999.          If *x And   StrStrI_(?l_ZIP, *x)
  3000.  
  3001.             scal_Temp(#SCAL_TempPath$)
  3002.  
  3003.             \ZipCount   =  ZIP_GetFilesCount(\File$)
  3004.  
  3005.             If \ZipCount   <= 2  ; Single zipped or TFMX (MDAT+SMPL)?
  3006.                i  =  1  ; First file in archive
  3007.             Else
  3008.                \IsZip   =  1  ; Playing subsongs from zip-archive (flag)
  3009.                ;\Songs  =  \ZipCount;
  3010.                \ZipSong =  SubSong  ; SongNumber of archive-file (for Info)
  3011.                i        =  SubSong  ; SongNumber of archive-file to unpack
  3012.                SubSong  =  #Null    ; No individual subsong when zipped archive
  3013.                If i  <= #Null :  i  =  1  :  EndIf
  3014.             EndIf
  3015.  
  3016.             t$ =  GetFilePart(ZIP_GetFileInfo(\File$, i))
  3017.  
  3018.             If Len(t$)  =  #Null :  SCAL_Free() :  ProcedureReturn   #Null :  EndIf
  3019.  
  3020.             CompilerIf  #IsAMP
  3021.                ; UnZIP always TFMX (almost same names for different songs/sample-banks (MDAT.ingame1...)
  3022.  
  3023.                *x =  PathFindExtension_(@t$)
  3024.  
  3025.                If StrStrI_(@t$, @"MDAT.") Or StrStrI_(@t$, @"SMPL.") Or ; TFMX
  3026.                   StrStrI_(*x,  @".TFX")  Or StrStrI_(*x,  @".SAM")  Or ; TFMX Custom
  3027.                   StrStrI_(*x,  @".KDM")  ; Ken's Digital Music (waves.kwv sfx-bank)
  3028.  
  3029.                   IsAMP =  #True
  3030.  
  3031.                   If ZIP_ExtractFile(\File$, i, \Temp$)  =  #False   ; Error?
  3032.                      SCAL_Free() :  ProcedureReturn   #Null
  3033.                   EndIf
  3034.  
  3035.                   If       StrStrI_(@t$, @"MDAT.") =  @t$   :  PokeS(@t$, "SMPL", -1, #PB_String_NoZero)
  3036.                   ElseIf   StrStrI_(@t$, @"SMPL.") =  @t$   :  PokeS(@t$, "MDAT", -1, #PB_String_NoZero)
  3037.                   ElseIf   StrStrI_(*x,  @".SAM")  :  PathRenameExtension_(@t$, @".TFX")  ; need the song.tfx
  3038.                   ElseIf   StrStrI_(*x,  @".TFX")  :  PathRenameExtension_(@t$, @".SAM")  ; need the sfx-file.sam
  3039.                   ElseIf   StrStrI_(*x,  @".KDM")  :  File$ =  t$ :  t$ =  "waves.kwv"    ; need kwv sfx-bank
  3040.                   EndIf
  3041.  
  3042.                   i  =  ZIP_GetFileNumber(\File$, t$)
  3043.  
  3044.                   If i  <= #Null Or ZIP_ExtractFile(\File$, i, \Temp$)  =  #False   ; Error?
  3045.                      SCAL_Free() :  ProcedureReturn   #Null
  3046.                   EndIf
  3047.  
  3048.                   ; Restore songname!
  3049.                   If       StrStrI_(@t$, @"SMPL.") =  @t$               :  PokeS(@t$, "MDAT", -1, #PB_String_NoZero)
  3050.                   ElseIf   StrStrI_(PathFindExtension_(@t$), @".SAM")   :  PathRenameExtension_(@t$, @".TFX")
  3051.                   ElseIf   StrStrI_(PathFindExtension_(@t$), @".KWV")   :  t$ =  File$
  3052.                   EndIf
  3053.  
  3054.                EndIf
  3055.             CompilerEndIf
  3056.  
  3057.             ; No AMP & Do not UnZip if already unzipped
  3058.             If IsAMP =  #Null And   FileSize(\Temp$ + t$)   <= #Null
  3059.                If ZIP_ExtractFile(\File$, i, \Temp$)  =  #False   ; Error?
  3060.                   SCAL_Free() :  ProcedureReturn   #Null
  3061.                EndIf
  3062.             EndIf
  3063.  
  3064.             ; Update to temporary unzipped filename
  3065.             \File$   =  \Temp$   +  t$
  3066.             \Title$  =  t$
  3067.             *Memory  =  @\File$
  3068.  
  3069.          EndIf
  3070.       EndIf
  3071.       ;}
  3072.       ; ==========================================================================
  3073.  
  3074.       ; ==========================================================================
  3075.       ;{ Check mode-flag (when own-call (*) [SCA] - change to default mode
  3076.       If Bool(Mode = #C2D_MUSIC_SCA Or Mode < #SCAL_MIN Or Mode > #SCAL_MAX)  ; (-1,0) .. Clamp(1 upto 29)
  3077.          If Length   >  #Null
  3078.             Mode  =  Default_Mode(*Memory, Length)
  3079.          Else
  3080.             Mode  =  Default_Mode(@\File$, #Null)
  3081.          EndIf
  3082.          If Mode  <= #Null
  3083.             SCAL_Free() :  ProcedureReturn   #Null
  3084.          EndIf
  3085.       EndIf
  3086.       ;}
  3087.       ; ==========================================================================
  3088.  
  3089.       ; ================================================================================
  3090.       ; Play from memory? Check if file-only mode -> reset to its default support-engine
  3091.       ; ================================================================================
  3092.       If Length   >  #Null
  3093.          Select   Mode  ; this can't play from memory
  3094.             Case  #C2D_MUSIC_AMP,
  3095.                   #C2D_MUSIC_MCI,
  3096.                   #C2D_MUSIC_MED,
  3097.                   #C2D_MUSIC_MOV
  3098.                Mode  =  Default_Mode(*Memory, Length)
  3099.          EndSelect
  3100.       EndIf
  3101.  
  3102.       \Mode =  Mode
  3103.  
  3104.       ; *** @File or *Memory?
  3105.       Select   \Mode
  3106.          Case  #C2D_MUSIC_AMP ; *Memory = @File (ascii)
  3107.          Case  #C2D_MUSIC_API ; *Memory & @File (ascii & utf8)
  3108.          Case  #C2D_MUSIC_BAS ; *Memory & @File (ascii)
  3109.          Case  #C2D_MUSIC_FLA ; *Memory & @File (ascii & utf8)
  3110.          Case  #C2D_MUSIC_MCI ; *Memory = @File (ascii & utf8)
  3111.          Case  #C2D_MUSIC_MED ; *Memory = @File (ascii)
  3112.          Case  #C2D_MUSIC_MOD ; *Memory & @File (ascii & utf8)
  3113.          Case  #C2D_MUSIC_MOV ; *Memory = @File (ascii & utf8)
  3114.          Case  #C2D_MUSIC_OGG ; *Memory & @File (ascii & utf8)
  3115.          Case  #C2D_MUSIC_S68 ; *Memory & @File (ascii)
  3116.          Case  #C2D_MUSIC_WAV ; *Memory & @File (ascii & utf8)
  3117.          Case  #C2D_MUSIC_XM2 ; *Memory & @File (ascii)
  3118.          Case  #C2D_MUSIC_YMP ; *Memory & @File (ascii)
  3119.  
  3120.          Default  ;{ Engines who supports *Memory only? }
  3121.  
  3122.             If Length   <= #Null
  3123.  
  3124.                If ReadFile(0, \File$)
  3125.                   Length   =  Lof(0)
  3126.                   If Length   >  0
  3127.                      \Memory  =  AllocateMemory(Length)
  3128.                      \IsAlloc =  Bool(\Memory>0)   ; flag to free temp *memory
  3129.                      If \IsAlloc
  3130.                         Length   =  ReadData(0, \Memory, Length)
  3131.                      Else
  3132.                         Length   =  #Null
  3133.                      EndIf
  3134.                   EndIf
  3135.                   CloseFile(0)
  3136.                EndIf
  3137.  
  3138.                If  Length  <= #Null
  3139.                   SCAL_Free() :  ProcedureReturn   #Null
  3140.                EndIf
  3141.  
  3142.                *Memory  =  \Memory
  3143.  
  3144.             EndIf
  3145.             ;}
  3146.  
  3147.       EndSelect
  3148.  
  3149.       If Length   >  *Memory  :  Length   -  *Memory  :  EndIf
  3150.  
  3151.       ; *** DEFAULTS ***
  3152.       \ID      =  #True ; ok by default
  3153.       \Memory  =  *Memory
  3154.       \Length  =  Length
  3155.       \SubSong =  SubSong
  3156.  
  3157.       ; *** Default name of Tracker- / Decoder ***
  3158.       If \Mode >= #SCAL_MIN   And   Mode <= #SCAL_MAX
  3159.          \Tracker$   =  StringField(PeekS(PeekI(?mode + \Mode * SizeOf(Integer))), 3, "|")
  3160.       EndIf
  3161.  
  3162.       ; =========================================================================
  3163.       ; Playback the music (na endlich...)
  3164.       ; =========================================================================
  3165.       Select   \Mode
  3166.  
  3167.          Case  #C2D_MUSIC_AHX ;{ *** Play AHX/THX (no HVL) (*Memory)
  3168.             ; http://lclevy.free.fr/exotica/ahx/ahxformat.txt
  3169.             \ID   =  ahx1play_PlaySong(\Memory, \Length, \SubSong - 1, \Freq)
  3170.             If \ID
  3171.                \Title$  =  PeekS(ahx1play_GetSongName(), -1, #PB_Ascii)
  3172.                If \Songs   =  #Null ; no zip archive?
  3173.                   \Songs   =  PeekB(\Memory  +  $D)   +  1
  3174.                EndIf
  3175.             EndIf
  3176.             ;}
  3177.  
  3178.          Case  #C2D_MUSIC_API ;{ *** Play API-Wave (*.WAV) (@File / *Memory)
  3179.             If \Length
  3180.                \ID   =  PlaySound_(\Memory, #Null, #SND_MEMORY|#SND_ASYNC|#SND_LOOP|#SND_NODEFAULT)   ; play from *Memory
  3181.             Else
  3182.                \ID   =  PlaySound_(\Memory, #Null, #SND_FILENAME|#SND_ASYNC|#SND_LOOP|#SND_NODEFAULT) ; play from file -> *Memory = @Filename$
  3183.             EndIf
  3184.             ;}
  3185.  
  3186.          Case  #C2D_MUSIC_FC4 ;{ *** Play FutureComposer 1..4 (FC) (*Memory)
  3187.             \ID   =  fc14play_PlaySong(\Memory, \Length, \Freq)
  3188.             If \ID   And   PeekL(\Memory) =  #ID_SMOD
  3189.                \Tracker$   +  " / SMOD"   ; 1.3
  3190.             EndIf
  3191.             ;}
  3192.  
  3193.          Case  #C2D_MUSIC_FLA ;{ *** Play native FLAC-decoder (*.FLAC) (@File / *Memory)
  3194.             scal_Init()
  3195.             If \Length
  3196.                \ID   =  CatchSound(0, \Memory, \Length)
  3197.             Else
  3198.                \ID   =  LoadSound(0, PeekS(\Memory))
  3199.             EndIf
  3200.             If \ID
  3201.                PlaySound(0, #PB_Sound_Loop)
  3202.                \Time =  SoundLength(0, #PB_Sound_Millisecond)
  3203.             EndIf
  3204.             ;}
  3205.  
  3206.          Case  #C2D_MUSIC_FT2 ;{ *** Play FastTracker I/II (FT/XM) & Amiga Tracker (MOD) (*Memory)
  3207.             \ID   =  ft2play_PlaySong(\Memory, \Length, 0, 1, \Freq)
  3208.             If \ID
  3209.                ft2play_SetAmp(18)
  3210.                If PeekL(\Memory) =  #ID_XM
  3211.                   \Title$     =  PeekS(\Memory + $11, 20, #PB_Ascii)
  3212.                Else
  3213.                   \Tracker$   +  " / Amiga Tracker"
  3214.                   \Title$     =  PeekS(\Memory, 20, #PB_Ascii)
  3215.                EndIf
  3216.             EndIf
  3217.             ;}
  3218.  
  3219.          Case  #C2D_MUSIC_MCI ;{ *** Play Systemfile (*.MP3;*.OGG;*.WAV;*.WMA...) (@File)
  3220.             ; https://www.vbarchiv.net/tipps/tipp_856-alles-ueber-das-multimedia-control-interface-mci-api.html
  3221.             t$ =  "OPEN " + #DQUOTE$ + PeekS(\Memory) + #DQUOTE$ + " TYPE MPEGVIDEO ALIAS 0"
  3222.             If mciSendString_(@t$, 0, 0, 0)  =  #S_OK
  3223.                t$ =  Space(#MAX_PATH)
  3224.                mciSendString_(@"SET 0 TIME FORMAT MILLISECONDS", 0, 0, 0)
  3225.                mciSendString_(@"PLAY 0 REPEAT", 0, 0, 0)
  3226.                mciSendString_(@"STATUS 0 LENGTH", @t$, #MAX_PATH, 0)
  3227.                \Time =  Val(t$)
  3228.             Else
  3229.                \ID   =  #False
  3230.             EndIf
  3231.             ;}
  3232.  
  3233.          Case  #C2D_MUSIC_MOD ;{ *** Play native Tracker (*.XM;*.IT;*.S3M;*.MOD;*.MTM;*.UMX;*.OKT;*.MED + PP20) (@File / *Memory)
  3234.             scal_Init()
  3235.             If \Length
  3236.                \ID   =  CatchMusic(0, \Memory, \Length)
  3237.             Else
  3238.                \ID   =  LoadMusic(0, PeekS(\Memory))
  3239.             EndIf
  3240.             If \ID
  3241.                PlayMusic(0)
  3242.             EndIf
  3243.             ;}
  3244.  
  3245.          Case  #C2D_MUSIC_MOV ;{ *** Play native Movie / Audio (same as MCI) (@File)
  3246.          CompilerIf  #IsMOV
  3247.             scal_Init()
  3248.             If LoadMovie(0, \File$)
  3249.                *Memory  =  GetForegroundWindow_()
  3250.                If MovieWidth(0)  >  0  ; 99 if portable
  3251.                   \WinID   =  OpenWindow(#PB_Any, 40, 40, MovieWidth(0), MovieHeight(0), GetFilePart(\File$), #PB_Window_Tool|#PB_Window_NoGadgets)
  3252.                   *Memory  =  WindowID(\WinID)
  3253.                EndIf
  3254.                If PlayMovie(0, *Memory)
  3255.                   \Time =  (MovieLength(0) / (MovieInfo(0, 0) + 1)) * 1000
  3256.                Else
  3257.                   \ID   =  #False
  3258.                EndIf
  3259.             Else
  3260.                \ID   =  #False
  3261.             EndIf
  3262.          CompilerElse
  3263.             \ID   =  #False
  3264.          CompilerEndIf
  3265.          ;}
  3266.  
  3267.          Case  #C2D_MUSIC_OGG ;{ *** Play native ogg-decoder (*.OGG) (@File / *Memory)
  3268.             scal_Init()
  3269.             If \Length
  3270.                \ID   =  CatchSound(0, \Memory, \Length)
  3271.             Else
  3272.                \ID   =  LoadSound(0, PeekS(\Memory))
  3273.             EndIf
  3274.             If \ID
  3275.                PlaySound(0, #PB_Sound_Loop)
  3276.                \Time =  SoundLength(0, #PB_Sound_Millisecond)
  3277.             EndIf
  3278.             ;}
  3279.  
  3280.          Case  #C2D_MUSIC_PT2 ;{ *** Play ProTracker 2.3D (MOD) (*Memory)
  3281.             If SCAL_IsFormat(#C2D_MUSIC_PT2, \Memory, \Length) ; check, coz pt2 crashes if an error;Default_Mode(\Memory, \Length)  =  #C2D_MUSIC_PT2
  3282.                \ID   =  pt2play_PlaySong(\Memory, \Length, #CIA_TEMPO_MODE, \Freq)
  3283.             Else
  3284.                \ID   =  #False
  3285.             EndIf
  3286.             If \ID
  3287.                \Title$  =  PeekS(pt2play_GetSongName(), -1, #PB_Ascii)
  3288.             EndIf
  3289.             ;}
  3290.  
  3291.          Case  #C2D_MUSIC_S3M ;{ *** Play ScreamTracker III (S3M) (*Memory)
  3292.             \ID   =  st3play_PlaySong(\Memory, \Length, 0, #SOUNDCARD_GUS, \Freq)
  3293.             If \ID
  3294.                \Title$  =  PeekS(st3play_GetSongName(), -1, #PB_Ascii)
  3295.             EndIf
  3296.             ;}
  3297.  
  3298.          Case  #C2D_MUSIC_STM ;{ *** Play Scream Tracker 2.3 (STM) (*Memory)
  3299.             \ID   =  st23play_PlaySong(\Memory, \Length, 0, \Freq)
  3300.             If \ID
  3301.                \Title$  =  PeekS(st23play_GetSongName(), -1, #PB_Ascii)
  3302.             EndIf
  3303.             ;}
  3304.  
  3305.          Case  #C2D_MUSIC_TPT ;{ +++ Tiny ProTracker 2.3D (MOD) (*Memory)
  3306.             If SCAL_IsFormat(#C2D_MUSIC_TPT, \Memory, \Length)
  3307.                \ID   =  tinypt2play_PlaySong(\Memory, \Length)
  3308.             EndIf
  3309.             If \ID
  3310.                \Title$  =  PeekS(\Memory, -1, #PB_Ascii)
  3311.             EndIf
  3312.             ;}
  3313.  
  3314.          Case  #C2D_MUSIC_TFC ;{ +++ Tiny FutureComposer 1..4 (FC) (*Memory)
  3315.             \ID   =  tinyfc14play_PlaySong(\Memory, \Length)
  3316.             If \ID   And   PeekL(\Memory) =  #ID_SMOD
  3317.                \Tracker$   +  " / SMOD"   ; 1.3
  3318.             EndIf
  3319.             ;}
  3320.  
  3321.          Case  #C2D_MUSIC_THX ;{ +++ Tiny AHX (no HVL) (*Memory)
  3322.             \ID   =  tinyahx1play_PlaySong(\Memory, \Length, \SubSong)
  3323.             ;}
  3324.  
  3325.          Case  #C2D_MUSIC_WAV ;{ *** Play native Wave-Decoder (*.WAV) (@File / *Memory)
  3326.             scal_Init()
  3327.             If \Length
  3328.                \ID   =  CatchSound(0, \Memory, \Length)
  3329.             Else
  3330.                \ID   =  LoadSound(0, PeekS(\Memory))
  3331.             EndIf
  3332.             If \ID
  3333.                PlaySound(0, #PB_Sound_Loop)
  3334.                \Time =  SoundLength(0, #PB_Sound_Millisecond)
  3335.             EndIf
  3336.          ;}
  3337.  
  3338.          CompilerIf  #IsAMP   ;{ *** x86 - Play AmpMaster Plugin (933+ formats) (@File)
  3339.          Case  #C2D_MUSIC_AMP
  3340.             If AmpMusicInit()
  3341.  
  3342.                ; Clone to temp & set Subsong - coz we will NOT change the original one by AmpMaster!
  3343.  
  3344.                scal_Temp(#SCAL_TempPath$) ; create temporary directory for all files
  3345.  
  3346.                Path$ =  GetPathPart(\File$)
  3347.                File$ =  GetFilePart(\File$)
  3348.  
  3349.                If StrStrI_(@File$, @"MDAT.")    ; *** MDAT.file ***
  3350.  
  3351.                   MDAT$ =  StringField(File$, 1, ".")
  3352.                   SMPL$ =  scal_Case("SMPL", MDAT$)   ; adapt upper/lower case
  3353.  
  3354.                   File$ =  StringField(File$, 2, ".") ; Filename (no extension)
  3355.  
  3356.                   ; path-check coz don't download again to temp if already downloaded
  3357.                   If (Path$   <> \Temp$)  And   scal_Size(\File$) <> scal_Size(\Temp$  + MDAT$ + File$)
  3358.                      scal_Copy(\File$,                      \Temp$ + MDAT$ + "." + File$)
  3359.                      scal_Copy(Path$ + SMPL$ + "." + File$, \Temp$ + SMPL$ + "." + File$)
  3360.                   EndIf
  3361.  
  3362.                   File$    =  \Temp$   +  MDAT$ +  "."   +  File$
  3363.                   \Memory  =  @File$
  3364.  
  3365.                   \Songs   =  AmpCountSubSongs(\Memory)
  3366.  
  3367.                ElseIf   StrStrI_(@File$, @".MDAT") ; *** file.MDAT (rare) ***
  3368.  
  3369.                   MDAT$ =  GetExtensionPart(File$)
  3370.                   SMPL$ =  scal_Case("SMPL", MDAT$)
  3371.  
  3372.                   PathRemoveExtension_(@File$)  ; no extension (MDAT)
  3373.  
  3374.                   If (Path$   <> \Temp$)  And   scal_Size(\File$) <> scal_Size(\Temp$  + MDAT$ + "." + File$)
  3375.                      scal_Copy(\File$,                      \Temp$ + MDAT$ + "." + File$)
  3376.                      scal_Copy(Path$ + File$ + "." + SMPL$, \Temp$ + SMPL$ + "." + File$)
  3377.                   EndIf
  3378.  
  3379.                   File$    =  \Temp$ + MDAT$ + "." + File$
  3380.                   \Memory  =  @File$
  3381.  
  3382.                   \Songs   =  AmpCountSubSongs(\Memory)
  3383.  
  3384.                ElseIf   StrStrI_(@File$, @".TFX")  ; *** file.TFX (MDAT Clone) ***
  3385.  
  3386.                   MDAT$ =  GetExtensionPart(File$)
  3387.                   SMPL$ =  scal_Case("SAM", MDAT$)
  3388.  
  3389.                   PathRemoveExtension_(@File$)  ; no extension (TFX)
  3390.  
  3391.                   If (Path$   <> \Temp$)  And   scal_Size(\File$) <> scal_Size(\Temp$ + File$ + "." + MDAT$)
  3392.                      scal_Copy(\File$,                      \Temp$ + File$ + "." + MDAT$)
  3393.                      scal_Copy(Path$ + File$ + "." + SMPL$, \Temp$ + File$ + "." + SMPL$)
  3394.                   EndIf
  3395.  
  3396.                   File$    =  \Temp$   +  File$ +  "." + MDAT$
  3397.                   \Memory  =  @File$
  3398.  
  3399.                   \Songs   =  AmpCountSubSongs(\Memory)
  3400.  
  3401.                ElseIf   StrStrI_(@File$, @".SID")  Or
  3402.                         StrStrI_(@File$, @".PSID") Or
  3403.                         StrStrI_(@File$, @".RSID") Or
  3404.                         StrStrI_(@File$, @".TFM")  Or
  3405.                         StrStrI_(@File$, @".TFMX") Or
  3406.                         StrStrI_(@File$, @".GBS")  Or
  3407.                         StrStrI_(@File$, @".NSF")  Or
  3408.                         StrStrI_(@File$, @".FRED") Or StrStrI_(@File$, @"FRED.")
  3409.  
  3410.                   File$    =  \Temp$   +  File$
  3411.                   \Memory  =  @File$
  3412.  
  3413.                   If (Path$   <> \Temp$)  And   scal_Size(File$)  <= #Null
  3414.                      scal_Copy(\File$, File$)
  3415.                   EndIf
  3416.  
  3417.                   \Songs   =  AmpCountSubSongs(\Memory)
  3418.  
  3419.                Else
  3420.  
  3421.                   \SubSong =  0
  3422.  
  3423.                EndIf
  3424.  
  3425.                \ID   =  AmpMusicPlay(\Memory, \SubSong)
  3426.  
  3427.                If \ID
  3428.                   \File$      =  PeekS(\Memory, -1, \StrFormat)
  3429.                   \Time       =  AmpMusicLength()
  3430.                   \Title$     =  PeekS(AmpMusicTitle(),  -1, #PB_Ascii)
  3431.                   \Tracker$   =  PeekS(AmpMusicInfo(),   -1, #PB_Ascii)
  3432.                EndIf
  3433.  
  3434.             Else
  3435.  
  3436.                \ID   =  #False   ; Error!
  3437.  
  3438.             EndIf
  3439.  
  3440.          CompilerEndIf
  3441.          ;}
  3442.  
  3443.          CompilerIf  #IsBAS   ;{ *** x86 - Play Modules (*.XM;*.IT;*.S3M;*.MOD;*.MTM;*.UMX) (@File / *Memory)
  3444.          Case  #C2D_MUSIC_BAS
  3445.             ; http://www.users.on.net/~jtlim/ImpulseTracker/
  3446.  
  3447.             BASSMOD_DllMain(GetModuleHandle_(#Null), #DLL_PROCESS_ATTACH, #Null)
  3448.  
  3449.             \ID   =  BASSMOD_Init(-1, \Freq, #Null)
  3450.  
  3451.             If \ID
  3452.  
  3453.                If \Length  ; play from *memory?
  3454.                   IsOK  =  BASSMOD_MusicLoad(#True, \Memory, 0, \Length)
  3455.                   Select   PeekL(\Memory)
  3456.                      Case  #ID_IT
  3457.                         \Tracker$   +  " / Impulse Tracker 2.14"
  3458.                      Case  #ID_UMX
  3459.                         \Tracker$   +  " / UMX Container"
  3460.                      Case  #ID_MTM
  3461.                         \Tracker$   +  " / Multi Tracker"
  3462.                      Case  #ID_XM
  3463.                         \Tracker$   +  " / Fast Tracker II"
  3464.                   EndSelect
  3465.                Else  ; play from file
  3466.                   \File$   =  PeekS(\Memory, -1, \StrFormat)
  3467.                   IsOK     =  BASSMOD_MusicLoad(#False, StrAsc(\Memory))
  3468.                EndIf
  3469.  
  3470.                If IsOK  And   BASSMOD_MusicPlay()
  3471.                   ;\Time      =  BASSMOD_MusicGetLength(1)  /  176.4 ; = 44100
  3472.                   \Time    =  BASSMOD_MusicGetLength(1)  /  (\Freq   /  250.0)   ; / 2 * 125 BPM
  3473.                   *Memory  =  BASSMOD_MusicGetName()
  3474.                   If *Memory
  3475.                      \Title$  =  PeekS(*Memory, -1, #PB_Ascii)
  3476.                   EndIf
  3477.                Else
  3478.                   \ID   =  #Null ; Error!
  3479.                EndIf
  3480.  
  3481.             EndIf
  3482.          CompilerEndIf
  3483.          ;}
  3484.  
  3485.          CompilerIf  #IsBMF   ;{ *** x86 - Play BeroTracker04 (*.BMF) (*Memory)
  3486.          Case  #C2D_MUSIC_BMF
  3487.             \ID   =  SynthCreate(SynthReadBMFSampleRate(\Memory, \Length), 2048, 1, 1)
  3488.             If \ID
  3489.                SynthReadBMF(\ID, \Memory, \Length)
  3490.                SynthPlay(\ID)
  3491.                SynthSetLooping(\ID, 1)
  3492.             EndIf
  3493.          CompilerEndIf
  3494.          ;}
  3495.  
  3496.          CompilerIf  #IsFCP   ;{ *** x86 - Play FutureComposer 1.4 (*.FC;*.FC14;*.FC4) (*Memory)
  3497.          Case  #C2D_MUSIC_FCP
  3498.             FCp_Open(GetForegroundWindow_())
  3499.             FCp_InitModule(\Memory)
  3500.             FCp_Start()
  3501.          CompilerEndIf
  3502.          ;}
  3503.  
  3504.          CompilerIf  #IsMED   ;{ *** x86 - Play OctaMED (*.MED;*.MMD0;*.MMD1;*.MMD2;*.MMD3;*.MOD + PP20) (@File)
  3505.          Case  #C2D_MUSIC_MED
  3506.             MEDPDLL_DllMain(GetModuleHandle_(#Null), #DLL_PROCESS_ATTACH, #Null)
  3507.             MEDP_Initialize(#Null, GetForegroundWindow_())
  3508.             If MEDP_Load(StrAsc(\Memory)) ; *Memory = always @Filename$
  3509.                If MEDP_IsLoaded()
  3510.                   t$ =  Space(100)
  3511.                   MEDP_Play()
  3512.                   MEDP_ModuleName(@t$, 100)
  3513.                   \Title$  =  PeekS(@t$, -1, #PB_Ascii)
  3514.                   \Time    =  Abs(MEDP_ModuleTime())  *  0.001 ; micro- to milliseconds (dear Andreas - it's buggy)
  3515.                Else
  3516.                   \ID   =  #False
  3517.                EndIf
  3518.             Else
  3519.                \ID   =  #False
  3520.             EndIf
  3521.          CompilerEndIf
  3522.          ;}
  3523.  
  3524.          CompilerIf  #IsS68   ;{ *** x86 - Play SC68 MC68000 Amiga/Atari (*.SC68;*.SNDH + GZIP) (@File / *Memory)
  3525.          Case  #C2D_MUSIC_S68
  3526.             \ID   =  sc68_Play(\Memory, \Length)
  3527.          CompilerEndIf
  3528.          ;}
  3529.  
  3530.          CompilerIf  #IsSID   ;{ *** x86 - Play C64 (*.SID) (*Memory) (need masm32.lib)
  3531.          Case  #C2D_MUSIC_SID
  3532.             If \SubSong
  3533.                \ID   =  SIDOpen(\Memory, \Length, #SID_MEMORY, #SID_NON_DEFAULT, \SubSong)
  3534.             Else
  3535.                \ID   =  SIDOpen(\Memory, \Length, #SID_MEMORY, #SID_DEFAULT, #Null)
  3536.             EndIf
  3537.             If \ID
  3538.                \Title$     =  PeekS(\Memory + $16, -1, #PB_Ascii)
  3539.                If \Songs   =  #Null
  3540.                   \Songs   =  PeekW(\Memory + $E)
  3541.                   \Songs   =  UINT16(\Songs)
  3542.                EndIf
  3543.             EndIf
  3544.          CompilerEndIf
  3545.          ;}
  3546.  
  3547.          CompilerIf  #IsTSR   ;{ *** x86 - Play C64 (*.SID) (*Memory) (no masm32.lib)
  3548.          Case  #C2D_MUSIC_TSR
  3549.             \Title$     =  PeekS(\Memory + $16, -1, #PB_Ascii)
  3550.             If \Songs   =  #Null
  3551.                \Songs      =  PeekW(\Memory + $E)
  3552.                \Songs      =  UINT16(\Songs)
  3553.             EndIf
  3554.             sid_sound_server_replay_init(\Memory, \Length, \SubSong)
  3555.             sid_sound_server_replay_play()
  3556.          CompilerEndIf
  3557.          ;}
  3558.  
  3559.          CompilerIf  #IsV1M   ;{ *** x86 - Play LibV2 1.0 (*.V2M) (*Memory)
  3560.          Case  #C2D_MUSIC_V1M
  3561.             \ID   =  ssInit(\Memory, GetForegroundWindow_())
  3562.             If \ID
  3563.                ssPlay()
  3564.                ssDoTick()
  3565.             EndIf
  3566.          CompilerEndIf
  3567.          ;}
  3568.  
  3569.          CompilerIf  #IsV2M   ;{ *** x86 - Play LibV2 1.5 (*.V2M) (*Memory)
  3570.          Case  #C2D_MUSIC_V2M
  3571.             \ID   =  V2MInit(\Memory, \Freq, GetForegroundWindow_())
  3572.             If \ID
  3573.                V2MSetRepeat(1)
  3574.                V2MPlay()
  3575.                \Time =  V2MGetTotalTime()
  3576.             EndIf
  3577.          CompilerEndIf
  3578.          ;}
  3579.  
  3580.          CompilerIf  #IsXM2   ;{ *** x86 - Play FastTracker II (*.XM) (@File / *Memory)
  3581.          Case  #C2D_MUSIC_XM2
  3582.             If \Length
  3583.                uFMOD_PlaySong(\Memory, \Length, #XM_MEMORY)       ; *memory
  3584.             Else
  3585.                uFMOD_PlaySong(StrAsc(\Memory), #Null, #XM_FILE)   ; @file
  3586.             EndIf
  3587.             \Title$     =  PeekS(uFMOD_GetTitle(), -1, #PB_Ascii)
  3588.          CompilerEndIf
  3589.          ;}
  3590.  
  3591.          CompilerIf  #IsYMP   ;{ *** x86 - Play Atari (*.YM) (@File / *Memory)
  3592.          Case  #C2D_MUSIC_YMP
  3593.             Protected   *RS_ymMusicInfo_t.RS_ymMusicInfo_t  =  AllocateStructure(RS_ymMusicInfo_t)
  3594.  
  3595.             YMPLUGIN_DllMain(GetModuleHandle_(#Null), #DLL_PROCESS_ATTACH, #Null)
  3596.             YM_Init()
  3597.  
  3598.             If \Length  >  0
  3599.                YM_Open(#Null, \Memory, \Length)
  3600.             Else
  3601.                YM_Open(StrAsc(@\File$), #Null, #Null)
  3602.             EndIf
  3603.  
  3604.             YM_Play()
  3605.             YM_Get_Info(*RS_ymMusicInfo_t)
  3606.  
  3607.             \Tracker$   +  " / " +  Trim(PeekS(*RS_ymMusicInfo_t\pSongPlayer, -1, #PB_Ascii), ".") +  " ("  +  PeekS(*RS_ymMusicInfo_t\pSongType, -1, #PB_Ascii)  +  ")"
  3608.             \Title$     =  PeekS(*RS_ymMusicInfo_t\pSongName, -1, #PB_Ascii)
  3609.             \Time       =  *RS_ymMusicInfo_t\musicTimeInSec *  1000  -  200   ; -200 ms coz no loop on (real) end
  3610.  
  3611.             FreeStructure(*RS_ymMusicInfo_t)
  3612.  
  3613.          CompilerEndIf
  3614.          ;}
  3615.  
  3616.          Default
  3617.  
  3618.             \ID   =  #False   ; unknown or play x86 on x64?
  3619.  
  3620.       EndSelect
  3621.  
  3622.       If \ID
  3623.  
  3624.          SCAL_SetVolume(\Volume)
  3625.  
  3626.          If \IsZip   ; restore subsongs from zip-archive?
  3627.             \Songs   =  \ZipCount
  3628.             \SubSong =  \ZipSong
  3629.          EndIf
  3630.  
  3631.          \TimePlay   =  ElapsedMilliseconds()
  3632.  
  3633.       Else
  3634.          SCAL_Free()
  3635.       EndIf
  3636.  
  3637.       ProcedureReturn   \ID
  3638.  
  3639.    EndWith
  3640.  
  3641. EndProcedure
  3642. ProcedureDLL   SCAL_Seek(Position, Flags)
  3643.  
  3644.    ; Position = ms or 0-100%
  3645.    ; Flags = 0 -> seek in ms, 1 -> seek in percent
  3646.  
  3647.    ; Remember: \TimePlay   =  ElapsedMilliseconds()   -  Position
  3648.  
  3649.    Protected   t$
  3650.  
  3651.    With  RS_SCAL
  3652.  
  3653.       ; Playing?
  3654.       If \ID   =  #Null :  ProcedureReturn   #Null :  EndIf
  3655.  
  3656.       If Flags ; Percent?
  3657.          If Position <  0  Or Position >  100
  3658.             Position =  #Null
  3659.          EndIf
  3660.       ElseIf   Position <  0  Or Position >  \Time    ; Milliseconds!
  3661.          Position =  #Null
  3662.       EndIf
  3663.  
  3664.       If Flags ; convert % to ms
  3665.          Position =  \Time *  0.01  *  Position
  3666.       EndIf
  3667.  
  3668.       Select   \Mode
  3669.          Case  #C2D_MUSIC_OGG, #C2D_MUSIC_FLA, #C2D_MUSIC_WAV
  3670.             If IsSound(0)
  3671.                SetSoundPosition(0, Position, #PB_Sound_Millisecond)
  3672.             EndIf
  3673.  
  3674.          Case  #C2D_MUSIC_MCI
  3675.             t$ =  "SEEK 0 TO " + Str(Position)
  3676.             mciSendString_(@t$, 0, 0, 0)
  3677.             mciSendString_(@"PLAY 0 REPEAT", 0, 0, 0)
  3678.  
  3679.          CompilerIf  #IsAMP
  3680.          Case  #C2D_MUSIC_AMP
  3681.             AmpMusicSetPosition(Position)
  3682.          CompilerEndIf
  3683.  
  3684.          CompilerIf  #IsBAS
  3685.          Case  #C2D_MUSIC_BAS
  3686.             \TimePlay   =  ElapsedMilliseconds()   -  Position
  3687.             Position =  $FFFF0000   |  (Position   /  1000)
  3688.             BASSMOD_MusicSetPosition(Position)
  3689.          CompilerEndIf
  3690.  
  3691.          CompilerIf  #IsMED   ; Error
  3692. ;        Case  #C2D_MUSIC_MED
  3693. ;           If Flags ; only percent (coz unknown / buggy? ticks)
  3694. ;              \TimePlay   =  ElapsedMilliseconds()   -  Position
  3695. ;              Position    =  Abs(MEDP_ModuleLength())   *  0.01  *  Position
  3696. ;              MEDP_SetPlayPosition(Position)
  3697. ;           EndIf
  3698.          CompilerEndIf
  3699.  
  3700.          CompilerIf  #IsV2M
  3701.          Case  #C2D_MUSIC_V2M
  3702.             V2MStop()
  3703.             dsClose()
  3704.             V2MInit(\Memory, \Freq, GetForegroundWindow_())
  3705.             V2MSetRepeat(1)
  3706.             dsSetVolume(0.01  *  \Volume)
  3707.             V2MPlay(Position)
  3708.          CompilerEndIf
  3709.  
  3710.          CompilerIf  #IsYMP
  3711.          Case  #C2D_MUSIC_YMP
  3712.             \TimePlay   =  ElapsedMilliseconds()   -  Position
  3713.             Position /  1000
  3714.             YM_Seek(Position)
  3715.          CompilerEndIf
  3716.  
  3717.       EndSelect
  3718.  
  3719.    EndWith
  3720.  
  3721. EndProcedure
  3722. ProcedureDLL   SCAL_SetFreq(Freq)
  3723.    If Freq  <= #Null
  3724.       Freq  =  44100
  3725.    EndIf
  3726.    RS_SCAL\Freq   =  Freq
  3727. EndProcedure
  3728. ProcedureDLL   SCAL_SetString(Format)
  3729.  
  3730.    ; Set stringformat to AscII, UTF8, Unicode
  3731.  
  3732.    ; Format:   ASCII =  1 or #PB_Ascii (24)
  3733.    ;           UTF8  =  3
  3734.    ;           UNICODE  =  any other number (default)
  3735.  
  3736.    ; Tipp = SizeOf(Character))
  3737.  
  3738.    With  RS_SCAL
  3739.       Select   Format
  3740.          Case  1, #PB_Ascii
  3741.             \StrFormat  =  #PB_Ascii
  3742.          Case  3; #PB_UTF8
  3743.             \StrFormat  =  #PB_UTF8
  3744.          Default
  3745.             \StrFormat  =  #PB_Unicode
  3746.       EndSelect
  3747.    EndWith
  3748.  
  3749. EndProcedure
  3750. ProcedureDLL   SCAL_SetVolume(Percent)
  3751.  
  3752.    Protected   t$
  3753.  
  3754.    With  RS_SCAL
  3755.  
  3756.       If Percent  <  0
  3757.          Percent  =  0
  3758.       ElseIf   Percent  >  100
  3759.          Percent  =  100
  3760.       EndIf
  3761.  
  3762.       \Volume  =  Percent
  3763.  
  3764.       ; Playing?
  3765.       If \ID   =  #Null :  ProcedureReturn   :  EndIf
  3766.  
  3767.       Select   \Mode
  3768.          Case  #C2D_MUSIC_FT2 :  ft2play_SetMasterVol(2.56  *  \Volume)
  3769.          Case  #C2D_MUSIC_PT2 :  pt2play_SetMasterVol(2.56  *  \Volume)
  3770.          Case  #C2D_MUSIC_FC4 :  fc14play_SetMasterVol(2.56 *  \Volume)
  3771.          Case  #C2D_MUSIC_STM :  st23play_SetMasterVol(2.56 *  \Volume)
  3772.          Case  #C2D_MUSIC_S3M :  st3play_SetMasterVol(2.56  *  \Volume)
  3773.  
  3774.          Case  #C2D_MUSIC_MCI
  3775.             t$ =  "SETAUDIO 0 VOLUME TO " + Str(10 * \Volume)
  3776.             mciSendString_(@t$, 0, 0, 0)  ; 0 - 1000
  3777.  
  3778.          Case  #C2D_MUSIC_MOD :  MusicVolume(0, \Volume)
  3779.          Case  #C2D_MUSIC_MOV :  MovieAudio(0,  \Volume, 0)
  3780.  
  3781.          Case  #C2D_MUSIC_FLA, #C2D_MUSIC_OGG, #C2D_MUSIC_WAV
  3782.             SoundVolume(0, \Volume)
  3783.  
  3784.          CompilerIf  #IsAMP
  3785.          Case  #C2D_MUSIC_AMP
  3786.             AmpMusicVolume(2.55  *  \Volume)
  3787.          CompilerEndIf
  3788.  
  3789.          CompilerIf  #IsBAS
  3790.          Case  #C2D_MUSIC_BAS
  3791.             BASSMOD_SetVolume(\Volume)
  3792.          CompilerEndIf
  3793.  
  3794.          CompilerIf  #IsV2M
  3795.          Case  #C2D_MUSIC_V2M
  3796.             dsSetVolume(0.01  *  \Volume)
  3797.          CompilerEndIf
  3798.  
  3799.          CompilerIf  #IsXM2
  3800.          Case  #C2D_MUSIC_XM2
  3801.             uFMOD_SetVolume(0.25 *  \Volume)
  3802.          CompilerEndIf
  3803.  
  3804.          CompilerIf  #IsYMP
  3805.          Case  #C2D_MUSIC_YMP
  3806.             YM_SetVolume(2.55 *  \Volume)
  3807.          CompilerEndIf
  3808.  
  3809.       EndSelect
  3810.  
  3811.    EndWith
  3812.  
  3813. EndProcedure
  3814. ProcedureDLL   SCAL_Struct()
  3815.  
  3816.    ; creates temporary directory for all files
  3817.    ; define RS_SCAL\Temp$ even if not exist
  3818.  
  3819.    ; Return: private *structure
  3820.  
  3821.    scal_Temp(#SCAL_TempPath$)
  3822.  
  3823.    ProcedureReturn   @RS_SCAL
  3824.  
  3825. EndProcedure
  3826. ProcedureDLL   SCAL_Table(Mode)
  3827.  
  3828.    ; Mode = #C2D_MUSIC_[ID]
  3829.  
  3830.    ; Return:   ptr to infostring or table
  3831.  
  3832.    Static   *Memory.Integer
  3833.  
  3834.    *Memory  =  ?mode
  3835.  
  3836.    If Mode >= #Null  And   Mode <= #SCAL_MAX
  3837.       *Memory  +  Mode  *  SizeOf(Integer)
  3838.       ProcedureReturn   *Memory\i
  3839.    EndIf
  3840.  
  3841.    ProcedureReturn   *Memory
  3842.  
  3843. EndProcedure
  3844. ProcedureDLL   SCAL_Version()
  3845.    ; 100 = 1.00
  3846.    ProcedureReturn   #SCAL_VERSION
  3847. EndProcedure
  3848.  
  3849. DataSection
  3850.  
  3851.    IncludePath "Include\"
  3852.  
  3853.    l_Start: ; Compare extensions
  3854.  
  3855.    l_AHX:   :  IncludeFile "i_AHX.pbi"
  3856.    l_FC4:   :  IncludeFile "i_FC4.pbi"
  3857.    l_FLA:   :  IncludeFile "i_FLA.pbi"
  3858.    l_FT2:   :  IncludeFile "i_FT2.pbi"
  3859.    l_MOD:   :  IncludeFile "i_MOD.pbi"
  3860.    l_OGG:   :  IncludeFile "i_OGG.pbi"
  3861.    l_PT2:   :  IncludeFile "i_PT2.pbi"
  3862.    l_S3M:   :  IncludeFile "i_S3M.pbi"
  3863.    l_STM:   :  IncludeFile "i_STM.pbi"
  3864.    l_API:   ; same as wav
  3865.    l_WAV:   :  IncludeFile "i_WAV.pbi"
  3866.    l_MOV:   ; same as mci
  3867.    l_MCI:   :  IncludeFile "i_MCI.pbi"
  3868.  
  3869.    CompilerIf  #IsAMP
  3870.    l_AMP:   :  IncludeFile "i_AMP.pbi"
  3871.    CompilerEndIf
  3872.    CompilerIf  #IsBAS
  3873.    l_BAS:   :  IncludeFile "i_BAS.pbi"
  3874.    CompilerEndIf
  3875.    CompilerIf  #IsBMF
  3876.    l_BMF:   :  IncludeFile "i_BMF.pbi"
  3877.    CompilerEndIf
  3878.    CompilerIf  #IsFCP
  3879.    l_FCP:   :  IncludeFile "i_FCP.pbi"
  3880.    CompilerEndIf
  3881.    CompilerIf  #IsMED
  3882.    l_MED:   :  IncludeFile "i_MED.pbi"
  3883.    CompilerEndIf
  3884.    CompilerIf  #IsS68
  3885.    l_SC68:  :  IncludeFile "i_S68.pbi"
  3886.    CompilerEndIf
  3887.    CompilerIf  (#IsSID  +  #IsTSR)
  3888.    l_TSR:   ; same as sid
  3889.    l_SID:   :  IncludeFile "i_SID.pbi"
  3890.    CompilerEndIf
  3891.    CompilerIf  (#IsV1M  +  #IsV2M)
  3892.    l_V1M:   ; same as v2m
  3893.    l_V2M:   :  IncludeFile "i_V2M.pbi"
  3894.    CompilerEndIf
  3895.    CompilerIf  #IsXM2
  3896.    l_XM2:   :  IncludeFile "i_XM2.pbi"
  3897.    CompilerEndIf
  3898.    CompilerIf  #IsYMP
  3899.    l_YMP:   :  IncludeFile "i_YMP.pbi"
  3900.    CompilerEndIf
  3901.  
  3902.    l_ZIP:   :  IncludeFile "i_ZIP.pbi"
  3903.  
  3904.    l_Finish:   :  Data.l   #Null ; End of compare extensions
  3905.  
  3906.    ; Playengines: ID | Processor x86-64 | Trackerinfo/name -> never change order (same as #C2D_MUSIC_[ID])!
  3907.    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
  3908.    m0:   :  Data.s   "AUTO|x86-64|Autodetect"
  3909.    m1:   :  Data.s   "AHX|x86-64|Amiga Abyss' Highest eXperience 1.00-1.27"
  3910.    m2:   :  Data.s   "AMP|x86|AmpMaster_x86.dll"
  3911.    m3:   :  Data.s   "API|x86-64|PlaySound Wave API"
  3912.    m4:   :  Data.s   "BAS|x86|BASSMOD 2.0"
  3913.    m5:   :  Data.s   "BMF|x86|BeRo 404 Tracker"
  3914.    m6:   :  Data.s   "FC4|x86-64|Amiga Future Composer 1.0-1.4"
  3915.    m7:   :  Data.s   "FCP|x86|Amiga Future Composer 1.4"
  3916.    m8:   :  Data.s   "FLA|x86-64|Pure Free Lossless Audio Codec"
  3917.    m9:   :  Data.s   "FT2|x86-64|FastTracker I / II"
  3918.    m10:  :  Data.s   "MCI|x86-64|Media Control Interface"
  3919.    m11:  :  Data.s   "MED|x86|Amiga OctaMED / MEDP 1.0"
  3920.    m12:  :  Data.s   "MOD|x86-64|Pure ModPlug Module"
  3921.    m13:  :  Data.s   "MOV|x86-64|Pure Movie Mediadecoder"
  3922.    m14:  :  Data.s   "OGG|x86-64|Pure OGG Vorbis Decoder"
  3923.    m15:  :  Data.s   "PT2|x86-64|Amiga ProTracker 2.3d"
  3924.    m16:  :  Data.s   "S3M|x86-64|ScreamTracker v3.21"
  3925.    m17:  :  Data.s   "S68|x86|SC68 MC68000 Amiga / Atari"
  3926.    m18:  :  Data.s   "SCA|x86-64|SCAL DLL"
  3927.    m19:  :  Data.s   "SID|x86|C64 TitchySid"
  3928.    m20:  :  Data.s   "STM|x86-64|ScreamTracker v2.2-2.3"
  3929.    m21:  :  Data.s   "TFC|x86-64|Tiny Future Composer 1.0-1.4"
  3930.    m22:  :  Data.s   "THX|x86-64|Tiny Abyss' Highest eXperience 1.00-1.27"
  3931.    m23:  :  Data.s   "TPT|x86-64|Tiny ProTracker 2.3d"
  3932.    m24:  :  Data.s   "TSR|x86|C64 Sid SoundServer"
  3933.    m25:  :  Data.s   "V1M|x86|Farbrausch V2 Synthesizer System v1.0"
  3934.    m26:  :  Data.s   "V2M|x86|Farbrausch V2 Synthesizer System v1.5"
  3935.    m27:  :  Data.s   "WAV|x86-64|Pure WAV Sound Decoder"
  3936.    m28:  :  Data.s   "XM2|x86|uFMOD FastTracker II"
  3937.    m29:  :  Data.s   "YMP|x86|Atari ST YM2149 (LZH-h0)"
  3938.  
  3939.    s_unknown:  :  Data.s   "?"
  3940.  
  3941. EndDataSection
RAW Paste Data