Core Audio Plugin

Questions and comments specific to a particular plugin should go here.
User avatar
kgschlosser
Site Admin
Posts: 4803
Joined: Fri Jun 05, 2015 5:43 am
Location: Rocky Mountains, Colorado USA

Core Audio Plugin

Post by kgschlosser » Tue Aug 06, 2019 4:05 am

Core Audio
Inspired by the AudioEndpoint plugin
v0.4.0a

EventGhost 0.5.0 and newer

This plugin is very much still a work in progress. If you encounter any problems or undesired behavior please follow the template below for reporting an issue to me.

Trouble Report Template

Code: Select all

Windows Version: {10}
Windows Build: {1806}

Description of problem: Please provide as much detail as possible. 
    If the problem can be recreated then describe the steps needed to reproduce the issue.
    If there is not an error and you are experiencing undesired behavior. Explain what is happening and then tell me what is supposed to be happening.
    
Error (if any):
[ code ]
If there is an error then copy the error and paste it here. I need all lines of the error. 
Make sure you remove the spaces in the code tag above and below the error.
[ /code ]

Fix:
    [ code ]
    If you happen to have fixed the issue then please paste the code here. remove the spaces in the tags please.
    [ /code ]
This plugin was inspired by the Audio Endpoint plugin made by sem;colon and Jonib.


Events:
CoreAudio.{DEVICE NAME}.{ENDPOINT NAME}.Session.{SESSION NAME}.Created
CoreAudio.{DEVICE NAME}.{ENDPOINT NAME}.{SESSION NAME}.NameChanged
CoreAudio.{DEVICE NAME}.{ENDPOINT NAME}.{SESSION NAME}.GroupChanged
CoreAudio.{DEVICE NAME}.{ENDPOINT NAME}.{SESSION NAME}.IconChanged
CoreAudio.{DEVICE NAME}.{ENDPOINT NAME}.{SESSION NAME}.Disconnected

CoreAudio.{DEVICE NAME}.{ENDPOINT NAME}.{SESSION NAME}.Volume.{0.0000 - 100.0000}
CoreAudio.{DEVICE NAME}.{ENDPOINT NAME}.{SESSION NAME}.MuteOn
CoreAudio.{DEVICE NAME}.{ENDPOINT NAME}.{SESSION NAME}.MuteOff

CoreAudio.{DEVICE NAME}.{ENDPOINT NAME}.{SESSION NAME}.AudioPlayback.Started
CoreAudio.{DEVICE NAME}.{ENDPOINT NAME}.{SESSION NAME}.AudioPlayback.Stopped
CoreAudio.{DEVICE NAME}.{ENDPOINT NAME}.{SESSION NAME}.AudioPlayback.Expired

CoreAudio.{DEVICE NAME}.{ENDPOINT NAME}.Volume.{0.0000 - 100.0000}
CoreAudio.{DEVICE NAME}.{ENDPOINT NAME}.MuteOff
CoreAudio.{DEVICE NAME}.{ENDPOINT NAME}.MuteOn
CoreAudio.{DEVICE NAME}.{ENDPOINT NAME}.Channel.{CHANNEL NUMBER}.Volume.{0.0000 - 100.0000}

CoreAudio.Device.{DEVICE NAME}.Added
CoreAudio.Device.{DEVICE NAME}.Removed

CoreAudio.{DEVICE NAME}.{ENDPOINT NAME}.Default.Render
CoreAudio.{DEVICE NAME}.{ENDPOINT NAME}.Default.Capture
CoreAudio.{DEVICE NAME}.{ENDPOINT NAME}.Default.All

This plugin triggers events for the audio starting and stopping, part for the event is going to be the name of the application causing the event.

This is a little twist for ya. This plugin does not have actions in the traditional sense. The actions are not located under the plugin. This plugin extends the System plugin and overrides the volume actions for the system plugin.

Here is a list of the actions again remember these actions are going to show up under the System plugin.

with any of the volume actions you have a relative and an absolute. relative means you want to increase or decrease the volume from it's current level. so say you have the volume at 30% and you set 10% in one of the relative actions. it is going to make the volume 40%

absolute is whatever you set in the action that is going to be the new volume level.

GetEndpointVolume
SetEndpointVolumeAbsolute
SetEndpointVolumeRelative

