シンク情報の取得
「シンク」は、サーバーが認識するオーディオ出力を意味します。
各クライアントから送られてきたオーディオデータは、最終的にこのシンクに送られます。
そして、シンクが選択しているハードウェアの端子に、オーディオが送られます。
by_index はシンクのインデックス番号、by_name はシンク名を指定して取得します。
list は、すべてのシンク情報を取得します。
各クライアントから送られてきたオーディオデータは、最終的にこのシンクに送られます。
そして、シンクが選択しているハードウェアの端子に、オーディオが送られます。
シンク情報の取得
pa_operation *pa_context_get_sink_info_by_index(pa_context *c, uint32_t idx, pa_sink_info_cb_t cb, void *userdata); pa_operation *pa_context_get_sink_info_by_name(pa_context *c, const char *name, pa_sink_info_cb_t cb, void *userdata); pa_operation *pa_context_get_sink_info_list(pa_context *c, pa_sink_info_cb_t cb, void *userdata); //コールバック関数 typedef void (*pa_sink_info_cb_t)(pa_context *c, const pa_sink_info *i, int eol, void *userdata);
by_index はシンクのインデックス番号、by_name はシンク名を指定して取得します。
list は、すべてのシンク情報を取得します。
シンクの数
サーバーは、複数のシンクを持つことができます。
ただし、カードのプロファイルごとに、作成されるシンクの数は決まっています。
出力が有効なプロファイルなら、通常は1です。
入力のみのプロファイルであれば、0となります。
ただし、カードのプロファイルごとに、作成されるシンクの数は決まっています。
出力が有効なプロファイルなら、通常は1です。
入力のみのプロファイルであれば、0となります。
プログラム
すべてのシンク情報を取得して、出力するプログラムです。
$ cc -o 07-sink 07-sink.c util.c -lpulse
#include <stdio.h> #include <pulse/pulseaudio.h> #include "util.h" PulseData *pulse; static void _sink_callback(pa_context *c,const pa_sink_info *i,int eol,void *userdata) { int j; char m[64]; pa_sink_port_info *sport; if(!i) { pa_threaded_mainloop_signal(pulse->mainloop, 0); return; } printf("=== [%d] ===\n", i->index); printf("name: %s\n", i->name); printf("description: '%s'\n", i->description); pa_sample_spec_snprint(m, 64, &i->sample_spec); printf("sample_spcec: %s\n", m); pa_channel_map_snprint(m, 64, &i->channel_map); printf("channel_map: '%s'\n", m); printf("owner_module: %u\n", i->owner_module); pa_cvolume_snprint(m, 64, &i->volume); printf("volume: '%s'\n", m); printf("mute: %d\n", i->mute); printf("monitor_source: %u\n", i->monitor_source); printf("monitor_source_name: %s\n", i->monitor_source_name); printf("latency(us): %lu\n", i->latency); printf("driver: %s\n", i->driver); printf("flags: 0x%X\n", i->flags); printf("configured_latency(us): %lu\n", i->configured_latency); pa_volume_snprint(m, 64, i->base_volume); printf("base_volume: %u '%s'\n", i->base_volume, m); printf("state: %d\n", i->state); printf("n_volume_steps: %u\n", i->n_volume_steps); printf("card: %u\n", i->card); printf("n_ports: %u\n", i->n_ports); printf("n_formats: %u\n", i->n_formats); pulse_put_proplist(i->proplist); //ports printf("\n-- ports --\n"); for(j = 0; j < i->n_ports; j++) { sport = i->ports[j]; printf("-[%d]-%s\n", j, (sport == i->active_port)? "(*)": ""); printf("name: %s\n", sport->name); printf("description: %s\n", sport->description); printf("priority: %u\n", sport->priority); printf("available: %d\n", sport->available); printf("availability_group: %s\n", sport->availability_group); printf("type: %u\n", sport->type); } //formats printf("\n-- formats --\n"); for(j = 0; j < i->n_formats; j++) { printf("[%d] encoding:%d\n", j, i->formats[j]->encoding); pulse_put_proplist(i->formats[j]->plist); } printf("\n"); } static pa_operation *_get_info(PulseData *p,void *data) { return pa_context_get_sink_info_list(pulse->ctx, _sink_callback, NULL); } int main(void) { pulse = pulse_connect(0); if(!pulse) return 1; pulse_wait_operation(pulse, _get_info, NULL); pulse_free(pulse); return 0; }
シンク情報 (pa_sink_info)
シンク情報は、pavucontol の「出力デバイス」タブで表示される情報になります。
インデックス番号は、サーバーでシンクが作成されるたびに増加するので、プロファイルを変更したりすると、値が変わります。
typedef struct pa_sink_info { const char *name; uint32_t index; const char *description; pa_sample_spec sample_spec; pa_channel_map channel_map; uint32_t owner_module; pa_cvolume volume; int mute; uint32_t monitor_source; const char *monitor_source_name; pa_usec_t latency; const char *driver; pa_sink_flags_t flags; pa_proplist *proplist; pa_usec_t configured_latency; pa_volume_t base_volume; pa_sink_state_t state; uint32_t n_volume_steps; uint32_t card; uint32_t n_ports; pa_sink_port_info **ports; pa_sink_port_info *active_port; uint8_t n_formats; pa_format_info **formats; } pa_sink_info; //シンクのポート情報 //(値はカードのポート情報と同じ) typedef struct pa_sink_port_info { const char *name; const char *description; uint32_t priority; int available; const char *availability_group; //ver 14.0 uint32_t type; //ver 14.0 } pa_sink_port_info; //フォーマット情報 typedef struct pa_format_info { pa_encoding_t encoding; pa_proplist *plist; } pa_format_info;
name | シンク名 |
---|---|
index | インデックス番号 |
description | シンクの詳細説明 |
sample_spec | サンプルスペック |
channel_map | チャンネルマップ |
owner_module | 所有モジュールのインデックス、または PA_INVALID_INDEX |
volume | 音量 |
mute | 0 以外でミュート状態 |
monitor_source | このシンクに接続されている、モニターソースのインデックス |
monitor_source_name | このシンクに接続されている、モニターソースの名前 |
latency | 出力バッファ内のキューに入れられたオーディオの長さ(マイクロ秒) |
driver | ドライバ名 |
flags | フラグ。 PA_SINK_NOFLAGS (0): フラグなし。 PA_SINK_HW_VOLUME_CTRL: ハードウェア音量コントロールをサポート。これは動的フラグであり、シンクが初期化された後、実行時に変更される可能性がある。 PA_SINK_LATENCY: 遅延要求をサポート。 PA_SINK_HARDWARE: 仮想/ソフトウェアシンクとは対照的に、ある種のハードウェアシンク。 PA_SINK_NETWORK: ある種のネットワーク化されたシンク。 PA_SINK_HW_MUTE_CTRL: ハードウェアのミュート操作をサポート。※動的フラグ PA_SINK_DECIBEL_VOLUME: 音量は、pa_sw_volume_to_dB() で dB に変換できる。※動的 PA_SINK_FLAT_VOLUME: このシンクはフラットボリュームモード。接続されているすべての入力の音量が、常に最大になる。 PA_SINK_DYNAMIC_LATENCY: 遅延は、接続されたストリームの要求に応じて動的に調整できる。 PA_SINK_SET_FORMATS: 接続されたハードウェアが、サポートするフォーマットを設定できる。これを行うための実際の機能は、拡張機能によって提供される場合がある。 |
proplist | プロパティリスト |
configured_latency | このデバイスに設定されているレイテンシ(マイクロ秒) |
base_volume | 出力デバイスのコンテキストで増幅/減衰されていないベース音量 |
state | 状態フラグ。 PA_SINK_INVALID_STATE: サーバーが、シンク状態の取得をサポートしていない。 PA_SINK_RUNNING: 実行中で、シンクが再生中。少なくとも1つの、停止中でないシンク入力によって使用されている。 PA_SINK_IDLE: アイドル状態。シンクは再生できるが、停止中でないシンク入力が接続されていない。 PA_SINK_SUSPENDED: 一時停止。シンクアクセスを閉じることができる。 |
n_volume_steps | 任意の音量値をサポートしない場合の、ボリュームステップの数 |
card | カードのインデックス番号、または PA_INVALID_INDEX |
n_ports | ports 配列の数 |
ports | シンクのポート情報のポインタの配列、または NULL |
active_port | 現在アクティブなシンクポートのポインタ(ports の配列内の一つ)、または NULL |
n_formats | formats 配列の数 |
formats | シンクがサポートしているフォーマット情報のポインタの配列。 出力されるオーディオのエンコーディングタイプ。 |
インデックス番号は、サーバーでシンクが作成されるたびに増加するので、プロファイルを変更したりすると、値が変わります。
出力結果 (1)
選択しているプロファイルが「アナログステレオデュプレックス」の場合。
volume は、音量コントロールなどで表示される値になります。

