Mercurial > audlegacy-plugins
diff src/timidity/xmms-timidity.c @ 1882:eed7c270e8dd
Fix MILLIONS of Makefiles.
author | Jonathan Schleifer <js@h3c.de> |
---|---|
date | Wed, 26 Sep 2007 14:53:37 +0200 |
parents | src/timidity/src/xmms-timidity.c@d447ee6c8bc0 |
children | 2ebeb7816c5e |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/timidity/xmms-timidity.c Wed Sep 26 14:53:37 2007 +0200 @@ -0,0 +1,436 @@ +/* + xmms-timidity - MIDI Plugin for XMMS + Copyright (C) 2004 Konstantin Korikov <lostclus@ua.fm> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include <config.h> + +#include "audacious/util.h" +#include "audacious/configdb.h" +#include "audacious/main.h" +#include "audacious/vfs.h" +#include <glib.h> +#include <gtk/gtk.h> +#include <string.h> +#include <timidity.h> +#include <stdio.h> +#include "audacious/output.h" +#include <audacious/i18n.h> + +#include "xmms-timidity.h" +#include "interface.h" + +InputPlugin xmmstimid_ip = { + .description = "TiMidity Audio Plugin", + .init = xmmstimid_init, + .about = xmmstimid_about, + .configure = xmmstimid_configure, + .play_file = xmmstimid_play_file, + .stop = xmmstimid_stop, + .pause = xmmstimid_pause, + .seek = xmmstimid_seek, + .get_time = xmmstimid_get_time, + .cleanup = xmmstimid_cleanup, + .get_song_info = xmmstimid_get_song_info, + .is_our_file_from_vfs = xmmstimid_is_our_fd, +}; + +InputPlugin *timidity_iplist[] = { &xmmstimid_ip, NULL }; + +DECLARE_PLUGIN(timidity, NULL, NULL, timidity_iplist, NULL, NULL, NULL, NULL, NULL); + +static struct { + gchar *config_file; + gint rate; + gint bits; + gint channels; + gint buffer_size; +} xmmstimid_cfg; + +static gboolean xmmstimid_initialized = FALSE; +static GThread *xmmstimid_decode_thread; +static gboolean xmmstimid_audio_error = FALSE; +static MidSongOptions xmmstimid_opts; +static MidSong *xmmstimid_song; +static gint xmmstimid_seek_to; + +static GtkWidget *xmmstimid_conf_wnd = NULL, *xmmstimid_about_wnd = NULL; +static GtkEntry + *xmmstimid_conf_config_file; +static GtkToggleButton + *xmmstimid_conf_rate_11000, + *xmmstimid_conf_rate_22000, + *xmmstimid_conf_rate_44100; +static GtkToggleButton + *xmmstimid_conf_bits_8, + *xmmstimid_conf_bits_16; +static GtkToggleButton + *xmmstimid_conf_channels_1, + *xmmstimid_conf_channels_2; + +void xmmstimid_init(void) { + ConfigDb *db; + + xmmstimid_cfg.config_file = NULL; + xmmstimid_cfg.rate = 44100; + xmmstimid_cfg.bits = 16; + xmmstimid_cfg.channels = 2; + xmmstimid_cfg.buffer_size = 512; + + db = bmp_cfg_db_open(); + + if (! bmp_cfg_db_get_string(db, "timidity", "config_file", + &xmmstimid_cfg.config_file)) + xmmstimid_cfg.config_file = g_strdup("/etc/timidity/timidity.cfg"); + + bmp_cfg_db_get_int(db, "timidity", "samplerate", &xmmstimid_cfg.rate); + bmp_cfg_db_get_int(db, "timidity", "bits", &xmmstimid_cfg.bits); + bmp_cfg_db_get_int(db, "timidity", "channels", &xmmstimid_cfg.channels); + bmp_cfg_db_close(db); + + if (mid_init(xmmstimid_cfg.config_file) != 0) { + xmmstimid_initialized = FALSE; + return; + } + xmmstimid_initialized = TRUE; +} + +void xmmstimid_about(void) { + if (!xmmstimid_about_wnd) { + gchar *about_title, *about_text; + about_text = g_strjoin( "" , + _("TiMidity Plugin\nhttp://libtimidity.sourceforge.net\nby Konstantin Korikov") , NULL ); + about_title = g_strdup_printf( _("TiMidity Plugin %s") , PACKAGE_VERSION ); + xmmstimid_about_wnd = audacious_info_dialog( about_title , about_text , _("Ok") , FALSE , NULL , NULL ); + g_signal_connect(G_OBJECT(xmmstimid_about_wnd), "destroy", + (GCallback)gtk_widget_destroyed, &xmmstimid_about_wnd); + g_free(about_title); + g_free(about_text); + } + else + { + gdk_window_raise(xmmstimid_about_wnd->window); + } +} + +void xmmstimid_conf_ok(GtkButton *button, gpointer user_data); + +void xmmstimid_configure(void) { + GtkToggleButton *tb; + if (xmmstimid_conf_wnd == NULL) { + xmmstimid_conf_wnd = create_xmmstimid_conf_wnd(); + +#define get_conf_wnd_item(type, name) \ + type (g_object_get_data(G_OBJECT(xmmstimid_conf_wnd), name)) + + xmmstimid_conf_config_file = get_conf_wnd_item( + GTK_ENTRY, "config_file"); + xmmstimid_conf_rate_11000 = get_conf_wnd_item( + GTK_TOGGLE_BUTTON, "rate_11000"); + xmmstimid_conf_rate_22000 = get_conf_wnd_item( + GTK_TOGGLE_BUTTON, "rate_22000"); + xmmstimid_conf_rate_44100 = get_conf_wnd_item( + GTK_TOGGLE_BUTTON, "rate_44100"); + xmmstimid_conf_bits_8 = get_conf_wnd_item( + GTK_TOGGLE_BUTTON, "bits_8"); + xmmstimid_conf_bits_16 = get_conf_wnd_item( + GTK_TOGGLE_BUTTON, "bits_16"); + xmmstimid_conf_channels_1 = get_conf_wnd_item( + GTK_TOGGLE_BUTTON, "channels_1"); + xmmstimid_conf_channels_2 = get_conf_wnd_item( + GTK_TOGGLE_BUTTON, "channels_2"); + + gtk_signal_connect_object( + get_conf_wnd_item(GTK_OBJECT, "conf_ok"), + "clicked", G_CALLBACK(xmmstimid_conf_ok), + NULL); + } + + gtk_entry_set_text(xmmstimid_conf_config_file, + xmmstimid_cfg.config_file); + switch (xmmstimid_cfg.rate) { + case 11000: tb = xmmstimid_conf_rate_11000; break; + case 22000: tb = xmmstimid_conf_rate_22000; break; + case 44100: tb = xmmstimid_conf_rate_44100; break; + default: tb = NULL; + } + if (tb != NULL) gtk_toggle_button_set_active(tb, TRUE); + switch (xmmstimid_cfg.bits) { + case 8: tb = xmmstimid_conf_bits_8; break; + case 16: tb = xmmstimid_conf_bits_16; break; + default: tb = NULL; + } + if (tb != NULL) gtk_toggle_button_set_active(tb, TRUE); + switch (xmmstimid_cfg.channels) { + case 1: tb = xmmstimid_conf_channels_1; break; + case 2: tb = xmmstimid_conf_channels_2; break; + default: tb = NULL; + } + if (tb != NULL) gtk_toggle_button_set_active(tb, TRUE); + + gtk_widget_show(xmmstimid_conf_wnd); + gdk_window_raise(xmmstimid_conf_wnd->window); +} + +void xmmstimid_conf_ok(GtkButton *button, gpointer user_data) { + ConfigDb *db; + + if (gtk_toggle_button_get_active(xmmstimid_conf_rate_11000)) + xmmstimid_cfg.rate = 11000; + else if (gtk_toggle_button_get_active(xmmstimid_conf_rate_22000)) + xmmstimid_cfg.rate = 22000; + else if (gtk_toggle_button_get_active(xmmstimid_conf_rate_44100)) + xmmstimid_cfg.rate = 44100; + if (gtk_toggle_button_get_active(xmmstimid_conf_bits_8)) + xmmstimid_cfg.bits = 8; + else if (gtk_toggle_button_get_active(xmmstimid_conf_bits_16)) + xmmstimid_cfg.bits = 16; + if (gtk_toggle_button_get_active(xmmstimid_conf_channels_1)) + xmmstimid_cfg.channels = 1; + else if (gtk_toggle_button_get_active(xmmstimid_conf_channels_2)) + xmmstimid_cfg.channels = 2; + + db = bmp_cfg_db_open(); + + g_free(xmmstimid_cfg.config_file); + xmmstimid_cfg.config_file = g_strdup( + gtk_entry_get_text(xmmstimid_conf_config_file)); + + bmp_cfg_db_set_string(db, "timidity", "config_file", xmmstimid_cfg.config_file); + + bmp_cfg_db_set_int(db, "timidity", "samplerate", xmmstimid_cfg.rate); + bmp_cfg_db_set_int(db, "timidity", "bits", xmmstimid_cfg.bits); + bmp_cfg_db_set_int(db, "timidity", "channels", xmmstimid_cfg.channels); + bmp_cfg_db_close(db); + + gtk_widget_hide(xmmstimid_conf_wnd); +} + +static gint xmmstimid_is_our_fd( gchar * filename, VFSFile * fp ) +{ + gchar magic_bytes[4]; + + vfs_fread( magic_bytes , 1 , 4 , fp ); + + if ( !memcmp( magic_bytes , "MThd" , 4 ) ) + return TRUE; + + if ( !memcmp( magic_bytes , "RIFF" , 4 ) ) + { + /* skip the four bytes after RIFF, + then read the next four */ + vfs_fseek( fp , 4 , SEEK_CUR ); + vfs_fread( magic_bytes , 1 , 4 , fp ); + if ( !memcmp( magic_bytes , "RMID" , 4 ) ) + return TRUE; + } + return FALSE; +} + +static void *xmmstimid_play_loop(void *arg) { + InputPlayback *playback = arg; + size_t buffer_size; + void *buffer; + size_t bytes_read; + AFormat fmt; + + buffer_size = ((xmmstimid_opts.format == MID_AUDIO_S16LSB) ? 16 : 8) * + xmmstimid_opts.channels / 8 * + xmmstimid_opts.buffer_size; + + buffer = g_malloc(buffer_size); + if (buffer == NULL) return(NULL); + + fmt = (xmmstimid_opts.format == MID_AUDIO_S16LSB) ? FMT_S16_LE : FMT_S8; + + while (playback->playing) { + bytes_read = mid_song_read_wave(xmmstimid_song, + buffer, buffer_size); + + if (bytes_read != 0) + produce_audio(mid_song_get_time(xmmstimid_song), + fmt, xmmstimid_opts.channels, + bytes_read, buffer, &playback->playing); + else { + playback->eof = TRUE; + playback->output->buffer_free (); + playback->output->buffer_free (); + while (playback->output->buffer_playing()) + g_usleep(10000); + playback->playing = FALSE; + } + + if (xmmstimid_seek_to != -1) { + mid_song_seek(xmmstimid_song, xmmstimid_seek_to * 1000); + playback->output->flush(xmmstimid_seek_to * 1000); + xmmstimid_seek_to = -1; + bytes_read = 0; + } + } + + g_free(buffer); + return(NULL); +} + +static gchar *xmmstimid_get_title(gchar *filename) { + Tuple *input; + gchar *title; + + input = tuple_new_from_filename(filename); + + title = tuple_formatter_make_title_string(input, get_gentitle_format()); + if (title == NULL || *title == '\0') + title = g_strdup(tuple_get_string(input, FIELD_FILE_NAME, NULL)); + + tuple_free(input); + + return title; +} + +void xmmstimid_play_file(InputPlayback * playback) { + char *filename = playback->filename; + MidIStream *stream; + gchar *title; + + if (!xmmstimid_initialized) { + xmmstimid_init(); + if (!xmmstimid_initialized) return; + } + + if (xmmstimid_song != NULL) { + mid_song_free(xmmstimid_song); + xmmstimid_song = NULL; + } + + stream = mid_istream_open_file(filename); + if (stream == NULL) return; + + xmmstimid_audio_error = FALSE; + + xmmstimid_opts.rate = xmmstimid_cfg.rate; + xmmstimid_opts.format = (xmmstimid_cfg.bits == 16) ? + MID_AUDIO_S16LSB : MID_AUDIO_S8; + xmmstimid_opts.channels = xmmstimid_cfg.channels; + xmmstimid_opts.buffer_size = xmmstimid_cfg.buffer_size; + + xmmstimid_song = mid_song_load(stream, &xmmstimid_opts); + mid_istream_close(stream); + + if (xmmstimid_song == NULL) { + xmmstimid_ip.set_info_text(_("Couldn't load MIDI file")); + return; + } + + if (playback->output->open_audio( + (xmmstimid_opts.format == MID_AUDIO_S16LSB) ? + FMT_S16_LE : FMT_S8, + xmmstimid_opts.rate, xmmstimid_opts.channels) == 0) { + xmmstimid_audio_error = TRUE; + mid_song_free(xmmstimid_song); + xmmstimid_song = NULL; + return; + } + + title = xmmstimid_get_title(filename); + xmmstimid_ip.set_info(title, + mid_song_get_total_time(xmmstimid_song), + 0, xmmstimid_opts.rate, xmmstimid_opts.channels); + g_free(title); + + mid_song_start(xmmstimid_song); + playback->playing = TRUE; + playback->eof = FALSE; + xmmstimid_seek_to = -1; + + xmmstimid_decode_thread = g_thread_self(); + playback->set_pb_ready(playback); + xmmstimid_play_loop(playback); +} + +void xmmstimid_stop(InputPlayback * playback) { + if (xmmstimid_song != NULL && playback->playing) { + playback->playing = FALSE; + g_thread_join(xmmstimid_decode_thread); + playback->output->close_audio(); + mid_song_free(xmmstimid_song); + xmmstimid_song = NULL; + } +} + +void xmmstimid_pause(InputPlayback * playback, short p) { + playback->output->pause(p); +} + +void xmmstimid_seek(InputPlayback * playback, int time) { + xmmstimid_seek_to = time; + playback->eof = FALSE; + + while (xmmstimid_seek_to != -1) + g_usleep(10000); +} + +int xmmstimid_get_time(InputPlayback * playback) { + if (xmmstimid_audio_error) + return -2; + if (xmmstimid_song == NULL) + return -1; + if (!playback->playing || (playback->eof && + playback->output->buffer_playing())) + return -1; + + return mid_song_get_time(xmmstimid_song); +} + +void xmmstimid_cleanup(void) { + if (xmmstimid_cfg.config_file) { + free(xmmstimid_cfg.config_file); + xmmstimid_cfg.config_file = NULL; + } + + if (xmmstimid_initialized) + mid_exit(); +} + +void xmmstimid_get_song_info(char *filename, char **title, int *length) { + MidIStream *stream; + MidSongOptions opts; + MidSong *song; + + if (!xmmstimid_initialized) { + xmmstimid_init(); + if (!xmmstimid_initialized) return; + } + + stream = mid_istream_open_file(filename); + if (stream == NULL) return; + + opts.rate = xmmstimid_cfg.rate; + opts.format = (xmmstimid_cfg.bits == 16) ? + MID_AUDIO_S16LSB : MID_AUDIO_S8; + opts.channels = xmmstimid_cfg.channels; + opts.buffer_size = 8; + + song = mid_song_load(stream, &opts); + mid_istream_close(stream); + + if (song == NULL) return; + + *length = mid_song_get_total_time(song); + *title = xmmstimid_get_title(filename); + + mid_song_free(song); +}