aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Reisner <dreisner@archlinux.org>2013-01-02 15:27:14 -0500
committerDave Reisner <dreisner@archlinux.org>2013-01-02 15:27:14 -0500
commit4292241040661f4b9b042b24d2f0773de0eb1366 (patch)
treebb251a4c06b5590b06076e10f4d439d1aefa7821
parente35ce0069094c135ed9065f2bda945fdf4b6d83e (diff)
downloadmirror-ponymix-4292241040661f4b9b042b24d2f0773de0eb1366.tar.gz
mirror-ponymix-4292241040661f4b9b042b24d2f0773de0eb1366.tar.bz2
mirror-ponymix-4292241040661f4b9b042b24d2f0773de0eb1366.zip
Derive the card from the targetted device
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
-rw-r--r--ponymix.cc16
-rw-r--r--pulse.cc62
-rw-r--r--pulse.h21
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 <string>
#include <algorithm>
+#include <stdexcept>
// External
#include <pulse/pulseaudio.h>
@@ -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<Device>& devices, const uint32_t& index) {
for (Device& device : devices) {
if (device.index_ == index) return &device;
@@ -172,6 +180,48 @@ Device* PulseClient::get_device(vector<Device>& 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<Device>& 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<typename T>
@@ -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<Device>& 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<Device>& 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<Card>& GetCards() const { return cards_; }
// Get or set the volume of a device.