Files
projectm/src/projectM-sdl/pmSDL.cpp
Mischa Spiegelmock 414d697f5c xcode cleanup
2019-01-01 13:27:57 +02:00

343 lines
10 KiB
C++

//
// pmSDL.cpp
// SDLprojectM
//
// Created by Mischa Spiegelmock on 2017-09-18.
//
#include "pmSDL.hpp"
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include "Renderer/ShaderEngine.hpp"
void projectMSDL::audioInputCallbackF32(void *userdata, unsigned char *stream, int len) {
projectMSDL *app = (projectMSDL *) userdata;
// printf("LEN: %i\n", len);
// stream is (i think) samples*channels floats (native byte order) of len BYTES
app->pcm()->addPCMfloat((float *)stream, len/sizeof(float));
}
void projectMSDL::audioInputCallbackS16(void *userdata, unsigned char *stream, int len) {
// printf("LEN: %i\n", len);
projectMSDL *app = (projectMSDL *) userdata;
short pcm16[2][512];
for (int i = 0; i < 512; i++) {
for (int j = 0; j < app->audioChannelsCount; j++) {
pcm16[j][i] = stream[i+j];
}
}
app->pcm()->addPCM16(pcm16);
}
SDL_AudioDeviceID projectMSDL::selectAudioInput(int _count) {
// ask the user which capture device to use
// printf("Please select which audio input to use:\n");
printf("Detected devices:\n");
for (int i = 0; i < _count; i++) {
printf(" %i: 🎤%s\n", i, SDL_GetAudioDeviceName(i, true));
}
return 0;
}
int projectMSDL::openAudioInput() {
// get audio driver name (static)
const char* driver_name = SDL_GetCurrentAudioDriver();
SDL_Log("Using audio driver: %s\n", driver_name);
// get audio input device
unsigned int i, count2 = SDL_GetNumAudioDevices(true); // capture, please
if (count2 == 0) {
SDL_LogCritical(SDL_LOG_CATEGORY_APPLICATION, "No audio capture devices found");
SDL_Quit();
}
for (i = 0; i < count2; i++) {
SDL_Log("Found audio capture device %d: %s", i, SDL_GetAudioDeviceName(i, true));
}
SDL_AudioDeviceID selectedAudioDevice = 0; // device to open
if (count2 > 1) {
// need to choose which input device to use
selectedAudioDevice = selectAudioInput(count2);
if (selectedAudioDevice > count2) {
SDL_LogCritical(SDL_LOG_CATEGORY_APPLICATION, "No audio input device specified.");
SDL_Quit();
}
}
// params for audio input
SDL_AudioSpec want, have;
// requested format
SDL_zero(want);
want.freq = 48000;
want.format = AUDIO_F32; // float
want.channels = 2;
want.samples = 512;
want.callback = projectMSDL::audioInputCallbackF32;
want.userdata = this;
audioDeviceID = SDL_OpenAudioDevice(SDL_GetAudioDeviceName(selectedAudioDevice, true), true, &want, &have, 0);
if (audioDeviceID == 0) {
SDL_LogCritical(SDL_LOG_CATEGORY_APPLICATION, "Failed to open audio capture device: %s", SDL_GetError());
SDL_Quit();
}
// read characteristics of opened capture device
SDL_Log("Opened audio capture device %i: %s", audioDeviceID, SDL_GetAudioDeviceName(selectedAudioDevice, true));
SDL_Log("Sample rate: %i, frequency: %i, channels: %i, format: %i", have.samples, have.freq, have.channels, have.format);
audioChannelsCount = have.channels;
audioSampleRate = have.freq;
audioSampleCount = have.samples;
audioFormat = have.format;
audioInputDevice = audioDeviceID;
return 1;
}
void projectMSDL::beginAudioCapture() {
// allocate a buffer to store PCM data for feeding in
SDL_PauseAudioDevice(audioDeviceID, false);
}
void projectMSDL::endAudioCapture() {
SDL_PauseAudioDevice(audioDeviceID, true);
}
void projectMSDL::maximize() {
SDL_DisplayMode dm;
if (SDL_GetDesktopDisplayMode(0, &dm) != 0) {
SDL_Log("SDL_GetDesktopDisplayMode failed: %s", SDL_GetError());
return;
}
SDL_SetWindowSize(win, dm.w, dm.h);
resize(dm.w, dm.h);
}
void projectMSDL::toggleFullScreen() {
maximize();
if (isFullScreen) {
SDL_SetWindowFullscreen(win, SDL_WINDOW_FULLSCREEN_DESKTOP);
isFullScreen = false;
SDL_ShowCursor(true);
} else {
SDL_ShowCursor(false);
SDL_SetWindowFullscreen(win, SDL_WINDOW_FULLSCREEN);
isFullScreen = true;
}
}
void projectMSDL::keyHandler(SDL_Event *sdl_evt) {
projectMEvent evt;
projectMKeycode key;
projectMModifier mod;
SDL_Keymod sdl_mod = (SDL_Keymod) sdl_evt->key.keysym.mod;
SDL_Keycode sdl_keycode = sdl_evt->key.keysym.sym;
// handle keyboard input (for our app first, then projectM)
switch (sdl_keycode) {
case SDLK_f:
if (sdl_mod & KMOD_LGUI || sdl_mod & KMOD_RGUI || sdl_mod & KMOD_LCTRL) {
// command-f: fullscreen
toggleFullScreen();
return; // handled
}
break;
}
// translate into projectM codes and perform default projectM handler
evt = sdl2pmEvent(sdl_evt);
key = sdl2pmKeycode(sdl_keycode);
mod = sdl2pmModifier(sdl_mod);
key_handler(evt, key, mod);
}
void projectMSDL::addFakePCM() {
int i;
short pcm_data[2][512];
/** Produce some fake PCM data to stuff into projectM */
for ( i = 0 ; i < 512 ; i++ ) {
if ( i % 2 == 0 ) {
pcm_data[0][i] = (float)( rand() / ( (float)RAND_MAX ) * (pow(2,14) ) );
pcm_data[1][i] = (float)( rand() / ( (float)RAND_MAX ) * (pow(2,14) ) );
} else {
pcm_data[0][i] = (float)( rand() / ( (float)RAND_MAX ) * (pow(2,14) ) );
pcm_data[1][i] = (float)( rand() / ( (float)RAND_MAX ) * (pow(2,14) ) );
}
if ( i % 2 == 1 ) {
pcm_data[0][i] = -pcm_data[0][i];
pcm_data[1][i] = -pcm_data[1][i];
}
}
/** Add the waveform data */
pcm()->addPCM16(pcm_data);
}
void projectMSDL::resize(unsigned int width_, unsigned int height_) {
width = width_;
height = height_;
projectM_resetGL(width, height);
}
void projectMSDL::pollEvent() {
SDL_Event evt;
while (SDL_PollEvent(&evt))
{
switch (evt.type) {
case SDL_WINDOWEVENT:
switch (evt.window.event) {
case SDL_WINDOWEVENT_RESIZED:
resize(evt.window.data1, evt.window.data2);
break;
}
break;
case SDL_KEYDOWN:
keyHandler(&evt);
break;
case SDL_QUIT:
done = true;
break;
}
}
}
void projectMSDL::renderFrame() {
glClearColor( 0.0, 0.0, 0.0, 0.0 );
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
projectM::renderFrame();
if (renderToTexture) {
renderTexture();
}
SDL_GL_SwapWindow(win);
}
projectMSDL::projectMSDL(Settings settings, int flags) : projectM(settings, flags) {
width = getWindowWidth();
height = getWindowHeight();
done = 0;
isFullScreen = false;
}
projectMSDL::projectMSDL(std::string config_file, int flags) : projectM(config_file, flags) {
width = getWindowWidth();
height = getWindowHeight();
done = 0;
isFullScreen = false;
}
void projectMSDL::init(SDL_Window *window, SDL_GLContext *_glCtx, const bool _renderToTexture) {
win = window;
glCtx = _glCtx;
projectM_resetGL(width, height);
// are we rendering to a texture?
renderToTexture = _renderToTexture;
if (renderToTexture) {
programID = ShaderEngine::CompileShaderProgram(ShaderEngine::v2f_c4f_t2f_vert, ShaderEngine::v2f_c4f_t2f_frag, "v2f_c4f_t2f");
textureID = projectM::initRenderToTexture();
float points[16] = {
-0.8, -0.8,
0.0, 0.0,
-0.8, 0.8,
0.0, 1.0,
0.8, -0.8,
1.0, 0.0,
0.8, 0.8,
1.0, 1.0,
};
glGenBuffers(1, &m_vbo);
glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 16, points, GL_DYNAMIC_DRAW);
glGenVertexArrays(1, &m_vao);
glBindVertexArray(m_vao);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float)*4, (void*)0); // Positions
glDisableVertexAttribArray(1);
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(float)*4, (void*)(sizeof(float)*2)); // Textures
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
}
std::string projectMSDL::getActivePresetName()
{
unsigned int index = 0;
if (selectedPresetIndex(index)) {
return getPresetName(index);
}
return std::string();
}
void projectMSDL::renderTexture() {
static int frame = 0;
frame++;
glClear(GL_COLOR_BUFFER_BIT);
glClear(GL_DEPTH_BUFFER_BIT);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glViewport(0, 0, getWindowWidth(), getWindowHeight());
glUseProgram(programID);
glUniform1i(glGetUniformLocation(programID, "texture_sampler"), 0);
glm::mat4 mat_proj = glm::frustum(-1.0f, 1.0f, -1.0f, 1.0f, 2.0f, 10.0f);
glEnable(GL_DEPTH_TEST);
glm::mat4 mat_model = glm::mat4(1.0f);
mat_model = glm::translate(mat_model, glm::vec3(cos(frame*0.023),
cos(frame*0.017),
-5+sin(frame*0.022)*2));
mat_model = glm::rotate(mat_model, glm::radians((float) sin(frame*0.0043)*360),
glm::vec3(sin(frame*0.0017),
sin(frame *0.0032),
1));
glm::mat4 mat_transf = glm::mat4(1.0f);
mat_transf = mat_proj * mat_model;
glUniformMatrix4fv(glGetUniformLocation(programID, "vertex_transformation"), 1, GL_FALSE, glm::value_ptr(mat_transf));
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, textureID);
glVertexAttrib4f(1, 1.0, 1.0, 1.0, 1.0);
glBindVertexArray(m_vao);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glBindVertexArray(0);
glDisable(GL_DEPTH_TEST);
}
void projectMSDL::presetSwitchedEvent(bool isHardCut, size_t index) const {
std::string presetName = getPresetName(index);
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Displaying preset: %s\n", presetName.c_str());
}