1

I want to get the system volume of Linux using C# code. How to do this?

Extra Info:

-->Is there any library/dll that I can use.

-->I have come across alsa-sharp but I did not find any function regarding volume.

--> I have come across C code which but I am not familiar on how I can use that in C#.

  • Have you checked ALSA related .net wrappers? A google search gives me [this one](https://github.com/crojewsk/SoundIOSharp) that claims to support ALSA as a backend. – Cleptus Sep 13 '19 at 07:26
  • Yes, I have checked them. But they don't have any volume function that I can use. For example, In both Alsa-Sharp and SoundIOSharp , They have imported some "SETVOLUME" function. But I **don't see any C# implementation** in their respective source code. Hence I am not able to use them – Clearskies Tumbled Sep 13 '19 at 09:15
  • Have not tested nor downloaded the API, but looks like that API has properties that return the volumen [github search on SoundIOSharp](https://github.com/crojewsk/SoundIOSharp/search?q=Volume&unscoped_q=Volume) – Cleptus Sep 13 '19 at 11:06
  • I am also not sure on how can I use that, SoundIOOutStream's constructor requires a parameter which I am not sure how to use. **internal SoundIOOutStream (Pointer handle)** – Clearskies Tumbled Sep 13 '19 at 11:31

1 Answers1

0

Better late than never, but I came across this while setting up an RPi-based internet radio and the following code, which you can also find at this git, works for me.

It's based on this answer and the native interop code from alsa-sharp by https://github.com/atsushieno.

Note: You might need to experiment with the "card" and "selemName" parameters.

using System;
using System.Runtime.InteropServices;

namespace Alsa
{
    public sealed class VolumeControl : IDisposable
    {
        private readonly long _min;
        private readonly long _max;
        private readonly IntPtr _sid;
        private readonly IntPtr _selem;
        private readonly IntPtr _handle;
        private const string LibraryName = "libasound";

        public VolumeControl(string card = "default", string selemName = "PCM")
        {
            snd_mixer_open(ref _handle, 0);
            snd_mixer_attach(_handle, card);
            snd_mixer_selem_register(_handle, default, default);
            snd_mixer_load(_handle);

            snd_mixer_selem_id_malloc(ref _sid);
            snd_mixer_selem_id_set_index(_sid, 0);
            snd_mixer_selem_id_set_name(_sid, selemName);
            _selem = snd_mixer_find_selem(_handle, _sid);

            snd_mixer_selem_get_playback_volume_range(_selem, ref _min, ref _max);
        }

        public void SetVolumePercent(int volume)
        {
            snd_mixer_selem_set_playback_volume_all(_selem, (int)(volume * _max / 100));
        }

        public void Dispose()
        {
            ReleaseUnmanagedResources();
            GC.SuppressFinalize(this);
        }

        private void ReleaseUnmanagedResources()
        {
            snd_mixer_selem_id_free(_sid);
            snd_mixer_close(_handle);
        }

        ~AlsaSoundOutput()
        {
            ReleaseUnmanagedResources();
        }

        [DllImport(LibraryName)]
        internal static extern int snd_mixer_open(ref IntPtr mixer, int mode);

        [DllImport(LibraryName, CharSet = CharSet.Ansi)]
        internal static extern int snd_mixer_attach(IntPtr mixer, [MarshalAs(UnmanagedType.LPStr)] string name);

        [DllImport(LibraryName)]
        internal static extern int snd_mixer_selem_register(IntPtr mixer, IntPtr options, IntPtr classp);

        [DllImport(LibraryName)]
        internal static extern int snd_mixer_load(IntPtr mixer);

        [DllImport(LibraryName)]
        internal static extern int snd_mixer_selem_id_malloc(ref IntPtr selem);

        [DllImport(LibraryName)]
        internal static extern void snd_mixer_selem_id_set_index(IntPtr selem, uint val);

        [DllImport(LibraryName, CharSet = CharSet.Ansi)]
        internal static extern void snd_mixer_selem_id_set_name(IntPtr selem, [MarshalAs(UnmanagedType.LPStr)] string value);

        [DllImport(LibraryName)]
        internal static extern IntPtr snd_mixer_find_selem(IntPtr mixer, IntPtr selem);

        [DllImport(LibraryName)]
        internal static extern int snd_mixer_selem_get_playback_volume_range(IntPtr selem, ref long min, ref long max);

        [DllImport(LibraryName)]
        internal static extern int snd_mixer_selem_set_playback_volume_all(IntPtr selem, int value);

        [DllImport(LibraryName)]
        internal static extern void snd_mixer_selem_id_free(IntPtr selem);

        [DllImport(LibraryName)]
        internal static extern int snd_mixer_close(IntPtr mixer);
    }
}
Daniel C. Weber
  • 1,011
  • 5
  • 12