You now have volume control over each individual channel. so if you wanted to only turn down you subwoofer.. you can now do that
GetEndpointChannelVolume
SetEndpointChannelVolumeAbsolute
SetEndpointChannelVolumeRelative

IsDeviceAttached
IsDeviceEnabled

GetEndpointMute
SetEndpointMute
ToggleEndpointMute

IsPlaybackEndpointActive

IsDefaultPlaybackEndpoint
GetDefaultPlaybackEndpoint
SetDefaultPlaybackEndpoint

IsDefaultRecordingEndpoint
GetDefaultRecordingEndpoint
SetDefaultRecordingEndpoint

I need to go over the importance of the IsDeviceAttached action. This is for the people that are running EG on a remote PC and administer it via RDP.
I need to explain what the problem is and then how this next action fixes that issue.

Here is the setup.
You have a PC running EG that you set up so you can RDP into it for administrative purposes.

you set an action to change the volume. This is all working as it should until you RDP into the computer. Then the bad things start to happen. Let me explain why bad things happen and then you will understand why this action is so important.
So when a single user is signed into Windows that user has direct access to the devices (kind of). When you sign in via RDP because you are not physically at that computer you cannot have direct access to the device. Windows sets up a virtual device that acts as a go between. this is the device that shows up instead of the actual device. Because this takes place when a macro runs to say change the volume you will get an error. The error is a wee bit more complex but that is the quick and dirty version of it.

This action allows you to check to see if the device exists before doing anything to it. This is an example of how to set it up

Code: Select all

macro 1:
    some_event
    IsDeviceAttached
    Jump If to Macro 2 with no return
    SetEndpointVolumeAbsolute (Virtual sound device)
    
macro 2:
     SetEndpointVolumeAbsolute (Physical sound device)
Now you can see how this is going to work to solve that issue!

**UPDATED**

version 0.3.0a
[*] adds action PlaybackEndpointHasOutput - checks if the endpoint is currently outputting audio. there is a low volume threshold you can set
[*] adds action RecordingEndpointHasInput - check if a capture endpoint is receiving audio, there is a low volume threshold you can set.

version 0.3.2a
[*] fixes traceback reported by @gibman viewtopic.php?p=53559#p53559
[*] Adds plugin description

version 0.4.0a
[*] adds events for audio output detection and input detection events are as follows
  • CoreAudio.{DEVICE NAME}.{ENDPOINT NAME}.AudioOutput.Started
  • CoreAudio.{DEVICE NAME}.{ENDPOINT NAME}.AudioOutput.Stopped
  • CoreAudio.{DEVICE NAME}.{ENDPOINT NAME}.AudioInput.Started
  • CoreAudio.{DEVICE NAME}.{ENDPOINT NAME}.AudioInput.Stopped
this detection process has a 1 second interval between checks and it also has a threshold of 2% to eliminate any kind of static.
Attachments
CoreAudio-0.4.0a.egplugin
(136.73 KiB) Downloaded 9 times
CoreAudio-0.3.2a.egplugin
(136.31 KiB) Downloaded 6 times
CoreAudio-0.3.0a.egplugin
(135.65 KiB) Downloaded 9 times
CoreAudio-0.2.0a.egplugin
(135.29 KiB) Downloaded 9 times
If you like the work I have been doing then feel free to Image

jonib
Plugin Developer
Posts: 1318
Joined: Thu Mar 26, 2009 9:33 pm
Location: Sweden

Re: Core Audio Plugin

Post by jonib » Tue Aug 06, 2019 7:42 am

Very interesting, hopefully I can try it out soon.
kgschlosser wrote:
Tue Aug 06, 2019 4:05 am
This plugin triggers events for the audio starting and stopping, part for the event is going to be the name of the application causing the event.
This is why I started my own audio library was to get these events, but I never got to that point :cry:

jonib
XBMC2 plugin to control XBMC. If you want to flatter me Image

User avatar
kgschlosser
Site Admin
Posts: 4803
Joined: Fri Jun 05, 2015 5:43 am
Location: Rocky Mountains, Colorado USA

Re: Core Audio Plugin

Post by kgschlosser » Tue Aug 06, 2019 11:52 am

Ya know.. the funny thing is.. that is not supposed to work. I am not sure as to why I am getting notifications for the audio playback from other sessions it kind of just happened.

