Skip to content

Commit b6e7bea

Browse files
committed
refactoring SDL app into a projectM subclass
1 parent 83ca579 commit b6e7bea

File tree

6 files changed

+341
-241
lines changed

6 files changed

+341
-241
lines changed

src/libprojectM/sdltoprojectM.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,8 @@ inline projectMEvent sdl2pmEvent( SDL_Event *event ) { \
5858
} \
5959
} \
6060

61-
inline projectMKeycode sdl2pmKeycode( SDL_Keysym keysym ) { \
62-
switch ( keysym.sym ) { \
61+
inline projectMKeycode sdl2pmKeycode( SDL_Keycode keycode ) { \
62+
switch ( keycode ) { \
6363
case SDLK_F1: \
6464
return PROJECTM_K_F1; \
6565
case SDLK_F2: \

src/projectM-sdl/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ INCLUDE(../cmake/CPack-projectM.cmake)
1111
SET(PROJECTM_INCLUDE ${PROJECTM_ROOT_SOURCE_DIR}/libprojectM ${PROJECTM_ROOT_SOURCE_DIR}/libprojectM/Renderer)
1212

1313
# we're producing an executable called projectMSDL
14-
ADD_EXECUTABLE(projectMSDL projectM_SDL_main.cpp
14+
ADD_EXECUTABLE(projectMSDL projectM_SDL_main.cpp pmSDL.cpp
1515
)
1616

1717
# openGL

src/projectM-sdl/SDLprojectM.xcodeproj/project.pbxproj

Lines changed: 37 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,10 @@
77
objects = {
88

99
/* Begin PBXBuildFile section */
10+
161070C41F703F13001905AB /* libprojectM.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 161070C31F703F13001905AB /* libprojectM.a */; };
11+
169502001F7009E9008FAF86 /* pmSDL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 169501FE1F7009E9008FAF86 /* pmSDL.cpp */; };
1012
C307DFD41D565B57002F6B9E /* presets in CopyFiles */ = {isa = PBXBuildFile; fileRef = C307DFD31D565B57002F6B9E /* presets */; };
1113
C345214F1BF022A5001707D2 /* projectM_SDL_main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C345214E1BF022A5001707D2 /* projectM_SDL_main.cpp */; };
12-
C34521511BF022B1001707D2 /* libprojectM.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C34521501BF022B1001707D2 /* libprojectM.a */; };
1314
C34521571BF0250D001707D2 /* libMilkdropPresetFactory.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C34521561BF0250D001707D2 /* libMilkdropPresetFactory.a */; };
1415
C34521591BF02516001707D2 /* libNativePresetFactory.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C34521581BF02516001707D2 /* libNativePresetFactory.a */; };
1516
C345215A1BF0259C001707D2 /* libRenderer.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C34521541BF02333001707D2 /* libRenderer.a */; };
@@ -25,6 +26,15 @@
2526
/* End PBXBuildFile section */
2627

