|  | @@ -348,25 +348,13 @@ void laaudio_DataCallback(ma_device* pDevice, void* pOutput, const void* pInput,
 | 
	
		
			
				|  |  |      laSpinUnlock(&MAIN.Audio->AudioStatusLock);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -void laInitMiniAudio(){
 | 
	
		
			
				|  |  | -    int SampleRate=48000;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    ma_context context;
 | 
	
		
			
				|  |  | -    if (ma_context_init(NULL, 0, NULL, &context) != MA_SUCCESS) {
 | 
	
		
			
				|  |  | -        printf("Can't init miniaudio context\n");
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    ma_device_info* pPlaybackInfos;
 | 
	
		
			
				|  |  | -    ma_uint32 playbackCount;
 | 
	
		
			
				|  |  | -    ma_device_info* pCaptureInfos;
 | 
	
		
			
				|  |  | -    ma_uint32 captureCount;
 | 
	
		
			
				|  |  | -    if (ma_context_get_devices(&context, &pPlaybackInfos, &playbackCount, &pCaptureInfos, &captureCount) != MA_SUCCESS) {
 | 
	
		
			
				|  |  | -        printf("Can't get audio devices\n");
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    for (ma_uint32 iDevice = 0; iDevice < playbackCount; iDevice += 1) {
 | 
	
		
			
				|  |  | -        printf("%d - %s\n", iDevice, pPlaybackInfos[iDevice].name);
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +void la_SelectAudioDevice(laAudioDevice* ad){
 | 
	
		
			
				|  |  | +    memAssignRef(MAIN.Audio, &MAIN.Audio->UsingDevice, ad);
 | 
	
		
			
				|  |  | +    ma_device_stop(&MAIN.Audio->AudioDevice);
 | 
	
		
			
				|  |  | +    ma_device_uninit(&MAIN.Audio->AudioDevice);
 | 
	
		
			
				|  |  | +    if(!ad) return;
 | 
	
		
			
				|  |  | +    int SampleRate=48000;
 | 
	
		
			
				|  |  |      ma_device_config config = ma_device_config_init(ma_device_type_playback);
 | 
	
		
			
				|  |  |      config.playback.pDeviceID= 0;
 | 
	
		
			
				|  |  |      config.playback.format   = ma_format_f32;
 | 
	
	
		
			
				|  | @@ -374,12 +362,44 @@ void laInitMiniAudio(){
 | 
	
		
			
				|  |  |      config.sampleRate        = SampleRate;
 | 
	
		
			
				|  |  |      config.dataCallback      = laaudio_DataCallback;
 | 
	
		
			
				|  |  |      config.pUserData         = 0;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |      if (ma_device_init(NULL, &config, &MAIN.Audio->AudioDevice) != MA_SUCCESS){ return; }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |      MAIN.Audio->AudioSampleRate=SampleRate;
 | 
	
		
			
				|  |  |      MAIN.Audio->NextAudioSample=LA_SYNTH_PLEN;
 | 
	
		
			
				|  |  |      MAIN.Audio->AudioFrameInterval=1.0f/SampleRate;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +void la_AddAudioDevice(int id, char* Name){
 | 
	
		
			
				|  |  | +    laAudioDevice* ad=memAcquire(sizeof(laAudioDevice));
 | 
	
		
			
				|  |  | +    strSafeSet(&ad->Name,Name); ad->MiniAudioID=id;
 | 
	
		
			
				|  |  | +    lstAppendItem(&MAIN.Audio->AudioDevices,ad);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +void la_ClearAudioDevices(){
 | 
	
		
			
				|  |  | +    laAudioDevice* ad; while(ad=lstPopItem(&MAIN.Audio->AudioDevices)){
 | 
	
		
			
				|  |  | +        strSafeDestroy(&ad->Name); memFree(ad);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +void laRefreshAudioDevices(){
 | 
	
		
			
				|  |  | +    if(!MAIN.Audio) return; la_ClearAudioDevices();
 | 
	
		
			
				|  |  | +    ma_device_info* pPlaybackInfos;
 | 
	
		
			
				|  |  | +    ma_uint32 playbackCount;
 | 
	
		
			
				|  |  | +    ma_device_info* pCaptureInfos;
 | 
	
		
			
				|  |  | +    ma_uint32 captureCount;
 | 
	
		
			
				|  |  | +    if (ma_context_get_devices(&MAIN.Audio->MiniAudioContext, &pPlaybackInfos, &playbackCount, &pCaptureInfos, &captureCount) != MA_SUCCESS) {
 | 
	
		
			
				|  |  | +        logPrintNew("Can't get audio devices.\n");
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    for (ma_uint32 iDevice = 0; iDevice < playbackCount; iDevice += 1) {
 | 
	
		
			
				|  |  | +        la_AddAudioDevice(iDevice, pPlaybackInfos[iDevice].name);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +void laInitMiniAudio(){
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    if (ma_context_init(NULL, 0, NULL, &MAIN.Audio->MiniAudioContext) != MA_SUCCESS) {
 | 
	
		
			
				|  |  | +        printf("Can't init miniaudio context\n");
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    laRefreshAudioDevices();
 | 
	
		
			
				|  |  | +    la_SelectAudioDevice(MAIN.Audio->AudioDevices.pFirst);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |      INITPACKET(MAIN.Audio->AudioSamples);
 | 
	
		
			
				|  |  |      laSpinInit(&MAIN.Audio->AudioStatusLock);
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -388,10 +408,15 @@ void laDeinitAudio(){
 | 
	
		
			
				|  |  |      laSpinDestroy(&MAIN.Audio->AudioStatusLock);
 | 
	
		
			
				|  |  |      ma_device_stop(&MAIN.Audio->AudioDevice);
 | 
	
		
			
				|  |  |      ma_device_uninit(&MAIN.Audio->AudioDevice);
 | 
	
		
			
				|  |  | +    ma_context_uninit(&MAIN.Audio->MiniAudioContext);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  // Operations
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +int OPINV_laRefreshAudioDevices(laOperator* a, laEvent* e){
 | 
	
		
			
				|  |  | +    laRefreshAudioDevices(); return LA_FINISHED;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  laSynth* laNewSynth(char* Name){
 | 
	
		
			
				|  |  |      laSynth* ss=memAcquireHyper(sizeof(laSynth));
 | 
	
		
			
				|  |  |      ss->Page=memAcquire(sizeof(laRackPage));
 | 
	
	
		
			
				|  | @@ -498,6 +523,9 @@ void laui_Synthersizers(laUiList *uil, laPropPack *This, laPropPack *Extra, laCo
 | 
	
		
			
				|  |  |  #undef ADD_PAGE
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +void* laget_FirstAudioDevice(void* unused1,void* unused2){
 | 
	
		
			
				|  |  | +    return MAIN.Audio->AudioDevices.pFirst;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  |  void* laget_FirstSynth(void* unused1,void* unused2){
 | 
	
		
			
				|  |  |      return MAIN.Audio->Synths.pFirst;
 | 
	
		
			
				|  |  |  }
 | 
	
	
		
			
				|  | @@ -512,6 +540,9 @@ int laget_SynthPlaying(laSynth* ss){
 | 
	
		
			
				|  |  |  void laset_CurrentSynth(laAudio* a,laSynth* s){
 | 
	
		
			
				|  |  |      memAssignRef(a,&a->CurrentSynth,s);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  | +void laset_CurrentAudioDevice(laAudio* a,laAudioDevice* ad){
 | 
	
		
			
				|  |  | +    la_SelectAudioDevice(ad);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  void la_AudioPreFrame(){
 | 
	
		
			
				|  |  |      if(MAIN.GraphNeedsRebuild){ laRebuildSynthGraphs(); }
 | 
	
	
		
			
				|  | @@ -534,6 +565,11 @@ void laInitAudio(){
 | 
	
		
			
				|  |  |      laCreateOperatorType("LA_remove_synth", "Remove Synthesizer", "Remove a synthesizer",OPCHK_IslaSynth,0,0,OPINV_ShedRemoveSynth,OPMOD_FinishOnData,L'🗴',0)
 | 
	
		
			
				|  |  |          ->UiDefine=laui_RemoveSynth;
 | 
	
		
			
				|  |  |      laCreateOperatorType("LA_synth_play", "Play Synthesizer", "Play a synthesizer",OPCHK_IslaSynth,0,0,OPINV_laSynthPlay,0,0,0);
 | 
	
		
			
				|  |  | +    laCreateOperatorType("LA_refresh_audio_devices", "Refresh Audio Devices", "Enumerate audio devices for selection",0,0,0,OPINV_laRefreshAudioDevices,0,U'🗘',0);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    pc = laAddPropertyContainer("la_audio_device","LaGUI Audio Device","LaGUI enumerated audio device",0,0,sizeof(laAudioDevice),0,0,1);{
 | 
	
		
			
				|  |  | +        laAddStringProperty(pc,"name","Name","Name of the audio device",0,0,0,0,1,offsetof(laAudioDevice,Name),0,0,0,0,LA_AS_IDENTIFIER);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      pc = laAddPropertyContainer("la_synth", "LaGUI Synthesizer", "LaGUI synthesizer", 0,0,sizeof(laSynth),lapost_Synth,0,2);{
 | 
	
		
			
				|  |  |          LA_PC_SYNTH=pc;
 |