But it is there and I know this is something many people have wanted to have. Before I made this I did quite a bit of research on how to achieve this one specific feature and the only solution I had come up with is to use the loopback so the output comes back in and then listen to the incoming stream for sound. This would only be able to tell you if something was playing and not where it is being played from. But by some hole I managed to find (I still have not figured out where it is) it ended up giving that feature when I didn't expect it.

Now I remember the purpose for the session notifications. An application can have more then a single audio session if it likes. Microsoft put into place the session notifications to make it easier for an application to monitor what is happening in each session. So an application does not have to have a polling loop to get updates from a session. It is not supposed to bleed into other applications like it has. I have something coded wrong (maybe right) somewhere that caused it i'll be damned if i can figure out where. It could be a GUID for an interface. or my method order for an interface is incorrect. or does not have the correct arguments.. who knows.
If you like the work I have been doing then feel free to Image

gibman
Posts: 4
Joined: Thu Aug 08, 2019 5:55 pm

Re: Core Audio Plugin

Post by gibman » Thu Aug 08, 2019 6:04 pm

I remoting my eventghost host using teamview, which does not have the same audio implications as RDP does.

I am also using vbcable drivers as a virtual soundcard.
https://www.vb-audio.com/Cable/

The PC is used in combination with tuneblade airfoil etc.

no events are received when starting stopping playback in spotify on the EG machine.

when I test the action I get:
Is Playback Endpoint Active: VB-Audio Virtual Cable

I have a custom created console app. written in c# that works ok. But I would like to have it working in EG.
Here it is for reference. it uses win32 api calls.
Essentially what it does is starting tuneblade when audio is active for 3 sec. and killing tuneblade once audio has been silent for X seconds.

Code: Select all

using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Configuration;
using System.Diagnostics;

namespace SilenceMonitor
{
    class Program
    {
        static void Main(string[] args)
        {
           int silenceTimeOutSec = Convert.ToInt32(ConfigurationManager.AppSettings["silenceTimeOutSec"]);
           int soundInitialPeriodSec = Convert.ToInt32(ConfigurationManager.AppSettings["soundInitialPeriodSec"]);

           string killProcess = ConfigurationManager.AppSettings["killProcess"];
           string startProcess = ConfigurationManager.AppSettings["startProcess"];

           DateTime? silenceSince = null;
           DateTime? soundSince = null;
           bool silenceDetectedHandled = false;
           bool soundDetectedHandled = false;

            while (true)
            {
                bool isplaying = IsWindowsPlayingSound();
                if (isplaying)
                {
                    silenceSince = null;
                    if (soundSince == null)
                    {
                        soundSince = DateTime.Now;
                    }

                    Console.WriteLine("playing sound");

                }
                else
                {
                    soundSince = null;
                    if (silenceSince == null)
                    {
                        silenceSince = DateTime.Now;
                    }

                    Console.WriteLine("silence");

                }

                var now = DateTime.Now;
                if (!silenceDetectedHandled)
                {
                    if (silenceSince != null && silenceSince.Value.AddSeconds(silenceTimeOutSec) < now)
                    {
                        
                        Console.WriteLine($"silence for {silenceTimeOutSec} sec detected");
                        var procesess = Process.GetProcessesByName(killProcess);
                        if (procesess?.Any() == true)
                        {
                            foreach (var p in procesess)
                            {
                                try
                                {
                                    Console.WriteLine($"killing: {p.ProcessName} (pid:{p.Id})");
                                    p.Kill();
                                }
                                catch (Exception e)
                                {
                                    Console.WriteLine(e);

                                }
                            }


                        }
                        else
                        {
                            Console.WriteLine();
                            Console.WriteLine($"process not killed (not found): {killProcess}");
                        }

                        silenceDetectedHandled = true;
                        soundDetectedHandled = false;

                    }
                }

                if (!soundDetectedHandled)
                {
                    if (soundSince != null && soundSince.Value.AddSeconds(soundInitialPeriodSec) < now)
                    {
                        Console.WriteLine($"sound for {soundInitialPeriodSec} sec detected");
                        Console.WriteLine($"starting: {startProcess}");
                        Process externalCmdProcess = new Process();

                        externalCmdProcess.StartInfo.WindowStyle = ProcessWindowStyle.Maximized;
                        externalCmdProcess.StartInfo.Verb = "runas";
                        externalCmdProcess.StartInfo.UseShellExecute = false;
                        //externalCmdProcess.StartInfo.Arguments = args;
                        externalCmdProcess.StartInfo.FileName = startProcess;
                        //externalCmdProcess.StartInfo.RedirectStandardOutput = true;
                        //externalCmdProcess.StartInfo.RedirectStandardError = true;
                        //externalCmdProcess.StartInfo.RedirectStandardInput = true;

                        //externalCmdProcess.OutputDataReceived += process_OutputDataReceived;
                        //externalCmdProcess.ErrorDataReceived += process_OutputDataReceived;

                        externalCmdProcess.Start();
                        soundDetectedHandled = true;
                        silenceDetectedHandled = false;
                    }
                }

                

                System.Threading.Thread.Sleep(1000);
            }
        }

