Mercurial > audlegacy-plugins
view src/vtx/vtx.c @ 943:584ab2a62af5 trunk
[svn] - if handle->cancel = TRUE, immediately abort the fread operation.
author | nenolod |
---|---|
date | Thu, 12 Apr 2007 12:02:56 -0700 |
parents | 26ff35aa9b2b |
children | cd854e8ced20 |
line wrap: on
line source
/* VTXplugin - VTX player for XMMS * * Copyright (C) 2002-2004 Sashnov Alexander * * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include <audacious/plugin.h> #include <audacious/output.h> #include <audacious/util.h> #include <audacious/titlestring.h> #include <audacious/vfs.h> #include <audacious/strings.h> #include <audacious/i18n.h> #include "vtx.h" #include <ayemu.h> extern InputPlugin vtx_ip; #define SNDBUFSIZE 1024 char sndbuf[SNDBUFSIZE]; static GThread *play_thread = NULL; int seek_to; int freq = 44100; int chans = 2; /* NOTE: if you change 'bits' you also need change constant FMT_S16_NE * to more appropriate in line * * (vtx_ip.output->open_audio (FMT_S16_NE, * freq, chans) == 0) * in function vtx_play_file() * * and in produce_audio() function call. */ const int bits = 16; ayemu_ay_t ay; ayemu_vtx_t vtx; static gchar *vtx_fmts[] = { "vtx", NULL }; int vtx_is_our_fd (char *filename, VFSFile *fp) { char buf[2]; vfs_fread (buf, 2, 1, fp); return (!strncasecmp (buf, "ay", 2) || !strncasecmp (buf, "ym", 2)); } int vtx_is_our_file (char *filename) { gboolean ret; VFSFile *fp; fp = vfs_fopen(filename, "rb"); ret = vtx_is_our_fd(filename, fp); vfs_fclose(fp); return ret; } TitleInput * vtx_get_song_tuple_from_vtx(const gchar *filename, ayemu_vtx_t *in) { TitleInput *out = bmp_title_input_new(); gchar *string; out->performer = g_strdup(in->hdr.author); out->track_name = g_strdup(in->hdr.title); out->file_name = g_strdup(g_basename(filename)); out->file_path = g_path_get_dirname(filename); if ((string = strrchr(out->file_name, '.'))) { out->file_ext = string + 1; *string = '\0'; } out->length = in->hdr.regdata_size / 14 * 1000 / 50; return out; } TitleInput * vtx_get_song_tuple(gchar *filename) { ayemu_vtx_t tmp; if (ayemu_vtx_open (&tmp, filename)) { TitleInput *ti = vtx_get_song_tuple_from_vtx(filename, &tmp); ayemu_vtx_free(&tmp); return ti; } return NULL; } /* sound playing thread, runing by vtx_play_file() */ static gpointer play_loop (gpointer args) { InputPlayback *playback = (InputPlayback *) args; void *stream; /* pointer to current position in sound buffer */ unsigned char regs[14]; int need; int left; /* how many sound frames can play with current AY register frame */ int donow; int rate; left = 0; rate = chans * (bits / 8); while (playback->playing && !playback->eof) { /* fill sound buffer */ stream = sndbuf; for (need = SNDBUFSIZE / rate ; need > 0 ; need -= donow) if (left > 0) { /* use current AY register frame */ donow = (need > left) ? left : need; left -= donow; stream = ayemu_gen_sound (&ay, (char *)stream, donow * rate); } else { /* get next AY register frame */ if (ayemu_vtx_get_next_frame (&vtx, regs) == 0) { playback->eof = TRUE; donow = need; memset (stream, 0, donow * rate); } else { left = freq / vtx.hdr.playerFreq; ayemu_set_regs (&ay, regs); donow = 0; } } while (playback->output->buffer_free () < SNDBUFSIZE && playback->playing && seek_to == -1) g_usleep(10000); if (playback->playing && seek_to == -1) produce_audio(playback->output->written_time (), FMT_S16_NE, chans , SNDBUFSIZE, sndbuf, &playback->playing); if (playback->eof) { playback->output->buffer_free (); playback->output->buffer_free (); } /* jump to time in seek_to (in seconds) */ if (seek_to != -1) { vtx.pos = seek_to * 50; /* (time in sec) * 50 = offset in AY register data frames */ playback->output->flush (seek_to * 1000); seek_to = -1; } } /* close sound and release vtx file must be done in vtx_stop() */ g_thread_exit (NULL); return NULL; } void vtx_play_file (InputPlayback *playback) { gchar *filename = playback->filename; gchar *buf; TitleInput *ti; memset (&ay, 0, sizeof(ay)); if (!ayemu_vtx_open (&vtx, filename)) g_print ("libvtx: Error read vtx header from %s\n", filename); else if (!ayemu_vtx_load_data (&vtx)) g_print ("libvtx: Error read vtx data from %s\n", filename); else { ayemu_init(&ay); ayemu_set_chip_type(&ay, vtx.hdr.chiptype, NULL); ayemu_set_chip_freq(&ay, vtx.hdr.chipFreq); ayemu_set_stereo(&ay, vtx.hdr.stereo, NULL); playback->error = FALSE; if (playback->output->open_audio (FMT_S16_NE, freq, chans) == 0) { g_print ("libvtx: output audio error!\n"); playback->error = TRUE; playback->playing = FALSE; return; } playback->eof = FALSE; seek_to = -1; ti = vtx_get_song_tuple_from_vtx(playback->filename, &vtx); buf = xmms_get_titlestring(xmms_get_gentitle_format(), ti); vtx_ip.set_info (buf, vtx.hdr.regdata_size / 14 * 1000 / 50, 14 * 50 * 8, freq, bits / 8); g_free (buf); bmp_title_input_free(ti); playback->playing = TRUE; play_thread = g_thread_create (play_loop, playback, TRUE, NULL); } } void vtx_stop (InputPlayback *playback) { if (playback->playing && play_thread != NULL) { playback->playing = FALSE; g_thread_join (play_thread); play_thread = NULL; playback->output->close_audio (); ayemu_vtx_free (&vtx); } } /* seek to specified number of seconds */ void vtx_seek (InputPlayback *playback, int time) { if (time * 50 < vtx.hdr.regdata_size / 14) { playback->eof = FALSE; seek_to = time; /* wait for affect changes in parallel thread */ while (seek_to != -1) g_usleep (10000); } } /* Pause or unpause */ void vtx_pause (InputPlayback *playback, short p) { playback->output->pause (p); } /* Function to grab the title string */ void vtx_get_song_info (char *filename, char **title, int *length) { ayemu_vtx_t tmp; (*length) = -1; (*title) = NULL; if (ayemu_vtx_open (&tmp, filename)) { TitleInput *ti = vtx_get_song_tuple_from_vtx(filename, &tmp); *title = xmms_get_titlestring(xmms_get_gentitle_format(), ti); *length = ti->length; ayemu_vtx_free (&tmp); bmp_title_input_free(ti); } } InputPlugin vtx_ip = { NULL, /* FILLED BY XMMS */ NULL, /* FILLED BY XMMS */ "VTX Plugin", /* Plugin description */ NULL, /* Initialization */ vtx_about, /* Show aboutbox */ vtx_config, /* Show/edit configuration */ vtx_is_our_file, /* Check file, return 1 if the plugin can handle this file */ NULL, /* Scan directory */ vtx_play_file, /* Play given file */ vtx_stop, /* Stop playing */ vtx_pause, /* Pause playing */ vtx_seek, /* Seek time */ NULL, /* Set equalizer */ NULL, /* Get playing time (obsoleted by InputPlayback API) */ NULL, /* Get volume */ NULL, /* Set volume */ NULL, /* Cleanup */ NULL, /* OBSOLETE! */ NULL, /* Send data to Visualization plugin */ NULL, NULL, /* FILLED BY XMMS */ vtx_get_song_info, /* Get song title and length */ vtx_file_info, /* Show file-information dialog */ NULL, /* FILLED BY XMMS */ vtx_get_song_tuple, /* Tuple */ NULL, /* Tuple */ NULL, /* Buffer */ vtx_is_our_fd, /* VFS */ vtx_fmts /* ext assist */ }; /* called from xmms for plug */ InputPlugin * get_iplugin_info (void) { vtx_ip.description = g_strdup (_("VTX Plugin")); return &vtx_ip; }