66
77#include < math.h>
88#include < projectM.h>
9+ #include < sdltoprojectM.h>
910
1011#include < emscripten.h>
1112#include < GL/gl.h>
1718
1819const float FPS = 60 ;
1920
20- typedef struct {
21- projectm_handle pm;
22- SDL_Window *win;
23- SDL_Renderer *rend;
24- bool done;
21+ struct projectMApp
22+ {
23+ projectm_handle pm{ nullptr };
24+ SDL_Window* win{ nullptr };
25+ SDL_Renderer* rend{ nullptr };
26+ bool done{ false };
2527 projectm_settings settings;
26- SDL_AudioDeviceID audioInputDevice;
27- } projectMApp;
28+ SDL_AudioDeviceID audioInputDevice{ 0 };
29+ int audioInputDevicesCount{ 0 };
30+ int audioChannelsCount{ 0 };
31+ bool isFullscreen{ false };
32+ };
2833
2934projectMApp app;
3035
31- int selectAudioInput (projectMApp *application) {
32- int i, count = SDL_GetNumAudioDevices (1 );
36+ void audioInputCallbackF32 (void * userdata, unsigned char * stream, int len)
37+ {
38+ if (app.audioChannelsCount == 1 )
39+ {
40+ projectm_pcm_add_float_1ch_data (app.pm , reinterpret_cast <float *>(stream), len / sizeof (float ));
41+ }
42+ else if (app.audioChannelsCount == 2 )
43+ {
44+ projectm_pcm_add_float_2ch_data (app.pm , reinterpret_cast <float *>(stream), len / sizeof (float ));
45+ }
46+ else
47+ {
48+ SDL_LogError (SDL_LOG_CATEGORY_APPLICATION, " Multichannel audio not supported" );
49+ }
50+ }
51+ 52+ bool selectAudioInput (projectMApp* application)
53+ {
54+ app.audioInputDevicesCount = SDL_GetNumAudioDevices (1 );
55+ 56+ if (!app.audioInputDevicesCount )
57+ {
58+ fprintf (stderr, " No audio input capture devices detected. Faking audio using random data.\n " );
59+ return false ;
60+ }
61+ 62+ printf (" count: %d\n " , app.audioInputDevicesCount );
63+ for (int i = 0 ; i < app.audioInputDevicesCount ; ++i)
64+ {
65+ printf (" Audio device %d: %s\n " , i, SDL_GetAudioDeviceName (i, 1 ));
66+ }
3367
34- if (! count) {
35- fprintf (stderr, " No audio input capture devices detected\n " );
36- return 0 ;
68+ SDL_AudioSpec want, have;
69+ 70+ SDL_zero (want);
71+ want.freq = 44100 ;
72+ want.format = AUDIO_F32;
73+ want.channels = 2 ;
74+ want.samples = projectm_pcm_get_max_samples ();
75+ want.callback = &audioInputCallbackF32;
76+ 77+ // Start with first device
78+ app.audioInputDevice = SDL_OpenAudioDevice (SDL_GetAudioDeviceName (0 , true ), true , &want, &have, 0 );
79+ app.audioChannelsCount = have.channels ;
80+ 81+ if (have.channels == 1 || have.channels == 2 )
82+ {
83+ SDL_PauseAudioDevice (app.audioInputDevice , false );
84+ printf (" Audio device specs: Channels=%d, Samplerate=%d, Format=%d\n " , have.channels , have.freq , have.format );
85+ }
86+ return true ;
87+ }
88+ 89+ void keyHandler (const SDL_Event& sdl_evt)
90+ {
91+ projectMEvent evt;
92+ projectMKeycode key;
93+ projectMModifier mod;
94+ auto sdl_mod = static_cast <SDL_Keymod>(sdl_evt.key .keysym .mod );
95+ SDL_Keycode sdl_keycode = sdl_evt.key .keysym .sym ;
96+ bool keyMod = false ;
97+ 98+ // Left or Right Gui or Left Ctrl
99+ if (sdl_mod & KMOD_LGUI || sdl_mod & KMOD_RGUI || sdl_mod & KMOD_LCTRL)
100+ {
101+ keyMod = true ;
37102 }
38103
39- printf (" count: %d\n " , count);
40- for (i = 0 ; i < count; ++i) {
41- printf (" Audio device %d: %s\n " , i, SDL_GetAudioDeviceName (i, 0 ));
104+ // handle keyboard input (for our app first, then projectM)
105+ switch (sdl_keycode)
106+ {
107+ case SDLK_BACKSPACE:
108+ projectm_delete_search_text (app.pm );
109+ break ;
110+ case SDLK_RETURN:
111+ if (!projectm_is_text_input_active (app.pm , false ))
112+ {
113+ SDL_StartTextInput ();
114+ }
115+ break ;
116+ case SDLK_ESCAPE:
117+ if (projectm_is_text_input_active (app.pm , false ))
118+ {
119+ SDL_StopTextInput ();
120+ }
121+ break ;
122+ case SDLK_f:
123+ if (keyMod)
124+ {
125+ app.isFullscreen = !app.isFullscreen ;
126+ SDL_SetWindowFullscreen (app.win , app.isFullscreen ? SDL_WINDOW_FULLSCREEN : 0 );
127+ return ; // handled
128+ }
129+ break ;
130+ 131+ case SDLK_SPACE:
132+ if (!projectm_is_text_input_active (app.pm , true ))
133+ {
134+ projectm_lock_preset (app.pm , !projectm_is_preset_locked (app.pm ));
135+ }
136+ break ;
137+ 42138 }
43139
44- return 1 ;
140+ // translate into projectM codes and perform default projectM handler
141+ evt = sdl2pmEvent (&sdl_evt);
142+ mod = sdl2pmModifier (sdl_mod);
143+ key = sdl2pmKeycode (sdl_keycode, sdl_mod);
144+ projectm_key_handler (app.pm , evt, key, mod);
45145}
46146
47- void renderFrame () {
48- int i;
49- short pcm_data[2 ][512 ];
147+ void renderFrame ()
148+ {
50149 SDL_Event evt;
51150
52151 SDL_PollEvent (&evt);
53- switch (evt.type ) {
152+ switch (evt.type )
153+ {
54154 case SDL_KEYDOWN:
55- // ...
155+ keyHandler (evt);
156+ break ;
157+ case SDL_TEXTINPUT:
158+ if (projectm_is_text_input_active (app.pm , true ))
159+ {
160+ projectm_set_search_text (app.pm , evt.text .text );
161+ projectm_populate_preset_menu (app.pm );
162+ }
56163 break ;
57164 case SDL_QUIT:
58165 app.done = true ;
59166 break ;
60167 }
61168
62- 63- // projectMEvent evt;
64- // projectMKeycode key;
65- // projectMModifier mod;
66- //
67- // /** Process SDL events */
68- // SDL_Event event;
69- // while ( SDL_PollEvent( &event ) ) {
70- // /** Translate into projectM codes and process */
71- // evt = sdl2pmEvent( event );
72- // key = sdl2pmKeycode( event.key.keysym.sym );
73- // mod = sdl2pmModifier( (SDLMod)event.key.keysym.mod );
74- // if ( evt == PROJECTM_KEYDOWN ) {
75- // pm->key_handler( evt, key, mod );
76- // }
77- // }
78- 79- /* * Produce some fake PCM data to stuff into projectM */
80- for ( i = 0 ; i < 512 ; i++ ) {
81- if ( i % 2 == 0 ) {
82- pcm_data[0 ][i] = (float )( rand () / ( (float )RAND_MAX ) * (pow (2 ,14 ) ) );
83- pcm_data[1 ][i] = (float )( rand () / ( (float )RAND_MAX ) * (pow (2 ,14 ) ) );
84- } else {
85- pcm_data[0 ][i] = (float )( rand () / ( (float )RAND_MAX ) * (pow (2 ,14 ) ) );
86- pcm_data[1 ][i] = (float )( rand () / ( (float )RAND_MAX ) * (pow (2 ,14 ) ) );
87- }
88- if ( i % 2 == 1 ) {
89- pcm_data[0 ][i] = -pcm_data[0 ][i];
90- pcm_data[1 ][i] = -pcm_data[1 ][i];
91- }
169+ if (app.audioInputDevicesCount == 0 )
170+ {
171+ short pcm_data[2 ][512 ];
172+ 173+ /* * Produce some fake PCM data to stuff into projectM */
174+ for (int i = 0 ; i < 512 ; i++)
175+ {
176+ if (i % 2 == 0 )
177+ {
178+ pcm_data[0 ][i] = (float ) (rand () / ((float ) RAND_MAX) * (pow (2 , 14 )));
179+ pcm_data[1 ][i] = (float ) (rand () / ((float ) RAND_MAX) * (pow (2 , 14 )));
180+ }
181+ else
182+ {
183+ pcm_data[0 ][i] = (float ) (rand () / ((float ) RAND_MAX) * (pow (2 , 14 )));
184+ pcm_data[1 ][i] = (float ) (rand () / ((float ) RAND_MAX) * (pow (2 , 14 )));
185+ }
186+ if (i % 2 == 1 )
187+ {
188+ pcm_data[0 ][i] = -pcm_data[0 ][i];
189+ pcm_data[1 ][i] = -pcm_data[1 ][i];
190+ }
191+ }
192+ 193+ /* * Add the waveform data */
194+ projectm_pcm_add_16bit_2ch_512 (app.pm , pcm_data);
92195 }
93196
94- /* * Add the waveform data */
95- projectm_pcm_add_16bit_2ch_512 (app.pm , pcm_data);
96197
97- glClearColor (0.0 , 0.5 , 0.0 , 0.0 );
98- glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
198+ glClearColor (0.0 , 0.5 , 0.0 , 0.0 );
199+ glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
99200
100201 projectm_render_frame (app.pm );
101202 glFlush ();
102203
103204 SDL_RenderPresent (app.rend );
104205}
105206
106- int main ( int argc, char *argv[] ) {
107- app.done = 0 ;
108- 109- int width = 784 ,
110- height = 784 ;
111- 207+ int main (int argc, char * argv[])
208+ {
209+ int width = 1024 ;
210+ int height = 1024 ;
112211
113212 SDL_Init (SDL_INIT_VIDEO | SDL_INIT_AUDIO);
114213
115- // get an audio input device
116- if (! selectAudioInput (&app)) {
117- fprintf (stderr, " Failed to open audio input device\n " );
118- return 1 ;
119- }
120- 121- // SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 5 );
122- // SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 5 );
123- // SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 5 );
124- // SDL_GL_SetAttribute( SDL_GL_ACCUM_RED_SIZE, 8 );
125- // SDL_GL_SetAttribute( SDL_GL_ACCUM_GREEN_SIZE, 8 );
126- // SDL_GL_SetAttribute( SDL_GL_ACCUM_BLUE_SIZE, 8 );
127- // SDL_GL_SetAttribute( SDL_GL_ALPHA_SIZE, 8 );
128- // SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 16 );
129- // SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
130- 131- app.win = SDL_CreateWindow (" SDL Fun Party Time" , 50 , 50 , width, height, 0 );
214+ app.win = SDL_CreateWindow (" projectM" , 50 , 50 , width, height, 0 );
132215 app.rend = SDL_CreateRenderer (app.win , 0 , SDL_RENDERER_ACCELERATED);
133- if (! app.rend ) {
216+ if (!app.rend )
217+ {
134218 fprintf (stderr, " Failed to create renderer: %s\n " , SDL_GetError ());
135219 return 1 ;
136220 }
137- SDL_SetWindowTitle (app.win , " SDL Fun Party Time" );
138- printf (" SDL init version 2\n " );
139221
140- 141- #ifdef PANTS
142- if ( fsaa ) {
143- SDL_GL_GetAttribute ( SDL_GL_MULTISAMPLEBUFFERS, &value );
144- printf ( " SDL_GL_MULTISAMPLEBUFFERS: requested 1, got %d\n " , value );
145- SDL_GL_GetAttribute ( SDL_GL_MULTISAMPLESAMPLES, &value );
146- printf ( " SDL_GL_MULTISAMPLESAMPLES: requested %d, got %d\n " , fsaa, value );
147- }
148- #endif
149222 app.settings .mesh_x = 48 ;
150223 app.settings .mesh_y = 32 ;
151- app.settings .fps = FPS;
152- app.settings .texture_size = 2048 ; // idk?
224+ app.settings .fps = FPS;
225+ app.settings .texture_size = 1024 ;
153226 app.settings .window_width = width;
154227 app.settings .window_height = height;
155228 app.settings .soft_cut_duration = 3 ; // seconds
@@ -170,42 +243,37 @@ int main( int argc, char *argv[] ) {
170243 projectm_set_window_size (app.pm , width, height);
171244 printf (" resetGL\n " );
172245
246+ // get an audio input device
247+ if (!selectAudioInput (&app))
248+ {
249+ fprintf (stderr, " Failed to open audio input device\n " );
250+ return 1 ;
251+ }
252+ 173253 // Allocate a new a stream given the current directory name
174- DIR* m_dir;
175- if ((m_dir = opendir (" /" )) == NULL )
254+ DIR* m_dir;
255+ if ((m_dir = opendir (" /" )) == nullptr )
176256 {
177257 printf (" error opening /\n " );
178- } else {
179- 180- struct dirent * dir_entry;
181- while ((dir_entry = readdir (m_dir)) != NULL )
182- {
183- printf (" %s\n " , dir_entry->d_name );
184- }
185- }
258+ }
259+ else
260+ {
261+ struct dirent * dir_entry;
262+ while ((dir_entry = readdir (m_dir)) != nullptr )
263+ {
264+ printf (" %s\n " , dir_entry->d_name );
265+ }
266+ }
186267
187268 auto playlistSize = projectm_get_playlist_size (app.pm );
188- for (unsigned int i = 0 ; i < playlistSize; i++) {
269+ for (unsigned int i = 0 ; i < playlistSize; i++)
270+ {
189271 auto presetName = projectm_get_preset_name (app.pm , i);
190272 printf (" %u\t %s\n " , i, presetName);
191273 projectm_free_string (presetName);
192274 }
193275
194- // mainloop. non-emscripten version here for comparison/testing
195- #ifdef EMSCRIPTEN
196276 emscripten_set_main_loop (renderFrame, 0 , 0 );
197- #else
198- // standard main loop
199- const Uint32 frame_delay = 1000 /FPS;
200- Uint32 last_time = SDL_GetTicks ();
201- while (! app.done ) {
202- renderFrame (&app);
203- Uint32 elapsed = SDL_GetTicks () - last_time;
204- if (elapsed < frame_delay)
205- SDL_Delay (frame_delay - elapsed);
206- last_time = SDL_GetTicks ();
207- }
208- #endif
209277
210278 return 0 ;
211279}
0 commit comments