*/}}
Browse Source

Audio device selection UI

YimingWu 1 year ago
parent
commit
eff673ba1c
4 changed files with 76 additions and 20 deletions
  1. 56 20
      la_audio.c
  2. 11 0
      la_interface.h
  3. 2 0
      resources/la_properties.c
  4. 7 0
      resources/la_templates.c

+ 56 - 20
la_audio.c

@@ -348,25 +348,13 @@ void laaudio_DataCallback(ma_device* pDevice, void* pOutput, const void* pInput,
     laSpinUnlock(&MAIN.Audio->AudioStatusLock);
     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);
     ma_device_config config = ma_device_config_init(ma_device_type_playback);
     config.playback.pDeviceID= 0;
     config.playback.pDeviceID= 0;
     config.playback.format   = ma_format_f32;
     config.playback.format   = ma_format_f32;
@@ -374,12 +362,44 @@ void laInitMiniAudio(){
     config.sampleRate        = SampleRate;
     config.sampleRate        = SampleRate;
     config.dataCallback      = laaudio_DataCallback;
     config.dataCallback      = laaudio_DataCallback;
     config.pUserData         = 0;
     config.pUserData         = 0;
-
     if (ma_device_init(NULL, &config, &MAIN.Audio->AudioDevice) != MA_SUCCESS){ return; }
     if (ma_device_init(NULL, &config, &MAIN.Audio->AudioDevice) != MA_SUCCESS){ return; }
-
     MAIN.Audio->AudioSampleRate=SampleRate;
     MAIN.Audio->AudioSampleRate=SampleRate;
     MAIN.Audio->NextAudioSample=LA_SYNTH_PLEN;
     MAIN.Audio->NextAudioSample=LA_SYNTH_PLEN;
     MAIN.Audio->AudioFrameInterval=1.0f/SampleRate;
     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);
     INITPACKET(MAIN.Audio->AudioSamples);
     laSpinInit(&MAIN.Audio->AudioStatusLock);
     laSpinInit(&MAIN.Audio->AudioStatusLock);
 
 
@@ -388,10 +408,15 @@ void laDeinitAudio(){
     laSpinDestroy(&MAIN.Audio->AudioStatusLock);
     laSpinDestroy(&MAIN.Audio->AudioStatusLock);
     ma_device_stop(&MAIN.Audio->AudioDevice);
     ma_device_stop(&MAIN.Audio->AudioDevice);
     ma_device_uninit(&MAIN.Audio->AudioDevice);
     ma_device_uninit(&MAIN.Audio->AudioDevice);
+    ma_context_uninit(&MAIN.Audio->MiniAudioContext);
 }
 }
 
 
 // Operations
 // Operations
 
 