2728
/* Begin PBXCopyFilesBuildPhase section */
29+
161070C81F704047001905AB /* CopyFiles */ = {
30+
isa = PBXCopyFilesBuildPhase;
31+
buildActionMask = 2147483647;
32+
dstPath = "";
33+
dstSubfolderSpec = 10;
34+
files = (
35+
);
36+
runOnlyForDeploymentPostprocessing = 0;
37+
};
2838
C34521421BF02293001707D2 /* CopyFiles */ = {
2939
isa = PBXCopyFilesBuildPhase;
3040
buildActionMask = 12;
@@ -39,10 +49,12 @@
3949
/* End PBXCopyFilesBuildPhase section */
4050

4151
/* Begin PBXFileReference section */
52+
161070C31F703F13001905AB /* libprojectM.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libprojectM.a; path = ../libprojectM/libprojectM.a; sourceTree = "<group>"; };
53+
169501FE1F7009E9008FAF86 /* pmSDL.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = pmSDL.cpp; sourceTree = "<group>"; };
54+
169501FF1F7009E9008FAF86 /* pmSDL.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = pmSDL.hpp; sourceTree = "<group>"; };
4255
C307DFD31D565B57002F6B9E /* presets */ = {isa = PBXFileReference; lastKnownFileType = folder; name = presets; path = ../../presets; sourceTree = "<group>"; };
4356
C34521441BF02294001707D2 /* SDLprojectM */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = SDLprojectM; sourceTree = BUILT_PRODUCTS_DIR; };
4457
C345214E1BF022A5001707D2 /* projectM_SDL_main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = projectM_SDL_main.cpp; sourceTree = SOURCE_ROOT; };
45-
C34521501BF022B1001707D2 /* libprojectM.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libprojectM.a; sourceTree = "<group>"; };
4658
C34521541BF02333001707D2 /* libRenderer.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libRenderer.a; path = ../libprojectM/Renderer/libRenderer.a; sourceTree = "<group>"; };
4759
C34521561BF0250D001707D2 /* libMilkdropPresetFactory.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libMilkdropPresetFactory.a; path = ../libprojectM/MilkdropPresetFactory/libMilkdropPresetFactory.a; sourceTree = "<group>"; };
4860
C34521581BF02516001707D2 /* libNativePresetFactory.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libNativePresetFactory.a; path = ../libprojectM/NativePresetFactory/libNativePresetFactory.a; sourceTree = "<group>"; };
@@ -62,41 +74,51 @@
6274
isa = PBXFrameworksBuildPhase;
6375
buildActionMask = 2147483647;
6476
files = (
77+
C345215E1BF025CF001707D2 /* CoreFoundation.framework in Frameworks */,
78+
C345215C1BF025A9001707D2 /* OpenGL.framework in Frameworks */,
6579
C34521651BF025E5001707D2 /* libbz2.a in Frameworks */,
6680
C34521661BF025E5001707D2 /* libfreetype.a in Frameworks */,
6781
C34521671BF025E5001707D2 /* libftgl.a in Frameworks */,
6882
C34521681BF025E5001707D2 /* libGLEW.a in Frameworks */,
6983
C34521691BF025E5001707D2 /* libpng15.a in Frameworks */,
7084
C345216A1BF025E5001707D2 /* libz.a in Frameworks */,
71-
C345215E1BF025CF001707D2 /* CoreFoundation.framework in Frameworks */,
72-
C345215C1BF025A9001707D2 /* OpenGL.framework in Frameworks */,
85+
161070C41F703F13001905AB /* libprojectM.a in Frameworks */,
7386
C345215A1BF0259C001707D2 /* libRenderer.a in Frameworks */,
7487
C34521591BF02516001707D2 /* libNativePresetFactory.a in Frameworks */,
7588
C34521571BF0250D001707D2 /* libMilkdropPresetFactory.a in Frameworks */,
76-
C34521511BF022B1001707D2 /* libprojectM.a in Frameworks */,
7789
);
7890
runOnlyForDeploymentPostprocessing = 0;
7991
};
8092
/* End PBXFrameworksBuildPhase section */
8193