        public static bool IsWindowsPlayingSound()
        {
            var enumerator = (IMMDeviceEnumerator)(new MMDeviceEnumerator());
            var speakers = enumerator.GetDefaultAudioEndpoint(EDataFlow.eRender, ERole.eMultimedia);
            var meter = (IAudioMeterInformation)speakers.Activate(typeof(IAudioMeterInformation).GUID, 0, IntPtr.Zero);
            var value = meter.GetPeakValue();

            // this is a bit tricky. 0 is the official "no sound" value
            // but for example, if you open a video and plays/stops with it (w/o killing the app/window/stream),
            // the value will not be zero, but something really small (around 1E-09)
            // so, depending on your context, it is up to you to decide
            // if you want to test for 0 or for a small value
            return value > 1E-08;
        }

        [ComImport, Guid("BCDE0395-E52F-467C-8E3D-C4579291692E")]
        private class MMDeviceEnumerator
        {
        }

        private enum EDataFlow
        {
            eRender,
            eCapture,
            eAll,
        }

        private enum ERole
        {
            eConsole,
            eMultimedia,
            eCommunications,
        }

        [InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("A95664D2-9614-4F35-A746-DE8DB63617E6")]
        private interface IMMDeviceEnumerator
        {
            void NotNeeded();
            IMMDevice GetDefaultAudioEndpoint(EDataFlow dataFlow, ERole role);
            // the rest is not defined/needed
        }

        [InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("D666063F-1587-4E43-81F1-B948E807363F")]
        private interface IMMDevice
        {
            [return: MarshalAs(UnmanagedType.IUnknown)]
            object Activate([MarshalAs(UnmanagedType.LPStruct)] Guid iid, int dwClsCtx, IntPtr pActivationParams);
            // the rest is not defined/needed
        }

        [InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("C02216F6-8C67-4B5B-9D00-D008E73E0064")]
        private interface IAudioMeterInformation
        {
            float GetPeakValue();
            // the rest is not defined/needed
        }
    }


}

User avatar
kgschlosser
Site Admin
Posts: 4803
Joined: Fri Jun 05, 2015 5:43 am
Location: Rocky Mountains, Colorado USA

Re: Core Audio Plugin

Post by kgschlosser » Thu Aug 08, 2019 9:42 pm

Hey that's a pretty nifty way to go about it. I like it. never thought about using the peak meters to get that information. the only thing is I will not be able to grab the program name that is creating the audio. I will only be able to spit out the peak meter values overall.

below is a outline of some of the available mechanisms in the CoreAudio plugin. You can gain access to them by using the Get Default Playback Endpoint or the Get Default Recording Endpoint actions. how to do this is explained below the outline


if the returned value class (bit after the last ".") begins with an "I" then it is a ctypes interface it is a connection to C code and the passing of parameters needs to be done a specific way.

All properties you can get from if there is a set available it is noted for that property

