# -*- coding: utf-8 -*-
#
# plugins/AudioEndpoint/__init__.py
# 
# This file is a plugin for EventGhost.

import eg

eg.RegisterPlugin(
    name = "AudioEndpoint",
    guid = "{31DE576B-5938-4C0B-A0E2-64F9ADF02BF8}",
    author = "Sem;colon",
    version = "2.1.3",
    kind = "other",
    canMultiLoad = False,
    description = "This plugin can set the default audio render device and generates events when an audio endpoint changes!",
    url = "http://www.eventghost.net/forum/viewtopic.php?f=9&t=6213",
)

import AudioEndpointControl
from time import sleep

class MMNotificationClient(object):
    
    def __init__(self, plugin):
        self.plugin = plugin

    def OnDeviceStateChanged(self, AudioDevice, NewState):
        NewState=str(NewState).replace("DEVICE_STATE_","")
        self.plugin.TriggerEvent("State."+NewState+"."+AudioDevice.getName(),[AudioDevice.getId()])
        if NewState == "ACTIVE":
            self.plugin.ReInitAudioDevices()
    
    def OnDeviceRemoved(self, AudioDevice):
        self.plugin.TriggerEvent("DeviceRemoved."+AudioDevice.getName(),[AudioDevice.getId()])
        self.plugin.ReInitAudioDevices()

    def OnDeviceAdded(self, AudioDevice):
        self.plugin.TriggerEvent("DeviceAdded."+AudioDevice.getName(),[AudioDevice.getId()])
        self.plugin.ReInitAudioDevices()
    
    def OnDefaultDeviceChanged(self, flow, role, AudioDevice):
        self.plugin.TriggerEvent("Default."+str(flow)[1:]+"."+str(role)[1:]+"."+AudioDevice.getName(),[AudioDevice.getId()])
            
    def OnPropertyValueChanged(self, AudioDevice, key):
        if self.plugin.advancedEndpointEvents:
            property=u"{%8.08x-%4.04x-%4.04x-%2.02x%2.02x-%2.02x%2.02x%2.02x%2.02x%2.02x%2.02x}" % (key.fmtid.Data1, key.fmtid.Data2, key.fmtid.Data3,	2**8+key.fmtid.Data4[0], 2**8+key.fmtid.Data4[1],	2**8+key.fmtid.Data4[2], 2**8+key.fmtid.Data4[3],	2**8+key.fmtid.Data4[4], 2**8+key.fmtid.Data4[5],	2**8+key.fmtid.Data4[6], 2**8+key.fmtid.Data4[7])
            self.plugin.TriggerEvent("Property."+AudioDevice.getName(),[AudioDevice.getId(),property,int(key.pid)])
    
    
class AudioEndpointVolumeCallback(object):
    
    def __init__(self, plugin):
        self.plugin = plugin
    
    def OnNotify(self, Notify, AudioDevice):
        if self.plugin.AudioDeviceData[AudioDevice.getId()]["volume"] != Notify.MasterVolume:
            self.plugin.AudioDeviceData[AudioDevice.getId()]["volume"] = Notify.MasterVolume
            self.plugin.TriggerEvent("Volume."+AudioDevice.getName(), [AudioDevice.getId(), str(round(Notify.MasterVolume*100,2))])
        if self.plugin.AudioDeviceData[AudioDevice.getId()]["mute"] != Notify.Muted:  
            self.plugin.AudioDeviceData[AudioDevice.getId()]["mute"] = Notify.Muted
            if Notify.Muted:
                self.plugin.TriggerEvent("Mute."+AudioDevice.getName(), [AudioDevice.getId(), Notify.Muted])
            else:
                self.plugin.TriggerEvent("UnMute."+AudioDevice.getName(), [AudioDevice.getId(), Notify.Muted])

        
