Репозиторий ALT Linux backports/2.4
Последнее обновление: 9 июля 2008 | Пакетов: 497 | Посещений: 1576674
 поиск   регистрация   авторизация 
 
Группа :: Звук
Пакет: xmms

 Главная   Изменения   Спек   Патчи   Загрузить   Bugs and FR 

Патч: xmms-alsa-backport.patch


Index: Output/alsa/audio.c
===================================================================
RCS file: /cvs/xmms/Output/alsa/audio.c,v
retrieving revision 1.28
retrieving revision 1.34
diff -u -r1.28 -r1.34
--- Output/alsa/audio.c	27 Jan 2004 22:36:45 -0000	1.28
+++ Output/alsa/audio.c	24 Aug 2004 18:30:08 -0000	1.34
@@ -36,12 +36,14 @@
 static snd_mixer_elem_t 	*pcm_element 	    = NULL;
 static snd_mixer_t 		*mixer 		    = NULL;
 
-static gboolean mmap, force_start, going, paused;
+static gboolean mmap, force_start, going = FALSE, paused, mixer_start = TRUE;
 
 static gpointer buffer;
 
 static int alsa_can_pause;
 
+static guint mixer_timeout;
+
 struct snd_format {
 	unsigned int rate;
 	unsigned int channels;
@@ -108,6 +110,7 @@
 
 int alsa_playing(void)
 {
+	debug("Alsa playing: %i %i\n", going, paused);
 	if (!going || paused)
 		return FALSE;
 
@@ -183,14 +186,34 @@
 
 void alsa_pause(short p)
 {
+	int err;
 	debug("alsa_pause");
 	if (p)
 		paused = TRUE;
 
-	if (alsa_can_pause)
-		snd_pcm_pause(alsa_pcm, p);
-	else if (p)
-		snd_pcm_drop(alsa_pcm);
+	if (alsa_pcm && going)
+	{
+		if (alsa_can_pause)
+		{
+			if ((err = snd_pcm_pause (alsa_pcm, p)) < 0)
+				g_warning("snd_pcm_pause() failed: %s",
+					  snd_strerror(-err));
+		}
+		else
+		{
+			if (p)
+			{
+				if ((err = snd_pcm_drop (alsa_pcm)) < 0)
+					g_warning("snd_pcm_drop() failed: %s",
+						  snd_strerror(-err));
+			}
+			else
+				if ((err = snd_pcm_prepare (alsa_pcm)) < 0)
+					g_warning("snd_pcm_prepare() failed: %s",
+						  snd_strerror(-err));
+			force_start = FALSE;
+		}
+	}
 
 	if (!p)
 		paused = FALSE;
@@ -205,14 +228,6 @@
 	started = going;
 	going = 0;
 
-	pcm_element = NULL;
-
-	if (mixer)
-	{
-		snd_mixer_close(mixer);
-		mixer = NULL;
-	}
-
 	if (alsa_pcm != NULL)
 	{
 		if (started)
@@ -406,28 +421,45 @@
 	return 0;
 }
 
+static int alsa_mixer_timeout(void *data)
+{
+	if (mixer)
+	{
+		snd_mixer_close(mixer);
+		mixer = NULL;
+		pcm_element = NULL;
+	}
+	mixer_timeout = 0;
+	mixer_start = TRUE;
+
+	g_message("alsa mixer timed out");
+	return FALSE;
+}
+
+
+
 void alsa_get_volume(int *l, int *r)
 {
-	static gboolean first = TRUE;
 	long ll = *l, lr = *r;
 
-	if (first)
+	if (mixer_start)
 	{
 		alsa_setup_mixer();
-		first = !first;
+		mixer_start = FALSE;
 	}
 
-	if (!pcm_element)
-		return;
-
-	snd_mixer_handle_events(mixer);
-
 	if (alsa_cfg.soft_volume)
 	{
 		*l = alsa_cfg.vol.left;
 		*r = alsa_cfg.vol.right;
 	}
-	else
+
+	if (!pcm_element)
+		return;
+
+	snd_mixer_handle_events(mixer);
+
+	if (!alsa_cfg.soft_volume)
 	{
 		snd_mixer_selem_get_playback_volume(pcm_element,
 						    SND_MIXER_SCHN_FRONT_LEFT,
@@ -438,26 +470,28 @@
 		*l = ll;
 		*r = lr;
 	}
+	if (mixer_timeout)
+		gtk_timeout_remove(mixer_timeout);
+	mixer_timeout = gtk_timeout_add(5000, alsa_mixer_timeout, NULL);
 }
 
 
 void alsa_set_volume(int l, int r)
 {
-	if (!pcm_element)
-		return;
-
 	if (alsa_cfg.soft_volume)
 	{
 		alsa_cfg.vol.left = l;
 		alsa_cfg.vol.right = r;
+		return;
 	}
-	else
-	{
-		snd_mixer_selem_set_playback_volume(pcm_element,
-						    SND_MIXER_SCHN_FRONT_LEFT, l);
-		snd_mixer_selem_set_playback_volume(pcm_element,
-						    SND_MIXER_SCHN_FRONT_RIGHT, r);
-	}
+
+	if (!pcm_element)
+		return;
+
+	snd_mixer_selem_set_playback_volume(pcm_element,
+					    SND_MIXER_SCHN_FRONT_LEFT, l);
+	snd_mixer_selem_set_playback_volume(pcm_element,
+					    SND_MIXER_SCHN_FRONT_RIGHT, r);
 }
 
 
@@ -499,7 +533,7 @@
 #define MONO_ADJUST(type, type2, endian)					\
 do {										\
 	type *ptr = data;							\
-	for (i = 0; i < length; i += 4)						\
+	for (i = 0; i < length; i += 2)						\
 	{									\
 		*ptr = type2##_TO_##endian(type2##_FROM_## endian(*ptr) *	\
 					   vol / 100);				\
@@ -530,7 +564,7 @@
 #define MONO_ADJUST8(type)			\
 do {						\
 	type *ptr = data;			\
-	for (i = 0; i < length; i += 4)		\
+	for (i = 0; i < length; i++)		\
 	{					\
 		*ptr = *ptr * vol / 100;	\
 		ptr++;				\
@@ -727,6 +761,14 @@
 		alsa_total_written += cnt;
 		
 		length -= cnt;
+
+		if (length > 0 &&
+		    snd_pcm_state(alsa_pcm) == SND_PCM_STATE_PREPARED)
+		{
+			if ((err = snd_pcm_start(alsa_pcm)) < 0)
+				g_warning("alsa_mmap_audio(): snd_pcm_start() "
+					  "failed: %s", snd_strerror(-err));
+		}
 	}
 }
 
@@ -747,7 +789,8 @@
 		return 0;
 	}
 
-	alsa_setup_mixer();
+	if (!mixer)
+		alsa_setup_mixer();
 
 	convertb = xmms_convert_buffers_new();
 	
Index: Output/alsa/configure.c
===================================================================
RCS file: /cvs/xmms/Output/alsa/configure.c,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -r1.16 -r1.17
--- Output/alsa/configure.c	17 Jan 2004 12:37:19 -0000	1.16
+++ Output/alsa/configure.c	25 Apr 2004 22:33:26 -0000	1.17
@@ -21,10 +21,12 @@
 
 static GtkWidget *configure_win = NULL;
 static GtkWidget *buffer_time_spin, *period_time_spin;
-static GtkWidget *mmap_button, *mixer_card_spin, *softvolume_toggle_button;
+static GtkWidget *mmap_button, *softvolume_toggle_button;
 
 static GtkWidget *devices_combo, *mixer_devices_combo;
 
+static int current_mixer_card;
+
 #define GET_SPIN_INT(spin) \
 	gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(spin))
 #define GET_TOGGLE(tb) gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(tb))
@@ -38,7 +40,7 @@
 	alsa_cfg.period_time = GET_SPIN_INT(period_time_spin);
 	alsa_cfg.mmap = GET_TOGGLE(mmap_button);
 	alsa_cfg.soft_volume = GET_TOGGLE(softvolume_toggle_button);
-	alsa_cfg.mixer_card = GET_SPIN_INT(mixer_card_spin);
+	alsa_cfg.mixer_card = current_mixer_card;
 	alsa_cfg.mixer_device = GET_CHARS(GTK_COMBO(mixer_devices_combo)->entry);
 	
 	alsa_save_config();
@@ -63,10 +65,50 @@
 	xmms_cfg_free(cfgfile);
 }
 
+static int get_cards(GtkOptionMenu *omenu, GtkSignalFunc cb, int active)
+{
+	GtkWidget *menu, *item;
+	int card = -1, err, set = 0, curr = -1;
+
+	menu = gtk_menu_new();
+	if ((err = snd_card_next(&card)) != 0)
+		g_warning("snd_next_card() failed: %s", snd_strerror(-err));
+	
+	while (card > -1)
+	{
+		char *label;
+
+		curr++;
+		if (card == active)
+			set = curr;
+		if ((err = snd_card_get_name(card, &label)) != 0)
+		{
+			g_warning("snd_carg_get_name() failed: %s",
+				  snd_strerror(-err));
+			break;
+		}
+		
+		item = gtk_menu_item_new_with_label(label);
+		gtk_signal_connect(GTK_OBJECT(item), "activate", cb,
+				   GINT_TO_POINTER(card));
+		gtk_widget_show(item);
+		gtk_menu_append(GTK_MENU(menu), item);
+		if ((err = snd_card_next(&card)) != 0)
+		{
+			g_warning("snd_next_card() failed: %s",
+				  snd_strerror(-err));
+			break;
+		}
+	}
+
+	gtk_option_menu_set_menu(omenu, menu);
+	return set;
+}
+
 static int get_mixer_devices(GtkCombo *combo, int card)
 {	
 	GList *items = NULL;
-	int err = 0;
+	int err;
 	snd_mixer_t *mixer;
 	snd_mixer_elem_t *current;
 
@@ -92,12 +134,10 @@
 static void get_devices_for_card(GtkCombo *combo, int card)
 {
 	GtkWidget *item;
-	int pcm_device = -1;
-	int err = 0;
+	int pcm_device = -1, err;
 	snd_pcm_info_t *pcm_info;
 	snd_ctl_t *ctl;
-	char dev[64];
-	char *card_name;
+	char dev[64], *card_name;
 	
 	sprintf(dev, "hw:%i", card);
 
@@ -192,29 +232,32 @@
 
 static void mixer_card_cb(GtkWidget * widget, gpointer card)
 {
-	if (get_mixer_devices(GTK_COMBO(mixer_devices_combo),
-			      gtk_spin_button_get_value_as_int(
-				      GTK_SPIN_BUTTON(mixer_card_spin))) < 0)
-		gtk_spin_button_set_value(GTK_SPIN_BUTTON(mixer_card_spin),
-					  0);
+	if (current_mixer_card == GPOINTER_TO_INT(card))
+		return;
+	current_mixer_card = GPOINTER_TO_INT(card);
+	get_mixer_devices(GTK_COMBO(mixer_devices_combo),
+			  current_mixer_card);
 }
 
 static void softvolume_toggle_cb(GtkToggleButton * widget, gpointer data)
 {
 	gboolean softvolume = gtk_toggle_button_get_active(widget);
-	gtk_widget_set_sensitive(GTK_WIDGET(mixer_card_spin), !softvolume);
-	gtk_widget_set_sensitive(GTK_WIDGET(mixer_devices_combo), !softvolume);
+	gtk_widget_set_sensitive(GTK_WIDGET(data), !softvolume);
+	gtk_widget_set_sensitive(mixer_devices_combo, !softvolume);
 }
 
 void alsa_configure(void)
 {
 	GtkWidget *vbox, *notebook;
 	GtkWidget *dev_vbox, *adevice_frame, *adevice_box;
-	GtkWidget *mixer_frame, *mixer_box, *mixer_card_box;
+	GtkWidget *mixer_frame, *mixer_box, *mixer_table, *mixer_card_om;
+	GtkWidget *mixer_card_label, *mixer_device_label;
 	GtkWidget *buffer_frame, *buffer_vbox, *buffer_table;
 	GtkWidget *buffer_time_label, *period_time_label;
-	GtkObject *buffer_time_adj, *period_time_adj, *mixer_card_adj;
+	GtkObject *buffer_time_adj, *period_time_adj;
 	GtkWidget *bbox, *ok, *cancel;
+
+	int mset;
 	
 	if (configure_win)
 	{
@@ -229,7 +272,7 @@
 	gtk_window_set_title(GTK_WINDOW(configure_win),
 			     _("ALSA Driver configuration"));
 	gtk_window_set_policy(GTK_WINDOW(configure_win),
-			      FALSE, FALSE, FALSE);
+			      FALSE, TRUE, FALSE);
 	gtk_container_border_width(GTK_CONTAINER(configure_win), 10);
 	
 	vbox = gtk_vbox_new(FALSE, 10);
@@ -264,42 +307,46 @@
 	
 	softvolume_toggle_button = gtk_check_button_new_with_label(
 		_("Use software volume control"));
-	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(softvolume_toggle_button),
-				     alsa_cfg.soft_volume);
-
-	gtk_signal_connect(GTK_OBJECT(softvolume_toggle_button), "toggled", 
-			   softvolume_toggle_cb, NULL);
 
 	gtk_box_pack_start(GTK_BOX(mixer_box), softvolume_toggle_button,
 			   FALSE, FALSE, 0);
 
-	mixer_card_box = gtk_hbox_new(FALSE, 5);
-	gtk_box_pack_start(GTK_BOX(mixer_box), mixer_card_box,
-			   FALSE, FALSE, 0);
-	gtk_box_pack_start(GTK_BOX(mixer_card_box), 
-			   gtk_label_new(_("Mixer card:")), FALSE, FALSE, 0);
-
-	mixer_card_adj = gtk_adjustment_new(alsa_cfg.mixer_card,
-					    0, 50, 1, 100, 100);
-	mixer_card_spin = gtk_spin_button_new(GTK_ADJUSTMENT(mixer_card_adj),
-					      8, 0);
-	
-	gtk_signal_connect(GTK_OBJECT(mixer_card_spin), "changed", 
-			   mixer_card_cb, NULL);
+	mixer_table = gtk_table_new(2, 2, FALSE);
+	gtk_table_set_row_spacings(GTK_TABLE(mixer_table), 5);
+	gtk_table_set_col_spacings(GTK_TABLE(mixer_table), 5);
+	gtk_box_pack_start(GTK_BOX(mixer_box), mixer_table, FALSE, FALSE, 0);
+
+	mixer_card_label = gtk_label_new(_("Mixer card:"));
+	gtk_label_set_justify(GTK_LABEL(mixer_card_label), GTK_JUSTIFY_LEFT);
+	gtk_misc_set_alignment(GTK_MISC(mixer_card_label), 0, 0.5);
+	gtk_table_attach(GTK_TABLE(mixer_table), mixer_card_label,
+			 0, 1, 0, 1, GTK_FILL, 0, 0, 0);
 
-	gtk_box_pack_start(GTK_BOX(mixer_card_box), mixer_card_spin,
-			   FALSE, FALSE, 0);
-	
-	gtk_box_pack_start(GTK_BOX(mixer_card_box),
-			   gtk_label_new(_("Mixer device:")), FALSE, FALSE, 0);
-	
+	mixer_card_om = gtk_option_menu_new();
+	mset = get_cards(GTK_OPTION_MENU(mixer_card_om),
+			 mixer_card_cb, alsa_cfg.mixer_card);
+
+	gtk_table_attach(GTK_TABLE(mixer_table), mixer_card_om,
+			 1, 2, 0, 1, GTK_FILL | GTK_EXPAND, GTK_FILL, 0, 0);
+
+	mixer_device_label = gtk_label_new(_("Mixer device:"));
+	gtk_label_set_justify(GTK_LABEL(mixer_device_label), GTK_JUSTIFY_LEFT);
+	gtk_misc_set_alignment(GTK_MISC(mixer_device_label), 0, 0.5);
+	gtk_table_attach(GTK_TABLE(mixer_table), mixer_device_label,
+			 0, 1, 1, 2, GTK_FILL, 0, 0, 0);
 	mixer_devices_combo = gtk_combo_new();
+	gtk_option_menu_set_history(GTK_OPTION_MENU(mixer_card_om), mset);
 	get_mixer_devices(GTK_COMBO(mixer_devices_combo), alsa_cfg.mixer_card);
 	gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(mixer_devices_combo)->entry),
 			   alsa_cfg.mixer_device);
 	
-	gtk_box_pack_start(GTK_BOX(mixer_card_box), 
-			   mixer_devices_combo, TRUE, TRUE, 0);
+	gtk_table_attach(GTK_TABLE(mixer_table), mixer_devices_combo,
+			 1, 2, 1, 2, GTK_FILL | GTK_EXPAND, 0, 0, 0);
+	
+	gtk_signal_connect(GTK_OBJECT(softvolume_toggle_button), "toggled", 
+			   softvolume_toggle_cb, mixer_card_om);
+	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(softvolume_toggle_button),
+				     alsa_cfg.soft_volume);
 
 	gtk_notebook_append_page(GTK_NOTEBOOK(notebook), dev_vbox,
 				 gtk_label_new(_("Device settings")));
@@ -371,6 +418,4 @@
 	gtk_box_pack_start(GTK_BOX(bbox), cancel, TRUE, TRUE, 0);
 	
 	gtk_widget_show_all(configure_win);
-
-	softvolume_toggle_cb(GTK_TOGGLE_BUTTON(softvolume_toggle_button), NULL);
 }
 
design & coding: Vladimir Lettiev aka crux © 2004-2005