[MP1-4838] Volume control no longer functions properly when changing audio device (1 Viewer)

Rick164

MP Donator
  • Premium Supporter
  • January 7, 2006
    1,335
    1,005
    Home Country
    Netherlands Netherlands
    Hi,

    Been debugging an issue with @Virtual in the AudioSwitcher topic and is as follows:

    - Start Mediaportal with volume control set to master:

    osd-png.185718

    osd_2-png.185717


    - Test out volume control via keyboard for instance ( + -), will notice your audio device changing volume from sys tray.
    - Let Mediaportal run and change your default Windows audio device to something else either via AudioSwitcher plugin or Windows sound panel.
    - Test out volume control via keyboard, will notice your volume changing on your old Windows audio device instead and keep the current one as-is.

    Now so far it can be inconsistent and looking over the code below can't find any red flags, best guess is that we only set the audio device on startup and hook that up to volume control but don't check for changes afterwards (during volume events).
    While it works fine during playback you do lose Mediaportal volume control, anyone have any idea what is causing this?

    https://github.com/MediaPortal/MediaPortal-1/blob/master/mediaportal/Core/Player/VolumeHandler.cs

    Added Installer to Jira : https://issues.team-mediaportal.com/browse/MP1-4838 :p
    Thanks @Rick164
     
    Last edited by a moderator:

    Stéphane Lenclud

    Retired Team Member
  • Premium Supporter
  • April 29, 2013
    2,576
    1,294
    Home Country
    Germany Germany
    Best guess is that we only set the audio device on startup and hook that up to volume control but don't check for changes afterwards (during volume events).
    It seems so.
    That's unlikely to be an issue when using an HID remote or HID multimedia keyboard since we don't do anything other than letting the system do volume changes for us.
     

    Rick164

    MP Donator
  • Premium Supporter
  • January 7, 2006
    1,335
    1,005
    Home Country
    Netherlands Netherlands
    Yeah that's how I do it at the moment for family and here via Flirc + Harmony which will be either via its bluetooth keyboard or emulated key press.
     

    Sebastiii

    Development Group
  • Team MediaPortal
  • November 12, 2007
    16,583
    10,403
    France
    Home Country
    France France
    In mediaportal.cs we have that : I think it's here the init is done : line 3123

    VolumeHandler.CreateInstance();
    GUIGraphicsContext.VolumeHandler = VolumeHandler.Instance;

    If we are looking in \mediaportal\Core\DShowNET\Helper\DirectShowUtil.cs line 905

    C#:
    try
                      {
                        // vh.Volume = 19660500 that means Audio endpoint device are not available.
                        if (GUIGraphicsContext.VolumeHandler != null && GUIGraphicsContext.VolumeHandler.Volume == 19660500) // Check if new audio device is connected
                        {
                          Log.Debug("DirectShowUtil: need dispose volume handler value {0}", GUIGraphicsContext.VolumeHandler.Volume);
                          VolumeHandler.Dispose();
                          GUIGraphicsContext.VolumeHandler = VolumeHandler.Instance;
                        }
                        if (GUIGraphicsContext.VolumeHandler != null && GUIGraphicsContext.VolumeHandler.Volume != 19660500 && GUIGraphicsContext.DeviceAudioConnected > 0)
                        {
                          Log.Debug("DirectShowUtil: volume handler value {0}", GUIGraphicsContext.VolumeHandler.Volume);
                          Log.Debug("DirectShowUtil: build the graph for PIN : {0}", pinName);
                          hr = graphBuilder.Render(pins[0]);
                        }
                      }
                      catch (Exception exception)
                      {
                        Log.Warn("DirectShowUtil: Could not initialize volume handler (don't connect Audio Pin) : {0}", exception.Message);
                      }

    That part does a reinit, maybe it's possible to reinit differently elsewhere ?
     

    Rick164

    MP Donator
  • Premium Supporter
  • January 7, 2006
    1,335
    1,005
    Home Country
    Netherlands Netherlands
    Looked at that and seems we can create a new volume instance but does only help with OSD display but not for the actual volume, think we need a way to re-init it in DirectShowUtil or some event that will trigger if audio device changes (no longer primary).

    Ideally the volume control should always change it's default Windows audio device if set to "Default direct sound device" but not sure if that can be done easily.

    Code:
        private void SetPlaybackDevice(CoreAudioDevice device)
        {
          try
          {
            Log.Debug($"Audio Switcher - setting default playback device to: {device.FullName}");
            device.SetAsDefault();
            Log.Debug($"Device audio connected: {GUIGraphicsContext.DeviceAudioConnected}");
    
            if (Settings.LAVbitstreamPerDevice)
            {
              SetLavBitstreamSettings(device.FullName);
            }
    
            Log.Debug("Resetting volume control");
            Thread.Sleep(1000);
            VolumeHandler.Dispose();
            Thread.Sleep(1000);
            VolumeHandler.CreateInstance();
            Log.Debug("Volume control reset");
          }
          catch (Exception ex)
          {
            Log.Error("Error occured during SetPlaybackDevice()");
            Log.Error(ex.Message);
          }
        }
     

    Sebastiii

    Development Group
  • Team MediaPortal
  • November 12, 2007
    16,583
    10,403
    France
    Home Country
    France France
    So ideally we should kept some volume instance value before the change and restore it on new instance :)
    But i think we need also to do : GUIGraphicsContext.VolumeHandler = VolumeHandler.Instance;
    What do you think ?

    Edit : we need to get and restore GUIGraphicsContext.VolumeHandler.Volume i think.
     
    Last edited:

    Rick164

    MP Donator
  • Premium Supporter
  • January 7, 2006
    1,335
    1,005
    Home Country
    Netherlands Netherlands
    Agree, we need to tie up the new instance however requires:

    - A way of knowing if it has changed and update accordingly
    - Change volume on the default Windows device if user has set video audio device to Default or new option in GUI where you can select which device to use like with video audio renderer (default directsound / device X etc..)

    Now the Win32 audio API is pretty hard to deal with and couldn't find any clear examples for events so far, this was one of the reasons I went with AudioSwitcher core API which has easy control and can be events driven (also async for most parts in latest beta)
    Integration with that probably won't work well with Mediaportal but the developer is very helpful as he wrote the wrapper for the Win32 audio API so might possibly have a solution so we could ask him on Github :)
     

    Stéphane Lenclud

    Retired Team Member
  • Premium Supporter
  • April 29, 2013
    2,576
    1,294
    Home Country
    Germany Germany

    Stéphane Lenclud

    Retired Team Member
  • Premium Supporter
  • April 29, 2013
    2,576
    1,294
    Home Country
    Germany Germany
    I've just cleaned up my usage of CScore to handle volume changes and default device change notification.
    It's now implemented in that AudioManager class. That could be a useful reference if ever we need to implement something similar in MP1.
     

    mm1352000

    Retired Team Member
  • Premium Supporter
  • September 1, 2008
    21,577
    8,224
    Home Country
    New Zealand New Zealand
    @Rick164
    If you're going down the path of investigating proper handling for audio device changes, I think our current code that tracks audio device connection/disconnection could do with a bit of love. Specifically:
    • Find an alternative way to enumerate audio devices at startup that doesn't require DirectShow (ie. replace -->this<--)
    • When an audio device is removed, detect whether that device was being used as the audio renderer for the playing media. Only stop playback if the device is being used. It might be possible to detect this better with a completely different method such as with DirectShow graph events (eg. this one).
     

    Users who are viewing this thread

    Top Bottom