diff options
-rw-r--r-- | src/mixer/OssMixerPlugin.cxx | 143 |
1 files changed, 92 insertions, 51 deletions
diff --git a/src/mixer/OssMixerPlugin.cxx b/src/mixer/OssMixerPlugin.cxx index 8d266b40a..83bc31f9f 100644 --- a/src/mixer/OssMixerPlugin.cxx +++ b/src/mixer/OssMixerPlugin.cxx @@ -40,15 +40,24 @@ #define VOLUME_MIXER_OSS_DEFAULT "/dev/mixer" -struct oss_mixer { - /** the base mixer class */ - struct mixer base; - +class OssMixer : public mixer { const char *device; const char *control; int device_fd; int volume_control; + +public: + OssMixer() { + mixer_init(this, &oss_mixer_plugin); + } + + bool Configure(const config_param *param, GError **error_r); + bool Open(GError **error_r); + void Close(); + + int GetVolume(GError **error_r); + bool SetVolume(unsigned volume, GError **error_r); }; /** @@ -75,95 +84,114 @@ oss_find_mixer(const char *name) return -1; } -static struct mixer * -oss_mixer_init(G_GNUC_UNUSED void *ao, const struct config_param *param, - GError **error_r) +inline bool +OssMixer::Configure(const config_param *param, GError **error_r) { - struct oss_mixer *om = g_new(struct oss_mixer, 1); - - mixer_init(&om->base, &oss_mixer_plugin); - - om->device = config_get_block_string(param, "mixer_device", + device = config_get_block_string(param, "mixer_device", VOLUME_MIXER_OSS_DEFAULT); - om->control = config_get_block_string(param, "mixer_control", NULL); + control = config_get_block_string(param, "mixer_control", NULL); - if (om->control != NULL) { - om->volume_control = oss_find_mixer(om->control); - if (om->volume_control < 0) { - g_free(om); + if (control != NULL) { + volume_control = oss_find_mixer(control); + if (volume_control < 0) { g_set_error(error_r, oss_mixer_quark(), 0, - "no such mixer control: %s", om->control); - return NULL; + "no such mixer control: %s", control); + return false; } } else - om->volume_control = SOUND_MIXER_PCM; + volume_control = SOUND_MIXER_PCM; - return &om->base; + return true; } -static void -oss_mixer_finish(struct mixer *data) +static struct mixer * +oss_mixer_init(G_GNUC_UNUSED void *ao, const struct config_param *param, + GError **error_r) { - struct oss_mixer *om = (struct oss_mixer *) data; + OssMixer *om = new OssMixer(); - g_free(om); + if (!om->Configure(param, error_r)) { + delete om; + return nullptr; + } + + return om; } static void -oss_mixer_close(struct mixer *data) +oss_mixer_finish(struct mixer *data) { - struct oss_mixer *om = (struct oss_mixer *) data; + OssMixer *om = (OssMixer *) data; + + delete om; +} - assert(om->device_fd >= 0); +void +OssMixer::Close() +{ + assert(device_fd >= 0); - close(om->device_fd); + close(device_fd); } -static bool -oss_mixer_open(struct mixer *data, GError **error_r) +static void +oss_mixer_close(struct mixer *data) { - struct oss_mixer *om = (struct oss_mixer *) data; + OssMixer *om = (OssMixer *) data; + om->Close(); +} - om->device_fd = open_cloexec(om->device, O_RDONLY, 0); - if (om->device_fd < 0) { +inline bool +OssMixer::Open(GError **error_r) +{ + device_fd = open_cloexec(device, O_RDONLY, 0); + if (device_fd < 0) { g_set_error(error_r, oss_mixer_quark(), errno, "failed to open %s: %s", - om->device, g_strerror(errno)); + device, g_strerror(errno)); return false; } - if (om->control) { + if (control) { int devmask = 0; - if (ioctl(om->device_fd, SOUND_MIXER_READ_DEVMASK, &devmask) < 0) { + if (ioctl(device_fd, SOUND_MIXER_READ_DEVMASK, &devmask) < 0) { g_set_error(error_r, oss_mixer_quark(), errno, "READ_DEVMASK failed: %s", g_strerror(errno)); - oss_mixer_close(data); + Close(); return false; } - if (((1 << om->volume_control) & devmask) == 0) { + if (((1 << volume_control) & devmask) == 0) { g_set_error(error_r, oss_mixer_quark(), 0, "mixer control \"%s\" not usable", - om->control); - oss_mixer_close(data); + control); + Close(); return false; } } + return true; } -static int -oss_mixer_get_volume(struct mixer *mixer, GError **error_r) +static bool +oss_mixer_open(struct mixer *data, GError **error_r) +{ + OssMixer *om = (OssMixer *) data; + + return om->Open(error_r); +} + +inline int +OssMixer::GetVolume(GError **error_r) { - struct oss_mixer *om = (struct oss_mixer *)mixer; int left, right, level; int ret; - assert(om->device_fd >= 0); + assert(device_fd >= 0); - ret = ioctl(om->device_fd, MIXER_READ(om->volume_control), &level); + ret = ioctl(device_fd, MIXER_READ(volume_control), &level); if (ret < 0) { g_set_error(error_r, oss_mixer_quark(), errno, "failed to read OSS volume: %s", @@ -182,19 +210,25 @@ oss_mixer_get_volume(struct mixer *mixer, GError **error_r) return left; } -static bool -oss_mixer_set_volume(struct mixer *mixer, unsigned volume, GError **error_r) +static int +oss_mixer_get_volume(struct mixer *mixer, GError **error_r) +{ + OssMixer *om = (OssMixer *)mixer; + return om->GetVolume(error_r); +} + +inline bool +OssMixer::SetVolume(unsigned volume, GError **error_r) { - struct oss_mixer *om = (struct oss_mixer *)mixer; int level; int ret; - assert(om->device_fd >= 0); + assert(device_fd >= 0); assert(volume <= 100); level = (volume << 8) + volume; - ret = ioctl(om->device_fd, MIXER_WRITE(om->volume_control), &level); + ret = ioctl(device_fd, MIXER_WRITE(volume_control), &level); if (ret < 0) { g_set_error(error_r, oss_mixer_quark(), errno, "failed to set OSS volume: %s", @@ -205,6 +239,13 @@ oss_mixer_set_volume(struct mixer *mixer, unsigned volume, GError **error_r) return true; } +static bool +oss_mixer_set_volume(struct mixer *mixer, unsigned volume, GError **error_r) +{ + OssMixer *om = (OssMixer *)mixer; + return om->SetVolume(volume, error_r); +} + const struct mixer_plugin oss_mixer_plugin = { oss_mixer_init, oss_mixer_finish, |