Author Topic: "Set Audio Level" Question  (Read 3936 times)

Yamanox

  • Guest
"Set Audio Level" Question
« on: May 15, 2017, 03:13:04 PM »
I'm having issues trying to figure out how to use set audio level with chrome, I can only get it to only work on a single tab and now on the application as a whole, if anyone knows how to get this to work I'd appreciate your wisdom!

Pfeil

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 4778
  • RTFM
Re: "Set Audio Level" Question
« Reply #1 on: May 15, 2017, 11:31:40 PM »
The volume mixer is supposed to affect the entire application when adjusted manually, but as Chrome uses a different process for each tab, adjusting it programmatically may not be as straightforward.

Presumably, Chrome starts as a single "parent" process that spawns "child" processes. Perhaps setting the volume on this "parent" process would have the desired effect.


You could try finding the parent using something like the following:
Code: [Select]
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Diagnostics;

    /// <summary>
    /// A utility class to determine a process parent.
    /// </summary>
    [StructLayout(LayoutKind.Sequential)]
    public struct ParentProcessUtilities
    {
        // These members must match PROCESS_BASIC_INFORMATION
        internal IntPtr Reserved1;
        internal IntPtr PebBaseAddress;
        internal IntPtr Reserved2_0;
        internal IntPtr Reserved2_1;
        internal IntPtr UniqueProcessId;
        internal IntPtr InheritedFromUniqueProcessId;

        [DllImport("ntdll.dll")]
        private static extern int NtQueryInformationProcess(IntPtr processHandle, int processInformationClass, ref ParentProcessUtilities processInformation, int processInformationLength, out int returnLength);

        /// <summary>
        /// Gets the parent process of the current process.
        /// </summary>
        /// <returns>An instance of the Process class.</returns>
        public static Process GetParentProcess()
        {
            return GetParentProcess(Process.GetCurrentProcess().Handle);
        }

        /// <summary>
        /// Gets the parent process of specified process.
        /// </summary>
        /// <param name="id">The process id.</param>
        /// <returns>An instance of the Process class.</returns>
        public static Process GetParentProcess(int id)
        {
            Process process = Process.GetProcessById(id);
            return GetParentProcess(process.Handle);
        }

        /// <summary>
        /// Gets the parent process of a specified process.
        /// </summary>
        /// <param name="handle">The process handle.</param>
        /// <returns>An instance of the Process class or null if an error occurred.</returns>
        public static Process GetParentProcess(IntPtr handle)
        {
            ParentProcessUtilities pbi = new ParentProcessUtilities();
            int returnLength;
            int status = NtQueryInformationProcess(handle, 0, ref pbi, Marshal.SizeOf(pbi), out returnLength);
            if (status != 0)
                return null;

            try
            {
                return Process.GetProcessById(pbi.InheritedFromUniqueProcessId.ToInt32());
            }
            catch (ArgumentException)
            {
                // not found
                return null;
            }
        }
    }

public class VAInline
{
public void main()
{
            try
            {
                Process[] ChromeProc = Process.GetProcessesByName("Chrome");
                foreach (Process p in ChromeProc)
                {
                    VA.WriteToLog(ParentProcessUtilities.GetParentProcess(ChromeProc[0].Id).ProcessName.ToString(), "black");
                    VA.WriteToLog(ParentProcessUtilities.GetParentProcess(ChromeProc[0].Id).Id.ToString(), "pink");
                }
            }
            catch(Exception e)
            {
                VA.WriteToLog(e.ToString(), "red");
            }
}
}
(Based on this example)

However, even if you know the parent's PID, VoiceAttack only accepts process names, not IDs, so you'd have to use something like NirCMD to actually set the volume.