CoreAudio.pyWinCoreAudio.endpoint.AudioDefaultEndpoint
  • PROPERTIES
    • data_flow = str
    • name = str
    • description = str
    • form_factor = str
    • type = dont remember
    • full_range_speakers = CoreAudio.pyWinCoreAudio.speakers.AudioSpeakers
    • guid = str
    • physical_speakers = CoreAudio.pyWinCoreAudio.speakers.AudioSpeakers
    • system_effects = bool
    • jack_descriptions = CoreAudio.pyWinCoreAudio.jack.AudioJackDescription
    • jack_information = CoreAudio.pyWinCoreAudio.jack.AudioJackSinkInformation
    • auto_gain_control = CoreAudio.pyWinCoreAudio.__core_audio.devicetopologyapi.IAudioAutoGainControl
    • bass = CoreAudio.pyWinCoreAudio.__core_audio.devicetopologyapi.IAudioBass
    • channel_config = CoreAudio.pyWinCoreAudio.__core_audio.devicetopologyapi.IAudioChannelConfig
    • input = CoreAudio.pyWinCoreAudio.__core_audio.devicetopologyapi.IAudioInputSelector
    • loudness = CoreAudio.pyWinCoreAudio.__core_audio.devicetopologyapi.IAudioLoudness
    • midrange = CoreAudio.pyWinCoreAudio.__core_audio.devicetopologyapi.IAudioMidrange
    • output = CoreAudio.pyWinCoreAudio.__core_audio.devicetopologyapi.IAudioOutputSelector
    • peak_meter = CoreAudio.pyWinCoreAudio.__core_audio.devicetopologyapi.IAudioPeakMeter
    • treble = CoreAudio.pyWinCoreAudio.__core_audio.devicetopologyapi.IAudioTreble
    • volume = CoreAudio.pyWinCoreAudio.volume.AudioVolume
    • is_default = bool
    • session_manager = CoreAudio.pyWinCoreAudio.session.AudioSessionManager
    • audio_client = IAudioClient, IAudioClient2 or IAudioClient3 depending on your windows version
    • id = str
    • device = CoreAudio.pyWinCoreAudio.device.AudioDevice
    • icon = str
  • METHODS
    • set_default()

CoreAudio.pyWinCoreAudio.jack.AudioJackSinkInformation: the names of the properties are pretty self descriptive.
  • PROPERTIES
    • manufacturer_id = str
    • product_id = str
    • audio_latency = ???
    • hdcp_capable = bool
    • ai_capable = bool
    • description = str
    • port_id = str
    • connection_type = str

CoreAudio.pyWinCoreAudio.jack.AudioJackDescription:
  • PROPERTIES
    • channel_mapping = CoreAudio.pyWinCoreAudio.speakers.AudioSpeakers
    • color = (red, green, blue)
    • type = str
    • location = str
    • port = str
    • is_connected = bool
    • presence_detection = bool
    • dynamic_format_change = ???
CoreAudio.pyWinCoreAudio.speakers.AudioSpeakers: this lets you know what speakers are connected and what speakers are not.
  • PROPERTIES
    • front_left = bool
    • front_right = bool
    • center = bool
    • high_left = bool
    • high_right = bool
    • side_left = bool
    • side_right = bool
    • back_left = bool
    • back_right = bool
    • back_center = bool
    • subwoofer = bool
    • string = str


CoreAudio.pyWinCoreAudio.session.AudioSessionManager: This is for generating the sesion events and there is nothing really usable here


CoreAudio.pyWinCoreAudio.volume.AudioVolume:
  • PROPERTIES
    • endpoint = CoreAudio.pyWinCoreAudio.endpoint.AudioEndpoint
    • channels = CoreAudio.pyWinCoreAudio.volume.AudioVolumeChannels
    • master = volume level from 0-100 percent based value as a float
    • master_scalar = volume level percentage / 100.0 so 0.0 = 0% and 1.0 = 100%
    • mute = get/set the mute True or False
    • min = the lowest the volume can go
    • max = the highest the volume can go
    • step = how much you can increase or decrease the volume by
    • peak_meter = CoreAudio.pyWinCoreAudio.volume.AudioPeakMeter
  • METHODS
    • up() = volume up one step
    • down() = volume down one step

CoreAudio.pyWinCoreAudio.volume.AudioVolumeChannels:
  • PROPERTIES:
    • count = the number of channels
you use this class as a list. so channels[0] is channel 1 and channels[1] is channel 2 and so on and so forth. the "channel" is
and instance of CoreAudio.pyWinCoreAudio.volume.AudioVolumeChannel


CoreAudio.pyWinCoreAudio.volume.AudioVolumeChannel
  • PROPERTIES:
    • level = get/set the volume for that channel 0.0-100.0%
    • level_scalar = get/set the scalar volume level for the channel 0.0 - 1.0
    • min = minimum allowed volume level as a float
    • max = maximum allowed volume level as a float
    • step = get the amount you can increase or decrease the level by as a float
CoreAudio.pyWinCoreAudio.volume.AudioPeakMeter
  • PROPERTIES
    • channel_peak_values = list of the peak channel values
    • channel_count = number of channels
    • peak_value = averaged peak of all channels (I think that is what it is)