class AudioEndpoint(eg.PluginBase):
  
    class Text:
        eventBox = "Trigger events:"
        volumeEvents = "Volume or mute changes on an audio endpoint"
        endpointEvents = "Audio endpoint state changes"
        advancedEndpointEvents = "Advanced audio endpoint state changes (property changes)"
    
    
    def __init__(self):
        self.AddAction(SetRender, "SetRender", "Set Default Audio Render", "Sets the default audio render device.(by id)")
        self.AddAction(GetRender, "GetRender", "Get Default Audio Render", "Returns the ID of the current Default Audio Render", hidden=True)
        self.AddAction(SetCapture, "SetCapture", "Set Default Audio Capture", "Sets the default audio Capture device.(by id)")
        self.AddAction(GetCapture, "GetCapture", "Get Default Audio Capture", "Returns the ID of the current Default Audio Capture", hidden=True)
        self.AddAction(GetDefaultDevice, "GetDefaultDevice", "Get Default Audio Device", "Returns the ID and the name of the current Default Audio Device")
        self.AddAction(NextRender, "NextRender", "Next Default Audio Render", "Selects the next available Default Audio Render")
        self.AddAction(PreviousRender, "PreviousRender", "Previous Default Audio Render", "Selects previous available Default Audio Render")
        self.AddAction(NextCapture, "NextCapture", "Next Default Audio Capture", "Selects the next available Default Audio Capture")
        self.AddAction(PreviousCapture, "PreviousCapture", "Previous Default Audio Capture", "Selects previous available Default Audio Capture")
        self.AddAction(GetMute, "GetMute", "Get Mute", "Returns True if a specific audio endpoint is muted, and False if not")
        self.AddAction(SetMute, "SetMute", "Set Mute", "Set mute for a specific audio endpoint (ON, OFF or TOGGLE)")
        self.AddAction(GetVolume, "GetVolume", "Get Volume", "Returns the current volume of a specific audio endpoint")
        self.AddAction(SetVolume, "SetVolume", "Set Volume", "Set the volume for a specific audio endpoint. Can be absolute or relative")
        self.AddAction(GetDefaultMute, "GetDefaultMute", "Get Default Mute", "Returns True if the default audio endpoint is muted, and False if not")
        self.AddAction(SetDefaultMute, "SetDefaultMute", "Set Default Mute", "Set mute for the default audio endpoint (ON, OFF or TOGGLE)")
        self.AddAction(GetDefaultVolume, "GetDefaultVolume", "Get Default Volume", "Returns the current volume of the default audio endpoint")
        self.AddAction(SetDefaultVolume, "SetDefaultVolume", "Set Default Volume", "Set the volume for the default audio endpoint. Can be absolute or relative")
        self.registeredAudioDevices = []
        self.AudioDeviceData = {}

        
    def __start__(self, volumeEvents=True, endpointEvents=True, advancedEndpointEvents=False):
        self.volumeEvents=volumeEvents
        self.endpointEvents=endpointEvents
        self.advancedEndpointEvents=advancedEndpointEvents
        self.AudioDevices = AudioEndpointControl.AudioEndpoints()
        if endpointEvents:
            self.AudioDevices.RegisterCallback(MMNotificationClient(self))
        if self.ReInitAudioDevices():
            print "Audio Endpoint plugin started."
            for flow in [0,1]:
                for role in [0,1,2]:
                    try:
                        device=self.AudioDevices.GetDefault(role,flow)
                        flow2=AudioEndpointControl.EDataFlow[flow][1:]
                        role2=AudioEndpointControl.ERole[role][1:]
                        self.TriggerEvent("Default."+flow2+"."+role2+"."+device.getName(),[device.getId()])
                    except:
                        pass
                        

    def __stop__(self):
        for AudioDevice in self.registeredAudioDevices:
            AudioDevice.UnregisterControlChangeNotify()
        self.registeredAudioDevices = []
        if self.endpointEvents:
            self.AudioDevices.UnregisterCallback()
        print "Audio Endpoint plugin stopped."

        
    def __close__(self):
        print "Audio Endpoint plugin closed."

        
    def ReInitAudioDevices(self):
        self.AudioDeviceIDs = []
        self.AudioDeviceNames = []
        self.AudioDeviceFlows = []
        self.ReInitAudioDevicesList(0)
        self.ReInitAudioDevicesList(1)
        return True
        
    def ReInitAudioDevicesList(self, flow):
        for AudioDevice in self.AudioDevices.__iter__(flow):
            if self.volumeEvents and AudioDevice not in self.registeredAudioDevices:
                AudioDevice.RegisterControlChangeNotify(AudioEndpointVolumeCallback(self))
                self.registeredAudioDevices.append(AudioDevice)
            self.AudioDeviceIDs.append(AudioDevice.getId())
            self.AudioDeviceNames.append(AudioDevice.getName())
            self.AudioDeviceFlows.append(flow)
            if AudioDevice.getId() not in self.AudioDeviceData:
                self.AudioDeviceData[AudioDevice.getId()] = {"volume":None,"mute":None}
            if self.AudioDeviceData[AudioDevice.getId()]["volume"] != AudioDevice.GetMasterVolumeLevel():
                self.AudioDeviceData[AudioDevice.getId()]["volume"] = AudioDevice.GetMasterVolumeLevel()
                #self.TriggerEvent("Volume."+AudioDevice.getName(),[AudioDevice.getId(),str(round(AudioDevice.GetMasterVolumeLevel()*100,2))])
            if self.AudioDeviceData[AudioDevice.getId()]["mute"] != (AudioDevice.GetMute() == 1):  
                self.AudioDeviceData[AudioDevice.getId()]["mute"] = AudioDevice.GetMute() == 1
                #if AudioDevice.GetMute() == 1:
                #    self.TriggerEvent("Mute."+AudioDevice.getName(),[AudioDevice.getId(),AudioDevice.GetMute() == 1])
                #else:
                #    self.TriggerEvent("UnMute."+AudioDevice.getName(),[AudioDevice.getId(),AudioDevice.GetMute() == 1])
        return True
            
            
    def Configure(self, volumeEvents=True, endpointEvents=True, advancedEndpointEvents=False):
        text = self.Text
        panel = eg.ConfigPanel()
        wx_volumeEvents = wx.CheckBox(panel, -1, text.volumeEvents)
        wx_volumeEvents.SetValue(volumeEvents)
        wx_endpointEvents = wx.CheckBox(panel, -1, text.endpointEvents)
        wx_endpointEvents.SetValue(endpointEvents)
        wx_advancedEndpointEvents = wx.CheckBox(panel, -1, text.advancedEndpointEvents)
        wx_advancedEndpointEvents.SetValue(advancedEndpointEvents)
        eventBox = panel.BoxedGroup(
            text.eventBox,
            ("",wx_volumeEvents),
            ("",wx_endpointEvents),
            ("",wx_advancedEndpointEvents),
        )

        panel.sizer.Add(eventBox, 0, wx.EXPAND)
        
        while panel.Affirmed():
            panel.SetResult(
                wx_volumeEvents.GetValue(),
                wx_endpointEvents.GetValue(),
                wx_advancedEndpointEvents.GetValue(),
            )
    
            
