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);
+}