Now for a quick and dirty way of doing this until i add the feature into the plugin.

I am going to assume you have that cable thing set to either the default rendered or default capture (recording) endpoint. either or you will be able to use this mechanism and it is going to expose all of the Windows API functions to you.


WARNING: DO NOT HOLD REFERENCE TO THIS OBJECT.
if you hold a reference to this object and for some reason the device gets removed from the system nd the added back in again if you perform a command on the object it is going to pitch a fit about it. So be sure to get a new object each and every single time.

create a macro.
In that macro add in either the Get Default Playback Endpoint or the Get Default Recording Endpoint depending on which one you are using.

this is going to return a reference to CoreAudio.pyWinCoreAudio.endpoint.AudioDefaultEndpoint this reference is an extension of CoreAudio.pyWinCoreAudio.endpoint.AudioEndpoint

if you paste this code into a python script action in that macro you made under the Get action then execute the macro (right click on the macro and then click on execute) it should spit out the peak values. from there you can make any adjustments you need. I do not know what your cutoff point is for determining if there is audio playing or not.

Code: Select all

# we are not using the peak_meter that is available directly in the endpoint because
# that is the C interface version of it. I have done all of the legwork for you and the 
# data type conversions. so use this peak meter instead.

# get the reference to the endpoint. eg.result gets set by the action above this script.
endpoint = eg.result

# now we get a reference to the peak meter. The reason why we set this as a 
# variable is so it will only execute the c code a single time instead of over and 
# over again
peak_meter = endpoint.volume.peak_meter
average = peak_meter.peak_value

print 'AVERAGE PEAK:', average

# enumerate the channel peak values.
for i, value in enumerate(peak_meter.channel_peak_values):
    print 'CHANNEL', i, 'PEAK VALUE:', value


# this ensures the reference to the object is removed and can be garbage collected.
del peak_meter
del endpoint 
eg.result = None

Let me know if this works or not.
If you like the work I have been doing then feel free to Image

User avatar
kgschlosser
Site Admin
Posts: 4803
Joined: Fri Jun 05, 2015 5:43 am
Location: Rocky Mountains, Colorado USA

Re: Core Audio Plugin

Post by kgschlosser » Thu Aug 08, 2019 9:43 pm

i wanted to mention this is an almost complete Python API for accessing the Audio features of Windows. there are several bits I still have to hammer out but all in all it is the most complete python API available.
If you like the work I have been doing then feel free to Image

User avatar
kgschlosser
Site Admin
Posts: 4803
Joined: Fri Jun 05, 2015 5:43 am
Location: Rocky Mountains, Colorado USA

Re: Core Audio Plugin

Post by kgschlosser » Thu Aug 08, 2019 10:17 pm

OK so i went ahead an added that feature already. it is available on the first port. I added 2 new actions.
If you like the work I have been doing then feel free to Image

gibman
Posts: 4
Joined: Thu Aug 08, 2019 5:55 pm

Re: Core Audio Plugin

Post by gibman » Fri Aug 09, 2019 9:16 am

thanks for the update.

I just tested it.
No events received on based on action: "Playback Endpoint Has Output: VB-Audio Virtual Cable"
when I hit the test button it just replies back to EG:
11:15:19 Playback Endpoint Has Output: VB-Audio Virtual Cable

regardless of audio being outputted or not.
opening the sound controls (windows control panel) I can see the vbcable happily outputting stuff as spotify is actively running.



btw. when I tried turning the vol up/down within the systay area icon EG caused a bucketload of exceptions:

11:08:19 Exception in thread Thread-17:
11:08:19 Traceback (most recent call last):
11:08:19 File "threading.pyc", line 801, in __bootstrap_inner
11:08:19 File "threading.pyc", line 754, in run
11:08:19 File "C:\ProgramData\EventGhost\plugins\CoreAudio\pyWinCoreAudio\volume.py", line 67, in do
11:08:19 mute
11:08:19 File "C:\ProgramData\EventGhost\plugins\CoreAudio\__init__.py", line 357, in endpoint_volume_change
11:08:19 vol_diff = new_vol - old_vol
11:08:19 TypeError: unsupported operand type(s) for -: 'float' and 'NoneType'

User avatar
kgschlosser
Site Admin
Posts: 4803
Joined: Fri Jun 05, 2015 5:43 am
Location: Rocky Mountains, Colorado USA

