Permalink
Fetching contributors…
Cannot retrieve contributors at this time
226 lines (189 sloc) 6.65 KB
//
// main.cpp
// projectM-sdl
//
// Created by Mischa Spiegelmock on 6/3/15.
//
// This is an implementation of projectM using libSDL2
#include "pmSDL.hpp"
#define FAKE_AUDIO 0
#define TEST_ALL_PRESETS 0
#if OGL_DEBUG
void DebugLog(GLenum source,
GLenum type,
GLuint id,
GLenum severity,
GLsizei length,
const GLchar* message,
const void* userParam) {
/*if (type != GL_DEBUG_TYPE_OTHER)*/
{
std::cerr << " -- \n" << "Type: " <<
type << "; Source: " <<
source <<"; ID: " << id << "; Severity: " <<
severity << "\n" << message << "\n";
}
}
#endif
// return path to config file to use
std::string getConfigFilePath() {
const char *path = DATADIR_PATH;
struct stat sb;
// check if datadir exists.
// it should exist if this application was installed. if not, assume we're developing it and use currect directory
if (stat(path, &sb) != 0) {
SDL_LogWarn(SDL_LOG_CATEGORY_ERROR, "Could not open datadir path %s.\n", DATADIR_PATH);
}
std::string configFilePath = path;
configFilePath += "/config.inp";
// check if config file exists
if (stat(configFilePath.c_str(), &sb) != 0) {
SDL_LogWarn(SDL_LOG_CATEGORY_ERROR, "No config file %s found. Using development settings.\n", configFilePath.c_str());
return "";
}
return configFilePath;
}
int main(int argc, char *argv[]) {
#if UNLOCK_FPS
setenv("vblank_mode", "0", 1);
#endif
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO);
if (! SDL_VERSION_ATLEAST(2, 0, 5)) {
SDL_Log("SDL version 2.0.5 or greater is required. You have %i.%i.%i", SDL_MAJOR_VERSION, SDL_MINOR_VERSION, SDL_PATCHLEVEL);
return 1;
}
// default window size to usable bounds (e.g. minus menubar and dock)
SDL_Rect initialWindowBounds;
#if SDL_VERSION_ATLEAST(2, 0, 5)
// new and better
SDL_GetDisplayUsableBounds(0, &initialWindowBounds);
#else
SDL_GetDisplayBounds(0, &initialWindowBounds);
#endif
int width = initialWindowBounds.w;
int height = initialWindowBounds.h;
int renderIndex = 0;
#ifdef USE_GLES
for(int i = 0; i < SDL_GetNumRenderDrivers(); i++) {
SDL_RendererInfo info;
if (SDL_GetRenderDriverInfo(i, &info) == 0) {
if (std::string(info.name) == "opengles2") {
renderIndex = i;
break;
}
}
}
// use GLES 2.0 (this may need adjusting)
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
#else
// Disabling compatibility profile
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
#endif
SDL_Window *win = SDL_CreateWindow("projectM", 0, 0, width, height, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);
SDL_GLContext glCtx = SDL_GL_CreateContext(win);
SDL_Log("GL_VERSION: %s", glGetString(GL_VERSION));
SDL_Log("GL_SHADING_LANGUAGE_VERSION: %s", glGetString(GL_SHADING_LANGUAGE_VERSION));
SDL_Log("GL_VENDOR: %s", glGetString(GL_VENDOR));
SDL_SetWindowTitle(win, "projectM Visualizer");
projectMSDL *app;
// load configuration file
std::string configFilePath = getConfigFilePath();
if (! configFilePath.empty()) {
// found config file, use it
app = new projectMSDL(configFilePath, 0);
SDL_Log("Using config from %s", configFilePath.c_str());
} else {
SDL_Log("Config file not found, using development settings");
float heightWidthRatio = (float)height / (float)width;
projectM::Settings settings;
settings.windowWidth = width;
settings.windowHeight = height;
settings.meshX = 300;
settings.meshY = settings.meshX * heightWidthRatio;
settings.fps = 60;
settings.smoothPresetDuration = 3; // seconds
settings.presetDuration = 7; // seconds
settings.beatSensitivity = 0.8;
settings.aspectCorrection = 1;
settings.shuffleEnabled = 1;
settings.softCutRatingsEnabled = 1; // ???
// get path to our app, use CWD for presets/fonts/etc
std::string base_path = SDL_GetBasePath();
settings.presetURL = base_path + "presets";
// settings.presetURL = base_path + "presets/presets_shader_test";
settings.menuFontURL = base_path + "fonts/Vera.ttf";
settings.titleFontURL = base_path + "fonts/Vera.ttf";
// init with settings
app = new projectMSDL(settings, 0);
}
app->init(win, &glCtx);
#if OGL_DEBUG
glEnable(GL_DEBUG_OUTPUT);
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
glDebugMessageCallback(DebugLog, NULL);
#endif
#if !FAKE_AUDIO
// get an audio input device
if (app->openAudioInput())
app->beginAudioCapture();
#endif
#if TEST_ALL_PRESETS
uint buildErrors = 0;
for(int i = 0; i < app->getPlaylistSize(); i++) {
std::cout << i << "\t" << app->getPresetName(i) << std::endl;
app->selectPreset(i);
if (app->getErrorLoadingCurrentPreset()) {
buildErrors++;
}
}
if (app->getPlaylistSize()) {
fprintf(stdout, "Preset loading errors: %d/%d [%d%%]\n", buildErrors, app->getPlaylistSize(), (buildErrors*100) / app->getPlaylistSize());
}
return PROJECTM_SUCCESS;
#endif
#if UNLOCK_FPS
int32_t frame_count = 0;
struct timespec now;
clock_gettime(CLOCK_MONOTONIC_RAW, &now);
int64_t start = ( ((int64_t)now.tv_sec * 1000L) + (now.tv_nsec / 1000000L) );
#endif
// standard main loop
int fps = app->settings().fps;
printf("fps: %d\n", fps);
if (fps <= 0)
fps = 60;
const Uint32 frame_delay = 1000/fps;
Uint32 last_time = SDL_GetTicks();
while (! app->done) {
app->renderFrame();
#if FAKE_AUDIO
app->addFakePCM();
#endif
#if UNLOCK_FPS
frame_count++;
clock_gettime(CLOCK_MONOTONIC_RAW, &now);
if (( ((int64_t)now.tv_sec * 1000L) + (now.tv_nsec / 1000000L) ) - start > 5000) {
SDL_GL_DeleteContext(glCtx);
delete(app);
fprintf(stdout, "Frames[%d]\n", frame_count);
exit(0);
}
#else
app->pollEvent();
Uint32 elapsed = SDL_GetTicks() - last_time;
if (elapsed < frame_delay)
SDL_Delay(frame_delay - elapsed);
last_time = SDL_GetTicks();
#endif
}
SDL_GL_DeleteContext(glCtx);
#if !FAKE_AUDIO
app->endAudioCapture();
#endif
delete app;
return PROJECTM_SUCCESS;
}