mixer/Oss: convert to a class
This commit is contained in:
		| @@ -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; | ||||
| } | ||||
|  | ||||
| inline bool | ||||
| OssMixer::Configure(const config_param *param, GError **error_r) | ||||
| { | ||||
| 	device = config_get_block_string(param, "mixer_device", | ||||
| 					     VOLUME_MIXER_OSS_DEFAULT); | ||||
| 	control = config_get_block_string(param, "mixer_control", NULL); | ||||
|  | ||||
| 	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", control); | ||||
| 			return false; | ||||
| 		} | ||||
| 	} else | ||||
| 		volume_control = SOUND_MIXER_PCM; | ||||
|  | ||||
| 	return true; | ||||
| } | ||||
|  | ||||
| static struct mixer * | ||||
| oss_mixer_init(G_GNUC_UNUSED void *ao, const struct config_param *param, | ||||
| 	       GError **error_r) | ||||
| { | ||||
| 	struct oss_mixer *om = g_new(struct oss_mixer, 1); | ||||
| 	OssMixer *om = new OssMixer(); | ||||
|  | ||||
| 	mixer_init(&om->base, &oss_mixer_plugin); | ||||
| 	if (!om->Configure(param, error_r)) { | ||||
| 		delete om; | ||||
| 		return nullptr; | ||||
| 	} | ||||
|  | ||||
| 	om->device = config_get_block_string(param, "mixer_device", | ||||
| 					     VOLUME_MIXER_OSS_DEFAULT); | ||||
| 	om->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); | ||||
| 			g_set_error(error_r, oss_mixer_quark(), 0, | ||||
| 				    "no such mixer control: %s", om->control); | ||||
| 			return NULL; | ||||
| 		} | ||||
| 	} else | ||||
| 		om->volume_control = SOUND_MIXER_PCM; | ||||
|  | ||||
| 	return &om->base; | ||||
| 	return om; | ||||
| } | ||||
|  | ||||
| static void | ||||
| oss_mixer_finish(struct mixer *data) | ||||
| { | ||||
| 	struct oss_mixer *om = (struct oss_mixer *) data; | ||||
| 	OssMixer *om = (OssMixer *) data; | ||||
|  | ||||
| 	g_free(om); | ||||
| 	delete om; | ||||
| } | ||||
|  | ||||
| void | ||||
| OssMixer::Close() | ||||
| { | ||||
| 	assert(device_fd >= 0); | ||||
|  | ||||
| 	close(device_fd); | ||||
| } | ||||
|  | ||||
| static void | ||||
| oss_mixer_close(struct mixer *data) | ||||
| { | ||||
| 	struct oss_mixer *om = (struct oss_mixer *) data; | ||||
| 	OssMixer *om = (OssMixer *) data; | ||||
| 	om->Close(); | ||||
| } | ||||
|  | ||||
| 	assert(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", | ||||
| 			    device, g_strerror(errno)); | ||||
| 		return false; | ||||
| 	} | ||||
|  | ||||
| 	close(om->device_fd); | ||||
| 	if (control) { | ||||
| 		int 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)); | ||||
| 			Close(); | ||||
| 			return false; | ||||
| 		} | ||||
|  | ||||
| 		if (((1 << volume_control) & devmask) == 0) { | ||||
| 			g_set_error(error_r, oss_mixer_quark(), 0, | ||||
| 				    "mixer control \"%s\" not usable", | ||||
| 				    control); | ||||
| 			Close(); | ||||
| 			return false; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return true; | ||||
| } | ||||
|  | ||||
| static bool | ||||
| oss_mixer_open(struct mixer *data, GError **error_r) | ||||
| { | ||||
| 	struct oss_mixer *om = (struct oss_mixer *) data; | ||||
| 	OssMixer *om = (OssMixer *) data; | ||||
|  | ||||
| 	om->device_fd = open_cloexec(om->device, O_RDONLY, 0); | ||||
| 	if (om->device_fd < 0) { | ||||
| 		g_set_error(error_r, oss_mixer_quark(), errno, | ||||
| 			    "failed to open %s: %s", | ||||
| 			    om->device, g_strerror(errno)); | ||||
| 		return false; | ||||
| 	} | ||||
|  | ||||
| 	if (om->control) { | ||||
| 		int devmask = 0; | ||||
|  | ||||
| 		if (ioctl(om->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); | ||||
| 			return false; | ||||
| 		} | ||||
|  | ||||
| 		if (((1 << om->volume_control) & devmask) == 0) { | ||||
| 			g_set_error(error_r, oss_mixer_quark(), 0, | ||||
| 				    "mixer control \"%s\" not usable", | ||||
| 				    om->control); | ||||
| 			oss_mixer_close(data); | ||||
| 			return false; | ||||
| 		} | ||||
| 	} | ||||
| 	return true; | ||||
| 	return om->Open(error_r); | ||||
| } | ||||
|  | ||||
| static int | ||||
| oss_mixer_get_volume(struct mixer *mixer, GError **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, | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Max Kellermann
					Max Kellermann