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