Mercurial > audlegacy-plugins
comparison src/sexypsf/plugin.c @ 1203:6eef4486e481
Fixed hangs when outputting to FileWriter and improved readability in
general
| author | michi@tux.homenetwork |
|---|---|
| date | Mon, 02 Jul 2007 23:02:43 +0200 |
| parents | |
| children | e9f10dac2f63 |
comparison
equal
deleted
inserted
replaced
| 1202:82ef51e8934a | 1203:6eef4486e481 |
|---|---|
| 1 /* sexyPSF - PSF1 player | |
| 2 * Copyright (C) 2002-2004 xodnizel | |
| 3 * | |
| 4 * This library is free software; you can redistribute it and/or | |
| 5 * modify it under the terms of the GNU Lesser General Public | |
| 6 * License as published by the Free Software Foundation; either | |
| 7 * version 2.1 of the License, or (at your option) any later version. | |
| 8 * | |
| 9 * This library is distributed in the hope that it will be useful, | |
| 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| 12 * Lesser General Public License for more details. | |
| 13 * | |
| 14 * You should have received a copy of the GNU Lesser General Public | |
| 15 * License along with this library; if not, write to the Free Software | |
| 16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
| 17 */ | |
| 18 | |
| 19 #include "audacious/output.h" | |
| 20 #include "audacious/plugin.h" | |
| 21 #include "audacious/titlestring.h" | |
| 22 #include "audacious/util.h" | |
| 23 #include "audacious/vfs.h" | |
| 24 #include <stdio.h> | |
| 25 #include <stdlib.h> | |
| 26 #include <string.h> | |
| 27 #include <unistd.h> | |
| 28 #include "driver.h" | |
| 29 | |
| 30 static volatile int seek = 0; | |
| 31 static volatile gboolean playing = FALSE; | |
| 32 static volatile gboolean paused = FALSE; | |
| 33 static volatile gboolean stop = FALSE; | |
| 34 static volatile gboolean nextsong = FALSE; | |
| 35 | |
| 36 extern InputPlugin sexypsf_ip; | |
| 37 static gboolean audio_error = FALSE; | |
| 38 | |
| 39 static PSFINFO *PSFInfo = NULL; | |
| 40 static gchar *fnsave = NULL; | |
| 41 static GThread *dethread = NULL; | |
| 42 static InputPlayback *playback = NULL; | |
| 43 | |
| 44 static gchar *get_title_psf(gchar *fn); | |
| 45 | |
| 46 static int is_our_fd(gchar *filename, VFSFile *file) { | |
| 47 gchar magic[4]; | |
| 48 vfs_fread(magic, 1, 4, file); | |
| 49 | |
| 50 // only allow PSF1 for now | |
| 51 if (!memcmp(magic, "PSF\x01", 4)) | |
| 52 return 1; | |
| 53 return 0; | |
| 54 } | |
| 55 | |
| 56 | |
| 57 void sexypsf_update(unsigned char *buffer, long count) | |
| 58 { | |
| 59 const int mask = ~((((16 / 8) * 2)) - 1); | |
| 60 | |
| 61 while (count > 0) | |
| 62 { | |
| 63 int t = playback->output->buffer_free() & mask; | |
| 64 if (t > count) | |
| 65 produce_audio(playback->output->written_time(), FMT_S16_NE, 2, count, buffer, NULL); | |
| 66 else | |
| 67 { | |
| 68 if (t) | |
| 69 produce_audio(playback->output->written_time(), FMT_S16_NE, 2, t, buffer, NULL); | |
| 70 g_usleep((count-t)*1000*5/441/2); | |
| 71 } | |
| 72 count -= t; | |
| 73 buffer += t; | |
| 74 } | |
| 75 if (seek) | |
| 76 { | |
| 77 if(sexypsf_seek(seek)) | |
| 78 { | |
| 79 playback->output->flush(seek); | |
| 80 seek = 0; | |
| 81 } | |
| 82 else // negative time - must make a C time machine | |
| 83 { | |
| 84 sexypsf_stop(); | |
| 85 return; | |
| 86 } | |
| 87 } | |
| 88 if (stop) | |
| 89 sexypsf_stop(); | |
| 90 } | |
| 91 | |
| 92 static gpointer sexypsf_playloop(gpointer arg) | |
| 93 { | |
| 94 while (TRUE) | |
| 95 { | |
| 96 sexypsf_execute(); | |
| 97 | |
| 98 /* we have reached the end of the song or a command was issued */ | |
| 99 | |
| 100 playback->output->buffer_free(); | |
| 101 playback->output->buffer_free(); | |
| 102 | |
| 103 if (stop) | |
| 104 break; | |
| 105 | |
| 106 if (seek) | |
| 107 { | |
| 108 playback->output->flush(seek); | |
| 109 if(!(PSFInfo = sexypsf_load(fnsave))) | |
| 110 break; | |
| 111 sexypsf_seek(seek); | |
| 112 seek = 0; | |
| 113 continue; | |
| 114 } | |
| 115 | |
| 116 break; | |
| 117 } | |
| 118 | |
| 119 playback->output->close_audio(); | |
| 120 if (!(stop)) nextsong = TRUE; | |
| 121 g_thread_exit(NULL); | |
| 122 return NULL; | |
| 123 } | |
| 124 | |
| 125 static void sexypsf_xmms_play(InputPlayback *data) | |
| 126 { | |
| 127 if (playing) | |
| 128 return; | |
| 129 | |
| 130 playback = data; | |
| 131 nextsong = FALSE; | |
| 132 paused = FALSE; | |
| 133 | |
| 134 if (!playback->output->open_audio(FMT_S16_NE, 44100, 2)) | |
| 135 { | |
| 136 audio_error = TRUE; | |
| 137 return; | |
| 138 } | |
| 139 | |
| 140 fnsave = malloc(strlen(data->filename)+1); | |
| 141 strcpy(fnsave, data->filename); | |
| 142 if(!(PSFInfo=sexypsf_load(data->filename))) | |
| 143 { | |
| 144 playback->output->close_audio(); | |
| 145 nextsong = 1; | |
| 146 } | |
| 147 else | |
| 148 { | |
| 149 stop = seek = 0; | |
| 150 | |
| 151 gchar *name = get_title_psf(data->filename); | |
| 152 sexypsf_ip.set_info(name, PSFInfo->length, 44100*2*2*8, 44100, 2); | |
| 153 g_free(name); | |
| 154 | |
| 155 playing = 1; | |
| 156 dethread = g_thread_create((GThreadFunc)sexypsf_playloop, | |
| 157 NULL, TRUE, NULL); | |
| 158 } | |
| 159 } | |
| 160 | |
| 161 static void sexypsf_xmms_stop(InputPlayback * playback) | |
| 162 { | |
| 163 if (!playing) return; | |
| 164 | |
| 165 if (paused) | |
| 166 playback->output->pause(0); | |
| 167 paused = FALSE; | |
| 168 | |
| 169 stop = TRUE; | |
| 170 g_thread_join(dethread); | |
| 171 playing = FALSE; | |
| 172 | |
| 173 if (fnsave) | |
| 174 { | |
| 175 free(fnsave); | |
| 176 fnsave = NULL; | |
| 177 } | |
| 178 sexypsf_freepsfinfo(PSFInfo); | |
| 179 PSFInfo = NULL; | |
| 180 } | |
| 181 | |
| 182 static void sexypsf_xmms_pause(InputPlayback *playback, short p) | |
| 183 { | |
| 184 if (!playing) return; | |
| 185 playback->output->pause(p); | |
| 186 paused = p; | |
| 187 } | |
| 188 | |
| 189 static void sexypsf_xmms_seek(InputPlayback * data, int time) | |
| 190 { | |
| 191 if (!playing) return; | |
| 192 seek = time * 1000; | |
| 193 } | |
| 194 | |
| 195 static int sexypsf_xmms_gettime(InputPlayback *playback) | |
| 196 { | |
| 197 if (audio_error) | |
| 198 return -2; | |
| 199 if (nextsong) | |
| 200 return -1; | |
| 201 if (!playing) | |
| 202 return 0; | |
| 203 return playback->output->output_time(); | |
| 204 } | |
| 205 | |
| 206 static void sexypsf_xmms_getsonginfo(char *fn, char **title, int *length) | |
| 207 { | |
| 208 PSFINFO *tmp; | |
| 209 | |
| 210 if((tmp = sexypsf_getpsfinfo(fn))) { | |
| 211 *length = tmp->length; | |
| 212 *title = get_title_psf(fn); | |
| 213 sexypsf_freepsfinfo(tmp); | |
| 214 } | |
| 215 } | |
| 216 | |
| 217 static TitleInput *get_tuple_psf(gchar *fn) { | |
| 218 TitleInput *tuple = NULL; | |
| 219 PSFINFO *tmp = sexypsf_getpsfinfo(fn); | |
| 220 | |
| 221 if (tmp->length) { | |
| 222 tuple = bmp_title_input_new(); | |
| 223 tuple->length = tmp->length; | |
| 224 tuple->performer = g_strdup(tmp->artist); | |
| 225 tuple->album_name = g_strdup(tmp->game); | |
| 226 tuple->track_name = g_strdup(tmp->title); | |
| 227 tuple->file_name = g_path_get_basename(fn); | |
| 228 tuple->file_path = g_path_get_dirname(fn); | |
| 229 sexypsf_freepsfinfo(tmp); | |
| 230 } | |
| 231 | |
| 232 return tuple; | |
| 233 } | |
| 234 | |
| 235 static gchar *get_title_psf(gchar *fn) { | |
| 236 gchar *title = NULL; | |
| 237 TitleInput *tinput = get_tuple_psf(fn); | |
| 238 | |
| 239 if (tinput != NULL) { | |
| 240 title = xmms_get_titlestring(xmms_get_gentitle_format(), | |
| 241 tinput); | |
| 242 bmp_title_input_free(tinput); | |
| 243 } | |
| 244 else | |
| 245 title = g_path_get_basename(fn); | |
| 246 | |
| 247 return title; | |
| 248 } | |
| 249 | |
| 250 gchar *sexypsf_fmts[] = { "psf", "minipsf", NULL }; | |
| 251 | |
| 252 InputPlugin sexypsf_ip = | |
| 253 { | |
| 254 NULL, | |
| 255 NULL, | |
| 256 "PSF Audio Plugin", | |
| 257 NULL, | |
| 258 NULL, | |
| 259 NULL, | |
| 260 NULL, | |
| 261 NULL, | |
| 262 sexypsf_xmms_play, | |
| 263 sexypsf_xmms_stop, | |
| 264 sexypsf_xmms_pause, | |
| 265 sexypsf_xmms_seek, | |
| 266 NULL, | |
| 267 sexypsf_xmms_gettime, | |
| 268 NULL, | |
| 269 NULL, | |
| 270 NULL, | |
| 271 NULL, | |
| 272 NULL, | |
| 273 NULL, | |
| 274 NULL, | |
| 275 sexypsf_xmms_getsonginfo, | |
| 276 NULL, | |
| 277 NULL, | |
| 278 get_tuple_psf, | |
| 279 NULL, | |
| 280 NULL, | |
| 281 is_our_fd, | |
| 282 sexypsf_fmts, | |
| 283 }; | |
| 284 | |
| 285 InputPlugin *sexypsf_iplist[] = { &sexypsf_ip, NULL }; | |
| 286 | |
| 287 DECLARE_PLUGIN(sexypsf, NULL, NULL, sexypsf_iplist, NULL, NULL, NULL, NULL); |
