Browse Source

Work on switching Timeline Editor over to use the Peak Server.

tags/non-daw-v1.1.0
Jonathan Moore Liles 17 years ago
parent
commit
b0d5b60a6f
14 changed files with 375 additions and 104 deletions
  1. +53
    -16
      Engine/Peak_Server.C
  2. +1
    -1
      Engine/Peaks.C
  3. +2
    -19
      Timeline/Audio_Track.C
  4. +70
    -0
      Timeline/Clip.H
  5. +1
    -3
      Timeline/Makefile
  6. +135
    -0
      Timeline/Peak_Client.C
  7. +40
    -0
      Timeline/Peak_Client.H
  8. +42
    -29
      Timeline/Region.C
  9. +5
    -7
      Timeline/Region.H
  10. +3
    -1
      Timeline/Timeline.H
  11. +0
    -1
      Timeline/Track_Widget.H
  12. +8
    -24
      Timeline/Waveform.C
  13. +4
    -3
      Timeline/Waveform.H
  14. +11
    -0
      Timeline/main.C

+ 53
- 16
Engine/Peak_Server.C View File

@@ -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;


+ 1
- 1
Engine/Peaks.C View File

@@ -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 */


+ 2
- 19
Timeline/Audio_Track.C View File

@@ -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" );
}

+ 70
- 0
Timeline/Clip.H View File

@@ -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 );
}
};

+ 1
- 3
Timeline/Makefile View File

@@ -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)


+ 135
- 0
Timeline/Peak_Client.C View File

@@ -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;
}

+ 40
- 0
Timeline/Peak_Client.H View File

@@ -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 );

};

+ 42
- 29
Timeline/Region.C View File

@@ -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() );
}

+ 5
- 7
Timeline/Region.H View File

@@ -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

+ 3
- 1
Timeline/Timeline.H View File

@@ -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>


+ 0
- 1
Timeline/Track_Widget.H View File

@@ -21,7 +21,6 @@

#include "Track.H"
#include "Loggable.H"
#include "Audio_File.H"
#include "Timeline.H"
#include <list>
#include <algorithm>


+ 8
- 24
Timeline/Waveform.C View File

@@ -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 ));
}


+ 4
- 3
Timeline/Waveform.H View File

@@ -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 );

};

+ 11
- 0
Timeline/main.C View File

@@ -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 );


Loading…
Cancel
Save