@@ -28,6 +28,8 @@ FILE *Loggable::_fp; | |||
int Loggable::_log_id = 0; | |||
vector <Loggable *> Loggable::_loggables; | |||
bool | |||
Loggable::open ( const char *filename ) | |||
{ | |||
@@ -56,3 +58,118 @@ Loggable::log ( const char *module, const char *action, const char *fmt, ... ) | |||
fprintf( _fp, "\n" ); | |||
} | |||
static | |||
void free_sa ( char **sa ) | |||
{ | |||
char **a = sa; | |||
for ( ; *a; a++ ) | |||
free( *a ); | |||
free( sa ); | |||
} | |||
static | |||
void | |||
log_print( char **o, char **n ) | |||
{ | |||
if ( n ) | |||
for ( ; *n; n++ ) | |||
printf( "%s%s", *n, *(n + 1) ? " " : "" ); | |||
if ( o && *o ) | |||
{ | |||
if ( n ) printf( " << " ); | |||
for ( ; *o; o++ ) | |||
printf( "%s%s", *o, *(o + 1) ? " " : "" ); | |||
} | |||
printf( "\n" ); | |||
} | |||
/** compare elements of dumps s1 and s2, removing those elements | |||
of dst which are not changed from src */ | |||
static | |||
void | |||
log_diff ( char **sa1, char **sa2 ) | |||
{ | |||
if ( ! sa1 ) | |||
return; | |||
int w = 0; | |||
for ( int i = 0; sa1[ i ]; ++i ) | |||
{ | |||
if ( ! strcmp( sa1[ i ], sa2[ i ] ) ) | |||
{ | |||
free( sa2[ i ] ); | |||
free( sa1[ i ] ); | |||
} | |||
else | |||
{ | |||
sa2[ w ] = sa2[ i ]; | |||
sa1[ w ] = sa1[ i ]; | |||
w++; | |||
} | |||
} | |||
sa1[ w ] = NULL; | |||
sa2[ w ] = NULL; | |||
} | |||
void | |||
Loggable::log_start ( void ) | |||
{ | |||
if ( ! _old_state ) | |||
_old_state = log_dump(); | |||
} | |||
void | |||
Loggable::log_end ( void ) | |||
{ | |||
char **_new_state = log_dump(); | |||
// if ( _old_state ) | |||
log_diff( _old_state, _new_state ); | |||
printf( "%s 0x%X set ", class_name(), _id ); | |||
log_print( _old_state, _new_state ); | |||
free_sa( _old_state ); | |||
if ( _new_state ) | |||
free_sa( _new_state ); | |||
_old_state = NULL; | |||
} | |||
void | |||
Loggable::log_create ( void ) | |||
{ | |||
printf( "%s 0x%X new ", class_name(), _id ); | |||
char **sa = log_dump(); | |||
log_print( NULL, sa ); | |||
free_sa( sa ); | |||
} | |||
void | |||
Loggable::log_destroy ( void ) | |||
{ | |||
printf( "%s 0x%X destroy ", class_name(), _id ); | |||
char **sa = log_dump(); | |||
log_print( sa, NULL ); | |||
free_sa( sa ); | |||
} |
@@ -22,6 +22,12 @@ | |||
#pragma once | |||
#include <stdio.h> | |||
#include <stdlib.h> | |||
#include <string.h> | |||
#include <vector> | |||
using std::vector; | |||
class Loggable | |||
{ | |||
@@ -29,28 +35,60 @@ class Loggable | |||
static FILE *_fp; | |||
static int _log_id; | |||
static vector <Loggable *> _loggables; | |||
private: | |||
int _id; | |||
char **_old_state; | |||
char **_new_state; | |||
public: | |||
static bool open ( const char *filename ); | |||
static | |||
Loggable * | |||
find ( int id ) | |||
{ | |||
if ( id > _log_id ) | |||
return NULL; | |||
return _loggables[ id ]; | |||
} | |||
Loggable ( ) | |||
{ | |||
_id = ++_log_id; | |||
_old_state = NULL; | |||
_loggables.push_back( this ); | |||
} | |||
/* log messages for journal */ | |||
virtual void log_create ( void ) = 0; | |||
virtual void log_destroy ( void ) = 0; | |||
virtual void log_move ( void ) = 0; | |||
virtual void log_change ( void ) = 0; | |||
virtual const char *class_name ( void ) = 0; | |||
virtual char ** log_dump ( void ) = 0; | |||
/* this method must parse an array of name/value pair strings and make the appropriate changes too | |||
the object state */ | |||
virtual void set ( char **sa ) = 0; | |||
// void log ( const char *module, const char *action, const char *fmt, ... ); | |||
protected: | |||
void log ( const char *module, const char *action, const char *fmt, ... ); | |||
void log_start ( void ); | |||
void log_end ( void ); | |||
void log_create ( void ); | |||
void log_destroy ( void ); | |||
}; | |||
#ifndef _LOGGABLE_C | |||
#define log( act, fmt, args... ) log( __CLASS__, act, fmt, ## args ) | |||
#endif | |||
/* #define LOG_START Logger _logger( this ) */ | |||
/* #define LOG_END _logger.print( this ) */ |
@@ -131,7 +131,7 @@ Region::trim ( enum trim_e t, int X ) | |||
long td = timeline->x_to_ts( d ); | |||
printf( "%li %li\n", td, _end - _start ); | |||
// printf( "%li %li\n", td, _end - _start ); | |||
if ( td >= 0 && _end - _start < td ) | |||
_end = _start + timeline->x_to_ts( 1 ); | |||
@@ -161,6 +161,7 @@ Region::handle ( int m ) | |||
int ret; | |||
log_start(); | |||
switch ( m ) | |||
{ | |||
@@ -178,11 +179,11 @@ Region::handle ( int m ) | |||
case 3: | |||
trim( trimming = RIGHT, X ); | |||
break; | |||
default: | |||
return 0; | |||
break; | |||
} | |||
fl_cursor( FL_CURSOR_WE ); | |||
return 1; | |||
} | |||
@@ -205,11 +206,13 @@ Region::handle ( int m ) | |||
else | |||
_selected = ! _selected; | |||
log_change(); | |||
redraw(); | |||
goto changed; | |||
} | |||
ret = Track_Widget::handle( m ); | |||
return ret | 1; | |||
} | |||
@@ -221,9 +224,9 @@ Region::handle ( int m ) | |||
if ( trimming != NO ) | |||
{ | |||
trimming = NO; | |||
log_change(); | |||
} | |||
return 1; | |||
printf( "releasing\n"); | |||
goto changed; | |||
case FL_DRAG: | |||
if ( Fl::event_state() & FL_SHIFT && | |||
@@ -278,20 +281,20 @@ Region::handle ( int m ) | |||
_track->prev()->add( this ); | |||
} | |||
// _track->redraw(); | |||
// _track->damage( FL_DAMAGE_EXPOSE, x(), y(), w(), h() ); | |||
ret = Track_Widget::handle( m ); | |||
return ret | 1; | |||
// _offset = timeline->x_to_ts( x() ); | |||
default: | |||
return Track_Widget::handle( m ); | |||
break; | |||
} | |||
changed: | |||
log_end(); | |||
return 1; | |||
} | |||
void | |||
@@ -35,6 +35,8 @@ using namespace std; | |||
#include "Track_Widget.H" | |||
#include "Loggable.H" | |||
/* got I hate C++ */ | |||
#define __CLASS__ "Region" | |||
@@ -56,25 +58,56 @@ class Region : public Track_Widget | |||
protected: | |||
/* general */ | |||
void log_create ( void ) | |||
{ | |||
log( "create", "%lu \"%s\" %d %f %lu %lu", _offset, _clip->name(), _selected, _scale, _start, _end ); | |||
} | |||
const char *class_name ( void ) { return "Region"; } | |||
void log_destroy ( void ) | |||
char ** log_dump ( void ) | |||
{ | |||
log( "destroy", NULL ); | |||
} | |||
// char *r; | |||
char **sa = (char**)malloc( sizeof( char* ) * 6 ); | |||
void log_move ( void ) | |||
{ | |||
log( "move", "%lu", _offset ); | |||
sa[5] = NULL; | |||
asprintf( &sa[0], ":x %lu", _offset ); | |||
asprintf( &sa[1], ":l %lu", _start ); | |||
asprintf( &sa[2], ":r %lu", _end ); | |||
asprintf( &sa[3], ":selected %d", _selected ); | |||
asprintf( &sa[4], ":gain %f", _scale ); | |||
// asprintf( &r, ":x %lu\n:l %lu\n:r %lu\n:selected %d\n:gain %f", _offset, _start, _end, _selected, _scale ); | |||
return sa; | |||
} | |||
void log_change ( void ) | |||
void | |||
set ( char **sa ) | |||
{ | |||
log( "change", "%d %f %lu %lu", _selected, _scale, _start, _end ); | |||
for ( int i = 0; sa[i]; ++i ) | |||
{ | |||
char *s = sa[i]; | |||
strtok( s, " " ); | |||
char *v = s + strlen( s ); | |||
if ( ! strcmp( s, ":x" ) ) | |||
_offset = atol( v ); | |||
else | |||
if ( ! strcmp( s, ":l" ) ) | |||
_start = atol( v ); | |||
else | |||
if ( ! strcmp( s, ":r" ) ) | |||
_end = atol( v ); | |||
else | |||
if ( ! strcmp( s, ":selected" ) ) | |||
_selected = atoi( v ); | |||
else | |||
if ( ! strcmp( s, ":gain" ) ) | |||
_scale = atof( v ); | |||
free( s ); | |||
} | |||
free( sa ); | |||
} | |||
public: | |||
@@ -38,6 +38,8 @@ class Tempo_Point : public Track_Point | |||
protected: | |||
const char *class_name ( void ) { return "Tempo_Point"; } | |||
void log_create ( void ) { log( "create", "%lu %f", _offset, _tempo ); } | |||
void log_destroy ( void ) { log( "destroy", NULL ); } | |||
void log_move ( void ) { log( "move", "%lu", _offset ); } | |||
@@ -52,6 +52,8 @@ class Time_Point : public Track_Point | |||
protected: | |||
const char *class_name ( void ) { return "Time_Point"; } | |||
void log_create ( void ) { log( "create", "%lu %d %d", _offset, _time.beats_per_bar, _time.note_type ); } | |||
void log_destroy ( void ) { log( "destroy", NULL ); } | |||
void log_move ( void ) { log( "move", "%lu", _offset ); } | |||
@@ -73,7 +73,6 @@ Track::remove ( Track_Widget *r ) | |||
Track_Widget * | |||
Track::event_widget ( void ) | |||
{ | |||
// FIXME: doesn't handle overlap! | |||
int ets = timeline->xoffset + timeline->x_to_ts( Fl::event_x() ); | |||
for ( list <Track_Widget *>::const_reverse_iterator r = _widgets.rbegin(); r != _widgets.rend(); r++ ) | |||
if ( ets > (*r)->offset() && ets < (*r)->offset() + (*r)->length() ) | |||
@@ -146,7 +145,7 @@ done: | |||
int | |||
Track::handle ( int m ) | |||
{ | |||
static Track_Widget *current_widget; | |||
static Track_Widget *pushed; | |||
switch ( m ) | |||
{ | |||
@@ -155,27 +154,24 @@ Track::handle ( int m ) | |||
return 1; | |||
default: | |||
{ | |||
Track_Widget *r = event_widget(); | |||
if ( current_widget ) | |||
r = current_widget; | |||
Track_Widget *r = pushed ? pushed : event_widget(); | |||
if ( r ) | |||
{ | |||
int retval = r->handle( m ); | |||
if ( retval && m == FL_PUSH ) | |||
current_widget = r; | |||
pushed = r; | |||
if ( retval && m == FL_RELEASE ) | |||
current_widget = NULL; | |||
pushed = NULL; | |||
if ( _queued_widget ) | |||
{ | |||
remove( _queued_widget ); | |||
delete _queued_widget; | |||
_queued_widget = NULL; | |||
current_widget = NULL; | |||
// redraw(); | |||
pushed = NULL; | |||
} | |||
return retval; | |||
@@ -28,6 +28,14 @@ protected: | |||
char *_label; | |||
void set ( char **a ) | |||
{ | |||
} | |||
char ** log_dump ( void ) | |||
{ | |||
return NULL; | |||
} | |||
void log_change ( void ) | |||
{ | |||
} | |||
@@ -206,6 +206,12 @@ public: | |||
switch ( m ) | |||
{ | |||
case FL_ENTER: | |||
fl_cursor( FL_CURSOR_HAND ); | |||
return 1; | |||
case FL_LEAVE: | |||
fl_cursor( FL_CURSOR_DEFAULT ); | |||
return 1; | |||
case FL_PUSH: | |||
{ | |||
ox = x() - X; | |||
@@ -226,7 +232,7 @@ public: | |||
case FL_RELEASE: | |||
if ( moved ) | |||
{ | |||
log_move(); | |||
// log_move(); | |||
moved = false; | |||
} | |||
// dump(); | |||