8294
/* Begin PBXGroup section */
95+
161070CE1F7041B0001905AB /* Frameworks */ = {
96+
isa = PBXGroup;
97+
children = (
98+
C345215D1BF025CF001707D2 /* CoreFoundation.framework */,
99+
C345215B1BF025A9001707D2 /* OpenGL.framework */,
100+
);
101+
name = Frameworks;
102+
sourceTree = "<group>";
103+
};
83104
C345213B1BF02293001707D2 = {
84105
isa = PBXGroup;
85106
children = (
107+
169501FE1F7009E9008FAF86 /* pmSDL.cpp */,
108+
169501FF1F7009E9008FAF86 /* pmSDL.hpp */,
109+
C345214E1BF022A5001707D2 /* projectM_SDL_main.cpp */,
86110
C307DFD31D565B57002F6B9E /* presets */,
87111
C345215F1BF025E5001707D2 /* libbz2.a */,
88112
C34521601BF025E5001707D2 /* libfreetype.a */,
89113
C34521611BF025E5001707D2 /* libftgl.a */,
90114
C34521621BF025E5001707D2 /* libGLEW.a */,
91115
C34521631BF025E5001707D2 /* libpng15.a */,
92116
C34521641BF025E5001707D2 /* libz.a */,
93-
C345215D1BF025CF001707D2 /* CoreFoundation.framework */,
94-
C345215B1BF025A9001707D2 /* OpenGL.framework */,
95117
C34521581BF02516001707D2 /* libNativePresetFactory.a */,
96118
C34521561BF0250D001707D2 /* libMilkdropPresetFactory.a */,
97119
C34521541BF02333001707D2 /* libRenderer.a */,
98-
C34521501BF022B1001707D2 /* libprojectM.a */,
99-
C34521461BF02294001707D2 /* SDLprojectM */,
120+
161070C31F703F13001905AB /* libprojectM.a */,
121+
161070CE1F7041B0001905AB /* Frameworks */,
100122
C34521451BF02294001707D2 /* Products */,
101123
C3D30B8F1BF02BE5009AAACD /* fonts */,
102124
);
@@ -110,14 +132,6 @@
110132
name = Products;
111133
sourceTree = "<group>";
112134
};
113-
C34521461BF02294001707D2 /* SDLprojectM */ = {
114-
isa = PBXGroup;
115-
children = (
116-
C345214E1BF022A5001707D2 /* projectM_SDL_main.cpp */,
117-
);
118-
path = SDLprojectM;
119-
sourceTree = "<group>";
120-
};
121135
/* End PBXGroup section */
122136

