123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398(*---------------------------------------------------------------------------
Copyright (c) 2016 The tsdl-mixer programmers. All rights reserved.
---------------------------------------------------------------------------*)openCtypesopenForeignopenTsdlmoduleMixer=structletbool=letread=function0->false|_->trueinletwrite=functiontrue->1|false->0inview~read~writeinttype'aresult='aSdl.resultletdebug=false(* set this to false before release *)leterror()=Error(`Msg(Sdl.get_error()))letwrite_never_=assertfalseletbool_to_ok=letread=function0->Okfalse|1->Oktrue|_->error()inview~read~write:write_neverintletnat_to_ok=letread=functionnwhenn<0->error()|n->Okninview~read~write:write_neverintletnonzero_to_ok=letread=function0->error()|_n->Ok()inview~read~write:write_neverintletzero_to_ok=letread=function0->Ok()|_->error()inview~read~write:write_neverintletsome_to_okt=letread=functionSomev->Okv|None->error()inview~read~write:write_nevertmoduleInit=structtypet=Unsigned.uint32leti=Unsigned.UInt32.of_intlet(+)=Unsigned.UInt32.logorlettestfm=Unsigned.UInt32.(compare(logandfm)zero<>0)leteqff'=Unsigned.UInt32.(compareff'=0)letempty=i0letflac=i1letmikmod=i2letmodplug=i4letmp3=i8letogg=i16letfluidsynth=i32end(* pkg-config --variable=libdir SDL2_mixer *)(* Use Configurator.V1.Pkg_config instead? *)letpkg_config()=tryletic=Unix.open_process_in"pkg-config --variable=libdir SDL2_mixer"inletdir=input_lineicinclose_inic;Somedirwith_->None(* This "hack" seems to be necessary for linux if you want to use
#require "tsdl-image"
in the toplevel, see
https://github.com/ocamllabs/ocaml-ctypes/issues/70 *)letfrom:Dl.libraryoption=(ifdebugthenSdl.(log_infoLog.category_system"Loading Sdl_mixer, Target = %s"Build_config.system));letenv=trySys.getenv"LIBSDL2_PATH"withNot_found->""inletfilename,path=matchBuild_config.systemwith|"macosx"->("libSDL2_mixer-2.0.0.dylib",["/opt/homebrew/lib/"])|_->("libSDL2_mixer-2.0.so.0",["/usr/lib/x86_64-linux-gnu/";"/usr/local/lib"])inletrecloop=function|[]->None|dir::rest->(letfilename=ifdir=""thenfilenameelseFilename.concatdirfilenameintrySomeDl.(dlopen~filename~flags:[RTLD_NOW])with_->looprest)inmatchloop(env::path)with|Somef->Somef|None->((* We execute pkg_config only if everything else failed. *)matchpkg_config()with|Somedir->loop[dir]|None->print_endline("Cannot find "^filename^", please set LIBSDL2_PATH");None)letforeign=foreign?fromletinit=foreign"Mix_Init"(uint32_t@->returninguint32_t)letinitflags=letflags'=initflagsinifflags'=Init.empty&&flags<>Init.emptythenerror()elseOkflags'letquit=foreign"Mix_Quit"(void@->returningvoid)letmix_channels=8letdefault_frequency=22050letdefault_format=Sdl.Audio.s16_sysletdefault_channels=2letmax_volume=128typefading=NoFading|FadingOut|FadingIntypemusic_type=|None|Cmd|Wav|Mod|Mid|Ogg|Mp3|Mp3_Mad|Flac|Modplugletfading=letread=function|0->NoFading|1->FadingOut|2->FadingIn|_->failwith"Unexpected value"inletwrite=functionNoFading->0|FadingOut->1|FadingIn->2inview~read~writeintletmusic_type=letread=function|0->None|1->Cmd|2->Wav|3->Mod|4->Mid|5->Ogg|6->Mp3|7->Mp3_Mad|8->Flac|9->Modplug|_->failwith"Unexpected value"inletwrite=function|None->0|Cmd->1|Wav->2|Mod->3|Mid->4|Ogg->5|Mp3->6|Mp3_Mad->7|Flac->8|Modplug->9inview~read~writeinttype_chunkletchunk_struct:_chunkstructuretyp=structure"Mix_Chunk"letchunk:_chunkstructureptrtyp=ptrchunk_structletchunk_opt:_chunkstructureptroptiontyp=ptr_optchunk_structtypechunk=_chunkstructureptrtype_musicletmusic_struct:_musicstructuretyp=structure"Mix_Music"letmusic:_musicstructureptrtyp=ptrmusic_structletmusic_opt:_musicstructureptroptiontyp=ptr_optmusic_structtypemusic=_musicstructureptrletopen_audio=foreign"Mix_OpenAudio"(int@->int@->int@->int@->returningzero_to_ok)letallocate_channels=foreign"Mix_AllocateChannels"(int@->returningint)letquery_spec=foreign"Mix_QuerySpec"(ptrint@->ptruint16_t@->ptrint@->returningint)letrw_ops=view~read:Sdl.unsafe_rw_ops_of_ptr~write:Sdl.unsafe_ptr_of_rw_opsnativeintletload_wav_rw=foreign"Mix_LoadWAV_RW"(rw_ops@->int@->returning(some_to_okchunk_opt))let(>>=)of=matchowithErrore->Errore|Oka->faletload_wavfile=Sdl.rw_from_filefile"rb">>=funrw->load_wav_rwrw1letload_mus=foreign"Mix_LoadMUS"(string@->returning(some_to_okmusic_opt))letload_mus_rw=foreign"Mix_LoadMUS_RW"(rw_ops@->int@->returning(some_to_okmusic_opt))letload_mus_type_rw=foreign"Mix_LoadMUSType_RW"(rw_ops@->music_type@->int@->returning(some_to_okmusic_opt))letquickload_wav=foreign"Mix_QuickLoad_WAV"(ptruint8_t@->returning(some_to_okchunk_opt))letquickload_raw=foreign"Mix_QuickLoad_RAW"(ptruint8_t@->uint32_t@->returning(some_to_okchunk_opt))letfree_chunk=foreign"Mix_FreeChunk"(chunk@->returningvoid)letfree_music=foreign"Mix_FreeMusic"(music@->returningvoid)letget_num_chunk_decoders=foreign"Mix_GetNumChunkDecoders"(void@->returningint)letget_chunk_decoder=foreign"Mix_GetChunkDecoder"(int@->returningstring)letget_num_music_decoders=foreign"Mix_GetNumMusicDecoders"(void@->returningint)letget_music_decoder=foreign"Mix_GetMusicDecoder"(int@->returningstring)letget_music_type=foreign"Mix_GetMusicType"(music_opt@->returningmusic_type)letmix_func=ptrvoid@->ptruint8_t@->int@->returningvoidletset_post_mix=foreign"Mix_SetPostMix"(funptrmix_func@->ptrvoid@->returningvoid)lethook_music=foreign"Mix_HookMusic"(funptrmix_func@->ptrvoid@->returningvoid)lethook_music_finished=foreign"Mix_HookMusicFinished"(funptr(void@->returningvoid)@->returningvoid)letget_music_hook_data=foreign"Mix_GetMusicHookData"(void@->returning(ptrvoid))letchannel_finished=foreign"Mix_ChannelFinished"(funptr(int@->returningvoid)@->returningvoid)letchannel_post=-2leteffect_func_t=int@->ptrvoid@->int@->ptrvoid@->returningvoidleteffect_done_t=int@->ptrvoid@->returningvoidletregister_effect=foreign"Mix_RegisterEffect"(int@->funptreffect_func_t@->funptreffect_done_t@->ptrvoid@->returningnonzero_to_ok)letunregister_effect=foreign"Mix_UnregisterEffect"(int@->funptreffect_func_t@->returningnonzero_to_ok)letunregister_all_effects=foreign"Mix_UnregisterAllEffects"(int@->returningnonzero_to_ok)leteffects_max_speed="MIX_EFFECTSMAXSPEED"letset_panning=foreign"Mix_SetPanning"(int@->uint8_t@->uint8_t@->returningnonzero_to_ok)letset_position=foreign"Mix_SetPosition"(int@->int16_t@->uint8_t@->returningnonzero_to_ok)letset_distance=foreign"Mix_SetDistance"(int@->uint8_t@->returningnonzero_to_ok)letset_reverse_stereo=foreign"Mix_SetReverseStereo"(int@->int@->returningnonzero_to_ok)letreserve_channels=foreign"Mix_ReserveChannels"(int@->returningnonzero_to_ok)letgroup_channel=foreign"Mix_GroupChannel"(int@->int@->returningbool_to_ok)letgroup_channels=foreign"Mix_GroupChannels"(int@->int@->int@->returningbool_to_ok)letgroup_available=foreign"Mix_GroupAvailable"(int@->returningnat_to_ok)letgroup_count=foreign"Mix_GroupCount"(int@->returningint)letgroup_oldest=foreign"Mix_GroupOldest"(int@->returningint)letgroup_newer=foreign"Mix_GroupNewer"(int@->returningint)letplay_channel_timed=foreign"Mix_PlayChannelTimed"(int@->chunk@->int@->int@->returningnat_to_ok)letplay_channelchannelchunkloops=play_channel_timedchannelchunkloops(-1)letplay_music=foreign"Mix_PlayMusic"(music@->int@->returningnat_to_ok)letfade_in_music=foreign"Mix_FadeInMusic"(music@->int@->int@->returningnat_to_ok)letfade_in_music_pos=foreign"Mix_FadeInMusicPos"(music@->int@->int@->double@->returningnat_to_ok)letfade_in_channel_timed=foreign"Mix_FadeInChannelTimed"(int@->chunk@->int@->int@->int@->returningnat_to_ok)letfade_in_channelchannelchunkloopsms=fade_in_channel_timedchannelchunkloopsms(-1)letvolume=foreign"Mix_Volume"(int@->int@->returningint)letvolume_chunk=foreign"Mix_VolumeChunk"(chunk@->int@->returningint)letvolume_music=foreign"Mix_VolumeMusic"(int@->returningint)lethalt_channel=foreign"Mix_HaltChannel"(int@->returningzero_to_ok)lethalt_group=foreign"Mix_HaltGroup"(int@->returningzero_to_ok)lethalt_music=foreign"Mix_HaltMusic"(void@->returningzero_to_ok)letexpire_channel=foreign"Mix_ExpireChannel"(int@->int@->returningint)letfade_out_channel=foreign"Mix_FadeOutChannel"(int@->int@->returningint)letfade_out_group=foreign"Mix_FadeOutGroup"(int@->int@->returningint)letfade_out_music=foreign"Mix_FadeOutMusic"(int@->returningnonzero_to_ok)letset_music_cmd=foreign"Mix_SetMusicCMD"(string@->returningzero_to_ok)letset_synchro_value=foreign"Mix_SetSynchroValue"(int@->returningzero_to_ok)letget_synchro_value=foreign"Mix_GetSynchroValue"(void@->returningnat_to_ok)letset_sound_fonts=foreign"Mix_SetSoundFonts"(string@->returningzero_to_ok)letget_sound_fonts=foreign"Mix_GetSoundFonts"(void@->returningstring)leteach_sound_font=foreign"Mix_EachSoundFont"(funptr(string@->ptrvoid@->returningint)@->ptrvoid@->returningnonzero_to_ok)letfading_music=foreign"Mix_FadingMusic"(void@->returningfading)letfading_channel=foreign"Mix_FadingChannel"(int@->returningfading)letpause=foreign"Mix_Pause"(int@->returningvoid)letresume=foreign"Mix_Resume"(int@->returningvoid)letpaused=foreign"Mix_Paused"(int@->returningbool)letpause_music=foreign"Mix_PauseMusic"(void@->returningvoid)letresume_music=foreign"Mix_ResumeMusic"(void@->returningvoid)letrewind_music=foreign"Mix_RewindMusic"(void@->returningvoid)letpaused_music=foreign"Mix_PausedMusic"(void@->returningbool)letset_music_position=foreign"Mix_SetMusicPosition"(double@->returningnat_to_ok)letplaying=foreign"Mix_Playing"(int@->returningbool)letplaying=function|Somechannel->playingchannel|None->playing(-1)letplaying_music=foreign"Mix_PlayingMusic"(void@->returningbool)letget_chunk=foreign"Mix_GetChunk"(int@->returning(some_to_okchunk_opt))letclose_audio=foreign"Mix_CloseAudio"(void@->returningvoid)end