sync_update is the only code-path that can end up calling any of the callbacks, so there's no need to store it in the device. This is a breaking change, so all users needs to update their code accordingly.
239 lines
5.4 KiB
C++
239 lines
5.4 KiB
C++
/* Copyright (C) 2007-2008 Erik Faye-Lund and Egbert Teeselink
|
|
* For conditions of distribution and use, see copyright notice in COPYING
|
|
* sdl+opengl examle by rasmus/loonies http://visualizethis.tumblr.com 2011
|
|
*/
|
|
|
|
#ifdef _WIN32
|
|
#define WIN32_LEAN_AND_MEAN
|
|
#include <windows.h>
|
|
#endif
|
|
#include <SDL.h>
|
|
#undef main /* avoid SDL's nasty SDLmain hack */
|
|
#include <SDL_opengl.h>
|
|
#include <bass.h>
|
|
#include <stdio.h>
|
|
#include <stdarg.h>
|
|
#include <math.h>
|
|
|
|
#include "../sync/sync.h"
|
|
|
|
static const float bpm = 150.0f; /* beats per minute */
|
|
static const int rpb = 8; /* rows per beat */
|
|
static const double row_rate = (double(bpm) / 60) * rpb;
|
|
|
|
static double bass_get_row(HSTREAM h)
|
|
{
|
|
QWORD pos = BASS_ChannelGetPosition(h, BASS_POS_BYTE);
|
|
double time = BASS_ChannelBytes2Seconds(h, pos);
|
|
return time * row_rate;
|
|
}
|
|
|
|
#ifndef SYNC_PLAYER
|
|
|
|
static void bass_pause(void *d, int flag)
|
|
{
|
|
if (flag)
|
|
BASS_ChannelPause((HSTREAM)d);
|
|
else
|
|
BASS_ChannelPlay((HSTREAM)d, false);
|
|
}
|
|
|
|
static void bass_set_row(void *d, int row)
|
|
{
|
|
QWORD pos = BASS_ChannelSeconds2Bytes((HSTREAM)d, row / row_rate);
|
|
BASS_ChannelSetPosition((HSTREAM)d, pos, BASS_POS_BYTE);
|
|
}
|
|
|
|
static int bass_is_playing(void *d)
|
|
{
|
|
return BASS_ChannelIsActive((HSTREAM)d) == BASS_ACTIVE_PLAYING;
|
|
}
|
|
|
|
static struct sync_cb bass_cb = {
|
|
bass_pause,
|
|
bass_set_row,
|
|
bass_is_playing
|
|
};
|
|
|
|
#endif /* !defined(SYNC_PLAYER) */
|
|
|
|
static void die(const char *fmt, ...)
|
|
{
|
|
char temp[4096];
|
|
va_list va;
|
|
va_start(va, fmt);
|
|
vsnprintf(temp, sizeof(temp), fmt, va);
|
|
va_end(va);
|
|
|
|
#if !defined(_WIN32) || defined(_CONSOLE)
|
|
fprintf(stderr, "*** error: %s\n", temp);
|
|
#else
|
|
MessageBox(NULL, temp, NULL, MB_OK | MB_ICONERROR);
|
|
#endif
|
|
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
static const unsigned int width = 800;
|
|
static const unsigned int height = 600;
|
|
|
|
SDL_Surface *setup_sdl()
|
|
{
|
|
if (SDL_Init(SDL_INIT_VIDEO))
|
|
die("%s", SDL_GetError());
|
|
|
|
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
|
|
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
|
|
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
|
|
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
|
|
SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
|
|
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
|
|
SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, 1);
|
|
|
|
return SDL_SetVideoMode(width, height, 32, SDL_OPENGL);
|
|
}
|
|
|
|
void draw_cube()
|
|
{
|
|
glBegin(GL_QUADS);
|
|
|
|
// Front Face
|
|
glColor3ub(255, 0, 0);
|
|
glVertex3f(-1.0f, -1.0f, 1.0f);
|
|
glVertex3f( 1.0f, -1.0f, 1.0f);
|
|
glVertex3f( 1.0f, 1.0f, 1.0f);
|
|
glVertex3f(-1.0f, 1.0f, 1.0f);
|
|
|
|
// Back Face
|
|
glColor3ub(0, 255, 0);
|
|
glVertex3f(-1.0f, -1.0f, -1.0f);
|
|
glVertex3f(-1.0f, 1.0f, -1.0f);
|
|
glVertex3f( 1.0f, 1.0f, -1.0f);
|
|
glVertex3f( 1.0f, -1.0f, -1.0f);
|
|
|
|
// Top Face
|
|
glColor3ub(0, 0, 255);
|
|
glVertex3f(-1.0f, 1.0f, -1.0f);
|
|
glVertex3f(-1.0f, 1.0f, 1.0f);
|
|
glVertex3f( 1.0f, 1.0f, 1.0f);
|
|
glVertex3f( 1.0f, 1.0f, -1.0f);
|
|
|
|
// Bottom Face
|
|
glColor3ub(255, 255, 0);
|
|
glVertex3f(-1.0f, -1.0f, -1.0f);
|
|
glVertex3f( 1.0f, -1.0f, -1.0f);
|
|
glVertex3f( 1.0f, -1.0f, 1.0f);
|
|
glVertex3f(-1.0f, -1.0f, 1.0f);
|
|
|
|
// Right face
|
|
glColor3ub(255, 0, 255);
|
|
glVertex3f( 1.0f, -1.0f, -1.0f);
|
|
glVertex3f( 1.0f, 1.0f, -1.0f);
|
|
glVertex3f( 1.0f, 1.0f, 1.0f);
|
|
glVertex3f( 1.0f, -1.0f, 1.0f);
|
|
|
|
// Left Face
|
|
glColor3ub(255, 255, 255);
|
|
glVertex3f(-1.0f, -1.0f, -1.0f);
|
|
glVertex3f(-1.0f, -1.0f, 1.0f);
|
|
glVertex3f(-1.0f, 1.0f, 1.0f);
|
|
glVertex3f(-1.0f, 1.0f, -1.0f);
|
|
|
|
glEnd();
|
|
}
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
SDL_Surface *screen;
|
|
HSTREAM stream;
|
|
|
|
const struct sync_track *clear_r, *clear_g, *clear_b;
|
|
const struct sync_track *cam_rot, *cam_dist;
|
|
|
|
screen = setup_sdl();
|
|
|
|
/* init BASS */
|
|
if (!BASS_Init(-1, 44100, 0, 0, 0))
|
|
die("failed to init bass");
|
|
stream = BASS_StreamCreateFile(false, "tune.ogg", 0, 0, 0);
|
|
if (!stream)
|
|
die("failed to open tune");
|
|
|
|
sync_device *rocket = sync_create_device("sync");
|
|
if (!rocket)
|
|
die("out of memory?");
|
|
|
|
#ifndef SYNC_PLAYER
|
|
if (sync_connect(rocket, "localhost", SYNC_DEFAULT_PORT))
|
|
die("failed to connect to host");
|
|
#endif
|
|
|
|
/* get tracks */
|
|
clear_r = sync_get_track(rocket, "clear.r");
|
|
clear_g = sync_get_track(rocket, "clear.g");
|
|
clear_b = sync_get_track(rocket, "clear.b");
|
|
cam_rot = sync_get_track(rocket, "cam.rot"),
|
|
cam_dist = sync_get_track(rocket, "cam.dist");
|
|
|
|
/* let's roll! */
|
|
BASS_Start();
|
|
BASS_ChannelPlay(stream, false);
|
|
|
|
bool done = false;
|
|
while (!done) {
|
|
double row = bass_get_row(stream);
|
|
#ifndef SYNC_PLAYER
|
|
if (sync_update(rocket, (int)floor(row), &bass_cb, (void *)stream))
|
|
sync_connect(rocket, "localhost", SYNC_DEFAULT_PORT);
|
|
#endif
|
|
|
|
/* draw */
|
|
|
|
glClearColor(sync_get_val(clear_r, row),
|
|
sync_get_val(clear_g, row),
|
|
sync_get_val(clear_b, row), 1.0f);
|
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
|
|
float rot = sync_get_val(cam_rot, row);
|
|
float dist = sync_get_val(cam_dist, row);
|
|
|
|
glMatrixMode(GL_PROJECTION);
|
|
glLoadIdentity();
|
|
gluPerspective(60.0f, 4.0f / 3, 0.1f, 100.0f);
|
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
glLoadIdentity();
|
|
glPushMatrix();
|
|
gluLookAt(sin(rot) * dist, 0, cos(rot) * dist,
|
|
0, 0, 0,
|
|
0, 1, 0);
|
|
|
|
glEnable(GL_DEPTH_TEST);
|
|
draw_cube();
|
|
|
|
glPopMatrix();
|
|
SDL_GL_SwapBuffers();
|
|
|
|
BASS_Update(0); /* decrease the chance of missing vsync */
|
|
|
|
SDL_Event e;
|
|
while (SDL_PollEvent(&e)) {
|
|
if (e.type == SDL_QUIT ||
|
|
(e.type == SDL_KEYDOWN &&
|
|
e.key.keysym.sym == SDLK_ESCAPE))
|
|
done = true;
|
|
}
|
|
}
|
|
|
|
#ifndef SYNC_PLAYER
|
|
sync_save_tracks(rocket);
|
|
#endif
|
|
sync_destroy_device(rocket);
|
|
|
|
BASS_StreamFree(stream);
|
|
BASS_Free();
|
|
SDL_Quit();
|
|
|
|
return 0;
|
|
}
|