comparison src/projectm-1.0/main.cxx @ 1920:a6d84a2cfaa7

projectm-1.0: add the new files this time
author Kieran Clancy <clancy.kieran+audacious@gmail.com>
date Sun, 30 Sep 2007 13:46:31 +0930
parents
children 47a4e93ed7ce
comparison
equal deleted inserted replaced
1919:266f1bf0d5fc 1920:a6d84a2cfaa7
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 #include <GL/gl.h>
38 #include <GL/glu.h>
39 extern "C" {
40 #include <audacious/util.h>
41 #include <audacious/plugin.h>
42 #include <audacious/auddrct.h>
43 }
44 #include <math.h>
45 #include "ConfigFile.h"
46
47 #include <libprojectM/BeatDetect.hpp>
48 #include <libprojectM/PCM.hpp>
49 #include <libprojectM/projectM.hpp>
50 #include <libprojectM/KeyHandler.hpp>
51 #include "sdltoprojectM.h"
52 #include "video_init.h"
53
54 #define CONFIG_FILE "/share/projectM/config.inp"
55
56 // Forward declarations
57 extern "C" void projectM_xmms_init(void);
58 extern "C" void projectM_cleanup(void);
59 extern "C" void projectM_about(void);
60 extern "C" void projectM_configure(void);
61 extern "C" void projectM_playback_start(void);
62 extern "C" void projectM_playback_stop(void);
63 extern "C" void projectM_render_pcm(gint16 pcm_data[2][512]);
64 extern "C" void projectM_render_freq(gint16 pcm_data[2][256]);
65 extern "C" int worker_func(void*);
66 std::string read_config();
67 void saveSnapshotToFile();
68
69 extern "C" VisPlugin projectM_vtable;
70
71 //extern preset_t * active_preset;
72
73 //FILE * debugFile = fopen("./dwrite-dump", "wb");
74
75 // Callback functions
76
77 // Our worker thread
78 SDL_Thread *worker_thread = NULL;
79 SDL_sem *sem = NULL;
80 SDL_mutex *mutex = NULL;
81
82 SDL_Event event;
83
84 SDL_Surface *screen;
85
86
87 projectM * globalPM = NULL;
88
89 int maxsamples=512;
90
91 int texsize=512;
92 int gx=32,gy=24;
93 int wvw=400,wvh=400;
94 int fvw=1024,fvh=768;
95 int fps=35, fullscreen=0;
96
97 // char *title;
98
99 gint disable_projectm(void *something) {
100 projectM_vtable.disable_plugin(&projectM_vtable);
101 return 0;
102 }
103
104 Uint32 get_xmms_title(Uint32 something, void *somethingelse) {
105 static char check_title = 1;
106 static int last_pos;
107 static char *last_title = NULL;
108 int pos;
109 char *title = NULL;
110
111 //Nice optimization, but we want the title no matter what so I can display it when the song changes
112 #if 0
113 if(!(globalPM->showtitle%2)) {
114 /* Repeat less often when not showing title */
115 return 1000;
116 }
117 #endif
118
119 pos = audacious_drct_pl_get_pos();
120 /* Only check every 1 second for title change, otherwise check pos */
121 if(check_title || pos != last_pos) {
122 title = audacious_drct_pl_get_title(pos);
123 if(title && (!last_title || strcmp(last_title,title))) {
124 globalPM->renderer->title = title;
125 globalPM->renderer->drawtitle = 1;
126 g_free(last_title);
127 last_title = title;
128 } else if(title && last_title != title) {
129 /* New copy of last title */
130 g_free(title);
131 }
132 check_title = !check_title;
133 }
134 last_pos = pos;
135 /* Repeat every 500ms */
136 return 500;
137 }
138
139 int capture = 0;
140
141 int worker_func(void*)
142 {
143 // char projectM_data[1024];
144 SDL_TimerID title_timer = NULL;
145 std::string config_file;
146 config_file = read_config();
147
148 ConfigFile config(config_file);
149
150 int wvw = config.read<int>( "Window Width", 512 );
151 int wvh = config.read<int>( "Window Height", 512 );
152 int fullscreen = 0;
153 if (config.read("Fullscreen", true)) fullscreen = 1;
154 else fullscreen = 0;
155
156 init_display(wvw,wvh,&fvw,&fvh,fullscreen);
157 SDL_WM_SetCaption("projectM v1.00", "projectM v1.00");
158
159
160 /** Initialise projectM */
161
162 globalPM = new projectM(config_file);
163
164 title_timer = SDL_AddTimer(500, (SDL_NewTimerCallback) get_xmms_title, NULL);
165 /** Initialise the thread */
166 // SDL_SemTryWait(sem);
167 while ( SDL_SemValue(sem)==1 ) {
168 projectMEvent evt;
169 projectMKeycode key;
170 projectMModifier mod;
171
172 /** Process SDL events */
173 SDL_Event event;
174 while ( SDL_PollEvent( &event ) ) {
175 /** Translate into projectM codes and process */
176 evt = sdl2pmEvent( event );
177
178 key = sdl2pmKeycode( event.key.keysym.sym );
179 mod = sdl2pmModifier( event.key.keysym.mod );
180
181 if ( evt == PROJECTM_KEYDOWN ) {
182
183 if(key == PROJECTM_K_c)
184 {
185 //SDL_SaveBMP(screen, "/home/pete/1.bmp");
186 saveSnapshotToFile();
187 }
188 if(key == PROJECTM_K_v)
189 {
190 // capture++;
191 }
192 if(key == PROJECTM_K_f)
193 {
194
195
196 int w, h;
197 if (fullscreen == 0) {
198 w = fvw;
199 h = fvh;
200 } else {
201 w = wvw;
202 h = wvh;
203 }
204 globalPM->fullscreen = fullscreen ^= 1;
205 resize_display(w, h, fullscreen);
206 globalPM->projectM_resetGL( w, h );
207 }
208 else globalPM->key_handler(evt,key,mod);
209
210 }
211 else if ( evt == PROJECTM_VIDEORESIZE )
212 {
213
214
215
216 wvw=event.resize.w;
217 wvh=event.resize.h;
218
219
220 resize_display(wvw,wvh,fullscreen);
221 globalPM->projectM_resetGL( wvw, wvh );
222
223 }
224 else if ( evt == PROJECTM_VIDEOQUIT ) {
225
226 (void) g_idle_add((GSourceFunc) disable_projectm, NULL);
227 }
228 }
229
230 /** Add the waveform data */
231
232
233 /** Render the new frame */
234 // strcpy(title,xmms_remote_get_playlist_title(projectM_vtable.xmms_session, xmms_remote_get_playlist_pos(projectM_vtable.xmms_session)));
235
236 //printf("%s\n",title);
237 // strcpy(globalPM->title,title);
238 //SDL_mutexP(mutex);
239 globalPM->renderFrame();
240 //SDL_mutexV(mutex);
241
242
243 SDL_GL_SwapBuffers();
244
245 if (capture % 2 == 1) saveSnapshotToFile();
246 // SDL_SemPost(sem);
247 }
248
249
250
251 printf("Worker thread: Exiting\n");
252 if(title_timer)
253 SDL_RemoveTimer(title_timer);
254 delete globalPM;
255 globalPM = NULL;
256 close_display();
257
258 return 0;
259 }
260
261 extern "C" void projectM_xmms_init(void)
262 {
263
264 printf("projectM plugin: Initializing\n");
265
266 SDL_EnableUNICODE(1);
267
268 mutex = SDL_CreateMutex();
269 sem = SDL_CreateSemaphore(1);
270 worker_thread = SDL_CreateThread ( *worker_func, NULL);
271
272 }
273
274
275
276 extern "C"void projectM_cleanup(void)
277 {
278
279 if(worker_thread) {
280 SDL_SemWait(sem);
281 SDL_WaitThread(worker_thread, NULL);
282 SDL_DestroyMutex(mutex);
283 SDL_DestroySemaphore(sem);
284 SDL_Quit();
285 worker_thread = NULL;
286 sem = NULL;
287 mutex = NULL;
288 printf("projectM plugin: Cleanup completed\n");
289 }
290 }
291 extern "C" void projectM_about(void)
292 {
293 printf("projectM plugin: About\n");
294 }
295 extern "C" void projectM_configure(void)
296 {
297 printf("projectM plugin: Configure\n");
298 }
299 extern "C" void projectM_playback_start(void)
300 {//thread_control = GO;
301 printf("projectM plugin: Playback starting\n");
302 }
303 extern "C" void projectM_playback_stop(void)
304 {//thread_control = STOP;
305 printf("projectM plugin: Playback stopping\n");
306 }
307 extern "C" void projectM_render_pcm(gint16 pcm_data[2][512])
308 {
309 //SDL_mutexP(mutex);
310
311 if(globalPM)
312 globalPM->beatDetect->pcm->addPCM16(pcm_data);
313
314 //SDL_mutexV(mutex);
315
316 }
317
318 extern "C" void projectM_render_freq(gint16 freq_data[2][256])
319 {
320 printf("NO GOOD\n");
321 }
322
323 std::string read_config()
324 {
325
326 // int n;
327
328 char num[512];
329 FILE *in;
330 FILE *out;
331
332 char* home;
333 char projectM_home[1024];
334 char projectM_config[1024];
335
336 strcpy(projectM_config, PROJECTM_PREFIX);
337 strcpy(projectM_config+strlen(PROJECTM_PREFIX), CONFIG_FILE);
338 projectM_config[strlen(PROJECTM_PREFIX)+strlen(CONFIG_FILE)]='\0';
339 printf("dir:%s \n",projectM_config);
340 home=getenv("HOME");
341 strcpy(projectM_home, home);
342 strcpy(projectM_home+strlen(home), "/.projectM/config.inp");
343 projectM_home[strlen(home)+strlen("/.projectM/config.inp")]='\0';
344
345
346 if ((in = fopen(projectM_home, "r")) != 0)
347 {
348 printf("reading ~/.projectM/config.inp \n");
349 fclose(in);
350 return std::string(projectM_home);
351 }
352 else
353 {
354 printf("trying to create ~/.projectM/config.inp \n");
355
356 strcpy(projectM_home, home);
357 strcpy(projectM_home+strlen(home), "/.projectM");
358 projectM_home[strlen(home)+strlen("/.projectM")]='\0';
359 mkdir(projectM_home,0755);
360
361 strcpy(projectM_home, home);
362 strcpy(projectM_home+strlen(home), "/.projectM/config.inp");
363 projectM_home[strlen(home)+strlen("/.projectM/config.inp")]='\0';
364
365 if((out = fopen(projectM_home,"w"))!=0)
366 {
367
368 if ((in = fopen(projectM_config, "r")) != 0)
369 {
370
371 while(fgets(num,80,in)!=NULL)
372 {
373 fputs(num,out);
374 }
375 fclose(in);
376 fclose(out);
377
378
379 if ((in = fopen(projectM_home, "r")) != 0)
380 {
381 printf("created ~/.projectM/config.inp successfully\n");
382 fclose(in);
383 return std::string(projectM_home);
384 }
385 else{printf("This shouldn't happen, using implementation defualts\n");abort();}
386 }
387 else{printf("Cannot find projectM default config, using implementation defaults\n");abort();}
388 }
389 else
390 {
391 printf("Cannot create ~/.projectM/config.inp, using default config file\n");
392 if ((in = fopen(projectM_config, "r")) != 0)
393 { printf("Successfully opened default config file\n");
394 fclose(in);
395 return std::string(projectM_config);}
396 else{ printf("Using implementation defaults, your system is really messed up, I'm suprised we even got this far\n"); abort();}
397
398 }
399
400 }
401
402
403
404 abort();
405 }
406
407 int frame = 1;
408 char dumpPath[128];
409
410
411 void saveSnapshotToFile()
412 {
413
414 SDL_Surface * bitmap;
415
416 GLint viewport[4];
417 long bytewidth;
418 GLint width, height;
419 long bytes;
420
421 glReadBuffer(GL_FRONT);
422 glGetIntegerv(GL_VIEWPORT, viewport);
423
424 width = viewport[2];
425 height = viewport[3];
426
427 bytewidth = width * 4;
428 bytewidth = (bytewidth + 3) & ~3;
429 bytes = bytewidth * height;
430
431 /*
432 glFinish();
433 glPixelStorei(GL_PACK_ALIGNMENT, 4);
434 glPixelStorei(GL_PACK_ROW_LENGTH, 0);
435 glPixelStorei(GL_PACK_SKIP_ROWS, 0);
436 glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
437 */
438
439
440 bitmap = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, 32,0,0,0,0);
441 glReadPixels(0, 0, width, height,
442 GL_BGRA,
443 GL_UNSIGNED_INT_8_8_8_8_REV,
444 bitmap->pixels);
445
446 sprintf(dumpPath, "/home/pete/.projectM/%.8d.bmp", frame++);
447
448 SDL_SaveBMP(bitmap, dumpPath);
449
450 SDL_FreeSurface(bitmap);
451
452
453 }
454