+int OPINV_laRefreshAudioDevices(laOperator* a, laEvent* e){
+    laRefreshAudioDevices(); return LA_FINISHED;
+}
+
 laSynth* laNewSynth(char* Name){
 laSynth* laNewSynth(char* Name){
     laSynth* ss=memAcquireHyper(sizeof(laSynth));
     laSynth* ss=memAcquireHyper(sizeof(laSynth));
     ss->Page=memAcquire(sizeof(laRackPage));
     ss->Page=memAcquire(sizeof(laRackPage));
@@ -498,6 +523,9 @@ void laui_Synthersizers(laUiList *uil, laPropPack *This, laPropPack *Extra, laCo
 #undef ADD_PAGE
 #undef ADD_PAGE
 }
 }
 
 
+void* laget_FirstAudioDevice(void* unused1,void* unused2){
+    return MAIN.Audio->AudioDevices.pFirst;
+}
 void* laget_FirstSynth(void* unused1,void* unused2){
 void* laget_FirstSynth(void* unused1,void* unused2){
     return MAIN.Audio->Synths.pFirst;
     return MAIN.Audio->Synths.pFirst;
 }
 }
@@ -512,6 +540,9 @@ int laget_SynthPlaying(laSynth* ss){
 void laset_CurrentSynth(laAudio* a,laSynth* s){
 void laset_CurrentSynth(laAudio* a,laSynth* s){
     memAssignRef(a,&a->CurrentSynth,s);
     memAssignRef(a,&a->CurrentSynth,s);
 }
 }
+void laset_CurrentAudioDevice(laAudio* a,laAudioDevice* ad){
+    la_SelectAudioDevice(ad);
+}
 
 
 void la_AudioPreFrame(){
 void la_AudioPreFrame(){
     if(MAIN.GraphNeedsRebuild){ laRebuildSynthGraphs(); }
     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)
     laCreateOperatorType("LA_remove_synth", "Remove Synthesizer", "Remove a synthesizer",OPCHK_IslaSynth,0,0,OPINV_ShedRemoveSynth,OPMOD_FinishOnData,L'🗴',0)
         ->UiDefine=laui_RemoveSynth;
         ->UiDefine=laui_RemoveSynth;
     laCreateOperatorType("LA_synth_play", "Play Synthesizer", "Play a synthesizer",OPCHK_IslaSynth,0,0,OPINV_laSynthPlay,0,0,0);
     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);{
     pc = laAddPropertyContainer("la_synth", "LaGUI Synthesizer", "LaGUI synthesizer", 0,0,sizeof(laSynth),lapost_Synth,0,2);{
         LA_PC_SYNTH=pc;
         LA_PC_SYNTH=pc;

+ 11 - 0
la_interface.h

@@ -1722,6 +1722,12 @@ STRUCTURE(laSynthNodeOutput){
 
 
 #include "miniaudio.h"
 #include "miniaudio.h"
 
 
+STRUCTURE(laAudioDevice){
+    laListItem Item;
+    int MiniAudioID;
+    laSafeString Name;
+};
+
 STRUCTURE(laAudio){
 STRUCTURE(laAudio){
     int AudioAny;
     int AudioAny;
     
     
@@ -1729,7 +1735,10 @@ STRUCTURE(laAudio){
     laSynth* CurrentSynth;
     laSynth* CurrentSynth;
 
 
     SYSLOCK AudioStatusLock;
     SYSLOCK AudioStatusLock;
+    ma_context MiniAudioContext;
     ma_device AudioDevice;
     ma_device AudioDevice;
+    laAudioDevice* UsingDevice;
+    laListHandle AudioDevices;
     laSynth* AudioEvalSynth;
     laSynth* AudioEvalSynth;
     real AudioFrameInterval;
     real AudioFrameInterval;
     real AudioEvalTime; uint64_t AudioEvalTotalSamples;
     real AudioEvalTime; uint64_t AudioEvalTotalSamples;
@@ -1738,8 +1747,10 @@ STRUCTURE(laAudio){
 
 
 
 
 int laget_SynthPlaying(laSynth* ss);
 int laget_SynthPlaying(laSynth* ss);
+void* laget_FirstAudioDevice(void* unused1,void* unused2);
 void* laget_FirstSynth(void* unused1,void* unused2);
 void* laget_FirstSynth(void* unused1,void* unused2);
 void laset_CurrentSynth(laAudio* a,laSynth* s);
 void laset_CurrentSynth(laAudio* a,laSynth* s);
+void laset_CurrentAudioDevice(laAudio* a,laAudioDevice* ad);
 
 
 void la_AudioPreFrame();
 void la_AudioPreFrame();
 
 

+ 2 - 0
resources/la_properties.c

@@ -1243,6 +1243,8 @@ void la_RegisterInternalProps(){
                 laAddSubGroup(p,"synths","Synthesizers","Synthesizers","la_synth",0,0,0,-1,0,0,0,0,0,0,offsetof(laAudio,Synths),0);
                 laAddSubGroup(p,"synths","Synthesizers","Synthesizers","la_synth",0,0,0,-1,0,0,0,0,0,0,offsetof(laAudio,Synths),0);
                 sp=laAddSubGroup(p, "current_synth", "Current Synthesizer", "Current synthesizer","la_synth",0,0,0,offsetof(laAudio,CurrentSynth),laget_FirstSynth,0,laget_ListNext,laset_CurrentSynth,0,0,0,LA_UDF_REFER);
                 sp=laAddSubGroup(p, "current_synth", "Current Synthesizer", "Current synthesizer","la_synth",0,0,0,offsetof(laAudio,CurrentSynth),laget_FirstSynth,0,laget_ListNext,laset_CurrentSynth,0,0,0,LA_UDF_REFER);
                 laSubGroupDetachable(sp,laget_FirstSynth,laget_ListNext);
                 laSubGroupDetachable(sp,laget_FirstSynth,laget_ListNext);
+                laAddSubGroup(p,"audio_devices","Audio Devices","Enumerated audio devices","la_audio_device",0,0,0,-1,0,0,0,0,0,0,offsetof(laAudio,AudioDevices),0);
+                laAddSubGroup(p, "current_audio_device", "Current Audio Device", "Current audio device","la_audio_device",0,0,0,offsetof(laAudio,UsingDevice),laget_FirstAudioDevice,0,laget_ListNext,laset_CurrentAudioDevice,0,0,0,LA_UDF_REFER);
             }
             }
         }
         }
 
 

+ 7 - 0
resources/la_templates.c

@@ -1279,6 +1279,13 @@ void laui_UserPreference(laUiList *uil, laPropPack *Base, laPropPack *OperatorIn
             laShowItemFull(muil, mcr, 0, "LA_refresh_controllers",0,"text=Refresh",0,0);
             laShowItemFull(muil, mcr, 0, "LA_refresh_controllers",0,"text=Refresh",0,0);
 #endif
 #endif
         }
         }
+        muil = laAddTabPage(bracket, "Audio");{
+            mc = laFirstColumn(muil); laSplitColumn(muil, mc, 0.5);
+            mcl = laLeftColumn(mc, 0); mcr = laRightColumn(mc, 0);
+            laShowLabel(muil,mc,"Audio Device:",0,0);
+            laShowItemFull(muil,mcl,0,"la.audio.current_audio_device",LA_WIDGET_COLLECTION_SELECTOR,0,laui_IdentifierOnly,0);
+            laShowItem(muil,mcr,0,"LA_refresh_audio_devices");
+        }
 
 
         muil = laAddTabPage(bracket, "Resource");{
         muil = laAddTabPage(bracket, "Resource");{
             //muil->HeightCoeff = -1;
             //muil->HeightCoeff = -1;