2

Normally from the terminal I use the command:

pacmd list-sinks|awk '/index:/ {print $0} /name:/ {print $0};'

which gives me an output like this:

    index: 0
    name: <alsa_output.pci-0000_01_00.1.hdmi-stereo>
    index: 1
    name: <alsa_output.pci-0000_00_1b.0.analog-stereo>
  * index: 2
    name: <alsa_output.usb-0d8c_C-Media_USB_Audio_Device-00-Device.iec958-stereo>

but apparently from Qt, when commanding using QProcess, parsing using awk isn't working, it just does not do any parsing at all and produces the whole output which you expect from commanding pacmd list-sinks. The whole output is as the following:

Welcome to PulseAudio! Use "help" for usage information.
>>> 3 sink(s) available.
    index: 0
    name: <alsa_output.pci-0000_01_00.1.hdmi-stereo>
    driver: <module-alsa-card.c>
    flags: HARDWARE DECIBEL_VOLUME LATENCY DYNAMIC_LATENCY
    state: SUSPENDED
    suspend cause: IDLE 
    priority: 9050
    volume: 0:  45% 1:  45%
            0: -20,78 dB 1: -20,78 dB
            balance 0,00
    base volume: 100%
                 0,00 dB
    volume steps: 65537
    muted: no
    current latency: 0,00 ms
    max request: 0 KiB
    max rewind: 0 KiB
    monitor source: 0
    sample spec: s16le 2ch 44100Hz
    channel map: front-left,front-right
                 Stereo
    used by: 0
    linked by: 0
    configured latency: 0,00 ms; range is 0,50 .. 371,52 ms
    card: 0 <alsa_card.pci-0000_01_00.1>
    module: 5
    properties:
        alsa.resolution_bits = "16"
        device.api = "alsa"
        device.class = "sound"
        alsa.class = "generic"
        alsa.subclass = "generic-mix"
        alsa.name = "HDMI 0"
        alsa.id = "HDMI 0"
        alsa.subdevice = "0"
        alsa.subdevice_name = "subdevice #0"
        alsa.device = "3"
        alsa.card = "1"
        alsa.card_name = "HDA NVidia"
        alsa.long_card_name = "HDA NVidia at 0xf7080000 irq 17"
        alsa.driver_name = "snd_hda_intel"
        device.bus_path = "pci-0000:01:00.1"
        sysfs.path = "/devices/pci0000:00/0000:00:01.0/0000:01:00.1/sound/card1"
        device.bus = "pci"
        device.vendor.id = "10de"
        device.vendor.name = "NVIDIA Corporation"
        device.product.id = "0e1b"
        device.product.name = "GK107 HDMI Audio Controller"
        device.string = "hdmi:1"
        device.buffering.buffer_size = "65536"
        device.buffering.fragment_size = "32768"
        device.access_mode = "mmap+timer"
        device.profile.name = "hdmi-stereo"
        device.profile.description = "Digital Stereo (HDMI)"
        device.description = "GK107 HDMI Audio Controller Digital Stereo (HDMI)"
        alsa.mixer_name = "Nvidia GPU 42 HDMI/DP"
        alsa.components = "HDA:10de0042,104383f3,00100100"
        module-udev-detect.discovered = "1"
        device.icon_name = "audio-card-pci"
    ports:
        hdmi-output-0: HDMI / DisplayPort (priority 5900, latency offset 0 usec, available: no)
            properties:
                device.icon_name = "video-display"
    active port: <hdmi-output-0>
    index: 1
    name: <alsa_output.pci-0000_00_1b.0.analog-stereo>
    driver: <module-alsa-card.c>
    flags: HARDWARE HW_MUTE_CTRL HW_VOLUME_CTRL DECIBEL_VOLUME LATENCY DYNAMIC_LATENCY
    state: SUSPENDED
    suspend cause: IDLE 
    priority: 9959
    volume: 0:  27% 1:  27%
            0: -34,20 dB 1: -34,20 dB
            balance 0,00
    base volume: 100%
                 0,00 dB
    volume steps: 65537
    muted: no
    current latency: 0,00 ms
    max request: 0 KiB
    max rewind: 0 KiB
    monitor source: 1
    sample spec: s16le 2ch 48000Hz
    channel map: front-left,front-right
                 Stereo
    used by: 0
    linked by: 0
    configured latency: 0,00 ms; range is 0,50 .. 341,33 ms
    card: 1 <alsa_card.pci-0000_00_1b.0>
    module: 6
    properties:
        alsa.resolution_bits = "16"
        device.api = "alsa"
        device.class = "sound"
        alsa.class = "generic"
        alsa.subclass = "generic-mix"
        alsa.name = "ALC269VB Analog"
        alsa.id = "ALC269VB Analog"
        alsa.subdevice = "0"
        alsa.subdevice_name = "subdevice #0"
        alsa.device = "0"
        alsa.card = "0"
        alsa.card_name = "HDA Intel PCH"
        alsa.long_card_name = "HDA Intel PCH at 0xf7330000 irq 38"
        alsa.driver_name = "snd_hda_intel"
        device.bus_path = "pci-0000:00:1b.0"
        sysfs.path = "/devices/pci0000:00/0000:00:1b.0/sound/card0"
        device.bus = "pci"
        device.vendor.id = "8086"
        device.vendor.name = "Intel Corporation"
        device.product.id = "1e20"
        device.product.name = "7 Series/C210 Series Chipset Family High Definition Audio Controller"
        device.form_factor = "internal"
        device.string = "front:0"
        device.buffering.buffer_size = "65536"
        device.buffering.fragment_size = "32768"
        device.access_mode = "mmap+timer"
        device.profile.name = "analog-stereo"
        device.profile.description = "Analog Stereo"
        device.description = "Built-in Audio Analog Stereo"
        alsa.mixer_name = "Realtek ALC269VB"
        alsa.components = "HDA:10ec0269,1028052c,00100100"
        module-udev-detect.discovered = "1"
        device.icon_name = "audio-card-pci"
    ports:
        analog-output: Analog Output (priority 9900, latency offset 0 usec, available: unknown)
            properties:

        analog-output-speaker: Speakers (priority 10000, latency offset 0 usec, available: no)
            properties:
                device.icon_name = "audio-speakers"
        analog-output-headphones: Headphones (priority 9000, latency offset 0 usec, available: yes)
            properties:
                device.icon_name = "audio-headphones"
    active port: <analog-output-headphones>
  * index: 2
    name: <alsa_output.usb-0d8c_C-Media_USB_Audio_Device-00-Device.iec958-stereo>
    driver: <module-alsa-card.c>
    flags: HARDWARE DECIBEL_VOLUME LATENCY DYNAMIC_LATENCY
    state: RUNNING
    suspend cause: 
    priority: 9048
    volume: 0:  45% 1:  45%
            0: -20,78 dB 1: -20,78 dB
            balance 0,00
    base volume: 100%
                 0,00 dB
    volume steps: 65537
    muted: no
    current latency: 31,29 ms
    max request: 4 KiB
    max rewind: 344 KiB
    monitor source: 4
    sample spec: s16le 2ch 48000Hz
    channel map: front-left,front-right
                 Stereo
    used by: 1
    linked by: 1
    configured latency: 26,00 ms; range is 26,00 .. 1837,50 ms
    card: 3 <alsa_card.usb-0d8c_C-Media_USB_Audio_Device-00-Device>
    module: 22
    properties:
        alsa.resolution_bits = "16"
        device.api = "alsa"
        device.class = "sound"
        alsa.class = "generic"
        alsa.subclass = "generic-mix"
        alsa.name = "USB Audio"
        alsa.id = "USB Audio"
        alsa.subdevice = "0"
        alsa.subdevice_name = "subdevice #0"
        alsa.device = "0"
        alsa.card = "2"
        alsa.card_name = "C-Media USB Audio Device"
        alsa.long_card_name = "C-Media USB Audio Device at usb-0000:00:14.0-1, full speed"
        alsa.driver_name = "snd_usb_audio"
        device.bus_path = "pci-0000:00:14.0-usb-0:1:1.0"
        sysfs.path = "/devices/pci0000:00/0000:00:14.0/usb1/1-1/1-1:1.0/sound/card2"
        udev.id = "usb-0d8c_C-Media_USB_Audio_Device-00-Device"
        device.bus = "usb"
        device.vendor.id = "0d8c"
        device.vendor.name = "C-Media Electronics, Inc."
        device.product.id = "000c"
        device.product.name = "Audio Adapter"
        device.serial = "0d8c_C-Media_USB_Audio_Device"
        device.string = "iec958:2"
        device.buffering.buffer_size = "352800"
        device.buffering.fragment_size = "176400"
        device.access_mode = "mmap+timer"
        device.profile.name = "iec958-stereo"
        device.profile.description = "Digital Stereo (IEC958)"
        device.description = "Audio Adapter Digital Stereo (IEC958)"
        alsa.mixer_name = "USB Mixer"
        alsa.components = "USB0d8c:000c"
        module-udev-detect.discovered = "1"
        device.icon_name = "audio-card-usb"
    ports:
        iec958-stereo-output: Digital Output (S/PDIF) (priority 0, latency offset 0 usec, available: unknown)
            properties:

    active port: <iec958-stereo-output>