class SetRender(eg.ActionBase):
    
    class Text:
        role = "Role:"
        setTo = "Set default to:"
    
    def __call__(self,target,role=0):
        try:
            self.plugin.AudioDevices.SetDefault(self.plugin.AudioDevices(target),role)
            return True
        except:
            eg.PrintError("AudioEndpoint SetRender: Device not found! "+str(target))
            return False
    
    def GetLabel(self, target="",role=0):
        try:
            target = self.plugin.AudioDevices(target).getName()
        except:
            target = "???"
        return target
        
    def all_indices(self, value, qlist):
        indices = []
        idx = -1
        while True:
            try:
                idx = qlist.index(value, idx+1)
                indices.append(idx)
            except ValueError:
                break
        return indices

    def Configure(self,target="",role=0):
        roles=["Console","Multimedia","Communications"]
        panel = eg.ConfigPanel(self)
        
        wx_role = wx.Choice(panel, -1, choices=roles)
        wx_role.SetSelection(role)
        st_role = panel.StaticText(self.Text.role)
        
        idx = self.all_indices(0, self.plugin.AudioDeviceFlows)        
        if target in self.plugin.AudioDeviceIDs and self.plugin.AudioDeviceIDs.index(target) in idx:
            target = idx.index(self.plugin.AudioDeviceIDs.index(target))
        else:
            target = 0
        wx_setTo = wx.Choice(panel, -1, choices= [row for row in self.plugin.AudioDeviceNames if self.plugin.AudioDeviceFlows[self.plugin.AudioDeviceNames.index(row)] == 0]  )
        wx_setTo.SetSelection(target)
        st_setTo = panel.StaticText(self.Text.setTo)
        
        panel.AddLine(st_role,wx_role)
        panel.AddLine(st_setTo,wx_setTo)

        while panel.Affirmed():
            panel.SetResult(self.plugin.AudioDeviceIDs[idx[wx_setTo.GetCurrentSelection()]],wx_role.GetCurrentSelection())    
    

class GetRender(eg.ActionBase):
    
    def __call__(self):
        return self.plugin.AudioDevices.GetDefault(0,0).getId() 

