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