From 4292241040661f4b9b042b24d2f0773de0eb1366 Mon Sep 17 00:00:00 2001 From: Dave Reisner Date: Wed, 2 Jan 2013 15:27:14 -0500 Subject: Derive the card from the targetted device MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Unless explicitly specified, target a card based on the selected device. Note that not all devices will be tied to a card. falconindy » put differently, if i have multiple cards, what determines which card is used by pulse for a given app? tanuk » In theory, the logic can be anything (it depends on what policy-implementing modules are loaded). By default, routing is mostly handled by module-stream-restore, which chooses the sink based on the user's previous routing choices. tanuk » If the user hasn't done any routing choices, the fallback logic is to select the current "default sink". tanuk » I don't recommend trying to guess the routing policy. falconindy » i guess my understanding of pulse internals is lacking falconindy » but that's rather enlightening falconindy » is there any way to figure out the connection between a sink and a card? tanuk » Yes... (One moment, I'll look up things.) falconindy » ah. uint32_t card falconindy » appears to be in pa_sink_info falconindy » so that ties the sink to the index of a card? tanuk » Yep. falconindy » awesome, that's good enough for what i need to do tanuk » Not all sinks are part of a card, though, but those that are will have the card index set. falconindy » also good to know --- ponymix.cc | 16 +++++++++++++--- pulse.cc | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---- pulse.h | 21 ++++++++++++++++++++- 3 files changed, 91 insertions(+), 8 deletions(-) diff --git a/ponymix.cc b/ponymix.cc index 824daa6..874728f 100644 --- a/ponymix.cc +++ b/ponymix.cc @@ -146,7 +146,8 @@ static int ListCards(PulseClient& ponymix, int, char*[]) { } static int ListProfiles(PulseClient& ponymix, int, char*[]) { - // TODO: Is there any sense of a "default card" ? + if (opt_card == nullptr) errx(1, "error: no card selected"); + auto card = ponymix.GetCard(opt_card); if (card == nullptr) errx(1, "error: no match found for card: %s", opt_card); @@ -500,15 +501,24 @@ int main(int argc, char* argv[]) { ponymix.Populate(); // defaults + ServerInfo defaults = ponymix.GetDefaults(); opt_action = "defaults"; opt_devtype = DEVTYPE_SINK; - opt_device = ponymix.GetDefaults().sink.c_str(); - opt_card = ponymix.GetCards()[0].Name().c_str(); + opt_device = defaults.sink.c_str(); if (!parse_options(argc, argv)) return 1; argc -= optind; argv += optind; + // cards are tricky... find the one that belongs to the chosen sink. + if (opt_card == nullptr) { + const Device* device = ponymix.GetDevice(opt_device, opt_devtype); + if (device) { + const Card* card = ponymix.GetCard(*device); + if (card) opt_card = card->Name().c_str(); + } + } + return CommandDispatch(ponymix, argc, argv); } diff --git a/pulse.cc b/pulse.cc index e42db12..b765d64 100644 --- a/pulse.cc +++ b/pulse.cc @@ -10,6 +10,7 @@ // C++ #include #include +#include // External #include @@ -155,6 +156,13 @@ Card* PulseClient::GetCard(const string& name) { return nullptr; } +Card* PulseClient::GetCard(const Device& device) { + for (Card& card : cards_) { + if (device.card_idx_ == card.index_) return &card; + } + return nullptr; +} + Device* PulseClient::get_device(vector& devices, const uint32_t& index) { for (Device& device : devices) { if (device.index_ == index) return &device; @@ -172,6 +180,48 @@ Device* PulseClient::get_device(vector& devices, const string& name) { return nullptr; } +Device* PulseClient::GetDevice(const uint32_t& index, enum DeviceType type) { + switch (type) { + case DEVTYPE_SINK: + return GetSink(index); + case DEVTYPE_SOURCE: + return GetSource(index); + case DEVTYPE_SINK_INPUT: + return GetSinkInput(index); + case DEVTYPE_SOURCE_OUTPUT: + return GetSourceOutput(index); + } + throw std::runtime_error("Impossible DeviceType encountered in GetDevice"); +} + +Device* PulseClient::GetDevice(const string& name, enum DeviceType type) { + switch (type) { + case DEVTYPE_SINK: + return GetSink(name); + case DEVTYPE_SOURCE: + return GetSource(name); + case DEVTYPE_SINK_INPUT: + return GetSinkInput(name); + case DEVTYPE_SOURCE_OUTPUT: + return GetSourceOutput(name); + } + throw std::runtime_error("Impossible DeviceType encountered in GetDevice"); +} + +const vector& PulseClient::GetDevices(enum DeviceType type) const { + switch (type) { + case DEVTYPE_SINK: + return GetSinks(); + case DEVTYPE_SOURCE: + return GetSources(); + case DEVTYPE_SINK_INPUT: + return GetSinkInputs(); + case DEVTYPE_SOURCE_OUTPUT: + return GetSourceOutputs(); + } + throw std::runtime_error("Impossible DeviceType encountered in GetDevices"); +} + Device* PulseClient::GetSink(const uint32_t& index) { return get_device(sinks_, index); } @@ -495,7 +545,8 @@ Device::Device(const pa_sink_info* info) : index_(info->index), name_(info->name ? info->name : ""), desc_(info->description), - mute_(info->mute) { + mute_(info->mute), + card_idx_(info->card) { update_volume(info->volume); memcpy(&channels_, &info->channel_map, sizeof(pa_channel_map)); balance_ = pa_cvolume_get_balance(&volume_, &channels_) * 100.0; @@ -510,7 +561,8 @@ Device::Device(const pa_source_info* info) : index_(info->index), name_(info->name ? info->name : ""), desc_(info->description), - mute_(info->mute) { + mute_(info->mute), + card_idx_(info->card) { update_volume(info->volume); memcpy(&channels_, &info->channel_map, sizeof(pa_channel_map)); balance_ = pa_cvolume_get_balance(&volume_, &channels_) * 100.0; @@ -524,7 +576,8 @@ Device::Device(const pa_sink_input_info* info) : type_(DEVTYPE_SINK_INPUT), index_(info->index), name_(info->name ? info->name : ""), - mute_(info->mute) { + mute_(info->mute), + card_idx_(-1) { update_volume(info->volume); memcpy(&channels_, &info->channel_map, sizeof(pa_channel_map)); balance_ = pa_cvolume_get_balance(&volume_, &channels_) * 100.0; @@ -543,7 +596,8 @@ Device::Device(const pa_source_output_info* info) : type_(DEVTYPE_SOURCE_OUTPUT), index_(info->index), name_(info->name ? info->name : ""), - mute_(info->mute) { + mute_(info->mute), + card_idx_(-1) { update_volume(info->volume); volume_percent_ = volume_as_percent(&volume_); balance_ = pa_cvolume_get_balance(&volume_, &channels_) * 100.0; diff --git a/pulse.h b/pulse.h index 9bb0733..2c010b2 100644 --- a/pulse.h +++ b/pulse.h @@ -68,6 +68,7 @@ class Device { pa_channel_map channels_; int mute_; int balance_; + uint32_t card_idx_; Operations ops_; }; @@ -96,6 +97,17 @@ class Card { struct ServerInfo { string sink; string source; + + const string GetDefault(enum DeviceType type) { + switch (type) { + case DEVTYPE_SINK: + return sink; + case DEVTYPE_SOURCE: + return source; + default: + return ""; + } + } }; template @@ -127,6 +139,11 @@ class PulseClient { // devices and cards are cleared before the new data is stored. void Populate(); + // Get a device by index or name and type, or all devices by type. + Device* GetDevice(const uint32_t& index, enum DeviceType type); + Device* GetDevice(const string& name, enum DeviceType type); + const vector& GetDevices(enum DeviceType type) const; + // Get a sink by index or name, or all sinks. Device* GetSink(const uint32_t& index); Device* GetSink(const string& name); @@ -147,9 +164,11 @@ class PulseClient { Device* GetSourceOutput(const string& name); const vector& GetSourceOutputs() const { return source_outputs_; } - // Get a card by index or name, or all cards. + // Get a card by index or name, all cards, or get the card which + // a sink is attached to. Card* GetCard(const uint32_t& index); Card* GetCard(const string& name); + Card* GetCard(const Device& device); const vector& GetCards() const { return cards_; } // Get or set the volume of a device. -- cgit v1.2.3