class SetCapture(eg.ActionBase):
    
    class Text:
        role = "Role:"
        setTo = "Set default to:"
    
    def __call__(self,target,role=0):
        try:
            self.plugin.AudioDevices.SetDefault(self.plugin.AudioDevices(target),role)
            return True
        except:
            eg.PrintError("AudioEndpoint SetRender: Device not found! "+str(target))
            return False
    
    def GetLabel(self, target="",role=0):
        try:
            target = self.plugin.AudioDevices(target).getName()
        except:
            target = "???"
        return target

    def all_indices(self, value, qlist):
        indices = []
        idx = -1
        while True:
            try:
                idx = qlist.index(value, idx+1)
                indices.append(idx)
            except ValueError:
                break
        return indices

    def Configure(self,target="",role=0):
        roles=["Console","Multimedia","Communications"]
        panel = eg.ConfigPanel(self)
        
        wx_role = wx.Choice(panel, -1, choices=roles)
        wx_role.SetSelection(role)
        st_role = panel.StaticText(self.Text.role)
        
        idx = self.all_indices(1, self.plugin.AudioDeviceFlows)        
        if target in self.plugin.AudioDeviceIDs and self.plugin.AudioDeviceIDs.index(target) in idx:
            target = idx.index(self.plugin.AudioDeviceIDs.index(target))
        else:
            target = 0
        wx_setTo = wx.Choice(panel, -1, choices= [row for row in self.plugin.AudioDeviceNames if self.plugin.AudioDeviceFlows[self.plugin.AudioDeviceNames.index(row)] == 1]  )
        wx_setTo.SetSelection(target)
        st_setTo = panel.StaticText(self.Text.setTo)
        
        panel.AddLine(st_role,wx_role)
        panel.AddLine(st_setTo,wx_setTo)

        while panel.Affirmed():
            panel.SetResult(self.plugin.AudioDeviceIDs[idx[wx_setTo.GetCurrentSelection()]],wx_role.GetCurrentSelection())    


class GetCapture(eg.ActionBase):
    
    def __call__(self):
        return self.plugin.AudioDevices.GetDefault(0,1).getId() 


class GetDefaultDevice(eg.ActionBase):
    
    class Text:
        flow = "Flow:"
        role = "Role:"
    
    def __call__(self,role=0,flow=0):
        try:
            device = self.plugin.AudioDevices.GetDefault(role,flow)
            return {"id":device.getId(),"name":device.getName()}
        except:
            eg.PrintError("AudioEndpoint GetDefaultDevice: Default device not found!")
            return False
        
    def Configure(self,role=0,flow=0):
        flows=["Render","Capture"]
        roles=["Console","Multimedia","Communications"]
        panel = eg.ConfigPanel(self)
        
        wx_role = wx.Choice(panel, -1, choices=roles)
        wx_role.SetSelection(role)
        st_role = panel.StaticText(self.Text.role)
        
        wx_flow = wx.Choice(panel, -1, choices=flows)
        wx_flow.SetSelection(flow)
        st_flow = panel.StaticText(self.Text.flow)
        
        panel.AddLine(st_role,wx_role)
        panel.AddLine(st_flow,wx_flow)

        while panel.Affirmed():
            panel.SetResult(wx_role.GetCurrentSelection(),wx_flow.GetCurrentSelection())    
        
        
class NextRender(eg.ActionBase):
    
    class Text:
        role = "Role:"
    
    def __call__(self,role=0):
        oldIndex = self.plugin.AudioDeviceIDs.index(self.plugin.AudioDevices.GetDefault(role,0).getId())
        i=oldIndex+1
        while i!=oldIndex:
            if i<len(self.plugin.AudioDeviceIDs) and self.plugin.AudioDeviceFlows[i] == 0:
                target = self.plugin.AudioDeviceIDs[i]
                self.plugin.AudioDevices.SetDefault(self.plugin.AudioDevices(target),role)
                return True
            if i>=len(self.plugin.AudioDeviceIDs):
                i=0
            else:
                i+=1
        eg.PrintError("AudioEndpoint NextRender: No (other) selectable Render!")
        return False

    def Configure(self,role=0):
        roles=["Console","Multimedia","Communications"]
        panel = eg.ConfigPanel(self)
        
        wx_role = wx.Choice(panel, -1, choices=roles)
        wx_role.SetSelection(role)
        st_role = panel.StaticText(self.Text.role)
        
        panel.AddLine(st_role,wx_role)

        while panel.Affirmed():
            panel.SetResult(wx_role.GetCurrentSelection())    
    
    
