@@ -38,10 +38,11 @@ | |||
Response looks like (in binary) | |||
> (int)channels (int)length (float)min max min max min max | |||
> length ... | |||
> min max min max | |||
Were length specifies the number of Peaks (min/max pairs). The | |||
first channel is transmitted first, and any others follow. | |||
Were length specifies the number of Peaks (min/max pairs) (for each | |||
channel) The first channel is transmitted first, and any others | |||
follow. | |||
*/ | |||
#include "Audio_File.H" | |||
@@ -72,12 +73,22 @@ Peak_Server::handle_request ( int s, const char *buf, int l ) | |||
float fpp; | |||
tick_t start, end; | |||
if ( 4 != sscanf( buf, "read_peaks \"%[^\"]\" %f %lu %lu", source, &fpp, &start, &end ) ) | |||
enum { GET_INFO, READ_PEAKS } request; | |||
if ( 1 == sscanf( buf, "get_info \"%[^\"]\"", source ) ) | |||
{ | |||
request = GET_INFO; | |||
} | |||
else if ( 4 == sscanf( buf, "read_peaks \"%[^\"]\" %f %lu %lu", source, &fpp, &start, &end ) ) | |||
{ | |||
request = READ_PEAKS; | |||
} | |||
else | |||
{ | |||
const char *err = "error: malformed request\n"; | |||
fprintf( stderr, err ); | |||
send( s, err, strlen( err ), 0 ); | |||
return; | |||
const char *err = "error: malformed request\n"; | |||
fprintf( stderr, err ); | |||
send( s, err, strlen( err ), 0 ); | |||
return; | |||
} | |||
Audio_File *af = Audio_File::from_file( source ); | |||
@@ -89,19 +100,45 @@ Peak_Server::handle_request ( int s, const char *buf, int l ) | |||
return; | |||
} | |||
int channels = af->channels(); | |||
switch ( request ) | |||
{ | |||
case GET_INFO: | |||
{ | |||
char buf[128]; | |||
snprintf( buf, sizeof( buf ), "length=%lu channels=%d\n", af->length(), af->channels() ); | |||
send( s, &channels, sizeof( int ), 0 ); | |||
send( s, buf, strlen( buf ), 0 ); | |||
for ( int i = 0; i < af->channels(); ++i ) | |||
{ | |||
const Peaks *pk = af->peaks( i ); | |||
break; | |||
} | |||
case READ_PEAKS: | |||
{ | |||
int data[2]; | |||
int peaks; | |||
data[0] = af->channels(); | |||
data[1] = peaks = (end - start) / fpp; | |||
send( s, &data, sizeof( data ), 0 ); | |||
for ( int i = 0; i < af->channels(); ++i ) | |||
{ | |||
const Peaks *pk = af->peaks( i ); | |||
int npeaks = pk->fill_buffer( fpp, start, end ); | |||
if ( ! ( peaks == npeaks ) ) | |||
printf( "wtf?! %d %d\n", peaks, npeaks ); | |||
int peaks = pk->fill_buffer( fpp, start, end ); | |||
// send( s, &peaks, sizeof( int ), 0 ); | |||
send( s, &peaks, sizeof( int ), 0 ); | |||
send( s, pk->peakbuf(), npeaks * sizeof( Peak ), 0 ); | |||
} | |||
send( s, pk->peakbuf(), peaks * sizeof( Peak ), 0 ); | |||
break; | |||
} | |||
} | |||
// delete af; | |||
@@ -56,7 +56,7 @@ Peaks::fill_buffer ( float fpp, int s, int e ) const | |||
read_peaks( s, e, (e - s) / fpp, fpp ); | |||
/* FIXME: are we *SURE* we got them all? */ | |||
return e - s; | |||
return (e - s) / fpp; | |||
} | |||
/* else */ | |||
@@ -88,12 +88,13 @@ Audio_Track::handle ( int m ) | |||
fl_cursor( FL_CURSOR_WAIT ); | |||
Fl::check(); | |||
Audio_File *c = Audio_File::from_file( file ); | |||
Clip *c = Clip::from_file( file ); | |||
fl_cursor( FL_CURSOR_DEFAULT ); | |||
if ( ! c ) | |||
{ | |||
printf( "could not open file\n" ); | |||
free( file ); | |||
return 0; | |||
} | |||
@@ -107,21 +108,3 @@ Audio_Track::handle ( int m ) | |||
return Track::handle( m ); | |||
} | |||
} | |||
void | |||
Audio_Track::dump ( void ) | |||
{ | |||
printf( "1 \"%s\" {\n", /* name() */ "Track" ); | |||
sort(); | |||
for ( list <Track_Widget *>::const_iterator r = _widgets.begin(); r != _widgets.end(); r++ ) | |||
{ | |||
printf( "\t" ); | |||
((Region*)(*r))->dump(); | |||
} | |||
printf( "}\n" ); | |||
} |
@@ -0,0 +1,70 @@ | |||
/*******************************************************************************/ | |||
/* Copyright (C) 2008 Jonathan Moore Liles */ | |||
/* */ | |||
/* 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 of the License, or (at your */ | |||
/* option) any later version. */ | |||
/* */ | |||
/* 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; see the file COPYING. If not,write to the Free Software */ | |||
/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | |||
/*******************************************************************************/ | |||
#pragma once | |||
typedef unsigned long nframes_t; | |||
/* a clip is just a stupid wrapper object for communicating with the peak server */ | |||
#include "Peak_Client.H" | |||
extern Peak_Client peak_client; | |||
class Clip | |||
{ | |||
const char *_filename; | |||
nframes_t _length; /* length of file in samples */ | |||
int _channels; | |||
public: | |||
Clip ( ) | |||
{ | |||
_filename = NULL; | |||
_length = _channels = 0; | |||
} | |||
const char *name ( void ) const { return _filename; } | |||
nframes_t length ( void ) const { return _length; } | |||
int channels ( void ) const { return _channels; } | |||
static Clip * | |||
from_file ( const char * filename ) | |||
{ | |||
Clip *c = new Clip; | |||
c->_filename = filename; | |||
if ( ! peak_client.get_info( filename, &c->_length, &c->_channels ) ) | |||
{ | |||
delete c; | |||
return false; | |||
} | |||
return c; | |||
} | |||
bool | |||
read_peaks ( float fpp, nframes_t start, nframes_t end, | |||
int *peaks, Peak **pbuf, int *channels ) | |||
{ | |||
return peak_client.read_peaks( _filename, fpp, start, end, peaks, pbuf, channels ); | |||
} | |||
}; |
@@ -8,9 +8,7 @@ SRCS= \ | |||
Timeline.C \ | |||
Track_Header.C \ | |||
Track_Widget.C \ | |||
../Engine/Audio_File.C \ | |||
../Engine/Audio_File_SF.C \ | |||
../Engine/Peaks.C \ | |||
Peak_Client.C \ | |||
../Engine/Loggable.C \ | |||
OBJS=$(SRCS:.C=.o) | |||
@@ -0,0 +1,135 @@ | |||
/*******************************************************************************/ | |||
/* Copyright (C) 2008 Jonathan Moore Liles */ | |||
/* */ | |||
/* 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 of the License, or (at your */ | |||
/* option) any later version. */ | |||
/* */ | |||
/* 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; see the file COPYING. If not,write to the Free Software */ | |||
/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | |||
/*******************************************************************************/ | |||
#include <netdb.h> | |||
#include <netinet/in.h> | |||
#include <unistd.h> | |||
#include <stdlib.h> | |||
#include <stdio.h> | |||
#include <string.h> | |||
#include <errno.h> | |||
#include <sys/socket.h> | |||
#include <sys/types.h> | |||
#include <sys/select.h> | |||
#include "Peak_Client.H" | |||
/* An interface to the peak server */ | |||
#define PEAK_PORT 6111 | |||
int | |||
connect_to_host ( const char *host, int port ) | |||
{ | |||
int s; | |||
struct sockaddr_in sa; | |||
struct hostent *hp; | |||
memset( &sa, 0, sizeof( sa ) ); | |||
hp = gethostbyname( host ); | |||
sa.sin_family = hp->h_addrtype; | |||
sa.sin_port = htons( port ); | |||
sa.sin_addr.s_addr = INADDR_ANY; | |||
if ( ( s = socket( AF_INET, SOCK_STREAM, 0 ) ) < 0 ) | |||
{ | |||
perror( "socket()" ); | |||
return -1; | |||
} | |||
if ( connect( s, (struct sockaddr *)&sa, sizeof( sa ) ) < 0 ) | |||
{ | |||
perror( "connect()" ); | |||
close( s ); | |||
return -1; | |||
} | |||
return s; | |||
} | |||
bool | |||
Peak_Client::connect ( const char *host ) | |||
{ | |||
if ( ( _socket = connect_to_host( host, PEAK_PORT ) ) < 0 ) | |||
return false; | |||
return true; | |||
} | |||
bool | |||
Peak_Client::get_info ( const char *source, nframes_t *len, int *channels ) | |||
{ | |||
/* FIXME: needs to handle errors/reconnect */ | |||
char buf[512]; | |||
snprintf( buf, sizeof( buf ), "get_info \"%s\"\n", source ); | |||
send( _socket, buf, strlen( buf ), 0 ); | |||
recv( _socket, buf, sizeof( buf ), 0 ); | |||
if ( sscanf( buf, "length=%lu channels=%d", len, channels ) != 2 ) | |||
return false; | |||
return true; | |||
} | |||
bool | |||
Peak_Client::read_peaks ( const char *source, float fpp, nframes_t start, nframes_t end, | |||
int *peaks, Peak **pbuf, int *channels ) | |||
{ | |||
/* FIXME: needs to handle errors/reconnect */ | |||
char buf[512]; | |||
snprintf( buf, sizeof( buf ), "read_peaks \"%s\" %f %lu %lu\n", source, fpp, start, end ); | |||
send( _socket, buf, strlen( buf ), 0 ); | |||
if ( recv( _socket, buf, sizeof( int ) * 2, 0 ) != sizeof( int ) * 2 ) | |||
{ | |||
printf( "error!\n" ); | |||
return false; | |||
} | |||
if ( ! strncmp( buf, "error", 5 ) ) | |||
return false; | |||
*channels = ((int*)buf)[0]; | |||
*peaks = ((int*)buf)[1]; | |||
if ( ! ( *peaks && *channels ) ) | |||
/* unknown error */; | |||
printf( "reading %d peaks for %d channels\n", *peaks, *channels ); | |||
*pbuf = new Peak[ *peaks * *channels ]; | |||
for ( int i = 0; i < *channels; ++i ) | |||
recv( _socket, *pbuf + (i * *peaks), *peaks * sizeof( Peak ), MSG_WAITALL ); | |||
printf( "done.\n" ); | |||
return true; | |||
} |
@@ -0,0 +1,40 @@ | |||
/*******************************************************************************/ | |||
/* Copyright (C) 2008 Jonathan Moore Liles */ | |||
/* */ | |||
/* 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 of the License, or (at your */ | |||
/* option) any later version. */ | |||
/* */ | |||
/* 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; see the file COPYING. If not,write to the Free Software */ | |||
/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | |||
/*******************************************************************************/ | |||
#pragma once | |||
int connect_to_host ( const char *host, int port ); | |||
typedef unsigned long nframes_t; | |||
struct Peak { | |||
float min, max; | |||
}; | |||
class Peak_Client | |||
{ | |||
int _socket; | |||
public: | |||
bool connect ( const char *host ); | |||
bool get_info ( const char *source, nframes_t *len, int *channels ); | |||
bool read_peaks ( const char *source, float fpp, nframes_t start, nframes_t end, int *peaks, Peak **pbuf, int *channels ); | |||
}; |
@@ -34,6 +34,9 @@ | |||
//using std::algorithm; | |||
using namespace std; | |||
#include "Peak_Client.H" | |||
extern Timeline *timeline; | |||
Fl_Boxtype Region::_box = FL_UP_BOX; | |||
@@ -107,7 +110,7 @@ Region::Region ( const Region & rhs ) | |||
} | |||
/* */ | |||
Region::Region ( Audio_File *c ) | |||
Region::Region ( Clip *c ) | |||
{ | |||
init(); | |||
_clip = c; | |||
@@ -118,7 +121,7 @@ Region::Region ( Audio_File *c ) | |||
/* used when DND importing */ | |||
Region::Region ( Audio_File *c, Track *t, nframes_t o ) | |||
Region::Region ( Clip *c, Track *t, nframes_t o ) | |||
{ | |||
init(); | |||
_clip = c; | |||
@@ -451,17 +454,42 @@ Region::draw ( int X, int Y, int W, int H ) | |||
fl_push_clip( rx, Y, rw, H ); | |||
/* dirty hack to keep the box from flipping to vertical at small sizes */ | |||
// fl_draw_box( box(), rx - 10, Y, rw + 50, H, _box_color ); | |||
/* get actual peak data */ | |||
int channels; | |||
int peaks; | |||
Peak *pbuf; | |||
_clip->read_peaks( timeline->fpp(), | |||
_start + offset, min( (_end - _start) - offset, _end), | |||
&peaks, &pbuf, &channels ); | |||
// fl_push_clip( x() + Fl::box_dx( box() ), y(), w() - Fl::box_dw( box() ), h() ); | |||
assert( pbuf ); | |||
int ch = (h() - Fl::box_dh( box() )) / _clip->channels(); | |||
for ( int i = _clip->channels(); i--; ) | |||
Waveform::draw( rx, X, (y() + Fl::box_dy( box() )) + (i * ch), W, ch, _clip, i, timeline->fpp(), | |||
_start + offset, min( (_end - _start) - offset, _end), | |||
_scale, selected() ? fl_invert_color( _color ) : _color ); | |||
int ch = (h() - Fl::box_dh( box() )) / channels; | |||
for ( int i = 0; i < channels; ++i ) | |||
{ | |||
Peak *pb = pbuf + (peaks * i); | |||
/* scale it */ | |||
for ( int j = peaks; j--; ) | |||
{ | |||
pb[ j ].min *= _scale; | |||
pb[ j ].max *= _scale; | |||
} | |||
Waveform::draw( rx, X, (y() + Fl::box_dy( box() )) + (i * ch), W, ch, | |||
pb, peaks, | |||
selected() ? fl_invert_color( _color ) : _color ); | |||
} | |||
delete pbuf; | |||
/* for ( int i = _clip->channels(); i--; ) */ | |||
/* Waveform::draw( rx, X, (y() + Fl::box_dy( box() )) + (i * ch), W, */ | |||
/* ch, _clip, i, timeline->fpp(), */ | |||
/* _start + offset, min( (_end - _start) - offset, _end), */ | |||
/* _scale, selected() ? fl_invert_color( _color ) : _color ); */ | |||
timeline->draw_measure_lines( rx, Y, rw, H, _box_color ); | |||
@@ -474,6 +502,8 @@ Region::draw ( int X, int Y, int W, int H ) | |||
if ( current() ) | |||
{ | |||
/* draw length bubble */ | |||
char pat[40]; | |||
snprintf( pat, sizeof( pat ), "%dm:%.1fs", (int)(length() / timeline->sample_rate()) / 60, (double)length() / timeline->sample_rate() ); | |||
@@ -481,15 +511,6 @@ Region::draw ( int X, int Y, int W, int H ) | |||
draw_label( pat, (Fl_Align)(FL_ALIGN_INSIDE | FL_ALIGN_CENTER), FL_GREEN ); | |||
} | |||
/* if ( _selected ) */ | |||
/* { */ | |||
/* fl_color( selection_color() ); */ | |||
/* fl_line_style( FL_SOLID, 4 ); */ | |||
/* fl_rect( x(), y(), w(), h() ); */ | |||
/* fl_line_style( FL_SOLID, 0 ); */ | |||
/* } */ | |||
fl_pop_clip(); | |||
} | |||
@@ -500,15 +521,7 @@ Region::normalize ( void ) | |||
{ | |||
printf( "normalize: start=%lu end=%lu\n", _start, _end ); | |||
/* FIXME: punt */ | |||
_scale = _clip->peaks( 0 )->normalization_factor( timeline->fpp(), _start, _end ); | |||
} | |||
/* FIXME: figure out a way to do this via the peak server */ | |||
/* _scale = _clip->peaks( 0 )->normalization_factor( timeline->fpp(), _start, _end ); */ | |||
void | |||
Region::dump ( void ) | |||
{ | |||
// printf( "Region %p %lu { \"%s\" %lu %lu }\n", this, _offset, _clip->name(), _start, _end ); | |||
/* how about in STD? */ | |||
printf( "Region\n\t%p\n\toffset\n\t\t%lu\n\tranage\n\t\t%lu\n\t\t%lu\n\tsource\n\t\t\"%s\"\n\n", this, _offset, _start, _end, _clip->name() ); | |||
} |
@@ -18,7 +18,7 @@ | |||
/*******************************************************************************/ | |||
#pragma once | |||
#include "Audio_File.H" | |||
#include "Clip.H" | |||
#include "Track.H" | |||
#include "Timeline.H" | |||
@@ -38,7 +38,7 @@ class Region_Base : public Track_Widget | |||
private: | |||
Audio_File *_clip; /* clip this region represents */ | |||
Clip *_clip; /* clip this region represents */ | |||
float _scale; /* amplitude adjustment */ | |||
@@ -100,7 +100,7 @@ protected: | |||
_scale = atof( v ); | |||
else if ( ! strcmp( s, ":source" ) ) | |||
{ | |||
if ( ! ( _clip = Audio_File::from_file( v ) ) ) | |||
if ( ! ( _clip = Clip::from_file( v ) ) ) | |||
{ | |||
printf( "Grave error: could not open source \"%s\"\n", v ); | |||
} | |||
@@ -194,8 +194,8 @@ public: | |||
Fl_Align align ( void ) const { return (Fl_Align)(FL_ALIGN_LEFT | FL_ALIGN_BOTTOM /*| FL_ALIGN_CLIP*/ | FL_ALIGN_INSIDE); } | |||
Region ( const Region & rhs ); | |||
Region ( Audio_File *c ); | |||
Region ( Audio_File *c, Track *t, nframes_t o ); | |||
Region ( Clip *c ); | |||
Region ( Clip *c, Track *t, nframes_t o ); | |||
int handle ( int m ); | |||
void draw_box( int X, int Y, int W, int H ); | |||
@@ -204,7 +204,5 @@ public: | |||
void normalize ( void ); | |||
void dump ( void ); | |||
}; | |||
#endif |
@@ -27,7 +27,9 @@ | |||
#include "Scalebar.H" | |||
#include "Audio_File.H" // just for nframes_t | |||
/* #include "Audio_File.H" // just for nframes_t */ | |||
typedef unsigned long nframes_t; | |||
#include <math.h> | |||
#include <assert.h> | |||
@@ -21,7 +21,6 @@ | |||
#include "Track.H" | |||
#include "Loggable.H" | |||
#include "Audio_File.H" | |||
#include "Timeline.H" | |||
#include <list> | |||
#include <algorithm> | |||
@@ -24,7 +24,6 @@ | |||
#include <FL/fl_draw.H> | |||
#include "Timeline.H" | |||
#include "Audio_File.H" | |||
#include "Waveform.H" | |||
@@ -43,20 +42,17 @@ bool Waveform::logarithmic = true; | |||
/** draw a portion of /clip/'s waveform. coordinates are the portion to draw */ | |||
void | |||
Waveform::draw ( int ox, int X, int Y, int W, int H, Audio_File *_clip, int channel, float fpp, nframes_t _start, nframes_t _end, float _scale, Fl_Color color ) | |||
Waveform::draw ( int ox, int X, int Y, int W, int H, | |||
Peak *pbuf, int peaks, | |||
Fl_Color color ) | |||
{ | |||
fl_push_clip( X, Y, W, H ); | |||
int j; | |||
// int start = timeline->ts_to_x( _start ); | |||
int start = timeline->ts_to_x( _start ) + (X - ox); | |||
// int start = timeline->ts_to_x( _start ) + (X - ox); | |||
const Peaks *pk = _clip->peaks( channel ); | |||
_start = timeline->x_to_ts( start ); | |||
pk->fill_buffer( fpp, _start, _start + timeline->x_to_ts( W ) ); | |||
int start = 0; | |||
const int halfheight = H / 2; | |||
const int mid = Y + halfheight; | |||
@@ -66,12 +62,7 @@ Waveform::draw ( int ox, int X, int Y, int W, int H, Audio_File *_clip, int chan | |||
j = start; | |||
for ( int x = X; x <= X + W; ++x, ++j ) | |||
{ | |||
// Peak p = (*pk)[ j ]; | |||
Peak p = pk->peak( timeline->x_to_ts( j ), timeline->x_to_ts( j + 1 ) ); | |||
p.max *= _scale; | |||
p.min *= _scale; | |||
const Peak p = pbuf[ j ]; | |||
const float diff = fabs( p.max - p.min ); | |||
@@ -103,7 +94,6 @@ Waveform::draw ( int ox, int X, int Y, int W, int H, Audio_File *_clip, int chan | |||
} | |||
} | |||
if ( Waveform::outline ) | |||
{ | |||
@@ -116,10 +106,7 @@ Waveform::draw ( int ox, int X, int Y, int W, int H, Audio_File *_clip, int chan | |||
j = start; | |||
for ( int x = X; x <= X + W; ++x, ++j ) | |||
{ | |||
// Peak p = (*pk)[ j ]; | |||
Peak p = pk->peak( timeline->x_to_ts( j ), timeline->x_to_ts( j + 1 ) ); | |||
p.min *= _scale; | |||
const Peak p = pbuf[ j ]; | |||
fl_vertex( x, Y + (H / 2) + ((float)H / 2 * p.min )); | |||
} | |||
@@ -131,10 +118,7 @@ Waveform::draw ( int ox, int X, int Y, int W, int H, Audio_File *_clip, int chan | |||
j = start; | |||
for ( int x = X; x <= X + W; ++x, ++j ) | |||
{ | |||
// Peak p = (*pk)[ j ]; | |||
Peak p = pk->peak( timeline->x_to_ts( j ), timeline->x_to_ts( j + 1 ) ); | |||
p.max *= _scale; | |||
const Peak p = pbuf[ j ]; | |||
fl_vertex( x, Y + (H / 2) + ((float)H / 2 * p.max )); | |||
} | |||
@@ -24,8 +24,7 @@ | |||
#include "Timeline.H" | |||
#include "Audio_File.H" | |||
#include "Peak_Client.H" | |||
class Waveform { | |||
@@ -36,6 +35,8 @@ public: | |||
static bool vary_color; | |||
static bool logarithmic; | |||
static void draw ( int rx, int X, int Y, int W, int H, Audio_File *_clip, int channel, float fpp, nframes_t _start, nframes_t _end, float _scale, Fl_Color color ); | |||
static void draw ( int ox, int X, int Y, int W, int H, | |||
Peak *pbuf, int peaks, | |||
Fl_Color color ); | |||
}; |
@@ -53,6 +53,10 @@ | |||
Timeline *timeline; | |||
#include "Peak_Client.H" | |||
Peak_Client peak_client; | |||
void cb_undo ( Fl_Widget *w, void *v ) | |||
{ | |||
Loggable::undo(); | |||
@@ -69,6 +73,13 @@ main ( int argc, char **argv ) | |||
Fl::scheme( "plastic" ); | |||
// Fl::scheme( "gtk+" ); | |||
if ( ! peak_client.connect( "localhost" ) ) | |||
{ | |||
fprintf( stderr, "Could not connect to peak server!\n" ); | |||
return 1; | |||
} | |||
Loggable::open( "history" ); | |||
/* welcome to C++ */ | |||
Loggable::register_create( "Region", &Region::create ); | |||