Skip to content

Commit

Permalink
Two mixer channels can be set in the configuration file. They can be …
Browse files Browse the repository at this point in the history
…switched

at run time by pressing x.


git-svn-id: svn://svn.daper.net/moc/trunk@1370 910807d9-36e0-0310-a014-e9ea483e2ba4
  • Loading branch information
daper committed Jun 10, 2005
1 parent 18ce856 commit 0e5aa5b
Show file tree
Hide file tree
Showing 12 changed files with 253 additions and 45 deletions.
132 changes: 97 additions & 35 deletions alsa.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,16 @@ static int alsa_buf_fill = 0;
static int bytes_per_frame;

static snd_mixer_t *mixer_handle = NULL;
static snd_mixer_elem_t *mixer_elem = NULL;
static long mixer_min = -1, mixer_max = -1;
static snd_mixer_elem_t *mixer_elem1 = NULL;
static snd_mixer_elem_t *mixer_elem2 = NULL;
static snd_mixer_elem_t *mixer_elem_curr = NULL;
static long mixer1_min = -1, mixer1_max = -1;
static long mixer2_min = -1, mixer2_max = -1;

/* Volume in range 1-100 despite the actual device resolution. */
static int volume;
/* Volume for first and second mixer in range 1-100 despite the actual device
* resolution. */
static int volume1;
static int volume2;

static void alsa_shutdown ()
{
Expand Down Expand Up @@ -147,22 +152,22 @@ static int fill_capabilities (struct output_driver_caps *caps)
return 1;
}