class PreviousRender(eg.ActionBase):
        
    class Text:
        role = "Role:"
    
    def __call__(self,role=0):
        oldIndex = self.plugin.AudioDeviceIDs.index(self.plugin.AudioDevices.GetDefault(role,0).getId())
        i=oldIndex-1
        while i!=oldIndex:
            if i>=0 and self.plugin.AudioDeviceFlows[i] == 1:
                target = self.plugin.AudioDeviceIDs[i]
                self.plugin.AudioDevices.SetDefault(self.plugin.AudioDevices(target),role)
                return True
            if i<=0:
                i=len(self.plugin.AudioDeviceIDs)-1
            else:
                i-=1
        eg.PrintError("AudioEndpoint PreviousRender: No (other) selectable Render!")
        return False

    def Configure(self,role=0):
        roles=["Console","Multimedia","Communications"]
        panel = eg.ConfigPanel(self)
        
        wx_role = wx.Choice(panel, -1, choices=roles)
        wx_role.SetSelection(role)
        st_role = panel.StaticText(self.Text.role)
        
        panel.AddLine(st_role,wx_role)

        while panel.Affirmed():
            panel.SetResult(wx_role.GetCurrentSelection())

            
class GetMute(eg.ActionBase):
    
    class Text:
        device="Device:"
        
    def __call__(self, deviceId=-1):
        try:
            targetDevice = self.plugin.AudioDevices(deviceId)
        except:
            eg.PrintError("AudioEndpoint GetMute: Device not found! "+str(deviceId))
            return None
        return targetDevice.GetMute() == 1
    
    def GetLabel(self, target):
        try:
            target = "for " + self.plugin.AudioDevices(target).getName()
        except:
            target = "???"
        return self.name + " " + target

    def Configure(self, deviceId=-1):
        panel = eg.ConfigPanel(self)
        
        if deviceId in self.plugin.AudioDeviceIDs:
            target = self.plugin.AudioDeviceIDs.index(deviceId)
        else:
            target = 0
        wx_device = wx.Choice(panel, -1, choices=self.plugin.AudioDeviceNames)
        wx_device.SetSelection(target)
        st_device = panel.StaticText(self.Text.device)
        
        panel.AddLine(st_device,wx_device)

        while panel.Affirmed():
            panel.SetResult(self.plugin.AudioDeviceIDs[wx_device.GetCurrentSelection()])
                    
                    
class SetMute(eg.ActionBase):
    
    class Text:
        device = "Device:"
        state  = "State:"
    
    def __call__(self, deviceId, targetState):
        try:
            targetDevice = self.plugin.AudioDevices(deviceId)
        except:
            eg.PrintError("AudioEndpoint SetMute: Device not found! "+str(deviceId))
            return False
        if targetState==1:
            targetDevice.SetMute(True)
        elif targetState==0:
            targetDevice.SetMute(False)
        else:
            targetDevice.SetMute(targetDevice.GetMute() == 0)
        return True
    
    def GetLabel(self, target, targetState=0):
        states=["OFF","ON","TOGGLE"]
        try:
            target = states[targetState] + " on " + self.plugin.AudioDevices(target).getName()
        except:
            target = "???"
        return self.name + " " + target
        
    def Configure(self, deviceId="", targetState=0):
        states=["OFF","ON","TOGGLE"]
        panel = eg.ConfigPanel(self)
        
        wx_state = wx.Choice(panel, -1, choices=states)
        wx_state.SetSelection(targetState)
        st_state = panel.StaticText(self.Text.state)
        
        if deviceId in self.plugin.AudioDeviceIDs:
            target = self.plugin.AudioDeviceIDs.index(deviceId)
        else:
            target = 0
        wx_device = wx.Choice(panel, -1, choices=self.plugin.AudioDeviceNames)
        wx_device.SetSelection(target)
        st_device = panel.StaticText(self.Text.device)
        
        panel.AddLine(st_device,wx_device)
        panel.AddLine(st_state,wx_state)

        while panel.Affirmed():
            panel.SetResult(self.plugin.AudioDeviceIDs[wx_device.GetCurrentSelection()],wx_state.GetCurrentSelection())
            
            
