ソース情報
「シンク (sink)」は出力のことでしたが、「ソース (source)」は、サーバー側で認識される、オーディオ入力のことです。
シンクと同様に、ソースの情報を取得してみます。
関数名が異なるだけで、シンクの場合とほぼ同じです。
pa_source_info 構造体なども、基本的に内容はシンクと同じです。
monitor_of_sink と monitor_of_sink_name メンバが異なるくらいです。
シンクと同様に、ソースの情報を取得してみます。
ソース情報の取得
pa_operation *pa_context_get_source_info_by_index(pa_context *c, uint32_t idx, pa_source_info_cb_t cb, void *userdata); pa_operation *pa_context_get_source_info_by_name(pa_context *c, const char *name, pa_source_info_cb_t cb, void *userdata); pa_operation *pa_context_get_source_info_list(pa_context *c, pa_source_info_cb_t cb, void *userdata); //コールバック関数 typedef void (*pa_source_info_cb_t)(pa_context *c, const pa_source_info *i, int eol, void *userdata);
関数名が異なるだけで、シンクの場合とほぼ同じです。
情報構造体
typedef struct pa_source_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_of_sink; const char *monitor_of_sink_name; pa_usec_t latency; const char *driver; pa_source_flags_t flags; pa_proplist *proplist; pa_usec_t configured_latency; pa_volume_t base_volume; pa_source_state_t state; uint32_t n_volume_steps; uint32_t card; uint32_t n_ports; pa_source_port_info **ports; pa_source_port_info *active_port; uint8_t n_formats; pa_format_info **formats; } pa_source_info; //ポート情報 typedef struct pa_source_port_info { const char *name; const char *description; uint32_t priority; int available; const char *availability_group; uint32_t type; } pa_source_port_info; //フラグ typedef enum pa_source_flags { PA_SOURCE_NOFLAGS = 0x0000U, PA_SOURCE_HW_VOLUME_CTRL = 0x0001U, PA_SOURCE_LATENCY = 0x0002U, PA_SOURCE_HARDWARE = 0x0004U, PA_SOURCE_NETWORK = 0x0008U, PA_SOURCE_HW_MUTE_CTRL = 0x0010U, PA_SOURCE_DECIBEL_VOLUME = 0x0020U, PA_SOURCE_DYNAMIC_LATENCY = 0x0040U, PA_SOURCE_FLAT_VOLUME = 0x0080U }; //状態 typedef enum pa_source_state { PA_SOURCE_INVALID_STATE = -1, PA_SOURCE_RUNNING = 0, PA_SOURCE_IDLE = 1, PA_SOURCE_SUSPENDED = 2 };
pa_source_info 構造体なども、基本的に内容はシンクと同じです。
monitor_of_sink と monitor_of_sink_name メンバが異なるくらいです。
プログラム
サーバーから、ソースの情報を取得して、出力するプログラムです。
$ cc -o 09-source 09-source.c util.c -lpulse
#include <stdio.h> #include <pulse/pulseaudio.h> #include "util.h" PulseData *pulse; static void _put_flags(uint32_t f) { if(f & PA_SOURCE_HW_VOLUME_CTRL) printf("HW_VOLUME_CTRL:"); if(f & PA_SOURCE_LATENCY) printf("LATENCY:"); if(f & PA_SOURCE_HARDWARE) printf("HARDWARE:"); if(f & PA_SOURCE_NETWORK) printf("NETWORK:"); if(f & PA_SOURCE_HW_MUTE_CTRL) printf("HW_MUTE_CTRL:"); if(f & PA_SOURCE_DECIBEL_VOLUME) printf("DECIBEL_VOLUME:"); if(f & PA_SOURCE_DYNAMIC_LATENCY) printf("DYNAMIC_LATENCY:"); if(f & PA_SOURCE_FLAT_VOLUME) printf("FLAT_VOLUME:"); printf("\n"); } static void _source_callback(pa_context *c,const pa_source_info *i,int eol,void *userdata) { int j; char m[64]; pa_source_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_of_sink: %u\n", i->monitor_of_sink); printf("monitor_of_sink_name: %s\n", i->monitor_of_sink_name); printf("latency(us): %lu\n", i->latency); printf("driver: %s\n", i->driver); printf("flags: 0x%X\n ", i->flags); _put_flags(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_source_info_list(pulse->ctx, _source_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; }
実行結果
pavucontrol などで、オーディオ入力が利用可能なプロファイルを選択しておいてください。
シンクの時とは異なり、2つのソースが作成されています。
「Monitor of 内部オーディオ アナログステレオ」は、flags に HARDWARE がないので、PulseAudio が仮想的に作成したソースです。
物理的なポートは利用できないので、ポート情報はありません。
monitor_of_sink, monitor_of_sink_name は、後で説明しますが、モニターソースが接続しているシンクの、インデックスと名前です。
録音時、このソースに接続すると、シンクでオーディオ出力されたものを、入力にすることができます。
もう一方の「内部オーディオ アナログステレオ」は、ハードウェア上のアナログ入力です。
前面マイク端子・背面マイク端子・ラインインの、3つのポートがあります。
=== [0] === name: alsa_output.pci-0000_00_1f.3.analog-stereo.monitor description: 'Monitor of 内部オーディオ アナログステレオ' sample_spcec: s16le 2ch 44100Hz channel_map: 'front-left,front-right' owner_module: 6 volume: '0: 100% 1: 100%' mute: 0 monitor_of_sink: 0 monitor_of_sink_name: alsa_output.pci-0000_00_1f.3.analog-stereo latency(us): 0 driver: module-alsa-card.c flags: 0x62 LATENCY:DECIBEL_VOLUME:DYNAMIC_LATENCY: configured_latency(us): 0 base_volume: 65536 '100%' state: 2 n_volume_steps: 65537 card: 0 n_ports: 0 n_formats: 1 <proplist> device.description = "Monitor of 内部オーディオ アナログステレオ" device.class = "monitor" 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 = "0" module-udev-detect.discovered = "1" device.icon_name = "audio-card-pci" -- ports -- -- formats -- [0] encoding:1 <proplist> === [1] === name: alsa_input.pci-0000_00_1f.3.analog-stereo description: '内部オーディオ アナログステレオ' sample_spcec: s16le 2ch 44100Hz channel_map: 'front-left,front-right' owner_module: 6 volume: '0: 27% 1: 27%' mute: 0 monitor_of_sink: 4294967295 monitor_of_sink_name: (null) latency(us): 0 driver: module-alsa-card.c flags: 0x77 HW_VOLUME_CTRL:LATENCY:HARDWARE:HW_MUTE_CTRL:DECIBEL_VOLUME:DYNAMIC_LATENCY: configured_latency(us): 0 base_volume: 6554 ' 10%' state: 2 n_volume_steps: 65537 card: 0 n_ports: 3 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-input-front-mic description: フロントマイクロフォン priority: 8500 available: 1 availability_group: (null) type: 5 -[1]- name: analog-input-rear-mic description: リアマイクロフォン priority: 8200 available: 1 availability_group: (null) type: 5 -[2]- name: analog-input-linein description: ラインイン priority: 8100 available: 1 availability_group: (null) type: 4 -- formats -- [0] encoding:1 <proplist>
シンクの時とは異なり、2つのソースが作成されています。
「Monitor of 内部オーディオ アナログステレオ」は、flags に HARDWARE がないので、PulseAudio が仮想的に作成したソースです。
物理的なポートは利用できないので、ポート情報はありません。
monitor_of_sink, monitor_of_sink_name は、後で説明しますが、モニターソースが接続しているシンクの、インデックスと名前です。
録音時、このソースに接続すると、シンクでオーディオ出力されたものを、入力にすることができます。
もう一方の「内部オーディオ アナログステレオ」は、ハードウェア上のアナログ入力です。
前面マイク端子・背面マイク端子・ラインインの、3つのポートがあります。