*/}}
Преглед изворни кода

Audio channel structure and ui

YimingWu пре 1 година
родитељ
комит
72d8f0db9c
3 измењених фајлова са 113 додато и 1 уклоњено
  1. 100 1
      la_audio.c
  2. 12 0
      la_interface.h
  3. 1 0
      resources/la_properties.c

+ 100 - 1
la_audio.c

@@ -24,6 +24,7 @@
 extern LA MAIN;
 
 laPropContainer* LA_PC_SYNTH;
+laPropContainer* LA_PC_CHANNEL;
 
 laNodeCategory* LA_NODE_CATEGORY_SYNTHESIZER;
 laNodeCategory* LA_NODE_CATEGORY_SYSTEM_SOUND;
@@ -634,7 +635,7 @@ int OPINV_ShedRemoveSynth(laOperator* a, laEvent* e){
     laSynth* ss=a->This?a->This->EndInstance:0; if(!ss)return LA_CANCELED;
     if(strSame(strGetArgumentString(a->ExtraInstructionsP,"confirm"),"true")){
         laRemoveSynth(ss);
-        laNotifyInstanceUsers(MAIN.Audio); laRecordAndPush(0,"la.audio","Remove la project", 0);
+        laNotifyInstanceUsers(MAIN.Audio); laRecordAndPush(0,"la.audio","Remove synthesizer", 0);
         return LA_FINISHED;
     }
     laEnableOperatorPanel(a,a->This,e->x,e->y,200,200,0,0,0,0,0,0,0,0,e);
@@ -658,6 +659,50 @@ int OPINV_laSynthPlay(laOperator* a, laEvent* e){
     return LA_FINISHED;
 }
 
+void laAudioEnsureChannelPtr(){
+    for(laAudioChannel* iac=MAIN.Audio->Channels.pFirst;iac;iac=iac->Item.pNext){
+        TNS_CLAMP(iac->ID,0,31);
+        MAIN.Audio->ChannelPtr[iac->ID]=iac;
+    }
+}
+laAudioChannel* laNewAudioChannel(char* Name){
+    laAudioChannel* ac=memAcquireHyper(sizeof(laAudioChannel)); lstAppendItem(&MAIN.Audio->Channels,ac);
+    strSafeSet(&ac->Name,Name); int has=0,i;
+    for(i=0;i<64;i++){
+        for(laAudioChannel* iac=MAIN.Audio->Channels.pFirst;iac;iac=iac->Item.pNext){ if(iac->ID==i){ has=1; break; } }
+    }
+    if(!has){ac->ID = i;}else{ac->ID=0;}
+    ac->Volume = 10.0f; laAudioEnsureChannelPtr();
+}
+void laRemoveAudioChannel(laAudioChannel* ac){
+    lstRemoveItem(&MAIN.Audio->Channels,ac); strSafeDestroy(&ac->Name);
+    memFree(ac); laAudioEnsureChannelPtr();
+}
+
+int OPCHK_IslaAudioChannel(laPropPack *This, laStringSplitor *ss){
+    if (This && This->EndInstance && la_EnsureSubTarget(This->LastPs->p,0) == LA_PC_CHANNEL) return 1;
+    return 0;
+}
+int OPINV_ShedNewAudioChannel(laOperator* a, laEvent* e){
+    laNewAudioChannel("Output");
+    laNotifyInstanceUsers(MAIN.Audio); laRecordAndPush(0,"la.audio","New channel", 0); // TODO: hint for laAudioEnsureChannelPtr
+    return LA_FINISHED;
+}
+int OPINV_ShedRemoveAudioChannel(laOperator* a, laEvent* e){
+    laAudioChannel*ac=a->This?a->This->EndInstance:0; if(!ac)return LA_CANCELED;
+    if(strSame(strGetArgumentString(a->ExtraInstructionsP,"confirm"),"true")){
+        laRemoveAudioChannel(ac); laNotifyInstanceUsers(MAIN.Audio); laRecordAndPush(0,"la.audio","Remove audio channel", 0);
+        return LA_FINISHED;
+    }
+    laEnableOperatorPanel(a,a->This,e->x,e->y,200,200,0,0,0,0,0,0,0,0,e);
+    return LA_RUNNING;
+}
+void laui_RemoveAudioChannel(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *UNUSED, int context){
+    laColumn* c=laFirstColumn(uil);
+    laShowItemFull(uil,c,This,"remove",0,"confirm=true;text=Confirm",0,0);
+}
+
+
 void lauidetached_Synthersizers(laPanel* p){
     la_MakeDetachedProp(p, "la.detached_view_switch", "detached");
     la_MakeDetachedProp(p, "la.audio.current_synth", "page");
@@ -704,6 +749,32 @@ void laui_Synthersizers(laUiList *uil, laPropPack *This, laPropPack *Extra, laCo
 
 #undef ADD_PAGE
 }
+void laui_AudioChannel(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *UNUSED, int context){
+    laColumn* c=laFirstColumn(uil); laSplitColumn(uil,c,0.3); laColumn* c1=laLeftColumn(c,1),*c2=laRightColumn(c,0); laUiItem* b;
+    
+    laShowHeightAdjuster(uil,c1,This,"__move",0);
+
+    laShowItem(uil,c2,This,"name");
+    b=laBeginRow(uil,c2,0,0);
+    laShowItem(uil,c2,This,"id")->Expand=1; laShowItem(uil,c,This,"remove")->Flags|=LA_UI_FLAGS_ICON;
+    laEndRow(uil,b);
+    laShowItem(uil,c2,This,"volume");
+
+    laShowSeparator(uil,c);
+}
+void laui_AudioChannels(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn *UNUSED, int context){
+    laColumn* c=laFirstColumn(uil);  laUiItem* b;
+
+    b=laBeginRow(uil,c,0,0);
+    laShowItem(uil,c,0,"LA_new_channel");
+    laEndRow(uil,b);
+    // if horizontal look:
+    // laUiItem* g=laMakeGroup(uil,c,"Racks",0);{ g->Flags|=/*LA_UI_FLAGS_NO_GAP|LA_UI_FLAGS_NO_DECAL|*/LA_UI_FLAGS_NODE_CONTAINER;
+    //     laUiList* gu=g->Page; laColumn* gc=laFirstColumn(gu); gu->HeightCoeff=-1; g->State=LA_UI_ACTIVE;
+    //     laShowItemFull(gu,gc,0,"la.audio.channels",0,0,laui_AudioChannel,0)->Expand=5;
+    // }
+    laShowItemFull(uil,c,0,"la.audio.channels",0,0,laui_AudioChannel,0);
+}
 
 void* laget_FirstAudioDevice(void* unused1,void* unused2){
     return MAIN.Audio->AudioDevices.pFirst;
@@ -725,10 +796,21 @@ void laset_CurrentSynth(laAudio* a,laSynth* s){
 void laset_CurrentAudioDevice(laAudio* a,laAudioDevice* ad){
     la_SelectAudioDevice(ad);
 }
+void laget_OutputSendChannelName(laSynthNodeOutput* n, char* str, char** target){
+    if(!MAIN.Audio||!MAIN.Audio->ChannelPtr[n->Send]) *target="-";
+    *target = SSTR(MAIN.Audio->ChannelPtr[n->Send]->Name);
+}
 void laset_QuantizeEnabledKeys(laSynthNodeQuantize* n, int index, int val_UNUSED){
     if(n->EnabledBits[index] & 0x1){ n->EnabledBits[index]=0; }
     else{ n->EnabledBits[index]=1; }
 }
+void laset_AudioChannelID(laAudioChannel* ac, int id){
+    ac->ID=id; laAudioEnsureChannelPtr();
+}
+void laset_AudioChannelMove(laAudioChannel* ac, int move){
+    if(move<0 && ac->Item.pPrev){ lstMoveUp(&MAIN.Audio->Channels, ac); laNotifyUsers("la.audio"); }
+    elif(move>0 && ac->Item.pNext){ lstMoveDown(&MAIN.Audio->Channels, ac); laNotifyUsers("la.audio"); }
+}
 
 void la_AudioPreFrame(){
     if(MAIN.GraphNeedsRebuild){ laRebuildSynthGraphs(); }
@@ -746,6 +828,7 @@ void laInitAudio(){
     laInitMiniAudio();
 
     laRegisterUiTemplate("LAUI_synthesizers","Synthesizers",laui_Synthersizers,lauidetached_Synthersizers,0,"Audio",0,0,0);
+    laRegisterUiTemplate("LAUI_audio_channels","Mixer",laui_AudioChannels,0,0,0,0,0,0);
 
     laCreateOperatorType("LA_new_synth", "New Synthesizer", "Add a synthesizer",0,0,0,OPINV_ShedNewSynth,0,'+',0);
     laCreateOperatorType("LA_remove_synth", "Remove Synthesizer", "Remove a synthesizer",OPCHK_IslaSynth,0,0,OPINV_ShedRemoveSynth,OPMOD_FinishOnData,L'🗴',0)
@@ -753,6 +836,10 @@ void laInitAudio(){
     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);
 
+    laCreateOperatorType("LA_new_channel", "New Channel", "Add an audio channel",0,0,0,OPINV_ShedNewAudioChannel,0,'+',0);
+    laCreateOperatorType("LA_remove_channel", "Remove Channel", "Remove an audio channel",OPCHK_IslaAudioChannel,0,0,OPINV_ShedRemoveAudioChannel,OPMOD_FinishOnData,L'🗴',0)
+        ->UiDefine=laui_RemoveAudioChannel;
+
     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);
     }
@@ -768,6 +855,16 @@ void laInitAudio(){
         laAddOperatorProperty(pc,"play","Play Synth", "Play synth", "LA_synth_play", 0, 0);
     }
 
+    pc = laAddPropertyContainer("la_audio_channel", "LaGUI Audio Channel", "LaGUI Audio Channel", 0,0,sizeof(laAudioChannel),0,0,2);{
+        LA_PC_CHANNEL=pc;
+        laAddStringProperty(pc,"name","Name","Name of the synthesizer",0,0,0,0,1,offsetof(laAudioChannel,Name),0,0,0,0,LA_AS_IDENTIFIER);
+        laAddIntProperty(pc,"id","ID","Identifier of this channel",0,0,0,31,0,0,0,0,offsetof(laAudioChannel,ID),0,laset_AudioChannelID,0,0,0,0,0,0,0,0,0);
+        //laAddIntProperty(pc,"id","ID","Identifier of this channel",0,0,0,31,0,0,0,0,offsetof(laAudioChannel,ID),0,laset_AudioChannelID,0,0,0,0,0,0,0,0,0);
+        laAddFloatProperty(pc,"volume","Volume","Volume of this channel",0,0,0,15,0,0.05,0,0,offsetof(laAudioChannel,Volume),0,0,0,0,0,0,0,0,0,0,0);
+        laAddOperatorProperty(pc,"remove","Remove Channel", "Remove this channel", "LA_remove_channel", L'🗴', 0);
+        laAddIntProperty(pc,"__move","Move Slider","Move Slider",LA_WIDGET_HEIGHT_ADJUSTER,0,0,0,0,0,0,0,0,0,laset_AudioChannelMove,0,0,0,0,0,0,0,0,LA_UDF_IGNORE);
+    }
+
     pc=laAddPropertyContainer("la_node_synth_fm", "FM OSC Node", "Osilliator node with frequency modulation",0,laui_FMNode,sizeof(laSynthNodeFM),lapost_Node,0,1);
     LA_PC_IDN_FM=pc; laPropContainerExtraFunctions(pc,0,0,0,0,laui_DefaultNodeOperationsPropUiDefine);
     laAddSubGroup(pc,"base","Base","Base node","la_base_node",0,0,0,0,0,0,0,0,0,0,0,LA_UDF_LOCAL);
@@ -823,6 +920,8 @@ void laInitAudio(){
     LA_PC_IDN_OUTPUT=pc; laPropContainerExtraFunctions(pc,0,0,0,0,laui_DefaultNodeOperationsPropUiDefine);
     laAddSubGroup(pc,"base","Base","Base node","la_base_node",0,0,0,0,0,0,0,0,0,0,0,LA_UDF_LOCAL);
     laAddSubGroup(pc,"in", "Input","Input sound","la_in_socket",0,0,0,offsetof(laSynthNodeOutput,In),0,0,0,0,0,0,0,LA_UDF_SINGLE);
+    laAddIntProperty(pc,"send","Send","Send to channel",0,0,0,128,0,0,0,0,offsetof(laSynthNodeOutput,Send),0,0,0,0,0,0,0,0,0,0,0);
+    laAddStringProperty(pc,"send_channel_name","Channel Name","Channel name of this send target",0,0,0,0,0,-1,0,laget_OutputSendChannelName,0,0,LA_READ_ONLY|LA_UDF_IGNORE);
 
     pc=laAddPropertyContainer("la_node_synth_envelope", "Envelope Node", "Sound envelope",0,laui_EnvelopeNode,sizeof(laSynthNodeEnvelope),lapost_Node,0,1);
     LA_PC_IDN_ENVELOPE=pc; laPropContainerExtraFunctions(pc,0,0,0,0,laui_DefaultNodeOperationsPropUiDefine);

+ 12 - 0
la_interface.h

@@ -1850,6 +1850,7 @@ STRUCTURE(laSynthNodeScope){
 STRUCTURE(laSynthNodeOutput){
     laBaseNode Base;
     laNodeInSocket* In;
+    int Send;
 };
 
 STRUCTURE(laSynthNodeEnvelope){
@@ -1874,6 +1875,14 @@ STRUCTURE(laSynthNodeQuantize){
 
 #include "miniaudio.h"
 
+STRUCTURE(laAudioChannel){
+    laListItem Item;
+    laSafeString* Name;
+    real Volume;
+    int ID;
+    int OutputChannel;
+};
+
 STRUCTURE(laAudioDevice){
     laListItem Item;
     int MiniAudioID;
@@ -1886,6 +1895,9 @@ STRUCTURE(laAudio){
     laListHandle Synths;
     laSynth* CurrentSynth;
 
+    laListHandle Channels;
+    laAudioChannel* ChannelPtr[32];
+
     SYSLOCK AudioStatusLock;
     ma_context MiniAudioContext;
     ma_device AudioDevice;

+ 1 - 0
resources/la_properties.c

@@ -1552,6 +1552,7 @@ void la_RegisterInternalProps(){
                 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);
+                laAddSubGroup(p,"channels","Channels","Audio channels","la_audio_channel",0,0,0,-1,0,0,0,0,0,0,offsetof(laAudio,Channels),0);
             }
         }