class GetVolume(eg.ActionBase):
    
    class Text:
        device="Device:"
        
    def __call__(self, deviceId=-1):
        try:
            targetDevice = self.plugin.AudioDevices(deviceId)
        except:
            eg.PrintError("AudioEndpoint GetVolume: Device not found! "+str(deviceId))
            return None
        return round(targetDevice.GetMasterVolumeLevel()*100,2)
        
    def GetLabel(self, target):
        try:
            target = "for " + self.plugin.AudioDevices(target).getName()
        except:
            target = "???"
        return self.name + " " + target
        
    def Configure(self, deviceId=-1):
        panel = eg.ConfigPanel(self)
        
        if deviceId in self.plugin.AudioDeviceIDs:
            target = self.plugin.AudioDeviceIDs.index(deviceId)
        else:
            target = 0
        wx_device = wx.Choice(panel, -1, choices=self.plugin.AudioDeviceNames)
        wx_device.SetSelection(target)
        st_device = panel.StaticText(self.Text.device)
        
        panel.AddLine(st_device,wx_device)

        while panel.Affirmed():
            panel.SetResult(self.plugin.AudioDeviceIDs[wx_device.GetCurrentSelection()])
                    
                    
class SetVolume(eg.ActionBase):
    
    class Text:
        device = "Device:"
        relative = "Relative"
        level = "Level:"
    
    def __call__(self, deviceId, level, relative=False):
        try:
            targetDevice = self.plugin.AudioDevices(deviceId)
        except:
            eg.PrintError("AudioEndpoint SetVolume: Device not found! "+str(deviceId))
            return False
        targetVolume=0.0
        if relative:
            targetVolume=round(targetDevice.GetMasterVolumeLevel()*100,2)+level
        else:
            targetVolume=level
        if targetVolume>100:
            targetVolume=100.0
        elif targetVolume<0:
            targetVolume=0.0
        targetDevice.SetMasterVolumeLevel(targetVolume/100)
        return True
        
    def GetLabel(self, target, level, relative=False):
        try:
            if relative:
                target = "Relative by " + str(level) + " on " + self.plugin.AudioDevices(target).getName()
            else:
                target = "to " + str(level) + " on " + self.plugin.AudioDevices(target).getName()
        except:
            target = "???"
        return self.name + " " + target
        
    def Configure(self, deviceId="", level=0.0, relative=False):
        panel = eg.ConfigPanel(self)
        
        if deviceId in self.plugin.AudioDeviceIDs:
            target = self.plugin.AudioDeviceIDs.index(deviceId)
        else:
            target = 0
        wx_device = wx.Choice(panel, -1, choices=self.plugin.AudioDeviceNames)
        wx_device.SetSelection(target)
        st_device = panel.StaticText(self.Text.device)
        
        wx_level = eg.SpinNumCtrl(panel, -1, level, min=-100.0, max=100.0)
        st_level = panel.StaticText(self.Text.level)
        
        wx_relative = wx.CheckBox(panel, -1, self.Text.relative)
        wx_relative.SetValue(relative)
        st_relative = panel.StaticText("")
        
        panel.AddLine(st_device,wx_device)
        panel.AddLine(st_level,wx_level)
        panel.AddLine(st_relative,wx_relative)

        while panel.Affirmed():
            panel.SetResult(self.plugin.AudioDeviceIDs[wx_device.GetCurrentSelection()],wx_level.GetValue(),wx_relative.GetValue())

class GetDefaultMute(eg.ActionBase):
    
    class Text:
        flow = "Flow:"
        role = "Role:"
        
    def __call__(self,role=0,flow=0):
        try:
            targetDevice = self.plugin.AudioDevices.GetDefault(role,flow)
        except:
            eg.PrintError("AudioEndpoint GetMute: Device not found!")
            return None
        return targetDevice.GetMute() == 1
    
    def GetLabel(self, role=0, flow=0, targetState=0):
        flows=["Render","Capture"]
        roles=["Console","Multimedia","Communications"]
        states=["OFF","ON","TOGGLE"]
        try:
            target = "on " + flows[flow] + " - " + roles[role]
        except:
            target = "???"
        return self.name + " " + target
    
    def Configure(self,role=0,flow=0):
        flows=["Render","Capture"]
        roles=["Console","Multimedia","Communications"]
        panel = eg.ConfigPanel(self)
        
        wx_role = wx.Choice(panel, -1, choices=roles)
        wx_role.SetSelection(role)
        st_role = panel.StaticText(self.Text.role)
        
        wx_flow = wx.Choice(panel, -1, choices=flows)
        wx_flow.SetSelection(flow)
        st_flow = panel.StaticText(self.Text.flow)
        
        panel.AddLine(st_role,wx_role)
        panel.AddLine(st_flow,wx_flow)

        while panel.Affirmed():
            panel.SetResult(wx_role.GetCurrentSelection(),wx_flow.GetCurrentSelection())    