シンクのポート情報は、基本的にカードのポート情報と同じですが、構造体やメンバは異なります。
シンクの ports 配列は、このシンクで出力できる端子のリストになります。
このシンクにおいて、ハードウェア上のどの端子に音が出力されるかは、active_port で判断できます。
pavucontrol などを使うと、ユーザーが、出力するポートを選択できます。
ここでは、ヘッドホン端子が選択されています。
フォーマットの encoding = 1 は、PA_ENCODING_PCM です。
volume は、音量コントロールなどで表示される値になります。

=== [0] === name: alsa_output.pci-0000_00_1f.3.analog-stereo description: '内部オーディオ アナログステレオ' sample_spcec: s16le 2ch 48000Hz channel_map: 'front-left,front-right' owner_module: 6 volume: '0: 23% 1: 23%' mute: 0 monitor_source: 0 monitor_source_name: alsa_output.pci-0000_00_1f.3.analog-stereo.monitor latency(us): 0 driver: module-alsa-card.c flags: 0xB7 HW_VOLUME_CTRL:LATENCY:HARDWARE:HW_MUTE_CTRL:DECIBEL_VOLUME:DYNAMIC_LATENCY: configured_latency(us): 0 base_volume: 65536 '100%' state: 2 n_volume_steps: 65537 card: 0 n_ports: 2 n_formats: 1 <proplist> alsa.resolution_bits = "16" device.api = "alsa" device.class = "sound" alsa.class = "generic" alsa.subclass = "generic-mix" alsa.name = "ALC892 Analog" alsa.id = "ALC892 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 0xdf140000 irq 130" alsa.driver_name = "snd_hda_intel" device.bus_path = "pci-0000:00:1f.3" sysfs.path = "/devices/pci0000:00/0000:00:1f.3/sound/card0" device.bus = "pci" device.vendor.id = "8086" device.vendor.name = "Intel Corporation" device.product.id = "a170" device.product.name = "100 Series/C230 Series Chipset Family HD Audio Controller" device.form_factor = "internal" device.string = "front:0" device.buffering.buffer_size = "352800" device.buffering.fragment_size = "176400" device.access_mode = "mmap+timer" device.profile.name = "analog-stereo" device.profile.description = "アナログステレオ" device.description = "内部オーディオ アナログステレオ" module-udev-detect.discovered = "1" device.icon_name = "audio-card-pci" -- ports -- -[0]- name: analog-output-lineout description: ライン出力 priority: 9000 available: 1 availability_group: (null) type: 4 -[1]-(*) name: analog-output-headphones description: アナログヘッドフォン priority: 9900 available: 2 availability_group: (null) type: 3 -- formats -- [0] encoding:1 <proplist>
シンクのポート情報は、基本的にカードのポート情報と同じですが、構造体やメンバは異なります。
シンクの ports 配列は、このシンクで出力できる端子のリストになります。
このシンクにおいて、ハードウェア上のどの端子に音が出力されるかは、active_port で判断できます。
pavucontrol などを使うと、ユーザーが、出力するポートを選択できます。
ここでは、ヘッドホン端子が選択されています。
フォーマットの encoding = 1 は、PA_ENCODING_PCM です。
出力結果 (2)
プロファイルが「Digital Stereo (HDMI) 出力」の場合。
=== [10] === name: alsa_output.pci-0000_00_1f.3.hdmi-stereo description: '内部オーディオ Digital Stereo (HDMI)' sample_spcec: s16le 2ch 44100Hz channel_map: 'front-left,front-right' owner_module: 6 volume: '0: 100% 1: 100%' mute: 0 monitor_source: 13 monitor_source_name: alsa_output.pci-0000_00_1f.3.hdmi-stereo.monitor latency(us): 40953 driver: module-alsa-card.c flags: 0x1A6 LATENCY:HARDWARE:DECIBEL_VOLUME:DYNAMIC_LATENCY:SET_FORMATS: configured_latency(us): 40000 base_volume: 65536 '100%' state: 1 n_volume_steps: 65537 card: 0 n_ports: 1 n_formats: 1 <proplist> alsa.resolution_bits = "16" device.api = "alsa" device.class = "sound" alsa.class = "generic" alsa.subclass = "generic-mix" alsa.name = "PHL 224E5" alsa.id = "HDMI 0" alsa.subdevice = "0" alsa.subdevice_name = "subdevice #0" alsa.device = "3" alsa.card = "0" alsa.card_name = "HDA Intel PCH" alsa.long_card_name = "HDA Intel PCH at 0xdf140000 irq 130" alsa.driver_name = "snd_hda_intel" device.bus_path = "pci-0000:00:1f.3" sysfs.path = "/devices/pci0000:00/0000:00:1f.3/sound/card0" device.bus = "pci" device.vendor.id = "8086" device.vendor.name = "Intel Corporation" device.product.id = "a170" device.product.name = "100 Series/C230 Series Chipset Family HD Audio Controller" device.form_factor = "internal" device.string = "hdmi:0" device.buffering.buffer_size = "352800" device.buffering.fragment_size = "176400" device.access_mode = "mmap+timer" device.profile.name = "hdmi-stereo" device.profile.description = "Digital Stereo (HDMI)" device.description = "内部オーディオ Digital Stereo (HDMI)" module-udev-detect.discovered = "1" device.icon_name = "audio-card-pci" -- ports -- -[0]-(*) name: hdmi-output-0 description: HDMI / DisplayPort priority: 5900 available: 2 availability_group: (null) type: 10 -- formats -- [0] encoding:1 <proplist>
シンクの操作
シンクのいくつかの情報は、クライアントから変更できます。
指定したシンクのミュート状態を変更します。
指定したシンクの音量を変更します。
一般的に、PulseAudio の出力の音量を変更したい場合は、この関数を使います。
音量についての詳細は、次回で説明します。
指定したシンクを、一時停止または再開させます。
これにより、このシンクに接続されている、すべてのオーディオ再生を止めることができます。
出力ポートの変更
指定したシンクで、出力先のポートを変更したい場合は、以下の関数を使います。
by_index はシンクのインデックス番号を指定、by_name はシンクの名前を指定します。
port 引数で、変更するポートの名前を指定します。
pa_operation *pa_context_set_sink_port_by_index(pa_context *c, uint32_t idx, const char *port, pa_context_success_cb_t cb, void *userdata); pa_operation *pa_context_set_sink_port_by_name(pa_context *c, const char *name, const char *port, pa_context_success_cb_t cb, void *userdata); //コールバック関数 typedef void (*pa_context_success_cb_t)(pa_context *c, int success, void *userdata);
by_index はシンクのインデックス番号を指定、by_name はシンクの名前を指定します。
port 引数で、変更するポートの名前を指定します。
ミュート状態の変更
pa_operation *pa_context_set_sink_mute_by_index(pa_context *c, uint32_t idx, int mute, pa_context_success_cb_t cb, void *userdata); pa_operation *pa_context_set_sink_mute_by_name(pa_context *c, const char *name, int mute, pa_context_success_cb_t cb, void *userdata);
指定したシンクのミュート状態を変更します。
音量変更
pa_operation *pa_context_set_sink_volume_by_index(pa_context *c, uint32_t idx, const pa_cvolume *volume, pa_context_success_cb_t cb, void *userdata); pa_operation *pa_context_set_sink_volume_by_name(pa_context *c, const char *name, const pa_cvolume *volume, pa_context_success_cb_t cb, void *userdata);
指定したシンクの音量を変更します。
一般的に、PulseAudio の出力の音量を変更したい場合は、この関数を使います。
音量についての詳細は、次回で説明します。
シンクの一時停止
pa_operation *pa_context_suspend_sink_by_name(pa_context *c, const char *sink_name, int suspend, pa_context_success_cb_t cb, void *userdata); pa_operation *pa_context_suspend_sink_by_index(pa_context *c, uint32_t idx, int suspend, pa_context_success_cb_t cb, void *userdata);
指定したシンクを、一時停止または再開させます。
これにより、このシンクに接続されている、すべてのオーディオ再生を止めることができます。