Package: alsaplayer-common
Version: 0.99.76-7
Severity: wishlist
Tags: patch, upstream

Forwarded from Viktor.

---------- Forwarded message ----------
Date: 2006-03-29 14:00:15 -0700
From: Viktor Radnai <[EMAIL PROTECTED]>
Subject: Alsaplayer patch

Hi all,

I'm addressing this to the three of you because...
1.) Andy, you are the author of alsaplayer
2.) Hubert, you are listed as the maintainer of the alsaplayer-gtk Debian 
package
3.) Paul, your name and address is listed with the numerous patches in the 
alsaplayer Debian source package.
(I hope I haven't missed anyone.)

The attached patch contains a number of small features I have added to 
alsaplayer a while ago, mainly to make it easier for myself to practice my bass 
playing along with music. Please feel free to add them to alsaplayer (the 
original source or the Debian package) if you think they are useful.

A summary of the changes:

* Basic keyboard navigation (skip, pause, etc.)
* Loop mode (looping around inside a selection)
* Pressing 'play' button or key during playback returns to the beginning of the 
song
* Speed changes one musical semitone a time using the keyboard shortcut (handy 
for changing the key the song is played back in)

This patch has been laying around on my laptop for a while, for two reasons. 
One is that it still has some bugs, the second is that the said laptop has been 
broken for about six months. It should apply to an unpatched unstable Debian 
alsaplayer source package (0.99.76 is what I used). I presume that this is the 
same as the source tarball available on alsaplayer.org

Hope this will be useful for you.

Cheers,
Vik

diff -ur ./interface/gtk/gladesrc.cpp ../alsaplayer-0.99.76.vik/interface/gtk/gladesrc.cpp
--- ./interface/gtk/gladesrc.cpp	2003-06-07 10:29:43.000000000 +0200
+++ ../alsaplayer-0.99.76.vik/interface/gtk/gladesrc.cpp	2005-04-28 09:18:01.000000000 +0200
@@ -313,11 +313,12 @@
   GtkWidget *load_button;
   GtkWidget *save_button;
   GtkWidget *clear_button;
+  GtkWidget *loop_button;
   GtkWidget *playlist_status;
 
   playlist_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
   gtk_object_set_data (GTK_OBJECT (playlist_window), "playlist_window", playlist_window);
-  gtk_widget_set_usize (playlist_window, 480, 300);
+  gtk_widget_set_usize (playlist_window, 480, 390);
   gtk_window_set_title (GTK_WINDOW (playlist_window), "Queue");
 
   vbox5 = gtk_vbox_new (FALSE, 0);
@@ -457,6 +458,13 @@
   gtk_box_pack_start (GTK_BOX (vbox24), clear_button, FALSE, FALSE, 0);
   gtk_widget_set_usize (clear_button, 70, -2);
 
+  loop_button = gtk_button_new_with_label ("Loop");
+  gtk_widget_ref (loop_button);
+  gtk_object_set_data_full (GTK_OBJECT (playlist_window), "loop_button", loop_button,
+                            (GtkDestroyNotify) gtk_widget_unref);
+  gtk_widget_show (loop_button);
+  gtk_box_pack_start (GTK_BOX (vbox6), loop_button, FALSE, FALSE, 0);
+
   playlist_status = gtk_vbox_new (FALSE, 0);
   gtk_widget_ref (playlist_status);
   gtk_object_set_data_full (GTK_OBJECT (playlist_window), "playlist_status", playlist_status,
diff -ur ./interface/gtk/gtk_interface.cpp ../alsaplayer-0.99.76.vik/interface/gtk/gtk_interface.cpp
--- ./interface/gtk/gtk_interface.cpp	2006-03-27 22:40:19.000000000 +0200
+++ ../alsaplayer-0.99.76.vik/interface/gtk/gtk_interface.cpp	2005-06-06 23:56:18.000000000 +0200
@@ -23,8 +23,10 @@
 #include <unistd.h>
 #include <sys/types.h>
 #include <assert.h>
+#include <math.h>
 //#define NEW_SCALE
 //#define SUBSECOND_DISPLAY 
+#include <assert.h>
 
 #include <algorithm>
 #include "utilities.h"
@@ -35,6 +37,7 @@
 
 #include "support.h"
 #include "gladesrc.h"
+#include "gtk_interface.h"
 #include "pixmaps/f_play.xpm"
 #include "pixmaps/r_play.xpm"
 #include "pixmaps/pause.xpm"
@@ -72,6 +75,8 @@
 #define MIN_BAL_TRESH   BAL_CENTER-10   // Center is a special case
 #define MAX_BAL_TRESH   BAL_CENTER+10   // so we build in some slack
 #define ZERO_PITCH_TRESH 2
+#define EQ_TEMP_STEP(freq, step)        freq * pow(2.0000, (float) step / 12.0)
+#define FPS_HACK	32	// number of audio frames
 
 // Global variables (get rid of these too... ;-) )
 int global_update = 1;
@@ -100,10 +105,24 @@
 	GtkWidget *bal_scale;
 	GtkWidget *pos_scale;
 	GtkWidget *speed_scale;
+	float speed;
 } update_struct;
 
 static update_struct global_ustr;
 
+#define LOOP_OFF	0
+#define LOOP_START_SET	1
+#define LOOP_ON		2
+
+typedef struct  _loop_struct {
+	int state;
+	gfloat start;
+	gfloat end;
+	unsigned int track; // used to exit loop mode when a new song is played
+} loop_struct;
+
+static loop_struct global_loop;
+
 // Static variables  (to be moved into a class, at some point)
 static GtkWidget *play_dialog;
 static int vol_scale[] = {
@@ -127,6 +146,14 @@
 void position_notify(void *data, int pos);
 void notifier_lock();
 void notifier_unlock();
+void play_cb(GtkWidget *widget, gpointer data);
+void pause_cb(GtkWidget *, gpointer data);
+void stop_cb(GtkWidget *, gpointer data);
+void loop_cb(GtkWidget *, gpointer data);
+void forward_skip_cb(GtkWidget *, gpointer data);
+void reverse_skip_cb(GtkWidget *, gpointer data);
+void forward_play_cb(GtkWidget *, gpointer data);
+void reverse_play_cb(GtkWidget *, gpointer data);
 
 void speed_changed(void *, float speed)
 {
@@ -386,7 +413,7 @@
 	adj = GTK_RANGE(ustr->speed_scale)->adjustment;
 
 	//speed_val = (int)GTK_ADJUSTMENT(adj)->value;
-	speed_val = (int)(speed * 100.0); // We need percentages
+	speed_val = (int) round(speed * 100.0); // We need percentages
 	if (speed_val < ZERO_PITCH_TRESH && speed_val > -ZERO_PITCH_TRESH) {
 		sprintf(str, "Speed: pause");
 	}
@@ -518,6 +545,147 @@
 	pthread_exit(NULL);
 }
 
+pthread_t looper_thread;
+pthread_mutex_t looper_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+void looper(void *data)
+{
+	// GtkAdjustment *adj = (GtkAdjustment *)data;
+	loop_struct *loop = &global_loop;
+	update_struct *ustr = &global_ustr;
+	Playlist *pl = (Playlist *)ustr->data;
+	unsigned int track = pl->GetCurrent();
+	CorePlayer *p = pl->GetCorePlayer();
+
+	if (pthread_mutex_trylock(&looper_mutex) != 0) {
+		pthread_exit(NULL);
+	}
+	
+	nice(5);
+	
+	while (loop->state == LOOP_ON && loop->track == track) {
+		if (loop->track != track) {
+			loop->state = LOOP_OFF;
+		} else if(p->GetPosition() >= loop->end) {
+			p->Seek(loop->start);
+			// global_update = 1;	
+		} 
+
+		dosleep(10000);
+	}
+	pthread_mutex_unlock(&looper_mutex);
+	pthread_exit(NULL);
+}
+
+gboolean key_press_cb (GtkWidget *widget, GdkEventKey *event, gpointer data)
+{
+	GtkAdjustment *adj;
+	update_struct *ustr = &global_ustr;
+	
+	/* key definitions are from enum gtk_keymap */
+	switch(event->keyval) {
+		case STOP_KEY:
+			stop_cb(NULL, ustr->data);
+			break;
+		case PLAY_KEY:
+			play_cb(NULL, ustr->data);
+			break;
+		case PAUSE_KEY:
+			pause_cb(NULL, ustr->speed_scale);
+			break;
+		case NEXT_KEY:
+			playlist_window_gtk_next(NULL, ustr->data);
+			break;
+		case PREV_KEY:
+			playlist_window_gtk_prev(NULL, ustr->data);
+			break;
+		case FWD_KEY:
+			forward_skip_cb(NULL, ustr->pos_scale);
+			break;
+		case BACK_KEY:
+			reverse_skip_cb(NULL, ustr->pos_scale);
+			break;
+		case FWD_PLAY_KEY:
+			forward_play_cb(NULL, ustr->speed_scale);
+			break;
+		case REV_PLAY_KEY:
+			reverse_play_cb(NULL, ustr->speed_scale);
+			break;
+		case SPEED_UP_KEY:
+			adj = GTK_RANGE(ustr->speed_scale)->adjustment;
+			gtk_adjustment_set_value(adj, EQ_TEMP_STEP(adj->value, 1));
+			break;
+		case SPEED_DOWN_KEY:
+			adj = GTK_RANGE(ustr->speed_scale)->adjustment;
+			gtk_adjustment_set_value(adj, EQ_TEMP_STEP(adj->value, -1));
+			break;
+		case VOL_UP_KEY:
+			break;
+		case VOL_DOWN_KEY:
+			break;
+		case LOOP_KEY:
+			loop_cb(NULL, ustr->pos_scale);
+			break;
+		default:
+			// printf("Unknown key pressed: %c\n", key);
+			break;
+	}
+	
+	return FALSE;
+}
+
+void loop_cb(GtkWidget *, gpointer data)
+{
+	GtkAdjustment *adj = GTK_RANGE(data)->adjustment;
+	update_struct *ustr = &global_ustr;
+	Playlist *pl = (Playlist *)ustr->data;
+	loop_struct *loop = &global_loop;
+	
+	switch(loop->state) {
+		case LOOP_OFF:
+			loop->track = pl->GetCurrent();
+			loop->start = adj->value;
+			loop->state = LOOP_START_SET;
+			break;
+		case LOOP_START_SET:
+			loop->end = adj->value;
+			loop->state = LOOP_ON;
+			pthread_create(&looper_thread, NULL,
+					(void * (*)(void *))looper, adj);
+			pthread_detach(looper_thread);
+			break;
+		case LOOP_ON:
+			loop->state = LOOP_OFF;
+			break;
+		default:
+			break;
+	}
+
+}
+
+void forward_skip_cb(GtkWidget *, gpointer data)
+{
+	GtkAdjustment *adj;
+	update_struct *ustr = &global_ustr;
+	Playlist *pl = (Playlist *)ustr->data;
+	CorePlayer *p = pl->GetCorePlayer();
+
+	adj = GTK_RANGE(data)->adjustment;
+	p->Seek((int)adj->value + 5 * FPS_HACK);
+	global_update = 1;	
+}
+
+void reverse_skip_cb(GtkWidget *, gpointer data)
+{
+	GtkAdjustment *adj;
+	update_struct *ustr = &global_ustr;
+	Playlist *pl = (Playlist *)ustr->data;
+	CorePlayer *p = pl->GetCorePlayer();
+
+	adj = GTK_RANGE(data)->adjustment;
+	p->Seek((int)adj->value - 5 * FPS_HACK);
+	global_update = 1;	
+}
 
 void forward_play_cb(GtkWidget *, gpointer data)
 {
@@ -562,6 +730,7 @@
 {
 	GtkAdjustment *adj;
 	int smooth_trans;
+	update_struct *ustr = &global_ustr;
 
 	adj = GTK_RANGE(data)->adjustment;
 
@@ -569,18 +738,20 @@
 		
 	if (smooth_trans) {
 		if (destination <= adj->value && destination != 0.0) {
+			ustr->speed = adj->value;
 			destination = 0.0;
 		} else {
-			destination = 100.0;
+			destination = ustr->speed;
 		}	
 		pthread_create(&smoother_thread, NULL,
 			(void * (*)(void *))smoother, adj);
 		pthread_detach(smoother_thread);
 	} else {
 		if (adj->value != 0.0) {
+			ustr->speed = adj->value;
 			gtk_adjustment_set_value(adj, 0.0);
 		} else {
-			gtk_adjustment_set_value(adj, 100.0);
+			gtk_adjustment_set_value(adj, ustr->speed);
 		}
 	}	
 }
@@ -607,15 +778,21 @@
 {
 	Playlist *pl = (Playlist *)data;
 	CorePlayer *p = pl->GetCorePlayer();
-	if (p) {
-		pl->UnPause();
-		if (p->IsPlaying() || !pl->Length()) {
-			eject_cb(widget, data);
-		} else if (!p->IsPlaying() && pl->Length()) {
-			GDK_THREADS_LEAVE();
-			pl->Play(pl->GetCurrent());
-			GDK_THREADS_ENTER();
-		}	
+	if (!p) {
+		return;
+	}
+	pl->UnPause();
+		
+	if (p->IsPlaying()) {
+	/* pressing Play when playing goes to the start of the song */
+		p->Seek(0); 
+	} else if (!pl->Length()) {
+	/* if playlist is empty, prompt for something to play */
+		eject_cb(widget, data);
+	} else if (!p->IsPlaying() && pl->Length()) {
+		GDK_THREADS_LEAVE();
+		pl->Play(pl->GetCurrent());
+		GDK_THREADS_ENTER();
 	}	
 }
 
@@ -694,7 +871,7 @@
 	adj = GTK_RANGE(ustr->pos_scale)->adjustment;
 	if (p->CanSeek()) {
 		adj->lower = 0;
-		adj->upper = p->GetFrames() - 32; // HACK!!
+		adj->upper = p->GetFrames() - FPS_HACK; // HACK!!
 		if (locking)
 			GDK_THREADS_ENTER();
 		gtk_widget_set_sensitive(GTK_WIDGET(ustr->pos_scale), true);
diff -ur ./interface/gtk/gtk_interface.h ../alsaplayer-0.99.76.vik/interface/gtk/gtk_interface.h
--- ./interface/gtk/gtk_interface.h	2002-06-05 19:56:09.000000000 +0200
+++ ../alsaplayer-0.99.76.vik/interface/gtk/gtk_interface.h	2005-05-06 15:25:05.000000000 +0200
@@ -22,10 +22,29 @@
 #include "CorePlayer.h"
 #include "Playlist.h"
 
+#include <gdk/gdkkeysyms.h>
+
 extern gint windows_x_offset;
 extern gint windows_y_offset;
 extern int global_update;
 
 void init_main_window(Playlist *);
 
+enum gtk_keymap {
+	STOP_KEY = GDK_v,
+	PLAY_KEY = GDK_x,
+	PAUSE_KEY = GDK_c,
+	NEXT_KEY = GDK_b,
+	PREV_KEY = GDK_z,
+	FWD_KEY = GDK_g,
+	BACK_KEY = GDK_a,
+	FWD_PLAY_KEY = GDK_f,
+	REV_PLAY_KEY = GDK_s,
+	SPEED_UP_KEY = GDK_t,
+	SPEED_DOWN_KEY = GDK_q,
+	VOL_UP_KEY = GDK_r,
+	VOL_DOWN_KEY = GDK_w,
+	LOOP_KEY = GDK_l
+};
+
 #endif /* _gtk_interface_h_ */
-- System Information:
Debian Release: testing/unstable
  APT prefers unstable
  APT policy: (500, 'unstable'), (500, 'stable'), (101, 'experimental')
Architecture: i386 (i686)
Shell:  /bin/sh linked to /bin/bash
Kernel: Linux 2.6.15.4
Locale: LANG=C, LC_CTYPE=C (charmap=ANSI_X3.4-1968)

Versions of packages alsaplayer-common depends on:
ii  alsaplayer-alsa [alsaplayer- 0.99.76-8   PCM player designed for ALSA (ALSA
ii  alsaplayer-gtk [alsaplayer-i 0.99.76-8   PCM player designed for ALSA (GTK 
ii  alsaplayer-jack [alsaplayer- 0.99.76-8   PCM player designed for ALSA (JACK
ii  alsaplayer-text [alsaplayer- 0.99.76-8   PCM player designed for ALSA (text
ii  libc6                        2.3.5-11    GNU C Library: Shared libraries an
ii  libflac7                     1.1.2-3.1   Free Lossless Audio Codec - runtim
ii  libgcc1                      1:4.1.0-0   GCC support library
ii  libid3tag0                   0.15.1b-7   ID3 tag reading library from the M
ii  libmad0                      0.15.1b-2.1 MPEG audio decoder library
ii  libmikmod2                   3.1.11-a-6  A portable sound library
ii  libogg0                      1.1.3-2     Ogg Bitstream Library
ii  liboggflac3                  1.1.2-3.1   Free Lossless Audio Codec - runtim
ii  libsndfile1                  1.0.11-1    Library for reading/writing audio 
ii  libstdc++6                   4.1.0-0     The GNU Standard C++ Library v3
ii  libvorbis0a                  1.1.2-1     The Vorbis General Audio Compressi
ii  libvorbisfile3               1.1.2-1     The Vorbis General Audio Compressi
ii  zlib1g                       1:1.2.3-11  compression library - runtime

alsaplayer-common recommends no packages.

-- no debconf information

Reply via email to