Re: Core Audio Plugin

Post by kgschlosser » Fri Aug 09, 2019 12:39 pm

thanks for the report of the exceptions..

Actions will not necessarily cause events. they may simply return information about what is going on.

create a macro. add the action to it. then add the EventGhost/Dump Result Action. then you will see in the log the returned data.

If you use one of the new actions you will want to place after it the jump if action. this allows you to run 2 different sets of actions based on what the return value is.
If you like the work I have been doing then feel free to Image

gibman
Posts: 4
Joined: Thu Aug 08, 2019 5:55 pm

Re: Core Audio Plugin

Post by gibman » Fri Aug 09, 2019 12:53 pm

thanks for the info.

I get this in the log window:

14:48:23 Playback Endpoint Has Output: VB-Audio Virtual Cable
14:48:23 Playback Endpoint Has Output: VB-Audio Virtual Cable
14:48:23 Dump Result to Log
14:48:23 True
14:48:28 Task.Deactivated.EventGhost
14:48:28 Task.Activated.Spotify
14:48:32 Task.Deactivated.Spotify
14:48:32 Task.Activated.EventGhost
14:48:38 Playback Endpoint Has Output: VB-Audio Virtual Cable
14:48:38 Playback Endpoint Has Output: VB-Audio Virtual Cable
14:48:38 Dump Result to Log
14:48:38 False
Unavngivet.png

so the result is true when audio is active and false when inactive.
So it works :)

although no events are thrown :(

User avatar
kgschlosser
Site Admin
Posts: 4803
Joined: Fri Jun 05, 2015 5:43 am
Location: Rocky Mountains, Colorado USA

Re: Core Audio Plugin

Post by kgschlosser » Fri Aug 09, 2019 1:01 pm

OK i updated the plugin to fix you traceback issue.
If you like the work I have been doing then feel free to Image

User avatar
kgschlosser
Site Admin
Posts: 4803
Joined: Fri Jun 05, 2015 5:43 am
Location: Rocky Mountains, Colorado USA

Re: Core Audio Plugin

Post by kgschlosser » Fri Aug 09, 2019 1:39 pm

OK sir... you have your events.
plugin has been updated.
If you like the work I have been doing then feel free to Image

gibman
Posts: 4
Joined: Thu Aug 08, 2019 5:55 pm

Re: Core Audio Plugin

Post by gibman » Fri Aug 09, 2019 2:10 pm

thank you my friend !!

It works now.

Is there any way to accomplish something like this:

1) throw stopped event after a user definable amount of time has passed with silence
2) the same for the started event, raise the event once audio has been active for x seconds.

I couldnt fine a builtin method within EG that could handle this.
But then again Im not too knowledgeable about EG either .)

User avatar
kgschlosser
Site Admin
Posts: 4803
Joined: Fri Jun 05, 2015 5:43 am
Location: Rocky Mountains, Colorado USA

Re: Core Audio Plugin

Post by kgschlosser » Fri Aug 09, 2019 7:51 pm

how long are we talking for a stop time?

you could do something like this

event for stopped comes in
action wait(duration)
action check output
jump if to empty macro with no return
actions that you want to run if there is no audio
If you like the work I have been doing then feel free to Image

z3us
Posts: 35
Joined: Fri Jul 29, 2011 2:35 am

Re: Core Audio Plugin

Post by z3us » Sat Sep 14, 2019 8:14 pm

Hi
I´m getting this error when EG loads plugins:

Code: Select all

      Error iniciando el plugin: Core Audio
      Traceback (most recent call last) (0.5.0-rc6):
        File "C:\Program Files (x86)\EventGhost\eg\Classes\PluginInstanceInfo.py", line 196, in Start
          self.instance.__start__(*self.args)
        File "C:\ProgramData\EventGhost\plugins\CoreAudio3\__init__.py", line 759, in __start__
          self.callbacks = Callbacks(self)
        File "C:\ProgramData\EventGhost\plugins\CoreAudio3\__init__.py", line 265, in __init__
          self.__map_device(device)
        File "C:\ProgramData\EventGhost\plugins\CoreAudio3\__init__.py", line 282, in __map_device
          endpoint.data_flow
      UnicodeEncodeError: 'ascii' codec can't encode character u'\xf3' in position 4: ordinal not in range(128)
EG 0.5.0 rc6
Windows 10


Thanks

Post Reply