Skip to content

Instantly share code, notes, and snippets.

@mazhe
Created November 24, 2012 12:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mazhe/4139492 to your computer and use it in GitHub Desktop.
Save mazhe/4139492 to your computer and use it in GitHub Desktop.
OSS backend for e17 mixer module
#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