>>> 

I guess I'm commanding the wrong way. The code I use for commanding and parsing using awk is the following:

QString prog = "pacmd";
QStringList arguments;
QProcess p;
arguments << "list-sinks"<<"|awk '/index:/ {print $0} /name:/ {print $0};'";
QString reply;
p.start(prog, arguments);
if (p.waitForStarted())
{
    p.waitForFinished();
    reply = p.readAllStandardOutput();
    qDebug()<<reply<<endl;
}
else
{
    qDebug()<< "Error using pacmd for getting list of sinks";
}

So, now, I'm trying to parse the indexes and the names without using awk. I'm able to find the indexes, but not the names. The code is as the following:

QString prog = "pacmd";
QStringList arguments;
QProcess p;
arguments << "list-sinks";
QString reply;
p.start(prog, arguments);
if (p.waitForStarted())
{
    p.waitForFinished();
    reply = p.readAllStandardOutput();
    QRegExp rx("index: \\d+|'", Qt::CaseInsensitive);
    QStringList indexList;
    int pos = 0;
    while ((pos = rx.indexIn(reply, pos)) != -1) {
        indexList << rx.capturedTexts();
        pos += rx.matchedLength();
    }
    foreach (QString index, indexList) {
        qDebug()<<index;
    }

    QRegExp rx1("name: \\s*|'", Qt::CaseInsensitive);
    QStringList nameList;
    pos = 0;
    while ((pos = rx1.indexIn(reply, pos)) != -1) {
        nameList << rx1.capturedTexts();
        pos += rx1.matchedLength();
    }
    foreach (QString index, nameList) {
        qDebug()<<index;
    }
}
else
{
    qDebug()<< "Error using pacmd for getting list of sinks";
}

The output I get from the code is the following:

"index: 0" 
"index: 1" 
"index: 2" 
"name: " 
"name: " 
"name: " 

How can I get the names as well like the following string?

name: <alsa_output.pci-0000_01_00.1.hdmi-stereo>

Is "name: \\s*|'" not the correct pattern for regexp for capturing the name as well?

Thanks.

the_naive
  • 2,936
  • 6
  • 39
  • 68
  • 1
    I think you'll need two `QProcess` instances -- one for `pacmd` and the other for `awk`. Then pipe the output of one into the other using [`QProcess::setStandardOutputProcess`](http://doc.qt.io/qt-5/qprocess.html#setStandardOutputProcess). – G.M. Nov 30 '16 at 12:13
  • Your suggestion lead me to this answer :) http://stackoverflow.com/questions/20901884/piping-or-command-chaining-with-qprocess – the_naive Nov 30 '16 at 12:38

1 Answers1

2

First off the reason why your first try running awk didn't work:

The pipe '|' is a feature of the shell (e.g. bash). When you run an executable with QProcess, this doesn't run the executable in a shell, it runs the executable directly. In your code, the pacmd executable is therefore run with the command line arguments list-sinks and |awk '/index:/ {print $0} /name:/ {print $0};'.

To make it work you either need to first run list-sinks, get its output, and then run awk and pass it this as the input, or if you are fine with depending on a specific shell, you can also run the shell and pass your command line to it (in the case of bash you'd pass -c and pacmd list-sinks|awk '/index:/ {print $0} /name:/ {print $0};' as arguments to /bin/bash).

Regarding parsing for name: something with regular expressions, the expression \s matches whitespace. So just change name: \\s* to name: \\S* (with an upper case S) for getting non-whitespace characters.

E4z9
  • 1,713
  • 9
  • 11