comparison src/projectm-1.0/main.cxx @ 3040:f13b61c91ada

go back to the SDL version
author William Pitcock <nenolod@atheme.org>
date Tue, 14 Apr 2009 14:47:25 -0500
parents
children c733dd93af62
comparison
equal deleted inserted replaced
3039:f856ff6a0055 3040:f13b61c91ada
1 /*
2 projectM v1.01 - xmms-projectm.sourceforge.net
3 --------------------------------------------------
4
5 Lead Developers: Carmelo Piccione (carmelo.piccione@gmail.com) &
6 Peter Sperl (peter@sperl.com)
7
8 We have also been advised by some professors at CMU, namely Roger B. Dannenberg.
9 http://www-2.cs.cmu.edu/~rbd/
10
11 The inspiration for this program was Milkdrop by Ryan Geiss. Obviously.
12
13 This code is distributed under the GPL.
14
15
16 THANKS FOR THE CODE!!!
17 -------------------------------------------------
18 The base for this program was andy@nobugs.org's XMMS plugin tutorial
19 http://www.xmms.org/docs/vis-plugin.html
20
21 We used some FFT code by Takuya OOURA instead of XMMS' built-in fft code
22 fftsg.c - http://momonga.t.u-tokyo.ac.jp/~ooura/fft.html
23
24 and some beat detection code was inspired by Frederic Patin @
25 www.gamedev.net/reference/programming/features/beatdetection/
26
27 */
28
29 #include <stdio.h>
30 #include <string.h>
31 #include <string>
32 #include <stdlib.h>
33 #include <unistd.h>
34 #include <fcntl.h>
35 #include <SDL/SDL.h>
36 #include <SDL/SDL_thread.h>
37
38 extern "C" {
39 #include <audacious/util.h>
40 #include <audacious/plugin.h>
41 #include <audacious/auddrct.h>
42 }
43
44 #include <math.h>
45 #include "ConfigFile.h"
46
47 #include <libprojectM/projectM.hpp>
48
49 #include "sdltoprojectM.h"
50 #include "video_init.h"
51
52 #include <GL/gl.h>
53 #define CONFIG_FILE "/share/projectM/config.inp"
54
55 // Forward declarations
56 extern "C" void projectM_xmms_init(void);
57 extern "C" void projectM_cleanup(void);
58 extern "C" void projectM_about(void);
59 extern "C" void projectM_configure(void);
60 extern "C" void projectM_playback_start(void);
61 extern "C" void projectM_playback_stop(void);
62 extern "C" void projectM_render_pcm(gint16 pcm_data[2][512]);
63 extern "C" void projectM_render_freq(gint16 pcm_data[2][256]);
64 extern "C" int worker_func(void*);
65 std::string read_config();
66 void saveSnapshotToFile();
67
68 extern "C" VisPlugin projectM_vtable;
69
70 //extern preset_t * active_preset;
71
72 //FILE * debugFile = fopen("./dwrite-dump", "wb");
73
74 // Our worker thread
75 SDL_Thread *worker_thread = NULL;
76 SDL_sem *sem = NULL;
77 SDL_Event event;
78
79 SDL_Surface *screen;
80
81
82 projectM * globalPM = NULL;
83
84 int maxsamples=512;
85
86 int texsize=512;
87 int gx=32,gy=24;
88 int wvw=400,wvh=400;
89 int fvw=1024,fvh=768;
90 int fps=35, fullscreen=0;
91
92 // char *title;
93
94 gint disable_projectm(void *something) {
95 projectM_vtable.disable_plugin(&projectM_vtable);
96 return 0;
97 }
98
99 Uint32 get_xmms_title(Uint32 something, void *somethingelse) {
100 static char check_title = 1;
101 static int last_pos;
102 static char *last_title = NULL;
103 int pos;
104 char *title = NULL;
105
106 //Nice optimization, but we want the title no matter what so I can display it when the song changes
107 #if 0
108 if(!(globalPM->showtitle%2)) {
109 /* Repeat less often when not showing title */
110 return 1000;
111 }
112 #endif
113
114 pos = audacious_drct_pl_get_pos();
115 /* Only check every 1 second for title change, otherwise check pos */
116 if(check_title || pos != last_pos) {
117 title = audacious_drct_pl_get_title(pos);
118 if(title && (!last_title || strcmp(last_title,title))) {
119 //globalPM->renderer->title = title;
120 //globalPM->renderer->drawtitle = 1;
121
122 std::string titlepp(title);
123 globalPM->projectM_setTitle(titlepp);
124 g_free(last_title);
125 last_title = title;
126 } else if(title && last_title != title) {
127 /* New copy of last title */
128 g_free(title);
129 }
130 check_title = !check_title;
131 }
132 last_pos = pos;
133 /* Repeat every 500ms */
134 return 500;
135 }
136
137 int capture = 0;
138
139 int worker_func(void*)
140 {
141 // char projectM_data[1024];
142 SDL_TimerID title_timer = NULL;
143 std::string config_file;
144 config_file = read_config();
145 ConfigFile config(config_file);
146
147 int wvw = config.read<int>( "Window Width", 512 );
148 int wvh = config.read<int>( "Window Height", 512 );
149
150 int fullscreen = 0;
151 if (config.read("Fullscreen", true)) fullscreen = 1;
152 else fullscreen = 0;
153
154 init_display(wvw,wvh,&fvw,&fvh,fullscreen);
155 SDL_WM_SetCaption("projectM v1.00", "projectM v1.00");
156
157 /** Initialise projectM */
158
159 globalPM = new projectM(config_file);
160 SDL_SemPost(sem);
161 title_timer = SDL_AddTimer(500, get_xmms_title, NULL);
162 /** Initialise the thread */
163 // SDL_SemTryWait(sem);
164 while ( SDL_SemValue(sem)==1 ) {
165 projectMEvent evt;
166 projectMKeycode key;
167 projectMModifier mod;
168
169 /** Process SDL events */
170 SDL_Event event;
171 while ( SDL_PollEvent( &event ) ) {
172 /** Translate into projectM codes and process */
173 evt = sdl2pmEvent( event );
174
175 key = sdl2pmKeycode( event.key.keysym.sym );
176 mod = sdl2pmModifier( event.key.keysym.mod );
177
178 if ( evt == PROJECTM_KEYDOWN ) {
179
180 if(key == PROJECTM_K_c)
181 {
182 //SDL_SaveBMP(screen, "/home/pete/1.bmp");
183 saveSnapshotToFile();
184 }
185 if(key == PROJECTM_K_v)
186 {
187 // capture++;
188 }
189 if(key == PROJECTM_K_f)
190 {
191
192
193 int w, h;
194 if (fullscreen == 0) {
195 w = fvw;
196 h = fvh;
197 fullscreen = 1;
198 } else {
199 w = wvw;
200 h = wvh;
201 fullscreen = 0;
202 }
203
204 resize_display(w, h, fullscreen);
205 globalPM->projectM_resetGL( w, h );
206 }
207 else globalPM->key_handler(evt,key,mod);
208
209 }
210 else if ( evt == PROJECTM_VIDEORESIZE )
211 {
212
213
214
215 wvw=event.resize.w;
216 wvh=event.resize.h;
217
218
219 resize_display(wvw,wvh,fullscreen);
220 globalPM->projectM_resetGL( wvw, wvh );
221
222 }
223 else if ( evt == PROJECTM_VIDEOQUIT ) {
224
225 (void) g_idle_add ((GSourceFunc) disable_projectm, NULL);
226 }
227 }
228
229 /** Add the waveform data */
230
231
232 /** Render the new frame */
233 // strcpy(title,xmms_remote_get_playlist_title(projectM_vtable.xmms_session, xmms_remote_get_playlist_pos(projectM_vtable.xmms_session)));
234
235 //printf("%s\n",title);
236 // strcpy(globalPM->title,title);
237
238 globalPM->renderFrame();
239
240
241
242 SDL_GL_SwapBuffers();
243
244 if (capture % 2 == 1) saveSnapshotToFile();
245 // SDL_SemPost(sem);
246 }
247
248 if(title_timer)
249 SDL_RemoveTimer(title_timer);
250 delete globalPM;
251
252
253 return 0;
254 }
255
256 extern "C" void projectM_xmms_init(void)
257 {
258
259 /* First, initialize SDL's video subsystem. */
260 // std::cerr << "sdl init begin" << std::endl;
261 if( SDL_Init( SDL_INIT_VIDEO | SDL_INIT_TIMER ) < 0 ) {
262 /* Failed, exit. */
263 fprintf( stderr, "Video initialization failed: %s\n",
264 SDL_GetError( ) );
265 //projectM_vtable.disable_plugin (&projectM_vtable);
266 return;
267
268 }
269 sem = SDL_CreateSemaphore(0);
270 // printf("projectM plugin: Initializing\n");
271
272 SDL_EnableUNICODE(1);
273
274 worker_thread = SDL_CreateThread ( *worker_func, NULL);
275
276 }
277
278
279
280 extern "C" void projectM_cleanup(void)
281 {
282
283 if(!sem) return;
284 SDL_SemWait(sem);
285 if(worker_thread) SDL_WaitThread(worker_thread, NULL);
286 // SDL_KillThread(worker_thread);
287 //printf("killed thread\n");
288
289 SDL_DestroySemaphore(sem);
290 //printf("Destroy Mutex\n");
291 SDL_Quit();
292
293 sem = NULL;
294 worker_thread = NULL;
295
296 // printf("projectM plugin: Cleanup completed\n");
297 }
298 extern "C" void projectM_about(void)
299 {
300 printf("projectM plugin: About\n");
301 }
302 extern "C" void projectM_configure(void)
303 {
304 printf("projectM plugin: Configure\n");
305 }
306 extern "C" void projectM_playback_start(void)
307 {//thread_control = GO;
308 printf("projectM plugin: Playback starting\n");
309 }
310 extern "C" void projectM_playback_stop(void)
311 {//thread_control = STOP;
312 printf("projectM plugin: Playback stopping\n");
313 }
314 extern "C" void projectM_render_pcm(gint16 pcm_data[2][512])
315 {
316 //SDL_mutexP(mutex); while ( SDL_SemValue(sem)==1 )
317 if ( SDL_SemValue(sem)==1 )
318 globalPM->pcm()->addPCM16(pcm_data);
319
320 //SDL_mutexV(mutex);
321
322 }
323
324 extern "C" void projectM_render_freq(gint16 freq_data[2][256])
325 {
326 printf("NO GOOD\n");
327 }
328
329 std::string read_config()
330 {
331
332 // int n;
333
334 char num[512];
335 FILE *in;
336 FILE *out;
337
338 char* home;
339 char projectM_home[1024];
340 char projectM_config[1024];
341
342 strcpy(projectM_config, PROJECTM_PREFIX);
343 strcpy(projectM_config+strlen(PROJECTM_PREFIX), CONFIG_FILE);
344 projectM_config[strlen(PROJECTM_PREFIX)+strlen(CONFIG_FILE)]='\0';
345 //printf("dir:%s \n",projectM_config);
346 home=getenv("HOME");
347 strcpy(projectM_home, home);
348 strcpy(projectM_home+strlen(home), "/.projectM/config.inp");
349 projectM_home[strlen(home)+strlen("/.projectM/config.inp")]='\0';
350
351
352 if ((in = fopen(projectM_home, "r")) != 0)
353 {
354 //printf("reading ~/.projectM/config.inp \n");
355 fclose(in);
356 return std::string(projectM_home);
357 }
358 else
359 {
360 printf("trying to create ~/.projectM/config.inp \n");
361
362 strcpy(projectM_home, home);
363 strcpy(projectM_home+strlen(home), "/.projectM");
364 projectM_home[strlen(home)+strlen("/.projectM")]='\0';
365 mkdir(projectM_home,0755);
366
367 strcpy(projectM_home, home);
368 strcpy(projectM_home+strlen(home), "/.projectM/config.inp");
369 projectM_home[strlen(home)+strlen("/.projectM/config.inp")]='\0';
370
371 if((out = fopen(projectM_home,"w"))!=0)
372 {
373
374 if ((in = fopen(projectM_config, "r")) != 0)
375 {
376
377 while(fgets(num,80,in)!=NULL)
378 {
379 fputs(num,out);
380 }
381 fclose(in);
382 fclose(out);
383
384
385 if ((in = fopen(projectM_home, "r")) != 0)
386 {
387 printf("created ~/.projectM/config.inp successfully\n");
388 fclose(in);
389 return std::string(projectM_home);
390 }
391 else{printf("This shouldn't happen, using implementation defualts\n");abort();}
392 }
393 else{printf("Cannot find projectM default config, using implementation defaults\n");abort();}
394 }
395 else
396 {
397 printf("Cannot create ~/.projectM/config.inp, using default config file\n");
398 if ((in = fopen(projectM_config, "r")) != 0)
399 { printf("Successfully opened default config file\n");
400 fclose(in);
401 return std::string(projectM_config);}
402 else{ printf("Using implementation defaults, your system is really messed up, I'm suprised we even got this far\n"); abort();}
403 }
404
405 }
406
407 abort();
408 }
409
410 int frame = 1;
411
412
413 void saveSnapshotToFile()
414 {
415 char dumpPath[512];
416 char Home[512];
417 //char *home;
418
419 SDL_Surface * bitmap;
420
421 GLint viewport[4];
422 long bytewidth;
423 GLint width, height;
424 long bytes;
425
426 glReadBuffer(GL_FRONT);
427 glGetIntegerv(GL_VIEWPORT, viewport);
428
429 width = viewport[2];
430 height = viewport[3];
431
432 bytewidth = width * 4;
433 bytewidth = (bytewidth + 3) & ~3;
434 bytes = bytewidth * height;
435
436 /*
437 glFinish();
438 glPixelStorei(GL_PACK_ALIGNMENT, 4);
439 glPixelStorei(GL_PACK_ROW_LENGTH, 0);
440 glPixelStorei(GL_PACK_SKIP_ROWS, 0);
441 glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
442 */
443
444
445 bitmap = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, 32,0,0,0,0);
446 glReadPixels(0, 0, width, height,
447 GL_BGRA,
448 GL_UNSIGNED_INT_8_8_8_8_REV,
449 bitmap->pixels);
450
451 sprintf(dumpPath, "/.projectM/%.8d.bmp", frame++);
452 // home=getenv("HOME");
453 strcpy(Home, getenv("HOME"));
454 strcpy(Home+strlen(Home), dumpPath);
455 Home[strlen(Home)]='\0';
456 SDL_SaveBMP(bitmap, Home);
457
458 SDL_FreeSurface(bitmap);
459
460
461 }
462