class SetDefaultMute(eg.ActionBase):
    
    class Text:
        flow = "Flow:"
        role = "Role:"
        state  = "State:"
    
    def __call__(self, role,flow, targetState):
        try:
            targetDevice = self.plugin.AudioDevices.GetDefault(role,flow)
        except:
            eg.PrintError("AudioEndpoint SetMute: Device not found! "+str(deviceId))
            return False
        if targetState==1:
            targetDevice.SetMute(True)
        elif targetState==0:
            targetDevice.SetMute(False)
        else:
            targetDevice.SetMute(targetDevice.GetMute() == 0)
        return True
    
    def GetLabel(self, role=0, flow=0, targetState=0):
        flows=["Render","Capture"]
        roles=["Console","Multimedia","Communications"]
        states=["OFF","ON","TOGGLE"]
        try:
            target = states[targetState] + " on " + flows[flow] + " - " + roles[role]
        except:
            target = "???"
        return self.name + " " + target
    
    def Configure(self, role=0, flow=0, targetState=0):
        flows=["Render","Capture"]
        roles=["Console","Multimedia","Communications"]
        states=["OFF","ON","TOGGLE"]
        panel = eg.ConfigPanel(self)
        
        wx_role = wx.Choice(panel, -1, choices=roles)
        wx_role.SetSelection(role)
        st_role = panel.StaticText(self.Text.role)
        
        wx_flow = wx.Choice(panel, -1, choices=flows)
        wx_flow.SetSelection(flow)
        st_flow = panel.StaticText(self.Text.flow)
        
        wx_state = wx.Choice(panel, -1, choices=states)
        wx_state.SetSelection(targetState)
        st_state = panel.StaticText(self.Text.state)
        
        panel.AddLine(st_role,wx_role)
        panel.AddLine(st_flow,wx_flow)
        panel.AddLine(st_state,wx_state)
        
        while panel.Affirmed():
            panel.SetResult(wx_role.GetCurrentSelection(),wx_flow.GetCurrentSelection(),wx_state.GetCurrentSelection())

class GetDefaultVolume(eg.ActionBase):
    
    class Text:
        flow = "Flow:"
        role = "Role:"
        
    def __call__(self, role=0, flow=0):
        try:
            targetDevice = self.plugin.AudioDevices.GetDefault(role,flow)
        except:
            eg.PrintError("AudioEndpoint GetVolume: Device not found! "+str(deviceId))
            return None
        return round(targetDevice.GetMasterVolumeLevel()*100,2)
        
    def GetLabel(self, target):
        flows=["Render","Capture"]
        roles=["Console","Multimedia","Communications"]
        try:
            target = "for " + flows[flow] + " - " + roles[role]
        except:
            target = "???"
        return self.name + " " + target
        
    def Configure(self,role=0,flow=0):
        flows=["Render","Capture"]
        roles=["Console","Multimedia","Communications"]
        panel = eg.ConfigPanel(self)
        
        wx_role = wx.Choice(panel, -1, choices=roles)
        wx_role.SetSelection(role)
        st_role = panel.StaticText(self.Text.role)
        
        wx_flow = wx.Choice(panel, -1, choices=flows)
        wx_flow.SetSelection(flow)
        st_flow = panel.StaticText(self.Text.flow)
        
        panel.AddLine(st_role,wx_role)
        panel.AddLine(st_flow,wx_flow)
        
        while panel.Affirmed():
            panel.SetResult(wx_role.GetCurrentSelection(),wx_flow.GetCurrentSelection())    

