@@ -1,6 +1,7 @@ | |||
SRCS= \ | |||
Server.C \ | |||
Peak_Server.C \ | |||
Timeline_Server.C \ | |||
main.C \ | |||
Audio_File.C \ | |||
@@ -17,6 +17,12 @@ | |||
/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | |||
/*******************************************************************************/ | |||
#include "Peak_Server.H" | |||
#include <stdio.h> | |||
#include <string.h> | |||
#include <sys/socket.h> | |||
/* Peak Server | |||
The peak server streams peak data to any timeline editors or other clients that ask for it. | |||
@@ -27,6 +33,59 @@ | |||
Response looks like (in binary floats): | |||
> length min max min max min max | |||
> channels length min max min max min max | |||
length ... | |||
*/ | |||
#include "Audio_File.H" | |||
#include "Peaks.H" | |||
typedef unsigned long tick_t; | |||
#define PEAK_PORT 6100 | |||
void | |||
Peak_Server::handle_new ( int s ) | |||
{ | |||
printf( "new connection\n" ); | |||
} | |||
void | |||
Peak_Server::handle_hang_up ( int s ) | |||
{ | |||
printf( "hangup\n" ); | |||
} | |||
void | |||
Peak_Server::handle_request ( int s, const char *buf, int l ) | |||
{ | |||
printf( "request: %s", buf ); | |||
char source[512]; | |||
float fpp; | |||
tick_t start, end; | |||
if ( 4 != sscanf( buf, "read_peaks \"%[^\"]\" %f %lu %lu", source, &fpp, &start, &end ) ) | |||
fprintf( stderr, "error: malformed peak request!\n" ); | |||
Audio_File *af = Audio_File::from_file( source ); | |||
int channels = af->channels(); | |||
send( s, &channels, sizeof( int ), 0 ); | |||
for ( int i = 0; i < af->channels(); ++i ) | |||
{ | |||
const Peaks *pk = af->peaks( i ); | |||
int peaks = pk->fill_buffer( fpp, start, end ); | |||
send( s, &peaks, sizeof( int ), 0 ); | |||
send( s, pk->peakbuf(), peaks * sizeof( Peak ), 0 ); | |||
} | |||
delete af; | |||
} |
@@ -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 | |||
#include "Server.H" | |||
class Peak_Server : public Server | |||
{ | |||
protected: | |||
void handle_new ( int s ); | |||
void handle_hang_up ( int s ); | |||
void handle_request ( int s, const char *s, int l ); | |||
public: | |||
Peak_Server ( int port ) : Server ( port ) | |||
{ | |||
fork( true ); | |||
echo( false ); | |||
} | |||
}; |
@@ -38,27 +38,33 @@ | |||
#include <math.h> | |||
Peaks::peakbuffer Peaks::peakbuf; | |||
Peaks::peakbuffer Peaks::_peakbuf; | |||
/** Prepare a buffer of peaks from /s/ to /e/ for reading. Must be | |||
* called before any calls to operator[] */ | |||
void | |||
int | |||
Peaks::fill_buffer ( float fpp, int s, int e ) const | |||
{ | |||
_fpp = fpp; | |||
if ( fpp < _peaks->chunksize ) | |||
/* FIXME: repair this */ | |||
// if ( fpp < _peaks->chunksize ) | |||
{ | |||
/* looks like we're going to have to switch to a higher resolution peak file | |||
or read directly from the source */ | |||
read_peaks( s, e, (e - s) / fpp, fpp ); | |||
/* FIXME: are we *SURE* we got them all? */ | |||
return e - s; | |||
} | |||
else | |||
{ | |||
/* we'll just downsample on the fly in this case--no need for extra copying into | |||
the buffer */ | |||
} | |||
/* else */ | |||
/* { */ | |||
/* /\* we'll just downsample on the fly in this case--no need for extra copying into */ | |||
/* the buffer *\/ */ | |||
/* } */ | |||
} | |||
@@ -123,19 +129,19 @@ Peaks::read_peaks ( int s, int e, int npeaks, int chunksize ) const | |||
{ | |||
printf( "reading peaks %d @ %d\n", npeaks, chunksize ); | |||
if ( peakbuf.size < npeaks ) | |||
if ( _peakbuf.size < npeaks ) | |||
{ | |||
peakbuf.size = npeaks; | |||
// printf( "reallocating peak buffer %li\n", peakbuf.size ); | |||
peakbuf.buf = (peakdata*)realloc( peakbuf.buf, sizeof( peakdata ) + (peakbuf.size * sizeof( Peak )) ); | |||
_peakbuf.size = npeaks; | |||
// printf( "reallocating peak buffer %li\n", _peakbuf.size ); | |||
_peakbuf.buf = (peakdata*)realloc( _peakbuf.buf, sizeof( peakdata ) + (_peakbuf.size * sizeof( Peak )) ); | |||
} | |||
_clip->open(); | |||
_clip->seek( s ); | |||
peakbuf.offset = s; | |||
peakbuf.buf->chunksize = chunksize; | |||
peakbuf.len = clip_read_peaks( peakbuf.buf->data, npeaks, chunksize ); | |||
_peakbuf.offset = s; | |||
_peakbuf.buf->chunksize = chunksize; | |||
_peakbuf.len = clip_read_peaks( _peakbuf.buf->data, npeaks, chunksize ); | |||
_clip->close(); | |||
} | |||
@@ -149,17 +155,17 @@ Peaks::peak ( nframes_t start, nframes_t end ) const | |||
if ( _fpp < _peaks->chunksize ) | |||
{ | |||
assert( _fpp == peakbuf.buf->chunksize ); | |||
assert( _fpp == _peakbuf.buf->chunksize ); | |||
start = (start - peakbuf.offset) / peakbuf.buf->chunksize; | |||
end = (end - peakbuf.offset) / peakbuf.buf->chunksize; | |||
start = (start - _peakbuf.offset) / _peakbuf.buf->chunksize; | |||
end = (end - _peakbuf.offset) / _peakbuf.buf->chunksize; | |||
if ( end > peakbuf.len ) | |||
end = peakbuf.len; | |||
if ( end > _peakbuf.len ) | |||
end = _peakbuf.len; | |||
// assert( peakbuf.len > start ); | |||
// assert( _peakbuf.len > start ); | |||
downsample( peakbuf.buf->data, start, end, &p.max, &p.min ); | |||
downsample( _peakbuf.buf->data, start, end, &p.max, &p.min ); | |||
} | |||
else | |||
{ | |||
@@ -175,17 +181,18 @@ Peaks::peak ( nframes_t start, nframes_t end ) const | |||
/* virtual array. Index is a Pixel value, and it returns the | |||
* (resampled) peaks for that pixel based on the current timeline | |||
* zoom. */ | |||
Peak & | |||
Peaks::operator[] ( int X ) const | |||
{ | |||
Peak p; | |||
p.min = 0; | |||
p.max = 0; | |||
return p; | |||
// return peak( timeline->x_to_ts( X ), timeline->x_to_ts( X + 1 ) ); | |||
/* Peak & */ | |||
/* Peaks::operator[] ( int X ) const */ | |||
/* { */ | |||
} | |||
/* Peak p; */ | |||
/* p.min = 0; */ | |||
/* p.max = 0; */ | |||
/* return p; */ | |||
/* // return peak( timeline->x_to_ts( X ), timeline->x_to_ts( X + 1 ) ); */ | |||
/* } */ | |||
const char * | |||
@@ -54,7 +54,7 @@ class Peaks | |||
} | |||
}; | |||
static peakbuffer peakbuf; | |||
static peakbuffer _peakbuf; | |||
Audio_File *_clip; | |||
int _channel; | |||
@@ -96,10 +96,11 @@ public: | |||
_channel = 0; | |||
} | |||
Peak *peakbuf ( void ) const { return Peaks::_peakbuf.buf->data; } | |||
void clip ( Audio_File *c ) { _clip = c; } | |||
void channel ( int v ) { _channel = v; } | |||
void fill_buffer ( float fpp, int s, int e ) const; | |||
int fill_buffer ( float fpp, int s, int e ) const; | |||
void downsample ( Peak *peaks, int s, int e, float *mhi, float *mlo ) const; | |||
void read ( int X, float *hi, float *lo ) const; | |||
@@ -83,6 +83,8 @@ Server::listen_on_port ( int port ) | |||
Server::Server ( int port ) | |||
{ | |||
_port = port; | |||
_echo = false; | |||
_fork = false; | |||
} | |||
void | |||
@@ -159,7 +161,7 @@ Server::run ( void ) | |||
else | |||
{ | |||
if ( echos() ) | |||
if ( echo() ) | |||
/* echo to others */ | |||
for ( int j = maxfd; j-- ; ) | |||
{ | |||
@@ -17,10 +17,14 @@ | |||
/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | |||
/*******************************************************************************/ | |||
#pragma once | |||
class Server | |||
{ | |||
int _port; | |||
bool _echo; | |||
bool _fork; | |||
static int listen_on_port ( int port ); | |||
@@ -29,9 +33,13 @@ public: | |||
Server ( int port ); | |||
void run ( void ); | |||
bool echo ( void ) { return _echo; } | |||
bool fork ( void ) { return _fork; } | |||
void echo ( bool b ) { _echo = b; } | |||
void fork ( bool b) { _fork = b; } | |||
protected: | |||
virtual bool echos ( void ) { return true; } | |||
virtual void handle_hang_up ( int s ) = 0; | |||
virtual void handle_new ( int s ) = 0; | |||
@@ -34,5 +34,7 @@ public: | |||
Timeline_Server ( int port ) : Server ( port ) | |||
{ | |||
fork( false ); | |||
echo( true ); | |||
} | |||
}; |
@@ -26,6 +26,7 @@ | |||
#include "Timeline_Server.H" | |||
#include "Peak_Server.H" | |||
/* TODO: | |||
@@ -60,7 +61,13 @@ | |||
int | |||
main ( int argc, char **argv ) | |||
{ | |||
Timeline_Server tls( 6110 ); | |||
tls.run(); | |||
/* Timeline_Server tls( 6110 ); */ | |||
/* tls.run(); */ | |||
Peak_Server pks( 6111 ); | |||
pks.run(); | |||
} |