static int alsa_read_mixer_raw ()
static int alsa_read_mixer_raw (snd_mixer_elem_t *elem)
{
if (mixer_handle) {
long volume = 0;
int nchannels = 0;
int i;

for (i = 0; i < SND_MIXER_SCHN_LAST; i++)
if (snd_mixer_selem_has_playback_channel(mixer_elem,
if (snd_mixer_selem_has_playback_channel(elem,
1 << i)) {
int err;
long vol;

nchannels++;
if ((err = snd_mixer_selem_get_playback_volume(
mixer_elem,
elem,
1 << i,
&vol)) < 0) {
error ("Can't read mixer: %s",
Expand All @@ -184,14 +189,42 @@ static int alsa_read_mixer_raw ()
return -1;
}

static snd_mixer_elem_t *alsa_init_mixer_channel (const char *name,
long *vol_min, long *vol_max)
{
snd_mixer_selem_id_t *sid;
snd_mixer_elem_t *elem;

snd_mixer_selem_id_malloc (&sid);
snd_mixer_selem_id_set_index (sid, 0);
snd_mixer_selem_id_set_name (sid, name);

if (!(elem = snd_mixer_find_selem(mixer_handle, sid))) {
snd_mixer_close (mixer_handle);
mixer_handle = NULL;
error ("Can't find mixer %s", name);
}
else if (!snd_mixer_selem_has_playback_volume(elem)) {
snd_mixer_close (mixer_handle);
mixer_handle = NULL;
error ("Mixer device has no playback volume (%s).", name);
elem = NULL;
}
else {
snd_mixer_selem_get_playback_volume_range (elem,
vol_min, vol_max);
logit ("Opened mixer (%s), volume range: %ld-%ld", name,
*vol_min, *vol_max);
}

snd_mixer_selem_id_free (sid);

return elem;
}

static int alsa_init (struct output_driver_caps *caps)
{
int err;
snd_mixer_selem_id_t *mixer_sid;

snd_mixer_selem_id_alloca (&mixer_sid);
snd_mixer_selem_id_set_index (mixer_sid, 0);
snd_mixer_selem_id_set_name (mixer_sid, options_get_str("AlsaMixer"));

if ((err = snd_mixer_open(&mixer_handle, 0)) < 0) {
error ("Can't open ALSA mixer: %s", snd_strerror(err));
Expand All @@ -214,28 +247,28 @@ static int alsa_init (struct output_driver_caps *caps)
mixer_handle = NULL;
error ("Can't load mixer: %s", snd_strerror(err));
}
else if (!(mixer_elem = snd_mixer_find_selem(mixer_handle,
mixer_sid))) {
snd_mixer_close (mixer_handle);
mixer_handle = NULL;
error ("Can't find mixer: %s", snd_strerror(err));
}
else if (!snd_mixer_selem_has_playback_volume(mixer_elem)) {
snd_mixer_close (mixer_handle);
mixer_handle = NULL;
error ("Mixer device has no playback volume.");
}
else {
snd_mixer_selem_get_playback_volume_range (mixer_elem,
&mixer_min, &mixer_max);
logit ("Opened mixer, volume range: %ld-%ld", mixer_min,
mixer_max);
}

if ((volume = alsa_read_mixer_raw()) != -1) {
mixer_elem1 = alsa_init_mixer_channel (options_get_str("AlsaMixer"),
&mixer1_min, &mixer1_max);

if (mixer_handle) /* mixer_handle could be set to NULL due to error */
mixer_elem2 = alsa_init_mixer_channel (
options_get_str("AlsaMixer2"), &mixer2_min,
&mixer2_max);

mixer_elem_curr = mixer_elem1;

if ((volume1 = alsa_read_mixer_raw(mixer_elem1)) != -1) {

/* Scale the mixer value to 0-100 range */
volume = (volume - mixer_min) * 100 / (mixer_max - mixer_min);
volume1 = (volume1 - mixer1_min) * 100
/ (mixer1_max - mixer1_min);
}
if ((volume2 = alsa_read_mixer_raw(mixer_elem2)) != -1) {

/* Scale the mixer value to 0-100 range */
volume2 = (volume2 - mixer2_min) * 100
/ (mixer2_max - mixer2_min);
}

return fill_capabilities (caps);
Expand Down Expand Up @@ -512,22 +545,34 @@ static int alsa_play (const char *buff, const size_t size)

static int alsa_read_mixer ()
{
return volume;
return mixer_elem_curr == mixer_elem1 ? volume1 : volume2;
}

static void alsa_set_mixer (int vol)
{
if (mixer_handle) {
int err;
long vol_alsa;
long mixer_max, mixer_min;

volume = vol;
vol_alsa = volume * (mixer_max - mixer_min) / 100;
if (mixer_elem_curr == mixer_elem1) {
volume1 = vol;
mixer_max = mixer1_max;
mixer_min = mixer1_min;
}
else {
volume2 = vol;
mixer_max = mixer2_max;
mixer_min = mixer2_min;
}


vol_alsa = vol * (mixer_max - mixer_min) / 100;

debug ("Setting vol to %ld", vol_alsa);

if ((err = snd_mixer_selem_set_playback_volume_all(
mixer_elem, vol_alsa)) < 0)
mixer_elem_curr, vol_alsa)) < 0)
error ("Can't set mixer: %s", snd_strerror(err));
}
}
Expand Down Expand Up @@ -577,6 +622,21 @@ static int alsa_get_rate ()
return params.rate;
}

static void alsa_toggle_mixer_channel ()
{
if (mixer_elem_curr == mixer_elem1)
mixer_elem_curr = mixer_elem2;
else
mixer_elem_curr = mixer_elem1;
}

static char *alsa_get_mixer_channel_name ()
{
if (mixer_elem_curr == mixer_elem1)
return xstrdup (options_get_str("AlsaMixer"));
return xstrdup (options_get_str("AlsaMixer2"));
}

void alsa_funcs (struct hw_funcs *funcs)
{
funcs->init = alsa_init;
Expand All @@ -589,4 +649,6 @@ void alsa_funcs (struct hw_funcs *funcs)
funcs->get_buff_fill = alsa_get_buff_fill;
funcs->reset = alsa_reset;
funcs->get_rate = alsa_get_rate;
funcs->toggle_mixer_channel = alsa_toggle_mixer_channel;
funcs->get_mixer_channel_name = alsa_get_mixer_channel_name;
}
8 changes: 8 additions & 0 deletions audio.c
Original file line number Diff line number Diff line change
Expand Up @@ -929,4 +929,12 @@ struct file_tags *audio_get_curr_tags ()
return player_get_curr_tags ();
}

char *audio_get_mixer_channel_name ()
{
return hw.get_mixer_channel_name ();
}

void audio_toggle_mixer_channel ()
{
hw.toggle_mixer_channel ();
}
16 changes: 16 additions & 0 deletions audio.h
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,20 @@ struct hw_funcs
* \return Sample rate in Hz.
*/
int (*get_rate) ();

/** Toggle the mixer channel.
*
* Toggle between the first and the second mixer channel.
*/
void (*toggle_mixer_channel) ();

/** Get the mixer channel's name.
*
* Get the currently used mixer channel's name.
*
* \return malloc()ed channel's name.
*/
char * (*get_mixer_channel_name) ();
};

/* Does the parameters p1 and p2 are equal? */
Expand Down Expand Up @@ -233,5 +247,7 @@ void audio_state_started_playing ();
int audio_plist_get_serial ();
void audio_plist_set_serial (const int serial);
struct file_tags *audio_get_curr_tags ();
char *audio_get_mixer_channel_name ();
void audio_toggle_mixer_channel ();

#endif
6 changes: 6 additions & 0 deletions config.example
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,15 @@ OSSMixerDevice = /dev/mixer
# OSS Mixer channel: pcm or master
OSSMixerChannel = pcm

# Second OSS Mixer channel: pcm or master
OSSMixerChannel2 = master

# ALSA mixer device
AlsaMixer = PCM

# Second ALSA mixer device
AlsaMixer2 = Master

# ALSA output device
AlsaDevice = default

Expand Down
34 changes: 32 additions & 2 deletions interface.c
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,8 @@ static int waiting_for_plist_load = 0; /* Are we waiting for the playlist we
have loaded and sent to the clients?
*/

static char mixer_name[15] = ""; /* mixer channel's name */

static void xterm_clear_title ()
{
if (has_xterm)
Expand Down Expand Up @@ -426,9 +428,9 @@ static void draw_mixer ()
return;

if (vol == 100)
sprintf (bar, " Vol %d%% ", vol);
sprintf (bar, "%14s %d%% ", mixer_name, vol);
else
sprintf (bar, " Vol %02d%% ", vol);
sprintf (bar, "%14s %02d%% ", mixer_name, vol);

wattrset (info_win, get_color(CLR_FRAME));
mvwaddch (info_win, 0, COLS - 38, lines.rtee);
Expand Down Expand Up @@ -1944,6 +1946,19 @@ static void init_lines ()
}
}

void get_mixer_name ()
{
char *name;

send_int_to_srv (CMD_GET_MIXER_CHANNEL_NAME);
name = get_data_str ();

assert (strlen(name) <= 14);

strcpy (mixer_name, name);
free (name);
}

/* Initialize the interface. args are command line file names. arg_num is the
* number of arguments. */
void init_interface (const int sock, const int logging, char **args,
Expand Down Expand Up @@ -2000,6 +2015,7 @@ void init_interface (const int sock, const int logging, char **args,

main_border ();
get_server_options ();
get_mixer_name ();

if (arg_num) {
process_args (args, arg_num);
Expand Down Expand Up @@ -2260,6 +2276,14 @@ static void update_curr_tags ()
}
}

/* Handle EV_MIXER_CHANGE. */
static void ev_mixer_change ()
{
get_mixer_name ();
update_info_win ();
wrefresh (info_win);
}

/* Handle server event. */
static void server_event (const int event, void *data)
{
Expand Down Expand Up @@ -2328,6 +2352,9 @@ static void server_event (const int event, void *data)
set_iface_status_ref (data);
free (data);
break;
case EV_MIXER_CHANGE:
ev_mixer_change ();
break;
default:
interface_message ("Unknown event: 0x%02x", event);
logit ("Unknown event 0x%02x", event);
Expand Down Expand Up @@ -3616,6 +3643,9 @@ static void menu_key (const int ch)
error ("FastDir10 not "
"defined");
break;
case KEY_CMD_TOGGLE_MIXER:
send_int_to_srv (CMD_TOGGLE_MIXER_CHANNEL);
break;
default:
debug ("Unhandled command: %d", cmd);
fatal ("Unhandled command");
Expand Down
11 changes: 11 additions & 0 deletions jack.c
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,15 @@ static int moc_jack_get_rate ()
return rate;
}

static char *moc_jack_get_mixer_channel_name ()
{
return xstrdup ("soft mixer");
}

static void moc_jack_toggle_mixer_channel ()
{
}

void moc_jack_funcs (struct hw_funcs *funcs)
{
funcs->init = moc_jack_init;
Expand All @@ -304,4 +313,6 @@ void moc_jack_funcs (struct hw_funcs *funcs)
funcs->reset = moc_jack_reset;
funcs->shutdown = moc_jack_shutdown;
funcs->get_rate = moc_jack_get_rate;
funcs->get_mixer_channel_name = moc_jack_get_mixer_channel_name;
funcs->toggle_mixer_channel = moc_jack_toggle_mixer_channel;
}
8 changes: 8 additions & 0 deletions keys.c
Original file line number Diff line number Diff line change
Expand Up @@ -572,6 +572,14 @@ static struct command commands[] = {
CON_MENU,
{ ')', -1 },
1
},
{
KEY_CMD_TOGGLE_MIXER,
"toggle_mixer",
"Toggles the mixer channel",
CON_MENU,
{ 'x', -1 },
1
}
};

Expand Down
1 change: 1 addition & 0 deletions keys.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ enum key_cmd
KEY_CMD_FAST_DIR_8,
KEY_CMD_FAST_DIR_9,
KEY_CMD_FAST_DIR_10,
KEY_CMD_TOGGLE_MIXER,
KEY_CMD_WRONG
};

Expand Down
Loading

0 comments on commit 0e5aa5b

Please sign in to comment.