123137
/* Begin PBXNativeTarget section */
@@ -128,6 +142,7 @@
128142
C34521401BF02293001707D2 /* Sources */,
129143
C34521411BF02293001707D2 /* Frameworks */,
130144
C34521421BF02293001707D2 /* CopyFiles */,
145+
161070C81F704047001905AB /* CopyFiles */,
131146
);
132147
buildRules = (
133148
);
@@ -174,6 +189,7 @@
174189
isa = PBXSourcesBuildPhase;
175190
buildActionMask = 2147483647;
176191
files = (
192+
169502001F7009E9008FAF86 /* pmSDL.cpp in Sources */,
177193
C345214F1BF022A5001707D2 /* projectM_SDL_main.cpp in Sources */,
178194
);
179195
runOnlyForDeploymentPostprocessing = 0;
@@ -279,6 +295,8 @@
279295
"$(inherited)",
280296
"$(LOCAL_LIBRARY_DIR)/Frameworks",
281297
"$(USER_LIBRARY_DIR)/Frameworks",
298+
"$(PROJECT_DIR)",
299+
"$(SRCROOT)",
282300
);
283301
HEADER_SEARCH_PATHS = "$(SRCROOT)/../libprojectM";
284302
LIBRARY_SEARCH_PATHS = (
@@ -300,6 +318,8 @@
300318
"$(inherited)",
301319
"$(LOCAL_LIBRARY_DIR)/Frameworks",
302320
"$(USER_LIBRARY_DIR)/Frameworks",
321+
"$(PROJECT_DIR)",
322+
"$(SRCROOT)",
303323
);
304324
HEADER_SEARCH_PATHS = "$(SRCROOT)/../libprojectM";
305325
LIBRARY_SEARCH_PATHS = (

src/projectM-sdl/pmSDL.cpp

Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
//
2+
// pmSDL.cpp
3+
// SDLprojectM
4+
//
5+
// Created by Mischa Spiegelmock on 2017-09-18.
6+
// Copyright © 2017 MVS Technical Group Inc. All rights reserved.
7+
//
8+
9+
#include "pmSDL.hpp"
10+
11+
void projectMSDL::audioInputCallbackF32(void *userdata, unsigned char *stream, int len) {
12+
projectMSDL *app = (projectMSDL *) userdata;
13+
// printf("LEN: %i\n", len);
14+
// stream is (i think) samples*channels floats (native byte order) of len BYTES
15+
app->pcm()->addPCMfloat((float *)stream, len/sizeof(float));
16+
}
17+
18+
void projectMSDL::audioInputCallbackS16(void *userdata, unsigned char *stream, int len) {
19+
// printf("LEN: %i\n", len);
20+
projectMSDL *app = (projectMSDL *) userdata;
21+
short pcm16[2][512];
22+
23+
for (int i = 0; i < 512; i++) { //
24+
for (int j = 0; j < app->audioChannelsCount; j++) {
25+
pcm16[j][i] = stream[i+j];
26+
}
27+
}
28+
app->pcm()->addPCM16(pcm16);
29+
}
30+
31+
32+
int projectMSDL::openAudioInput() {
33+
// get audio input device
34+
int i, count = SDL_GetNumAudioDevices(true); // capture, please
35+
if (count == 0) {
36+
SDL_LogCritical(SDL_LOG_CATEGORY_APPLICATION, "No audio capture devices found");
37+
SDL_Quit();
38+
}
39+
for (i = 0; i < count; i++) {
40+
SDL_Log("Found audio capture device %d: %s", i, SDL_GetAudioDeviceName(i, true));
41+
}
42+
43+
// params for audio input
44+
SDL_AudioSpec want, have;
45+
46+
// TODO: let user somehow select audio input device
47+
SDL_AudioDeviceID selectedAudioDevice = 0; // hardcoded to use first device for now :/
48+
49+
// requested format
50+
SDL_zero(want);
51+
want.freq = 48000;
52+
want.format = AUDIO_F32; // float
53+
want.channels = 2;
54+
want.samples = 512;
55+
want.callback = projectMSDL::audioInputCallbackF32;
56+
want.userdata = this;
57+
58+
audioDeviceID = SDL_OpenAudioDevice(SDL_GetAudioDeviceName(selectedAudioDevice, true), true, &want, &have, 0);
59+
60+
if (audioDeviceID == 0) {
61+
SDL_LogCritical(SDL_LOG_CATEGORY_APPLICATION, "Failed to open audio capture device: %s", SDL_GetError());
62+
SDL_Quit();
63+
}
64+
65+
// read characteristics of opened capture device
66+
SDL_Log("Opened audio capture device %i: %s", audioDeviceID, SDL_GetAudioDeviceName(selectedAudioDevice, true));
67+
SDL_Log("Sample rate: %i, frequency: %i, channels: %i, format: %i", have.samples, have.freq, have.channels, have.format);
68+
audioChannelsCount = have.channels;
69+
audioSampleRate = have.freq;
70+
audioSampleCount = have.samples;
71+
audioFormat = have.format;
72+
73+
return 1;
74+
}
75+
76+
void projectMSDL::beginAudioCapture() {
77+
// allocate a buffer to store PCM data for feeding in
78+
unsigned int maxSamples = audioChannelsCount * audioSampleCount;
79+
pcmBuffer = (unsigned char *) malloc(maxSamples);
80+
SDL_PauseAudioDevice(audioDeviceID, false);
81+
// pm->pcm()->initPCM(maxSamples);
82+
}
83+
84+
void projectMSDL::endAudioCapture() {
85+
free(pcmBuffer);
86+
SDL_PauseAudioDevice(audioDeviceID, true);
87+
}
88+
89+
void projectMSDL::toggleFullScreen() {
90+
if (isFullScreen) {
91+
SDL_SetWindowFullscreen(win, SDL_WINDOW_FULLSCREEN_DESKTOP);
92+
isFullScreen = false;
93+
} else {
94+
SDL_SetWindowFullscreen(win, SDL_WINDOW_FULLSCREEN);
95+
isFullScreen = true;
96+
}
97+
}
98+
99+
void projectMSDL::keyHandler(SDL_Event *sdl_evt) {
100+
projectMEvent evt;
101+
projectMKeycode key;
102+
projectMModifier mod;
103+
SDL_Keymod sdl_mod = (SDL_Keymod) sdl_evt->key.keysym.mod;
104+
SDL_Keycode sdl_keycode = sdl_evt->key.keysym.sym;
105+
106+
// handle keyboard input (for our app first, then projectM)
107+
switch (sdl_keycode) {
108+
case SDLK_f:
109+
if (sdl_mod & KMOD_LGUI || sdl_mod & KMOD_RGUI) {
110+
// command-f: fullscreen
111+
toggleFullScreen();
112+
return; // handled
113+
}
114+
break;
115+
}
116+
117+
// translate into projectM codes and perform default projectM handler
118+
evt = sdl2pmEvent(sdl_evt);
119+
key = sdl2pmKeycode(sdl_keycode);
120+
mod = sdl2pmModifier(sdl_mod);
121+
key_handler(evt, key, mod);
122+
}
123+
124+
void projectMSDL::addFakePCM() {
125+
int i;
126+
short pcm_data[2][512];
127+
/** Produce some fake PCM data to stuff into projectM */
128+
for ( i = 0 ; i < 512 ; i++ ) {
129+
if ( i % 2 == 0 ) {
130+
pcm_data[0][i] = (float)( rand() / ( (float)RAND_MAX ) * (pow(2,14) ) );
131+
pcm_data[1][i] = (float)( rand() / ( (float)RAND_MAX ) * (pow(2,14) ) );
132+
} else {
133+
pcm_data[0][i] = (float)( rand() / ( (float)RAND_MAX ) * (pow(2,14) ) );
134+
pcm_data[1][i] = (float)( rand() / ( (float)RAND_MAX ) * (pow(2,14) ) );
135+
}
136+
if ( i % 2 == 1 ) {
137+
pcm_data[0][i] = -pcm_data[0][i];
138+
pcm_data[1][i] = -pcm_data[1][i];
139+
}
140+
}
141+
142+
/** Add the waveform data */
143+
pcm()->addPCM16(pcm_data);
144+
}
145+
146+
void projectMSDL::resize(unsigned int width, unsigned int height) {
147+
width = width;
148+
height = height;
149+
settings.windowWidth = width;
150+
settings.windowHeight = height;
151+
projectM_resetGL(width, height);
152+
}
153+
154+
void projectMSDL::pollEvent() {
155+
SDL_Event evt;
156+
157+
SDL_PollEvent(&evt);
158+
switch (evt.type) {
159+
case SDL_WINDOWEVENT:
160+
switch (evt.window.event) {
161+
case SDL_WINDOWEVENT_RESIZED:
162+
resize(evt.window.data1, evt.window.data2);
163+
break;
164+
}
165+
break;
166+
case SDL_KEYDOWN:
167+
keyHandler(&evt);
168+
break;
169+
case SDL_QUIT:
170+
done = true;
171+
break;
172+
}
173+
}
174+
175+
void projectMSDL::renderFrame() {
176+
glClearColor( 0.0, 0.0, 0.0, 0.0 );
177+
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
178+
179+
projectM::renderFrame();
180+
glFlush();
181+
182+
SDL_RenderPresent(rend);
183+
}
184+
185+
projectMSDL::projectMSDL(Settings settings, int flags) : projectM(settings, flags) {
186+
width = settings.windowWidth;
187+
height = settings.windowHeight;
188+
done = 0;
189+
isFullScreen = false;
190+
}
191+
192+
void projectMSDL::init(SDL_Window *window, SDL_Renderer *renderer) {
193+
win = window;
194+
rend = renderer;
195+
selectRandom(true);
196+
projectM_resetGL(width, height);
197+
}

0 commit comments

Comments
 (0)