Created
November 24, 2012 12:34
-
-
Save mazhe/4139492 to your computer and use it in GitHub Desktop.
OSS backend for e17 mixer module
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "e_mod_system.h" | |
#include <sys/uio.h> | |
#include <sys/types.h> | |
#include <fcntl.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <unistd.h> | |
#if defined __FreeBSD__ | |
# include <sys/soundcard.h> | |
#elif defined __NetBSD__ \ | |
|| defined __OpenBSD__ | |
# include <soundcard.h> | |
#endif | |
static const char *sound_device_labels[] = SOUND_DEVICE_LABELS; | |
static const char default_mixer[] = "/dev/mixer"; | |
E_Mixer_System * | |
e_mixer_system_new(const char *name) | |
{ | |
int devfd = 0; | |
if (name == NULL) | |
{ | |
return NULL; | |
} | |
if ((devfd = open(name, O_RDWR)) < 0) | |
{ | |
goto error_open; | |
} | |
/* Offset descriptor value so it won't be tought as NULL pointer */ | |
return (void *)(devfd+1); | |
error_open: | |
fprintf(stderr, "MIXER: Cannot open %s: %s\n", | |
name, | |
strerror(errno)); | |
return NULL; | |
} | |
void | |
e_mixer_system_del(E_Mixer_System *self) | |
{ | |
close((int)(self)-1); | |
} | |
int | |
e_mixer_system_callback_set(E_Mixer_System *self, | |
int (*func)(void *data, E_Mixer_System *self), | |
void *data) | |
{ | |
(void)self; | |
(void)func; | |
(void)data; | |
return 0; | |
} | |
Eina_List * | |
e_mixer_system_get_cards(void) | |
{ | |
Eina_List *cards = NULL; | |
int devfd = 0; | |
int c = 0; | |
if ((devfd = open(default_mixer, O_RDWR)) >= 0) | |
{ | |
close(devfd); | |
cards = eina_list_append(cards, eina_stringshare_add(default_mixer)); | |
} | |
while (1) | |
{ | |
char devpath[32]; | |
snprintf(devpath, 31, "/dev/mixer%d", c); | |
if ((devfd = open(devpath, O_RDWR)) < 0) | |
{ | |
break; | |
} | |
close(devfd); | |
cards = eina_list_append(cards, eina_stringshare_add(devpath)); | |
c++; | |
} | |
return cards; | |
} | |
void | |
e_mixer_system_free_cards(Eina_List *cards) | |
{ | |
eina_list_free(cards); | |
} | |
const char * | |
e_mixer_system_get_default_card(void) | |
{ | |
int devfd = 0; | |
if ((devfd = open(default_mixer, O_RDWR)) < 0) | |
{ | |
goto error_open; | |
} | |
close(devfd); | |
return eina_stringshare_add(default_mixer); | |
error_open: | |
fprintf(stderr, "MIXER: Cannot open %s: %s\n", | |
default_mixer, | |
strerror(errno)); | |
return NULL; | |
} | |
const char * | |
e_mixer_system_get_card_name(const char *card) | |
{ | |
/* Is it possible to get a card name with OSS? */ | |
/* /dev/sndstat don't have a formated output (when it exists...) */ | |
return card; | |
} | |
Eina_List * | |
e_mixer_system_get_channels(E_Mixer_System *self) | |
{ | |
Eina_List *channels = NULL; | |
int devmask = 0x0; | |
short c = 0; | |
if (ioctl((int)self-1, SOUND_MIXER_READ_DEVMASK, &devmask) == -1) | |
{ | |
goto error_ioctl; | |
} | |
for (c = 0; c < SOUND_MIXER_NRDEVICES; c++) | |
{ | |
if ((1 << c) & devmask) | |
{ | |
/* Offset channel value so it won't be tought as NULL pointer */ | |
channels = eina_list_append(channels, (void *)(c+1)); | |
} | |
} | |
return channels; | |
error_ioctl: | |
fprintf(stderr, "MIXER: Cannot check available mixer channels: %s\n", | |
strerror(errno)); | |
return NULL; | |
} | |
void | |
e_mixer_system_free_channels(Eina_List *channels) | |
{ | |
eina_list_free(channels); | |
} | |
Eina_List * | |
e_mixer_system_get_channels_names(E_Mixer_System *self) | |
{ | |
Eina_List *channels_names = NULL; | |
int devmask = 0x0; | |
short c = 0; | |
if (ioctl((int)self-1, SOUND_MIXER_READ_DEVMASK, &devmask) == -1) | |
{ | |
goto error_ioctl; | |
} | |
for (c = 0; c < SOUND_MIXER_NRDEVICES; c++) | |
{ | |
if ((1 << c) & devmask) | |
{ | |
channels_names = | |
eina_list_append(channels_names, | |
eina_stringshare_add(sound_device_labels[c])); | |
} | |
} | |
return channels_names; | |
error_ioctl: | |
fprintf(stderr, "MIXER: Cannot check available mixer channel names: %s\n", | |
strerror(errno)); | |
return NULL; | |
} | |
void | |
e_mixer_system_free_channels_names(Eina_List *channels_names) | |
{ | |
eina_list_free(channels_names); | |
} | |
const char * | |
e_mixer_system_get_default_channel_name(E_Mixer_System *self) | |
{ | |
return eina_stringshare_add(sound_device_labels[SOUND_MIXER_VOLUME]); | |
} | |
E_Mixer_Channel * | |
e_mixer_system_get_channel_by_name(E_Mixer_System *self, const char *name) | |
{ | |
int c = 0; | |
if (self == NULL || name == NULL) | |
{ | |
return NULL; | |
} | |
for (c = 0; c < SOUND_MIXER_NRDEVICES; c++) | |
{ | |
if (strcmp(sound_device_labels[c], name) == 0) | |
{ | |
/* Offset channel value so it won't be tought as NULL pointer */ | |
return (void *)(c+1); | |
} | |
} | |
return NULL; | |
} | |
void | |
e_mixer_system_channel_del(E_Mixer_Channel *channel) | |
{ | |
(void)channel; | |
} | |
const char * | |
e_mixer_system_get_channel_name(E_Mixer_System *self, E_Mixer_Channel *channel) | |
{ | |
const char *name = NULL; | |
(void)self; | |
name = eina_stringshare_add(sound_device_labels[(size_t)channel-1]); | |
return name; | |
} | |
int | |
e_mixer_system_get_volume(E_Mixer_System *self, | |
E_Mixer_Channel *channel, | |
int *left, | |
int *right) | |
{ | |
int vol = 0; | |
if ((!left) || (!right)) | |
{ | |
return 0; | |
} | |
if (ioctl((int)self-1, MIXER_READ((int)channel-1), &vol) == -1) | |
{ | |
goto error_ioctl; | |
} | |
*left = vol & 0xff; | |
*right = (vol & 0xff00) >> 8; | |
return 1; | |
error_ioctl: | |
fprintf(stderr, "MIXER: Cannot get mixer volume: %s\n", | |
strerror(errno)); | |
return 0; | |
} | |
int | |
e_mixer_system_set_volume(E_Mixer_System *self, | |
E_Mixer_Channel *channel, | |
int left, | |
int right) | |
{ | |
int vol = 0; | |
vol |= left & 0xff; | |
vol |= (right & 0xff) << 8; | |
if (ioctl((int)self-1, MIXER_WRITE((int)channel-1), &vol) == -1) | |
{ | |
goto error_ioctl; | |
} | |
return 0; | |
error_ioctl: | |
fprintf(stderr, "MIXER: Cannot set mixer volume: %s\n", | |
strerror(errno)); | |
return 1; | |
} | |
int | |
e_mixer_system_can_mute(E_Mixer_System *self, E_Mixer_Channel *channel) | |
{ | |
/* Mute is not really managed in OSS. Other mixers create a mute sys by | |
* saving/restoring volumes before setting them to zero. */ | |
(void)self; | |
(void)channel; | |
return 0; | |
} | |
int | |
e_mixer_system_get_mute(E_Mixer_System *self, E_Mixer_Channel *channel, int *mute) | |
{ | |
(void)self; | |
(void)channel; | |
if (!mute) | |
{ | |
return 0; | |
} | |
return 1; | |
} | |
int | |
e_mixer_system_set_mute(E_Mixer_System *self, E_Mixer_Channel *channel, int mute) | |
{ | |
(void)self; | |
(void)channel; | |
(void)mute; | |
return 0; | |
} | |
int | |
e_mixer_system_get_state(E_Mixer_System *self, | |
E_Mixer_Channel *channel, | |
E_Mixer_Channel_State *state) | |
{ | |
if (!state) | |
{ | |
return 0; | |
} | |
if (e_mixer_system_get_mute(self, channel, &state->mute) == 0) | |
{ | |
return 0; | |
} | |
if (e_mixer_system_get_volume(self, channel, &state->left, &state->right) == 0) | |
{ | |
return 0; | |
} | |
return 1; | |
} | |
int | |
e_mixer_system_set_state(E_Mixer_System *self, | |
E_Mixer_Channel *channel, | |
const E_Mixer_Channel_State *state) | |
{ | |
if (!state) | |
{ | |
return 0; | |
} | |
if (e_mixer_system_set_mute(self, channel, state->mute) == 0) | |
{ | |
return 0; | |
} | |
if (e_mixer_system_set_volume(self, channel, state->left, state->right) == 0) | |
{ | |
return 0; | |
} | |
return 0; | |
} | |
int | |
e_mixer_system_has_capture(E_Mixer_System *self, E_Mixer_Channel *channel) | |
{ | |
(void)self; | |
(void)channel; | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment