diff --git a/CMakeLists.txt b/CMakeLists.txt index 455e35f..9380790 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -50,6 +50,7 @@ if(NOT DEFINED BUILD_TRACER) endif() add_subdirectory (libol) +add_subdirectory (include) add_subdirectory (output) add_subdirectory (tools) add_subdirectory (python) diff --git a/Modules/FindFFmpeg.cmake b/Modules/FindFFmpeg.cmake index 4eec7dc..0941e49 100644 --- a/Modules/FindFFmpeg.cmake +++ b/Modules/FindFFmpeg.cmake @@ -75,6 +75,12 @@ endif (NOT WIN32) ${PC_LIBAVCODEC_LIBRARY_DIRS} ) + find_library(AVRESAMPLE_LIBRARIES NAMES avresample + HINTS + ${PC_LIBAVCODEC_LIBDIR} + ${PC_LIBAVCODEC_LIBRARY_DIRS} + ) + set(FFMPEG_LIBRARIES ) @@ -94,6 +100,11 @@ endif (NOT WIN32) set(FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} ${AVDEVICE_LIBRARIES}) endif (AVDEVICE_LIBRARIES) + if (AVRESAMPLE_LIBRARIES) + set(FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} ${AVRESAMPLE_LIBRARIES}) + set(AVRESAMPLE_FOUND TRUE) + endif (AVRESAMPLE_LIBRARIES) + if (FFMPEG_LIBRARIES AND FFMPEG_INCLUDE_DIR) set(FFMPEG_FOUND TRUE) endif (FFMPEG_LIBRARIES AND FFMPEG_INCLUDE_DIR) @@ -121,6 +132,7 @@ endif (NOT WIN32) AVFORMAT_LIBRARIES AVUTIL_LIBRARIES AVDEVICE_LIBRARIES + AVRESAMPLE_LIBRARIES FFMPEG_INCLUDE_DIR FFMPEG_INCLUDE_DIR_OLD_STYLE) diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index b9be0f4..e3947d2 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -21,25 +21,42 @@ link_directories (${CMAKE_BINARY_DIR}/libol) add_executable(circlescope circlescope.c) target_link_libraries(circlescope ${JACK_LIBRARIES} m) +install(TARGETS circlescope DESTINATION bin) add_executable(scope scope.c) target_link_libraries(scope ${JACK_LIBRARIES} m) +install(TARGETS scope DESTINATION bin) add_executable(simple simple.c) target_link_libraries(simple openlase) +install(TARGETS simple DESTINATION bin) + +add_executable(spin-text spin-text.c) +target_link_libraries(spin-text openlase) +install(TARGETS spin-text DESTINATION bin) + +add_executable(show-text show-text.c) +target_link_libraries(show-text openlase) +install(TARGETS show-text DESTINATION bin) add_executable(pong pong.c) target_link_libraries(pong openlase) +install(TARGETS pong DESTINATION bin) + +add_executable(test-static-frames test-static-frames.c) +target_link_libraries(test-static-frames openlase) if(ALSA_FOUND) add_executable(midiview midiview.c) target_link_libraries(midiview openlase ${ALSA_LIBRARIES}) + install(TARGETS midiview DESTINATION bin) else() message(STATUS "Will NOT build midiview (ALSA missing)") endif() add_executable(harp harp.c) target_link_libraries(harp openlase) +install(TARGETS harp DESTINATION bin) #add_subdirectory(27c3_slides) diff --git a/examples/show-text.c b/examples/show-text.c new file mode 100644 index 0000000..d950ab0 --- /dev/null +++ b/examples/show-text.c @@ -0,0 +1,122 @@ +/* + * show-text.c Copyright (C) 2013 Kamal Mostafa + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 or version 3. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "libol.h" +#include "text.h" + +#include +#include +#include +#include +#include +#include +#include + + +void +draw_text_frame( Font *font, float height, char *text ) +{ + float width; + olLoadIdentity3(); + olLoadIdentity(); + width = olGetStringWidth(font, height, text); + olDrawString(font, -width/2, height/2, height, C_WHITE, text); +} + + +int main (int argc, char *argv[]) +{ + if ( argc < 2 || argc > 3) { + fprintf(stderr, + "usage: show-text {fontname} ['Text to Render']\n" + " fontname - a Hershey font name (e.g. gothiceng) or 'default'\n" + ); + return 1; + } + char *fontname = argv[1]; + char *text = NULL; + + if ( argc == 3 ) + text = argv[2]; + + + OLRenderParams params; + + memset(¶ms, 0, sizeof params); + params.rate = 48000; + params.on_speed = 1.0/100.0; + params.off_speed = 2.0/100.0; + params.start_wait = 8; + params.start_dwell = 7; // helps slow turn-on + params.curve_dwell = 0; + params.corner_dwell = 8; + params.curve_angle = cosf(10.0*(M_PI/180.0)); // 10 deg + params.end_dwell = 3; + params.end_wait = 10; // helps slow turn-off + params.snap = 1/100000.0; + params.render_flags = RENDER_GRAYSCALE; + params.render_flags |= RENDER_NOREORDER; + params.flatness = 0.0000001; // for default font + + if(olInit(3, 30000) < 0) + return 1; + + olSetRenderParams(¶ms); + + olFontType fonttype; + if ( strcasecmp(fontname,"default") == 0 ) + fonttype = OL_FONT_DEFAULT; + else + fonttype = OL_FONT_HERSHEY; + + Font *font = olGetFont(fonttype, fontname); + if ( ! font ) { + perror(fontname); + return 1; + } + + + float height = 0.3; + if ( text ) { + + draw_text_frame(font, height, text); + olRenderFrame(120); + + printf("Hit Enter to quit...\n"); + fflush(stdout); + getchar(); + + } else { + + char buf[1024]; + while ( fgets(buf, sizeof(buf), stdin) ) { + int n = strlen(buf); + if ( n == 0 ) + continue; + if ( buf[n-1] == '\n' ) + buf[--n] = 0; + draw_text_frame(font, height, buf); + olRenderFrame(120); + usleep(n*250000); + } + + } + + olShutdown(); + exit (0); +} + diff --git a/examples/spin-text.c b/examples/spin-text.c new file mode 100644 index 0000000..2dd614e --- /dev/null +++ b/examples/spin-text.c @@ -0,0 +1,141 @@ +/* + * spin-text.c Copyright (C) 2013 Kamal Mostafa + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 or version 3. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "libol.h" +#include "text.h" + +#include +#include +#include +#include +#include +#include +#include + + +void +draw_spinning_glyph( float x, float y, float rot, Font *font, float fonth, char c ) +{ + float w = olGetCharWidth(font, fonth, c); + olPushMatrix3(); + + olRotate3Y(rot); + + olDrawChar(font, + //-(4*w0) + i*w0 + (w0-w)/2, + -w/2, + y, + fonth, C_WHITE, c); + + olPopMatrix3(); + +} + + + +int main (int argc, char *argv[]) +{ + if ( argc < 2 ) { + fprintf(stderr, + "usage: spin-text {fontname} ['Text to Render']\n" + " fontname - a Hershey font name (e.g. gothiceng) or 'default'\n" + ); + return 1; + } + char *fontname = argv[1]; + + + OLRenderParams params; + + memset(¶ms, 0, sizeof params); + params.rate = 48000; + params.on_speed = 2.0/100.0; + params.off_speed = 2.0/100.0; + params.start_wait = 8; + params.start_dwell = 7; // helps slow turn-on + params.curve_dwell = 0; + params.corner_dwell = 8; + params.curve_angle = cosf(10.0*(M_PI/180.0)); // 10 deg + params.end_dwell = 3; + params.end_wait = 10; // helps slow turn-off + params.snap = 1/100000.0; + params.render_flags = RENDER_GRAYSCALE; + params.render_flags |= RENDER_NOREORDER; + params.flatness = 0.0000001; // for default font + + if(olInit(3, 30000) < 0) + return 1; + + olSetRenderParams(¶ms); + + float mytime = 0; + float ftime; + + int frames = 0; + + olFontType fonttype; + if ( strcasecmp(fontname,"default") == 0 ) + fonttype = OL_FONT_DEFAULT; + else + fonttype = OL_FONT_HERSHEY; + + Font *font = olGetFont(fonttype, fontname); + if ( ! font ) { + perror(fontname); + return 1; + } + + + float rflip = M_PI; + float r0 = 0.0; + + int spintime = 100; + + const char *s = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + if ( argc == 3 ) + s = argv[2]; + + const char *p = s; + char c = *p; + while(1) { + olLoadIdentity3(); + olLoadIdentity(); + + if ( frames % (spintime/2) == (spintime/4) ) { + if ( *p == 0 ) + p = s; + c = *p++; + r0 = ( r0 == 0.0 ) ? rflip : 0.0; + } + + float rot = (frames % spintime) * M_PI * 2 / spintime - r0; + draw_spinning_glyph(-1.0, 1.0, rot, font, 1.6, c); + + ftime = olRenderFrame(60); + frames++; + mytime += ftime; + if ( (frames % 10) == 0 ) { + printf("Frame time: %3.0f msec FPS: %4.1f\r", + ftime*1000, frames/mytime); + fflush(stdout); + } + } + + olShutdown(); + exit (0); +} + diff --git a/examples/test-static-frames.c b/examples/test-static-frames.c new file mode 100644 index 0000000..b39f4aa --- /dev/null +++ b/examples/test-static-frames.c @@ -0,0 +1,110 @@ +/* + * test-static-frames.c Copyright (C) 2013 Kamal Mostafa + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 or version 3. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "libol.h" + +#include +#include +#include +#include +#include +#include +#include + + +void +drawChevron() +{ + int color = C_WHITE; + olBegin(OL_LINESTRIP); + olVertex3( -0.2, 0, 0, color); + olVertex3( 0, +0.2, 0, color); + olVertex3( +0.2, 0, 0, color); + olEnd(); +} + + + +int main (int argc, char *argv[]) +{ + if ( argc != 1 ) { + fprintf(stderr, "usage: test-static-frames\n"); + return 1; + } + + + OLRenderParams params; + + memset(¶ms, 0, sizeof params); + params.rate = 48000; + params.on_speed = 2.0/100.0; + params.off_speed = 2.0/100.0; + params.start_wait = 100; + params.start_dwell = 7; // helps slow turn-on + params.curve_dwell = 0; + params.corner_dwell = 24; + params.curve_angle = cosf(10.0*(M_PI/180.0)); // 10 deg + params.end_dwell = 12; + params.end_wait = 10; // helps slow turn-off + params.snap = 1/100000.0; + params.render_flags = RENDER_GRAYSCALE; + params.render_flags |= RENDER_NOREORDER; + + if(olInit(3, 30000) < 0) + return 1; + + olSetRenderParams(¶ms); + + + int i; + float ftime; + + for ( i=0; i<5; i++ ) { + olLoadIdentity3(); + olLoadIdentity(); + olTranslate3(-0.5, 0.3 + -0.2 * i, 0); + drawChevron(); + + ftime = olRenderFrame(0); + printf("Frame time: %3.0f msec FPS: %4.1f\n", + ftime*1000, 1/ftime); + fflush(stdout); + + sleep(1); + } + + for ( i=0; i<5; i++ ) { + olLoadIdentity3(); + olLoadIdentity(); + olTranslate3(+0.5, 0.3 + -0.2 * i, 0); + drawChevron(); + + ftime = olRenderFrame(0); + printf("Frame time: %3.0f msec FPS: %4.1f\n", + ftime*1000, 1/ftime); + fflush(stdout); + + sleep(1); + } + + + sleep(5); + + olShutdown(); + exit (0); +} + diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt new file mode 100644 index 0000000..9e2b149 --- /dev/null +++ b/include/CMakeLists.txt @@ -0,0 +1,20 @@ +# OpenLase - a realtime laser graphics toolkit +# +# Copyright (C) 2009-2013 Hector Martin "marcan" +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 or version 3. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +# + +install(FILES ilda.h libol.h text.h trace.h DESTINATION include/openlase) + diff --git a/include/text.h b/include/text.h index cd9c155..6ac4d6f 100644 --- a/include/text.h +++ b/include/text.h @@ -23,6 +23,12 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA #include #include +typedef enum { + OL_FONT_DEFAULT = 0, + OL_FONT_HERSHEY, + /* future: add more OL_FONT_SOMETHING types here */ +} olFontType; + typedef struct { int flag; float x; @@ -38,10 +44,14 @@ typedef struct { float height; float overlap; const FontChar *chars; + void *font_data; + olFontType font_type; } Font; Font *olGetDefaultFont(void); -float olGetCharWidth(Font *fnt, char c); +Font *olGetFont(olFontType font_type, const char *fontname); +void olFreeFont(Font *font); +float olGetCharWidth(Font *font, float height, char c); float olGetStringWidth(Font *fnt, float height, const char *s); float olGetCharOverlap(Font *font, float height); float olDrawChar(Font *fnt, float x, float y, float height, uint32_t color, char c); diff --git a/libol/CMakeLists.txt b/libol/CMakeLists.txt index da9ffd0..a6bcbf4 100644 --- a/libol/CMakeLists.txt +++ b/libol/CMakeLists.txt @@ -20,6 +20,7 @@ check_include_files(malloc.h HAVE_MALLOC_H) check_function_exists(memalign HAVE_MEMALIGN) check_function_exists(posix_memalign HAVE_POSIX_MEMALIGN) check_function_exists(_aligned_malloc HAVE_ALIGNED_MALLOC) +check_include_files(hersheyfont.h HAVE_HERSHEYFONT) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h) include_directories (${CMAKE_SOURCE_DIR}/include ${CMAKE_CURRENT_BINARY_DIR}) @@ -34,8 +35,9 @@ else() endif() add_library (openlase SHARED libol.c text.c ilda.c ${TRACER_SOURCES} ${CMAKE_CURRENT_BINARY_DIR}/fontdef.c) -target_link_libraries (openlase ${CMAKE_THREAD_LIBS_INIT} m jack) +target_link_libraries (openlase ${CMAKE_THREAD_LIBS_INIT} m jack hersheyfont) set_target_properties(openlase PROPERTIES VERSION 0 SOVERSION 0) +install(TARGETS openlase LIBRARY DESTINATION lib) add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/fontdef.c DEPENDS ${CMAKE_SOURCE_DIR}/tools/genfont.py diff --git a/libol/config.h.in b/libol/config.h.in index dbc2408..06ae19e 100644 --- a/libol/config.h.in +++ b/libol/config.h.in @@ -26,4 +26,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA #cmakedefine HAVE POSIX_MEMALIGN #cmakedefine HAVE_ALIGNED_MALLOC +#cmakedefine HAVE_HERSHEYFONT + #endif diff --git a/libol/imgproc_sse2.asm b/libol/imgproc_sse2.asm index be0f3b5..f1d5f6d 100644 --- a/libol/imgproc_sse2.asm +++ b/libol/imgproc_sse2.asm @@ -32,16 +32,6 @@ %include "x86inc.asm" -%ifidn __OUTPUT_FORMAT__,elf -section .note.GNU-stack noalloc noexec nowrite progbits -%endif -%ifidn __OUTPUT_FORMAT__,elf32 -section .note.GNU-stack noalloc noexec nowrite progbits -%endif -%ifidn __OUTPUT_FORMAT__,elf64 -section .note.GNU-stack noalloc noexec nowrite progbits -%endif - SECTION .text INIT_XMM diff --git a/libol/libol.c b/libol/libol.c index 3387d68..d155ba5 100644 --- a/libol/libol.c +++ b/libol/libol.c @@ -61,6 +61,8 @@ typedef struct { typedef struct { int pmax; int pnext; + int first_wait_point; + int first_real_point; Point *points; float *audio_l; float *audio_r; @@ -88,13 +90,13 @@ static DrawState dstate; static OLRenderParams params; static Point last_render_point; +static Point last_out_point; static volatile int crbuf; static volatile int cwbuf; static int fbufs; static int buflag; static int out_point; -static int first_time_full; static int first_output_frame; float bbox[2][2]; @@ -124,6 +126,10 @@ AudioCallbackFunc audiocb; LogCallbackFunc log_cb; +//// visual debugging aid: light up the inter-object traversal: +#define C_INTEROBJ_BLACK C_BLACK +//#define C_INTEROBJ_BLACK C_RED + static uint32_t colmul(uint32_t a, uint32_t b) { uint32_t out = 0; @@ -165,6 +171,7 @@ static void jack_shutdown (void *arg) static int process (nframes_t nframes, void *arg) { + //olLog("---------------------------- process(nframes=%d)\n", nframes); sample_t *o_x = (sample_t *) jack_port_get_buffer (out_x, nframes); sample_t *o_y = (sample_t *) jack_port_get_buffer (out_y, nframes); sample_t *o_r = (sample_t *) jack_port_get_buffer (out_r, nframes); @@ -173,19 +180,8 @@ static int process (nframes_t nframes, void *arg) sample_t *o_al = (sample_t *) jack_port_get_buffer (out_al, nframes); sample_t *o_ar = (sample_t *) jack_port_get_buffer (out_ar, nframes); - if (!first_time_full) { - //olLog("Dummy frame!\n"); - memset(o_x, 0, nframes * sizeof(sample_t)); - memset(o_y, 0, nframes * sizeof(sample_t)); - memset(o_r, 0, nframes * sizeof(sample_t)); - memset(o_g, 0, nframes * sizeof(sample_t)); - memset(o_b, 0, nframes * sizeof(sample_t)); - memset(o_al, 0, nframes * sizeof(sample_t)); - memset(o_ar, 0, nframes * sizeof(sample_t)); - return 0; - } - while(nframes) { + int duplicate_frame = 0; if (out_point == -1) { if (!first_output_frame) { //olLog("First frame! %d\n", crbuf); @@ -193,18 +189,77 @@ static int process (nframes_t nframes, void *arg) } else { if ((crbuf+1)%fbufs == cwbuf) { //olLog("Duplicated frame! %d\n", crbuf); + duplicate_frame = 1; } else { crbuf = (crbuf+1)%fbufs; //olLog("Normal frame! %d\n", crbuf); } } - out_point = 0; + + if (frames[crbuf].pnext == 0) { + //olLog("Dummy frame!\n"); + memset(o_x, 0, nframes * sizeof(sample_t)); + memset(o_y, 0, nframes * sizeof(sample_t)); + memset(o_r, 0, nframes * sizeof(sample_t)); + memset(o_g, 0, nframes * sizeof(sample_t)); + memset(o_b, 0, nframes * sizeof(sample_t)); + memset(o_al, 0, nframes * sizeof(sample_t)); + memset(o_ar, 0, nframes * sizeof(sample_t)); + return 0; + } + + if (duplicate_frame) { + // Generate black points to traverse from the last + // output point to the first real point of the + // current (duplicate) frame. + int new_out_point = frames[crbuf].first_wait_point; + Point *start = &frames[crbuf].points[new_out_point]; + float dx = start->x - last_out_point.x; + float dy = start->y - last_out_point.y; + float distance = fmaxf(fabsf(dx),fabsf(dy)); + if (distance > params.snap) { + int i; + int points = ceilf(distance/params.off_speed); + float x = last_out_point.x; + float y = last_out_point.y; + for (i=1; (i<=points && nframes>0); i++) { + nframes--; + x = last_out_point.x + (float)i*dx/points; + y = last_out_point.y + (float)i*dy/points; + *o_x++ = x; + *o_y++ = y; + unsigned int color = C_INTEROBJ_BLACK; + *o_r++ = ((color >> 16) & 0xff) / 255.0f; + *o_g++ = ((color >> 8) & 0xff) / 255.0f; + *o_b++ = (color & 0xff) / 255.0f; + *o_al++ = 0; + *o_ar++ = 0; + //olLog("%f %f %06x\n", x, y, color); + } + //olLog("process: dup frame traverse=%d of %d pts\n", i-1, points); + last_out_point.x = x; + last_out_point.y = y; + if (i == points+1) + out_point = new_out_point; + } else { + out_point = frames[crbuf].first_real_point; + } + if (nframes == 0) + return 0; + } else { + out_point = 0; + } } + + /* + * Output the pre-rendered points for this frame. + */ int count = nframes; int left = frames[crbuf].pnext - out_point; if (count > left) count = left; int i; + //olLog("process: count=%d left=%d pnext=%d out_point=%d\n", count, left, frames[crbuf].pnext, out_point); for (i=0; ix; @@ -214,10 +269,18 @@ static int process (nframes_t nframes, void *arg) *o_g++ = ((p->color >> 8) & 0xff) / 255.0f; *o_b++ = (p->color & 0xff) / 255.0f; - *o_al++ = frames[crbuf].audio_l[out_point]; - *o_ar++ = frames[crbuf].audio_r[out_point]; + if (duplicate_frame) { + *o_al++ = 0; + *o_ar++ = 0; + } else { + *o_al++ = frames[crbuf].audio_l[out_point]; + *o_ar++ = frames[crbuf].audio_r[out_point]; + } out_point++; - //olLog("%06x %f %f\n", p->x, p->y, p->color); + //olLog("%f %f %06x\n", p->x, p->y, p->color); + + last_out_point.x = p->x; + last_out_point.y = p->y; } if (out_point == frames[crbuf].pnext) out_point = -1; @@ -244,7 +307,6 @@ int olInit(int buffer_count, int max_points) cwbuf = 0; crbuf = 0; out_point = -1; - first_time_full = 0; first_output_frame = 0; memset(&wframe, 0, sizeof(Frame)); wframe.objmax = 16; @@ -629,6 +691,8 @@ static void render_object(Object *obj) chkpts(2 * (obj->pointcnt + params.start_wait + params.end_wait + points)); Point *out_start = NULL; int skip_out_start_wait = 0; + int did_interobject_traverse = 0; + static int first_frame = 1; Point *ip = obj->points; for (i=0; ipointcnt; i++, ip++) { @@ -641,20 +705,36 @@ static void render_object(Object *obj) if (i == obj->pointcnt) // null object return; + int first_object_of_frame = 0; + if (frames[cwbuf].pnext == 0) { + first_object_of_frame = 1; + frames[cwbuf].first_wait_point = 0; + frames[cwbuf].first_real_point = 0; + } + if (start->x < bbox[0][0] || start->x > bbox[1][0] || start->y < bbox[0][1] || start->y > bbox[1][1]) { out_start = &last_render_point; skip_out_start_wait = 1; } else if (distance > params.snap) { + //olLog("interobject traverse: %d pts\n", points); for (i=0; ix, start->y, C_BLACK); + addrndpoint(start->x, start->y, C_INTEROBJ_BLACK); } + first_frame = 0; } + if (first_object_of_frame) + frames[cwbuf].first_real_point = frames[cwbuf].pnext; Point *op = &frames[cwbuf].points[frames[cwbuf].pnext]; ip = obj->points; for (i=0; ipointcnt; i++, ip++) { @@ -722,14 +802,18 @@ float olRenderFrame(int max_fps) int i; int count = 0; - int min_points = params.rate / max_fps; + int min_points; + if (max_fps <= 0) + min_points = 0; + else + min_points = params.rate / max_fps; + memset(&last_info, 0, sizeof(last_info)); while (((cwbuf+1)%fbufs) == crbuf) { //olLog("Waiting %d %d\n", cwbuf, crbuf); usleep(1000); - first_time_full = 1; } frames[cwbuf].pnext=0; int cnt = wframe.objcnt; diff --git a/libol/text.c b/libol/text.c index c8324ac..6be253e 100644 --- a/libol/text.c +++ b/libol/text.c @@ -17,7 +17,14 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config.h" + #include +#include +#include +#ifdef HAVE_HERSHEYFONT +# include +#endif #include "libol.h" #include "text.h" @@ -28,26 +35,85 @@ Font *olGetDefaultFont(void) return &default_font; } -float olGetCharWidth(Font *font, char c) +void olFreeFont(Font *font) { - if (!font) + if ( !font || (font == &default_font) ) + return; + +#ifdef HAVE_HERSHEYFONT + if ( font->font_type == OL_FONT_HERSHEY ) { + struct hershey_font *hf = font->font_data; + hershey_font_free(hf); + } +#endif + + free(font); +} + +#ifdef HAVE_HERSHEYFONT +static Font *olGetFont_Hershey(const char *fontname) +{ + struct hershey_font *hf; + Font *font; + + font = malloc(sizeof(Font)); + if ( !font ) + return 0; + + hf = hershey_font_load(fontname); + if ( !hf ) { + free(font); return 0; - return font->chars[(uint8_t)c].width / font->height; + } + + font->font_type = OL_FONT_HERSHEY; + font->font_data = hf; + font->height = 32; // Hershey fonts are fixed height (?) + + return font; } +#endif -float olGetCharOverlap(Font *font, float height) +Font *olGetFont(olFontType font_type, const char *fontname) +{ + if ( font_type == OL_FONT_HERSHEY ) { +#ifdef HAVE_HERSHEYFONT + return olGetFont_Hershey(fontname); +#else + errno = ENOTSUP; + return 0; +#endif + } + + return olGetDefaultFont(); +} + +float olGetCharWidth(Font *font, float height, char c) { if (!font) return 0; float ratio = height / font->height; - return font->overlap * ratio; + +#ifdef HAVE_HERSHEYFONT + if ( font->font_type == OL_FONT_HERSHEY ) { + struct hershey_font *hf = font->font_data; + return hf->glyphs[(uint8_t)c].width * ratio; + } +#endif + + return font->chars[(uint8_t)c].width * ratio; } -float olDrawChar(Font *font, float x, float y, float height, uint32_t color, char c) +float olGetCharOverlap(Font *font, float height) { if (!font) return 0; + float ratio = height / font->height; + return font->overlap * ratio; +} +static float olDrawChar_Default(Font *font, float x, float y, float height, uint32_t color, char c) +{ const FontChar *chr = &font->chars[(uint8_t)c]; const FontPoint *p = chr->points; @@ -74,6 +140,45 @@ float olDrawChar(Font *font, float x, float y, float height, uint32_t color, cha return chr->width * ratio; } +#ifdef HAVE_HERSHEYFONT +static float olDrawChar_Hershey(Font *font, float x, float y, float height, uint32_t color, char c) +{ + struct hershey_font *hf = font->font_data; + struct hershey_glyph *hg = hershey_font_glyph(hf, (uint8_t)c); + if ( hg->width == 0 ) + return 0; + + float ratio = height / font->height; + + struct hershey_path *hp; + for ( hp=hg->paths; hp; hp=hp->next ) { + olBegin(OL_LINESTRIP); + int i; + for ( i=0; inverts; i++ ) { + short px = hp->verts[i].x; + short py = hp->verts[i].y; + olVertex3(x + px*ratio, y - height + py*ratio, 0, color); + } + olEnd(); + } + + return hg->width * ratio; +} +#endif + +float olDrawChar(Font *font, float x, float y, float height, uint32_t color, char c) +{ + if (!font) + return 0; + +#ifdef HAVE_HERSHEYFONT + if ( font->font_type == OL_FONT_HERSHEY ) + return olDrawChar_Hershey(font, x, y, height, color, c); +#endif + + return olDrawChar_Default(font, x, y, height, color, c); +} + float olDrawString(Font *font, float x, float y, float height, uint32_t color, const char *s) { float w = 0; @@ -93,8 +198,11 @@ float olGetStringWidth(Font *font, float height, const char *s) float w = 0; float ratio = height / font->height; + if (!font) + return 0; + while(*s) { - w += font->chars[(uint8_t)*s].width * ratio - font->overlap * ratio; + w += olGetCharWidth(font, height, *s) - font->overlap * ratio; s++; } diff --git a/output/CMakeLists.txt b/output/CMakeLists.txt index 2fcdac0..444d773 100644 --- a/output/CMakeLists.txt +++ b/output/CMakeLists.txt @@ -26,6 +26,7 @@ if(QT4_FOUND) add_executable(output output.cpp output_settings.cpp ${output_UIS_H} ${output_MOCS}) target_link_libraries(output ${JACK_LIBRARIES} ${QT_LIBRARIES}) + install(TARGETS output DESTINATION bin) else() message(STATUS "Will NOT build output (Qt4 missing)") endif() diff --git a/python/pylase.pyx b/python/pylase.pyx index 28661f7..818cee0 100644 --- a/python/pylase.pyx +++ b/python/pylase.pyx @@ -427,7 +427,7 @@ cdef extern from "text.h": ctypedef struct _Font "Font" _Font *olGetDefaultFont() - float olGetCharWidth(_Font *fnt, char c) + float olGetCharWidth(_Font *fnt, float height, char c) float olGetStringWidth(_Font *fnt, float height, char *s) float olGetCharOverlap(_Font *font, float height) float olDrawChar(_Font *fnt, float x, float y, float height, uint32_t color, char c) @@ -441,9 +441,9 @@ cpdef getDefaultFont(): f.font = olGetDefaultFont() return f -cpdef float getCharWidth(object font, char c): +cpdef float getCharWidth(object font, float height, char c): cdef Font fnt = font - return olGetCharWidth(fnt.font, c) + return olGetCharWidth(fnt.font, height, c) cpdef float getStringWidth(object font, float height, char *s): cdef Font fnt = font return olGetStringWidth(fnt.font, height, s) diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 71d8756..3b372e7 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -21,27 +21,34 @@ link_directories (${CMAKE_BINARY_DIR}/libol) add_executable(playilda playilda.c) target_link_libraries(playilda ${JACK_LIBRARIES}) +install(TARGETS playilda DESTINATION bin) add_executable(invert invert.c) target_link_libraries(invert ${JACK_LIBRARIES}) +install(TARGETS invert DESTINATION bin) add_executable(cal cal.c) target_link_libraries(cal ${JACK_LIBRARIES} m) +install(TARGETS cal DESTINATION bin) -#if(FFMPEG_FOUND AND BUILD_TRACER) -# include_directories(${FFMPEG_INCLUDE_DIR}) -# add_executable(playvid playvid.c) -# target_link_libraries(playvid openlase ${FFMPEG_LIBRARIES} avresample) +#if(FFMPEG_FOUND AND AVRESAMPLE_FOUND AND BUILD_TRACER) +# include_directories(${FFMPEG_INCLUDE_DIR}) +# add_executable(playvid playvid.c) +# target_link_libraries(playvid openlase ${FFMPEG_LIBRARIES}) +# install(TARGETS playvid DESTINATION bin) #else() -# message(STATUS "Will NOT build playvid (FFmpeg or tracer missing)") +# message(STATUS "Will NOT build playvid (FFmpeg or libavresample or tracer missing)") #endif() if(OPENGL_FOUND AND GLUT_FOUND) add_executable(simulator simulator.c) include_directories(${OPENGL_INCLUDE_DIRS} ${GLUT_INCLUDE_DIRS}) target_link_libraries(simulator m ${OPENGL_LIBRARIES} ${GLUT_LIBRARY} ${JACK_LIBRARIES}) + install(TARGETS simulator DESTINATION bin) else() message(STATUS "Will NOT build simulator (OpenGL or GLUT missing)") endif() +install(PROGRAMS svg2ild.py DESTINATION bin RENAME svg2ild) + add_subdirectory(qplayvid) diff --git a/tools/qplayvid/CMakeLists.txt b/tools/qplayvid/CMakeLists.txt index b68e5de..693d304 100644 --- a/tools/qplayvid/CMakeLists.txt +++ b/tools/qplayvid/CMakeLists.txt @@ -16,7 +16,7 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # -if(QT4_FOUND AND FFMPEG_FOUND AND SWSCALE_FOUND AND BUILD_TRACER) +if(QT4_FOUND AND FFMPEG_FOUND AND AVRESAMPLE_FOUND AND SWSCALE_FOUND AND BUILD_TRACER) include(${QT_USE_FILE}) QT4_WRAP_CPP(qplayvid_MOCS qplayvid_gui.h) @@ -24,7 +24,8 @@ if(QT4_FOUND AND FFMPEG_FOUND AND SWSCALE_FOUND AND BUILD_TRACER) include_directories(${CMAKE_CURRENT_BINARY_DIR}) add_executable(qplayvid qplayvid.c qplayvid_gui.cpp ${qplayvid_MOCS}) - target_link_libraries(qplayvid openlase ${FFMPEG_LIBRARIES} ${SWSCALE_LIBRARIES} ${QT_LIBRARIES} avresample) + target_link_libraries(qplayvid openlase ${FFMPEG_LIBRARIES} ${SWSCALE_LIBRARIES} ${QT_LIBRARIES}) + install(TARGETS qplayvid DESTINATION bin) else() - message(STATUS "Will NOT build qplayvid (Qt4 or FFmpeg or tracer missing)") + message(STATUS "Will NOT build qplayvid (Qt4 or FFmpeg or libavresample or tracer missing)") endif() diff --git a/tools/qplayvid/qplayvid.c b/tools/qplayvid/qplayvid.c index 99fda77..47cd222 100644 --- a/tools/qplayvid/qplayvid.c +++ b/tools/qplayvid/qplayvid.c @@ -137,7 +137,11 @@ size_t decode_audio(PlayerCtx *ctx, AVPacket *packet, int new_packet, int32_t se ctx->a_frame = avcodec_alloc_frame(); ctx->a_frame->nb_samples = AVCODEC_MAX_AUDIO_FRAME_SIZE; +#if (LIBAVCODEC_VERSION_MAJOR >= 56) ctx->a_codec_ctx->get_buffer2(ctx->a_codec_ctx, ctx->a_frame, 0); +#else + ctx->a_codec_ctx->get_buffer(ctx->a_codec_ctx, ctx->a_frame); +#endif decoded = avcodec_decode_audio4(ctx->a_codec_ctx, ctx->a_frame, &got_frame, packet); if (!got_frame) { fprintf(stderr, "Error while decoding audio frame\n"); @@ -222,7 +226,9 @@ size_t decode_video(PlayerCtx *ctx, AVPacket *packet, int new_packet, int32_t se // The pts magic guesswork int64_t pts = AV_NOPTS_VALUE; int64_t frame_pts = AV_NOPTS_VALUE; +#if (LIBAVFORMAT_VERSION_MAJOR >= 56) frame_pts = av_frame_get_best_effort_timestamp(ctx->v_frame); +#endif if (packet->dts != AV_NOPTS_VALUE) { ctx->v_faulty_dts += packet->dts <= ctx->v_last_dts;