class SetDefaultVolume(eg.ActionBase):
    
    class Text:
        flow = "Flow:"
        role = "Role:"
        relative = "Relative"
        level = "Level:"
    
    def __call__(self, role, flow, level, relative=False):
        try:
            targetDevice = self.plugin.AudioDevices.GetDefault(role,flow)
        except:
            eg.PrintError("AudioEndpoint SetVolume: Device not found! "+str(deviceId))
            return False
        targetVolume=0.0
        if relative:
            targetVolume=round(targetDevice.GetMasterVolumeLevel()*100,2)+level
        else:
            targetVolume=level
        if targetVolume>100:
            targetVolume=100.0
        elif targetVolume<0:
            targetVolume=0.0
        targetDevice.SetMasterVolumeLevel(targetVolume/100)
        return True
        
    def GetLabel(self, role, flow, level, relative=False):
        flows=["Render","Capture"]
        roles=["Console","Multimedia","Communications"]
        try:
            if relative:
                target = "Relative by " + str(level) + " on " + flows[flow] + " - " + roles[role]
            else:
                target = "to " + str(level) + " on " + + flows[flow] + " - " + roles[role]
        except:
            target = "???"
        return self.name + " " + target
        
    def Configure(self, role=0, flow=0, level=0.0, relative=False):
        flows=["Render","Capture"]
        roles=["Console","Multimedia","Communications"]
        panel = eg.ConfigPanel(self)
        
        wx_role = wx.Choice(panel, -1, choices=roles)
        wx_role.SetSelection(role)
        st_role = panel.StaticText(self.Text.role)
        
        wx_flow = wx.Choice(panel, -1, choices=flows)
        wx_flow.SetSelection(flow)
        st_flow = panel.StaticText(self.Text.flow)
        
        wx_level = eg.SpinNumCtrl(panel, -1, level, min=-100.0, max=100.0)
        st_level = panel.StaticText(self.Text.level)
        
        wx_relative = wx.CheckBox(panel, -1, self.Text.relative)
        wx_relative.SetValue(relative)
        st_relative = panel.StaticText("")
        
        panel.AddLine(st_role,wx_role)
        panel.AddLine(st_flow,wx_flow)
        panel.AddLine(st_level,wx_level)
        panel.AddLine(st_relative,wx_relative)
        
        while panel.Affirmed():
            panel.SetResult(wx_role.GetCurrentSelection(),wx_flow.GetCurrentSelection(),wx_level.GetValue(),wx_relative.GetValue())

class NextCapture(eg.ActionBase):
    
    class Text:
        role = "Role:"
    
    def __call__(self,role=0,flow=0):
        oldIndex = self.plugin.AudioDeviceIDs.index(self.plugin.AudioDevices.GetDefault(role,1).getId())
        i=oldIndex+1
        while i!=oldIndex:
            if i<len(self.plugin.AudioDeviceIDs) and self.plugin.AudioDeviceFlows[i] == 0:
                    target = self.plugin.AudioDeviceIDs[i]
                    self.plugin.AudioDevices.SetDefault(self.plugin.AudioDevices(target),role)
                    return True
            if i>=len(self.plugin.AudioDeviceIDs):
                i=0
            else:
                i+=1
        eg.PrintError("AudioEndpoint NextRender: No (other) selectable Render!")
        return False

    def Configure(self,role=0,flow=0):
        roles=["Console","Multimedia","Communications"]
        panel = eg.ConfigPanel(self)
        
        wx_role = wx.Choice(panel, -1, choices=roles)
        wx_role.SetSelection(role)
        st_role = panel.StaticText(self.Text.role)
        
        panel.AddLine(st_role,wx_role)

        while panel.Affirmed():
            panel.SetResult(wx_role.GetCurrentSelection())    
    
    
class PreviousCapture(eg.ActionBase):
        
    class Text:
        role = "Role:"
    
    def __call__(self,role=1):
        oldIndex = self.plugin.AudioDeviceIDs.index(self.plugin.AudioDevices.GetDefault(role,1).getId())
        i=oldIndex-1
        while i!=oldIndex:
            if i>=0 and self.plugin.AudioDeviceFlows[i] == 1:
                target = self.plugin.AudioDeviceIDs[i]
                self.plugin.AudioDevices.SetDefault(self.plugin.AudioDevices(target),role)
                return True
            if i<=0:
                i=len(self.plugin.AudioDeviceIDs)-1
            else:
                i-=1
        eg.PrintError("AudioEndpoint PreviousRender: No (other) selectable Render!")
        return False

    def Configure(self,role=0):
        roles=["Console","Multimedia","Communications"]
        panel = eg.ConfigPanel(self)
        
        wx_role = wx.Choice(panel, -1, choices=roles)
        wx_role.SetSelection(role)
        st_role = panel.StaticText(self.Text.role)
        
        panel.AddLine(st_role,wx_role)

        while panel.Affirmed():
            panel.SetResult(wx_role.GetCurrentSelection())    
			
			