static void track_head(bs1770gain_print_t *p, bs1770gain_track_t *t) { #if defined (W_WIN32) // [ wchar_t *wbasename; if (NULL==t) wbasename=NULL; else if (NULL==(wbasename=pbu_s2w(pbu_basename(t->ipath)))) { DMESSAGE("converting UTF-8 to UTF-16"); goto wbasename; } #endif // ] p->t=t; if (NULL==t) { #if defined (W_WIN32) // [ fwprintf(p->f,L" [ALBUM]:"); #else // ] [ fprintf(p->f," [ALBUM]:"); #endif // ] } else { #if defined (W_WIN32) // [ fwprintf(p->f,L" [%d/%d] \"%s\"",t->n,p->a->n,wbasename); fwprintf(p->f,L": "); #else // ] [ fprintf(p->f," [%d/%d] \"%s\"",t->n,p->a->n,pbu_basename(t->ipath)); fprintf(p->f,": "); #endif // ] fflush(p->f); } #if defined (W_WIN32) // [ free(wbasename); wbasename: return; #endif // ] }
/* determine number of output ports, signal if changed. */ void Chain::configure_ports ( void ) { int nouts = 0; client()->lock(); for ( int i = 0; i < modules(); ++i ) { module( i )->configure_inputs( nouts ); nouts = module( i )->noutputs(); } unsigned int req_buffers = required_buffers(); DMESSAGE( "required_buffers = %i", req_buffers ); if ( scratch_port.size() < req_buffers ) { for ( unsigned int i = scratch_port.size(); i--; ) free(scratch_port[i].buffer()); scratch_port.clear(); for ( unsigned int i = 0; i < req_buffers; ++i ) { Module::Port p( NULL, Module::Port::OUTPUT, Module::Port::AUDIO ); p.connect_to( buffer_alloc( client()->nframes() ) ); buffer_fill_with_silence( (sample_t*)p.buffer(), client()->nframes() ); scratch_port.push_back( p ); } } build_process_queue(); client()->unlock(); parent()->redraw(); }
void Module::menu_cb ( const Fl_Menu_ *m ) { char picked[256]; if ( ! m->mvalue() || m->mvalue()->flags & FL_SUBMENU_POINTER || m->mvalue()->flags & FL_SUBMENU ) return; strncpy( picked, m->mvalue()->label(), sizeof( picked ) ); // m->item_pathname( picked, sizeof( picked ) ); DMESSAGE( "%s", picked ); Logger log( this ); if ( ! strcmp( picked, "Edit Parameters" ) ) command_open_parameter_editor(); else if ( ! strcmp( picked, "Bypass" ) ) bypass( ! ( m->mvalue()->flags & FL_MENU_VALUE ) ); else if ( ! strcmp( picked, "Cut" ) ) { copy(); chain()->remove( this ); Fl::delete_widget( this ); } else if ( ! strcmp( picked, "Copy" ) ) { copy(); } else if ( ! strcmp( picked, "Paste" ) ) { paste_before(); } else if ( ! strcmp( picked, "Remove" ) ) command_remove(); }
/* rename chain... we have to let our modules know our name has * changed so they can take the appropriate action (in particular the * JACK module). */ void Chain::name ( const char *name ) { char ename[512]; snprintf( ename, sizeof(ename), "%s%s%s/%s", APP_NAME, instance_name ? "." : "", instance_name ? instance_name : "", name ); if ( ! _engine ) { _engine = new Engine( &Chain::process, this ); engine()->buffer_size_callback( &Chain::buffer_size, this ); const char *jack_name = engine()->init( ename ); if ( ! jack_name ) { _engine = NULL; fl_alert( "Could not create JACK client. Perhaps the sound device already in use. In any event, now I'll die." ); exit( 1 ); return; } } else { DMESSAGE( "Renaming JACK client from \"%s\" to \"%s\"", _name, ename ); _name = engine()->name( ename ); /* FIXME: discarding the name jack picked is technically wrong! */ } _name = name; for ( int i = 0; i < modules(); ++i ) module( i )->handle_chain_name_changed(); }
void Module::set_parameters ( const char *parameters ) { char *s = strdup( parameters ); char *start = s; unsigned int i = 0; for ( char *sp = s; ; ++sp ) { if ( ':' == *sp || '\0' == *sp ) { char was = *sp; *sp = '\0'; DMESSAGE( start ); if ( i < control_input.size() ) control_input[i].control_value( atof( start ) ); else { WARNING( "Module has no parameter at index %i", i ); break; } i++; if ( '\0' == was ) break; start = sp + 1; } } free( s ); }
void save ( void ) { DMESSAGE( "Sending process save signal" ); if ( _pid ) ::kill( _pid, _save_signal ); }
void Track::menu_cb ( const Fl_Menu_ *m ) { char picked[256]; m->item_pathname( picked, sizeof( picked ) ); DMESSAGE( "Picked: %s", picked ); Logger log( this ); if ( ! strcmp( picked, "Type/Mono" ) ) { command_configure_channels( 1 ); } else if ( ! strcmp( picked, "Type/Stereo" ) ) { command_configure_channels( 2 ); } else if ( ! strcmp( picked, "Type/Quad" ) ) { command_configure_channels( 4 ); } else if ( ! strcmp( picked, "Type/..." ) ) { const char *s = fl_input( "How many channels?", "3" ); if ( s ) { int c = atoi( s ); if ( c <= 0 || c > 10 ) fl_alert( "Invalid number of channels." ); else { command_configure_channels(c); } } } else if ( ! strcmp( picked, "/Add Control" ) ) { /* add audio track */ char *name = get_unique_control_name( "Control" ); timeline->wrlock(); new Control_Sequence( this, name ); timeline->unlock(); } else if ( ! strcmp( picked, "/Overlay controls" ) ) { overlay_controls( ! m->mvalue()->value() ); } else if ( ! strcmp( picked, "/Add Annotation" ) ) { add( new Annotation_Sequence( this ) ); } else if ( ! strcmp( picked, "/Color" ) ) { unsigned char r, g, b; Fl::get_color( color(), r, g, b ); if ( fl_color_chooser( "Track Color", r, g, b ) ) { color( fl_rgb_color( r, g, b ) ); } redraw(); } else if ( ! strcmp( picked, "Flags/Record" ) ) { armed( m->mvalue()->flags & FL_MENU_VALUE ); } else if ( ! strcmp( picked, "Flags/Mute" ) ) { mute( m->mvalue()->flags & FL_MENU_VALUE ); } else if ( ! strcmp( picked, "Flags/Solo" ) ) { solo( m->mvalue()->flags & FL_MENU_VALUE ); } else if ( ! strcmp( picked, "Size/Small" ) ) { size( 0 ); } else if ( ! strcmp( picked, "Size/Medium" ) ) { size( 1 ); } else if ( ! strcmp( picked, "Size/Large" ) ) { size( 2 ); } else if ( ! strcmp( picked, "Size/Huge" ) ) { size( 3 ); } else if ( ! strcmp( picked, "/Remove" ) ) { int r = fl_choice( "Are you certain you want to remove track \"%s\"?", "Cancel", NULL, "Remove", name() ); if ( r == 2 ) { timeline->command_remove_track( this ); Fl::delete_widget( this ); } } else if ( ! strcmp( picked, "/Rename" ) ) { ((Fl_Sometimes_Input*)name_field)->take_focus(); } else if ( ! strcmp( picked, "/Move Up" ) ) { timeline->command_move_track_up( this ); } else if ( ! strcmp( picked, "/Move Down" ) ) { timeline->command_move_track_down( this ); } else if ( !strcmp( picked, "Takes/Show all takes" ) ) { show_all_takes( ! m->mvalue()->value() ); } else if ( !strcmp( picked, "Takes/New" ) ) { timeline->wrlock(); sequence( (Audio_Sequence*)sequence()->clone_empty() ); timeline->unlock(); } else if ( !strcmp( picked, "Takes/Remove" ) ) { if ( takes->children() ) { Loggable::block_start(); timeline->wrlock(); Audio_Sequence *s = sequence(); sequence( (Audio_Sequence*)takes->child( 0 ) ); delete s; timeline->unlock(); Loggable::block_end(); } } else if ( !strcmp( picked, "Takes/Remove others" )) { if ( takes->children() ) { Loggable::block_start(); takes->clear(); Loggable::block_end(); } } else if ( !strncmp( picked, "Takes/", sizeof( "Takes/" ) - 1 ) ) { Audio_Sequence* s = (Audio_Sequence*)m->mvalue()->user_data(); timeline->wrlock(); sequence( s ); timeline->unlock(); } }
int Track::handle ( int m ) { /* if ( m != FL_NO_EVENT ) */ /* DMESSAGE( "%s", event_name( m ) ); */ static Fl_Widget *dragging = NULL; switch ( m ) { case FL_DND_ENTER: case FL_DND_LEAVE: case FL_DND_DRAG: case FL_DND_RELEASE: case FL_PASTE: if ( Fl::event_x() > Track::width() ) return sequence()->handle(m); default: break; } switch ( m ) { case FL_KEYBOARD: { Fl_Menu_Button * men = &menu(); if ( Fl::event_key() == FL_Menu ) { menu_popup( men ); return 1; } else return men->test_shortcut() || Fl_Group::handle( m ); } case FL_MOUSEWHEEL: { Logger log( this ); if ( ! Fl::event_shift() ) return Fl_Group::handle( m ); int d = Fl::event_dy(); if ( d < 0 ) size( size() - 1 ); else size( size() + 1 ); return 1; } case FL_PUSH: { if ( Fl::event_button1() && Fl::event_inside( ((Track_Header*)child(0))->color_box ) ) { dragging = this; return 1; } if ( Fl::event_button1() && Fl::event_inside( ((Track_Header*)child(0))->output_connector_handle ) ) return 1; Logger log( this ); if ( Fl_Group::handle( m ) ) return 1; if ( test_press( FL_BUTTON3 ) && Fl::event_x() < Track::width() ) { menu_popup( &menu() ); return 1; } return 0; } /* we have to prevent Fl_Group::handle() from getting these, otherwise it will mess up Fl::belowmouse() */ case FL_ENTER: case FL_LEAVE: case FL_MOVE: if ( Fl::event_x() >= Track::width() ) { return Fl_Group::handle(m); } return 1; case FL_DND_ENTER: return 1; case FL_DND_LEAVE: if ( ! Fl::event_inside(this) && this == receptive_to_drop ) { receptive_to_drop = 0; redraw(); Fl::selection_owner(0); } return 1; case FL_RELEASE: if ( dragging == this ) { dragging = NULL; timeline->insert_track( this, timeline->event_inside() ); return 1; } return 0; break; case FL_DND_RELEASE: receptive_to_drop = 0; redraw(); Fl::selection_owner(0); return 1; case FL_DND_DRAG: { if ( receptive_to_drop == ((Track_Header*)child(0))->input_connector_handle ) return 1; if ( Fl::event_inside( ((Track_Header*)child(0))->input_connector_handle ) && receptive_to_drop != ((Track_Header*)child(0))->input_connector_handle ) { receptive_to_drop = ((Track_Header*)child(0))->input_connector_handle; redraw(); return 1; } else { receptive_to_drop = NULL; redraw(); return 0; } } case FL_PASTE: { receptive_to_drop = 0; redraw(); if (! Fl::event_inside( ((Track_Header*)child(0))->input_connector_handle ) ) return 0; /* NOW we get the text... */ const char *text = Fl::event_text(); DMESSAGE( "Got drop text \"%s\"",text); if ( strncmp( text, "jack.port://", strlen( "jack.port://" ) ) ) { return 0; } std::vector<std::string> port_names; char *port_name; int end; while ( sscanf( text, "jack.port://%a[^\r\n]\r\n%n", &port_name, &end ) > 0 ) { DMESSAGE( "Scanning %s", port_name ); port_names.push_back( port_name ); free(port_name ); text += end; } for ( unsigned int i = 0; i < input.size() && i < port_names.size(); i++) { const char *pn = port_names[i].c_str(); JACK::Port *ji = &input[i]; if ( ji->connected_to( pn ) ) { DMESSAGE( "Disconnecting from \"%s\"", pn ); ji->disconnect( pn ); } else { DMESSAGE( "Connecting to %s", pn ); ji->connect( pn ); } } Fl::selection_owner(0); return 1; } case FL_DRAG: { if ( this != Fl::selection_owner() && Fl::event_inside( ((Track_Header*)child(0))->output_connector_handle ) ) { char *s = (char*)malloc(256); s[0] = 0; for ( unsigned int i = 0; i < output.size(); ++i ) { char *s2; asprintf(&s2, "jack.port://%s:%s\r\n", instance_name, output[i].name() ); s = (char*)realloc( s, strlen( s ) + strlen( s2 ) + 1 ); strcat( s, s2 ); free( s2 ); } Fl::copy(s, strlen(s) + 1, 0); Fl::selection_owner(this); free( s ); Fl::dnd(); return 1; } else { return 1; } } default: return Fl_Group::handle( m ); } return 0; }
void Record_DS::disk_thread ( void ) { _thread.name( "Capture" ); DMESSAGE( "capture thread running..." ); track()->record( _capture, _frame ); const nframes_t nframes = _nframes * _disk_io_blocks; /* buffer to hold the interleaved data returned by the track reader */ sample_t *buf = new sample_t[ nframes * channels() ]; #ifndef AVOID_UNNECESSARY_COPYING sample_t *cbuf = new sample_t[ nframes ]; #endif const size_t block_size = nframes * sizeof( sample_t ); int blocks_ready = 0; while ( wait_for_block() ) { if ( ++blocks_ready < _disk_io_blocks ) continue; else blocks_ready = 0; /* pull data from the per-channel ringbuffers and interlace it */ for ( int i = channels(); i--; ) { #ifdef AVOID_UNNECESSARY_COPYING /* interleave direcectly from the ringbuffer to avoid * unnecessary copying */ jack_ringbuffer_data_t rbd[2]; memset( rbd, 0, sizeof( rbd ) ); jack_ringbuffer_get_read_vector( _rb[ i ], rbd ); if ( rbd[ 0 ].len >= block_size ) { /* it'll all fit in one go */ buffer_interleave_one_channel( buf, (sample_t*)rbd[ 0 ].buf, i, channels(), nframes ); } else if ( rbd[ 0 ].len + rbd[ 1 ].len >= block_size ) { /* there's enough space in the ringbuffer, but it's not contiguous */ assert( ! ( rbd[ 0 ].len % sizeof( sample_t ) ) ); const nframes_t f = rbd[ 0 ].len / sizeof( sample_t ); /* do the first half */ buffer_deinterleave_one_channel( (sample_t*)rbd[ 0 ].buf, buf, i, channels(), f ); buffer_interleave_one_channel( buf, (sample_t*)rbd[ 0 ].buf, i, channels(), f ); assert( rbd[ 1 ].len >= ( nframes - f ) * sizeof( sample_t ) ); /* do the second half */ buffer_interleave_one_channel( buf + f, (sample_t*)rbd[ 0 ].buf, i, channels(), nframes - f ); } else ++_xruns; jack_ringbuffer_read_advance( _rb[ i ], block_size ); #else if ( jack_ringbuffer_read( _rb[ i ], (char*)cbuf, block_size ) < block_size ) ++_xruns; buffer_interleave_one_channel( buf, cbuf, i, channels(), nframes ); #endif } write_block( buf, nframes ); } DMESSAGE( "capture thread terminating" ); /* flush what remains in the buffer out to disk */ { /* use JACk sized blocks for this last bit */ const nframes_t nframes = _nframes; const size_t block_size = _nframes * sizeof( sample_t ); #ifdef AVOID_UNNECESSARY_COPYING sample_t *cbuf = new sample_t[ nframes ]; #endif while ( blocks_ready-- > 0 || ( ! sem_trywait( &_blocks ) && errno != EAGAIN ) ) { for ( int i = channels(); i--; ) { jack_ringbuffer_read( _rb[ i ], (char*)cbuf, block_size ); buffer_interleave_one_channel( buf, cbuf, i, channels(), nframes ); } const nframes_t frames_remaining = (_stop_frame - _frame ) - _frames_written; if ( frames_remaining < nframes ) { /* this is the last block, might be partial */ write_block( buf, frames_remaining ); break; } else write_block( buf, nframes ); } #ifdef AVOID_UNNECESSARY_COPYING delete[] cbuf; #endif } delete[] buf; #ifndef AVOID_UNNECESSARY_COPYING delete[] cbuf; #endif DMESSAGE( "finalzing capture" ); Track::Capture *c = _capture; _capture = NULL; /* now finalize the recording */ track()->finalize( c, _stop_frame ); delete c; _terminate = false; DMESSAGE( "capture thread gone" ); _thread.exit(); }
void Mixer::cb_menu(Fl_Widget* o) { Fl_Menu_Bar *menu = (Fl_Menu_Bar*)o; /* const Fl_Menu_Item *mi = &menu->menu()[menu->value()]; */ char picked[256]; // const char *picked = menu->text(); menu->item_pathname( picked, sizeof( picked ) ); if (! strcmp( picked, "&Project/&New") ) { DMESSAGE( "New project" ); const char *templates[] = { "Default", NULL }; char *default_path; char *selected_template; read_line( user_config_dir, "default_path", &default_path ); char *path = new_project_chooser( templates, &default_path, &selected_template ); if ( path ) { if ( ! Project::create( path, selected_template ) ) fl_alert( "Error creating project!" ); free( path ); free( selected_template ); } update_menu(); if ( default_path ) { write_line( user_config_dir, "default_path", default_path ); free( default_path ); } } else if (! strcmp( picked, "&Project/&Open" ) ) { char *path = NULL; // read_line( user_config_dir, "default_path", &path ); const char *name = fl_dir_chooser( "Open Project", path ); free( path ); mixer->hide(); if ( int err = Project::open( name ) ) { fl_alert( "Error opening project: %s", Project::errstr( err ) ); } update_menu(); mixer->show(); } else if (! strcmp( picked, "&Project/&Save" ) ) { command_save(); } else if (! strcmp( picked, "&Project/&Quit") ) { command_quit(); } else if ( !strcmp( picked, "&Mixer/&Add Strip" ) ) { command_add_strip(); } else if ( !strcmp( picked, "&Mixer/Add &N Strips" ) ) { const char *s = fl_input( "Enter number of strips to add" ); if ( s ) { for ( int i = atoi( s ); i > 0; i-- ) command_add_strip(); } } else if ( !strcmp( picked, "&Mixer/&Import Strip" ) ) { const char *s = fl_file_chooser( "Export strip to filename:", "*.strip", NULL, 0 ); if ( s ) { if (! Mixer_Strip::import_strip( s ) ) fl_alert( "%s", "Failed to import strip!" ); } } else if (! strcmp( picked, "&Mixer/&Rows/One") ) { rows( 1 ); } else if (! strcmp( picked, "&Mixer/&Rows/Two") ) { rows( 2 ); } else if (! strcmp( picked, "&Mixer/&Rows/Three") ) { rows( 3 ); } else if (! strcmp( picked, "&View/&Theme") ) { fl_theme_chooser(); } else if (! strcmp( picked, "&Options/&Display/&Knobs/&Burnished") ) { Fl_Dial::default_style( Fl_Dial::BURNISHED_DIAL ); redraw_windows(); } else if (! strcmp( picked, "&Options/&Display/&Knobs/&Arc") ) { Fl_Dial::default_style( Fl_Dial::ARC_DIAL ); redraw_windows(); } else if (! strcmp( picked, "&Options/&Display/&Knobs/&Plastic") ) { Fl_Dial::default_style( Fl_Dial::PLASTIC_DIAL ); redraw_windows(); } else if (! strcmp( picked, "&Options/&Display/&Sliders/&Nice") ) { Fl_Value_SliderX::default_style( Fl_Value_SliderX::NICE_SLIDER ); redraw_windows(); } else if (! strcmp( picked, "&Options/&Display/&Sliders/&Fill") ) { Fl_Value_SliderX::default_style( Fl_Value_SliderX::FILL_SLIDER ); redraw_windows(); } else if (! strcmp( picked, "&Options/&Display/&Sliders/&Simple") ) { Fl_Value_SliderX::default_style( Fl_Value_SliderX::SIMPLE_SLIDER ); redraw_windows(); } else if ( ! strcmp( picked, "&Help/&About" ) ) { About_Dialog ab( PIXMAP_PATH "/non-mixer/icon-256x256.png" ); ab.logo_box->label( VERSION ); ab.title->label( "The Non Mixer" ); ab.copyright->label( "Copyright (C) 2008-2010 Jonathan Moore Liles" ); ab.credits->label( "Non-Mixer was written from scratch by\n" "Jonathan Moore Liles for his own use\n" "(see the manual).\n" "\n" "Nobody planned. Nobody helped.\n" "You can help now by donating time, money,\n" "and/or replacing the rest of Linux Audio\n" "with fast, light, reliable alternatives.\n" ); ab.website_url->label( "http://non-mixer.tuxfamily.org" ); ab.run(); } else if ( !strcmp( picked, "&Help/&Manual" )) { char *pat; asprintf( &pat, "file://%s.html", DOCUMENT_PATH "/non-mixer/MANUAL" ); open_url( pat ); free( pat ); } }
/** load entire sequence from file, replacing everything */ bool sequence::load ( const char *name ) { smf f; if ( ! f.open( name, smf::READ ) ) { WARNING( "error opening file: %s", strerror( errno ) ); return false; } f.read_header(); if ( f.format() != 2 ) { WARNING( "not a Non song file" ); return false; } f.next_track(); DMESSAGE( "reading song info" ); /* read song info */ int mode = PATTERN; int phrases = 0; int patterns = 0; char *sname = NULL; char *notes = NULL; if ( ! f.read_song_info( &mode, &phrases, &patterns, &sname, ¬es ) ) { WARNING( "not a Non song file" ); return false; } song.play_mode = (play_mode_e)mode; if ( sname ) this->name( sname ); if ( notes ) this->notes( notes ); /* tear it down */ reset(); DMESSAGE( "reading playlist" ); // f.read_playlist( this ); lock(); char *s; while ( (s = f.read_cue_point() ) ) { int n; sscanf( s, "%d:", &n ); _rw->phrases.insert( _find( _rw->num++ ), n ); } /* read playlist */ DMESSAGE( "reading phrases" ); while ( phrases-- && f.next_track() ) { phrase *p = new phrase; p->load( &f ); } DMESSAGE( "reading patterns" ); while ( patterns-- && f.next_track() ) { pattern *p = new pattern; p->load( &f ); } unlock(); signal_new_song(); return true; }
void Playback_DS::disk_thread ( void ) { _thread.name( "Playback" ); DMESSAGE( "playback thread running" ); /* buffer to hold the interleaved data returned by the track reader */ sample_t *buf = new sample_t[ _nframes * channels() * _disk_io_blocks ]; #ifndef AVOID_UNNECESSARY_COPYING sample_t *cbuf = new sample_t[ _nframes * _disk_io_blocks ]; #endif int blocks_ready = 0; const nframes_t nframes = _nframes * _disk_io_blocks; while ( wait_for_block() ) { // lock(); // for seeking if ( seek_pending() ) { /* FIXME: non-RT-safe IO */ DMESSAGE( "performing seek to frame %lu", (unsigned long)_pending_seek ); _frame = _pending_seek; _pending_seek = -1; blocks_ready = 0; } if ( ++blocks_ready < _disk_io_blocks ) { /* wait for more space */ continue; } /* reset */ blocks_ready = 0; read_block( buf, nframes ); // unlock(); // for seeking /* deinterleave the buffer and stuff it into the per-channel ringbuffers */ const size_t block_size = nframes * sizeof( sample_t ); for ( int i = channels(); i--; ) { #ifdef AVOID_UNNECESSARY_COPYING /* deinterleave direcectly into the ringbuffer to avoid * unnecessary copying */ jack_ringbuffer_data_t rbd[2]; memset( rbd, 0, sizeof( rbd ) ); jack_ringbuffer_get_write_vector( _rb[ i ], rbd ); if ( rbd[ 0 ].len >= block_size ) { /* it'll all fit in one go */ buffer_deinterleave_one_channel( (sample_t*)rbd[ 0 ].buf, buf, i, channels(), nframes ); } else if ( rbd[ 0 ].len + rbd[ 1 ].len >= block_size ) { /* there's enough space in the ringbuffer, but it's not contiguous */ assert( ! ( rbd[ 0 ].len % sizeof( sample_t ) ) ); // assert( ! ( rbd[ 1 ].len % sizeof( sample_t ) ) ); const nframes_t f = rbd[ 0 ].len / sizeof( sample_t ); /* do the first half */ buffer_deinterleave_one_channel( (sample_t*)rbd[ 0 ].buf, buf, i, channels(), f ); assert( rbd[ 1 ].len >= ( nframes - f ) * sizeof( sample_t ) ); /* do the second half */ buffer_deinterleave_one_channel( (sample_t*)rbd[ 1 ].buf, buf + f, i, channels(), nframes - f ); } else ++_xruns; jack_ringbuffer_write_advance( _rb[ i ], block_size ); #else buffer_deinterleave_one_channel( cbuf, buf, i, channels(), nframes ); if ( jack_ringbuffer_write( _rb[ i ], (char*)cbuf, block_size ) < block_size ) ++_xruns; #endif } } DMESSAGE( "playback thread terminating" ); delete[] buf; #ifndef AVOID_UNNECESSARY_COPYING delete[] cbuf; #endif _terminate = false; }
static int row_smart_r2l(fsbuf_type buf[FSHEIGHT][FSBUFWIDTH], int bx, int by, int bw, int bh, int flags, int width, int height, int *resultx, int *resulty) { /* handle vertical direction */ bool t2b = (flags & FSPLACE_TOP_TO_BOTTOM); const int y0 = t2b ? by : by + bh - 1; const int y1 = t2b ? by + bh - height : by + height - 1; const int ydir = t2b ? 1 : -1; /* get offsets and indices of boundary */ int x0offset = 0; int x1offset = 0; int x0index = x_to_index_offset(bx + bw - 1, &x0offset); int x1index = x_to_index_offset(bx, &x1offset); /* offset and index of furthest point where placement may reach */ int xwoffset = 0; int xwindex = x_to_index_offset(bx + width - 1, &xwoffset); /* note: the index (horizontal) loop must test against the boundary * as the loop is a state-machine with two states: * * 1) non-scanning: placement is decisivly impossible at the * location (index, offset). when in this state, * the loop should break out past (xwindex, * xwoffset) ie the last position of possible * placement. * * 2) scanning: placement is possible at the location (index, * offset) and scanning is underway for an area * width x height. in this case the loop may need * to go right to the boundary edge (x1index, * x1offset). */ int y; #ifdef FSDEBUG DMESSAGE("--------------------------------------------\n" "x0 index:%d offset:%d\nx1 index:%d offset:%d\n", x0index, x0offset, x1index, x1offset); DMESSAGE("\nxw index:%d offset:%d\n", xwindex, xwoffset); DMESSAGE("\ny0: %d y1:%d ydir:%d\n",y0,y1,ydir); #endif for (y = y0; t2b ? y <= y1 : y >= y1; y += ydir) { int index; int offset = 0; int bits_remaining = 0; int scanning = false; #ifdef FSDEBUG DMESSAGE("\nline:%d\n",y); #endif for (index = x0index; index >= x1index; --index) { fsbuf_type mask = 0; int h; if (!scanning) /* check enough room remains for area at */ { /* (index, offset) (see note above) */ if (index < xwindex) { #ifdef FSDEBUG DMESSAGE("index:%d < xwindex\n", index); #endif break; } offset = (index == x0index) ? x0offset : 0; if (index == xwindex && offset > xwoffset) { #ifdef FSDEBUG DMESSAGE("no room remains at index:%d offset:%d\n", index, offset); #endif break; } } if (buf[y][index] == fsbuf_max) { scanning = false; continue; } if (!scanning) { scanning = true; bits_remaining = width; #ifdef FSDEBUG DMESSAGE("start scan index:%d offset:%d br:%d\n", index, offset, bits_remaining); #endif } retry: if (bits_remaining < FSBUFBITS - offset) { /* ie br = 4, offset = 2: 00111100 */ mask = (((fsbuf_type)1 << bits_remaining) - 1) << offset; #ifdef FSDEBUG DMESSAGE("mask... index:%d offset:%d br:%d\n", index, offset, bits_remaining); binary_dump("br <= FSBITS - offset mask:", mask); #endif } else { /* ie br = 8, offset = 2: 11111100 */ mask = fsbuf_max << offset; #ifdef FSDEBUG DMESSAGE("mask... index:%d offset:%d br:%d\n", index, offset, bits_remaining); binary_dump("br > FSBITS - offset mask:", mask); #endif } for (h = 0; h < height; ++h) { int v = buf[y + h * ydir][index] & mask; if (v) { #ifdef FSDEBUG binary_dump("obstructed by v:", v); #endif offset = FSBUFBITS - LEADING_ZEROS(v); if (offset < FSBUFBITS) { if (!(index < xwindex) && !(index == xwindex && offset > xwoffset)) { bits_remaining = width; #ifdef FSDEBUG DMESSAGE("rety: index:%d offset:%d br:%d\n", index, offset, bits_remaining); #endif goto retry; } } #ifdef FSDEBUG DMESSAGE("breaking vertical scan\n"); #endif scanning = false; break; /* break to continue */ } } if (!scanning) continue; if (bits_remaining <= FSBUFBITS - offset) /***** RESULT!! *****/ { #ifdef FSDEBUG DMESSAGE("result index:%d offset:%d\n", index, offset); #endif *resultx = index * FSBUFBITS + (FSBUFBITS - offset) - bits_remaining; *resulty = t2b ? y : y + 1 - height; return true; } bits_remaining -= FSBUFBITS - offset; offset = 0; } } #ifdef FSDEBUG DMESSAGE("no free space\n"); #endif return false; }
void Controller_Module::connect_to ( Port *p ) { control_output[0].connect_to( p ); clear(); Fl_Widget *w; if ( p->hints.type == Module::Port::Hints::BOOLEAN ) { Fl_Light_Button *o = new Fl_Light_Button( 0, 0, 40, 40, p->name() ); w = o; o->value( p->control_value() ); _type = TOGGLE; /* FIXME: hack */ control = (Fl_Valuator*)o; } else if ( p->hints.type == Module::Port::Hints::INTEGER ) { Fl_Counter *o = new Fl_Counter(0, 0, 58, 24, p->name() ); control = o; w = o; o->type(1); o->step(1); if ( p->hints.ranged ) { o->minimum( p->hints.minimum ); o->maximum( p->hints.maximum ); } _type = SPINNER; o->value( p->control_value() ); } else if ( p->hints.type == Module::Port::Hints::LOGARITHMIC ) { Fl_Value_SliderX *o = new Fl_Value_SliderX(0, 0, 30, 250, p->name() ); control = o; w = o; o->type(4); o->color( FL_DARK1 ); o->selection_color( fl_color_average( FL_GRAY, FL_CYAN, 0.5 ) ); o->minimum(1.5); o->maximum(0); o->value(1); o->textsize(9); if ( p->hints.ranged ) { o->minimum( p->hints.maximum ); o->maximum( p->hints.minimum ); } o->value( p->control_value() ); _type = SLIDER; } else { { Fl_DialX *o = new Fl_DialX( 0, 0, 50, 50, p->name() ); w = o; control = o; if ( p->hints.ranged ) { DMESSAGE( "Min: %f, max: %f", p->hints.minimum, p->hints.maximum ); o->minimum( p->hints.minimum ); o->maximum( p->hints.maximum ); } o->color( fl_darker( FL_GRAY ) ); o->selection_color( FL_WHITE ); o->value( p->control_value() ); } _type = KNOB; } control_value = p->control_value(); w->set_visible_focus(); w->align(FL_ALIGN_TOP); w->labelsize( 10 ); w->callback( cb_handle, this ); if ( _pad ) { Fl_Labelpad_Group *flg = new Fl_Labelpad_Group( w ); flg->set_visible_focus(); size( flg->w(), flg->h() ); flg->position( x(), y() ); add( flg ); } else { /* HACK: hide label */ w->labeltype( FL_NO_LABEL ); w->resize( x(), y(), this->w(), h() ); add( w ); resizable( w ); // init_sizes(); } }
static int source_run(source_t *n) { packet_consumer_t *consumer; int64_t ts; AVPacket *pkt=&n->pkt; switch (n->state) { case STATE_RUN: for (;;) { n->consumer.n=n->consumer.h; #if defined (FFSOX_DEPRECATED_AV_FREE_PACKET) // { av_free_packet(pkt); #else // } { av_packet_unref(pkt); #endif // } if (av_read_frame(n->f.fc,pkt)<0) { n->state=STATE_FLUSH; goto flush; } if (NULL!=n->cb) n->cb(n,n->data); //DVWRITELN("pkt->stream_index: %d",pkt->stream_index); while (NULL!=n->consumer.n) { consumer=n->consumer.n->consumer; //DVWRITELN("consumer->vmt->name: \"%s\", consumer->si.stream_index: %d",consumer->vmt->name,consumer->si.stream_index); if (pkt->stream_index==consumer->si.stream_index) { if (0ll<n->ts) { ts=av_rescale_q(n->ts,AV_TIME_BASE_Q,consumer->si.st->time_base); if (pkt->dts!=AV_NOPTS_VALUE) pkt->dts-=ts; if (pkt->pts!=AV_NOPTS_VALUE) pkt->pts-=ts; } consumer->vmt->set_packet(consumer,pkt); n->next=consumer; return MACHINE_PUSH; } LIST_NEXT(&n->consumer.n,n->consumer.h); //DVWRITELN("n->consumer.n: %p",n->consumer.n); } } case STATE_FLUSH: flush: if (NULL==n->consumer.n) { n->next=NULL; n->state=STATE_END; return MACHINE_POP; } else { consumer=n->consumer.n->consumer; consumer->state=STATE_FLUSH; //DVWRITELN("consumer->vmt->name: \"%s\"",consumer->vmt->name); consumer->vmt->set_packet(consumer,NULL); n->next=consumer; LIST_NEXT(&n->consumer.n,n->consumer.h); return MACHINE_PUSH; } case STATE_END: return MACHINE_POP; default: DMESSAGE("illegal source state"); return -1; } }
bool freespace_find( freespace* fs, basebox* boundary, int flags, int width, int height, int* resultx, int* resulty ) { *resultx = *resulty = -1; #ifdef FSDEBUG char* pstr = freespace_placement_to_str(flags); DMESSAGE("\n---------------------------\n" "flags:%s\tarea w:%d, h:%d\n" "boundary x:%d,y:%d, w:%d, h:%d\n", pstr, width, height, boundary->x, boundary->y, boundary->w, boundary->h); #endif if (width < 1 || width > boundary->w || height < 1 || height > boundary->h) { #ifdef FSDEBUG DWARNING("\ninvalid area or area does not fit in boundary\n"); #endif return false; } if (flags & FSPLACE_ROW_SMART) { if (flags & FSPLACE_LEFT_TO_RIGHT) { return row_smart_l2r(fs->row_buf, boundary->x, boundary->y, boundary->w, boundary->h, flags, width, height, resultx, resulty); } else { return row_smart_r2l(fs->row_buf, boundary->x, boundary->y, boundary->w, boundary->h, flags, width, height, resultx, resulty); } } else { /* the row smart algorithm can be used for column-smart by rotating 90 degrees clockwise... */ bool ret; int rx = FSWIDTH - boundary->y - boundary->h; int ry = boundary->x; int rflags = (flags & FSPLACE_LEFT_TO_RIGHT) ? FSPLACE_TOP_TO_BOTTOM : 0; rflags |= (flags & FSPLACE_TOP_TO_BOTTOM) ? 0 : FSPLACE_LEFT_TO_RIGHT; #ifdef FSDEBUG pstr = freespace_placement_to_str(rflags); DMESSAGE("\n---------------------------\n" "rflags:%s\tarea w:%d, h:%d\n" "boundary rx:%d, ry:%d, w:%d, h:%d\n", pstr, width, height, rx, ry, boundary->w, boundary->h); #endif if (rflags & FSPLACE_LEFT_TO_RIGHT) { ret = row_smart_l2r(fs->col_buf, rx, ry, boundary->h, boundary->w, rflags, height, width, resultx, resulty); } else { ret = row_smart_r2l(fs->col_buf, rx, ry, boundary->h, boundary->w, rflags, height, width, resultx, resulty); } if (!ret) return false; /* translate result back by 'rotation' 90 anti-clockwise */ rx = *resultx; *resultx = *resulty; *resulty = FSWIDTH - rx - height; return true; } WARNING("unrecognized placement flags:%d\n", flags); return false; }
void Module::insert_menu_cb ( const Fl_Menu_ *m ) { const char * picked = m->mvalue()->label(); DMESSAGE("picked = %s", picked ); Module *mod = NULL; if ( !strcmp( picked, "Aux" ) ) { int n = 0; for ( int i = 0; i < chain()->modules(); i++ ) { if ( !strcmp( chain()->module(i)->name(), "AUX" ) ) n++; } AUX_Module *jm = new AUX_Module(); jm->chain( chain() ); jm->number( n ); jm->configure_inputs( ninputs() ); jm->configure_outputs( ninputs() ); jm->initialize(); mod = jm; } if ( !strcmp( picked, "Spatializer" ) ) { int n = 0; for ( int i = 0; i < chain()->modules(); i++ ) { if ( !strcmp( chain()->module(i)->name(), "Spatializer" ) ) n++; } if ( n == 0 ) { Spatializer_Module *jm = new Spatializer_Module(); jm->chain( chain() ); // jm->number( n ); // jm->configure_inputs( ninputs() ); // jm->configure_outputs( ninputs() ); jm->initialize(); mod = jm; } } else if ( !strcmp( picked, "Gain" ) ) mod = new Gain_Module(); /* else if ( !strcmp( picked, "Spatializer" ) ) */ /* mod = new Spatializer_Module(); */ else if ( !strcmp( picked, "Meter" ) ) mod = new Meter_Module(); else if ( !strcmp( picked, "Mono Pan" )) mod = new Mono_Pan_Module(); else if ( !strcmp(picked, "Plugin" )) { unsigned long id = Plugin_Chooser::plugin_chooser( this->ninputs() ); if ( id == 0 ) return; Plugin_Module *m = new Plugin_Module(); m->load( id ); mod = m; } if ( mod ) { if ( ! chain()->insert( this, mod ) ) { fl_alert( "Cannot insert this module at this point in the chain" ); delete mod; return; } redraw(); } }
Module::~Module ( ) { /* we assume that the client for this chain is already locked */ if ( _editor ) { delete _editor; _editor = NULL; } for ( unsigned int i = 0; i < audio_input.size(); ++i ) audio_input[i].disconnect(); for ( unsigned int i = 0; i < audio_output.size(); ++i ) audio_output[i].disconnect(); for ( unsigned int i = 0; i < aux_audio_input.size(); ++i ) { aux_audio_input[i].disconnect(); aux_audio_input[i].jack_port()->shutdown(); delete aux_audio_input[i].jack_port(); } for ( unsigned int i = 0; i < aux_audio_output.size(); ++i ) { aux_audio_output[i].disconnect(); aux_audio_output[i].jack_port()->shutdown(); delete aux_audio_output[i].jack_port(); } for ( unsigned int i = 0; i < control_input.size(); ++i ) { /* destroy connected Controller_Module */ if ( control_input[i].connected() ) { Module *o = (Module*)control_input[i].connected_port()->module(); if ( ! o->is_default() ) { control_input[i].disconnect(); DMESSAGE( "Deleting connected module %s", o->label() ); delete o; } else { control_input[i].disconnect(); } } control_input[i].destroy_osc_port(); } for ( unsigned int i = 0; i < control_output.size(); ++i ) control_output[i].disconnect(); audio_input.clear(); audio_output.clear(); control_input.clear(); control_output.clear(); if ( parent() ) parent()->remove( this ); }
/* mark_used marks an area in the freespace grid as used space. it must operate on two or three arrays. */ static void mark_used( fsbuf_type buf_row[FSHEIGHT][FSBUFWIDTH], fsbuf_type buf_col[FSHEIGHT][FSBUFWIDTH], fsbuf_type aux_row[FSHEIGHT][FSBUFWIDTH], fsbuf_type aux_col[FSHEIGHT][FSBUFWIDTH], int x0, int y0, int w0, int h0 ) { int rx, ry; int width = w0; int height = h0; int offset = 0; int index = x_to_index_offset(x0, &offset); #ifdef FSDEBUG DMESSAGE("x:%d y:%d, width:%d, height:%d\n",x0,y0,width,height); DMESSAGE("index:%d offset:%d\n",index,offset); #endif for (; width > 0 && index < FSBUFWIDTH; ++index) { int y; fsbuf_type v; if (width < offset + 1) v = (((fsbuf_type)1 << width) - 1) << (offset - width + 1); else v = (((fsbuf_type)1 << offset) - 1) << 1 | 1; for (y = y0; y < y0 + height; ++y) { buf_row[y][index] |= v; aux_row[y][index] |= v; } width -= offset + 1; offset = FSBUFBITS - 1; } width = h0; height = w0; offset = 0; rx = FSWIDTH - y0 - h0; ry = x0; index = x_to_index_offset(rx, &offset); #ifdef FSDEBUG DMESSAGE("rx:%d ry:%d, width:%d, height:%d\n",rx,ry,width,height); DMESSAGE("index:%d offset:%d\n",index,offset); #endif for (; width > 0 && index < FSBUFWIDTH; ++index) { int y; fsbuf_type v; if (width < offset + 1) v = (((fsbuf_type)1 << width) - 1) << (offset - width + 1); else v = (((fsbuf_type)1 << offset) - 1) << 1 | 1; for (y = ry; y < ry + height; ++y) { buf_col[y][index] |= v; aux_col[y][index] |= v; } width -= offset + 1; offset = FSBUFBITS - 1; } }
int ffsox_source_create(source_t *n, const char *path, int ai, int vi, source_cb_t cb, void *data) { if (ffsox_node_create(&n->node)<0) { DMESSAGE("creating node"); goto base; } n->vmt=ffsox_source_get_vmt(); n->f.path=path; n->f.fc=NULL; if (avformat_open_input(&n->f.fc,path,0,0)<0) { DMESSAGE("opening input file"); goto fc; } n->f.fc->flags|=AVFMT_FLAG_GENPTS; if (avformat_find_stream_info(n->f.fc,0)<0) { DMESSAGE("finding stream info"); goto find; } //// n->ai=ai; n->vi=vi; if (ffsox_audiostream(n->f.fc,&n->ai,&n->vi)<0) { DMESSAGE("missing audio"); goto audio; } //// //// n->cb=cb; n->data=data; //// n->consumer.h=NULL; n->consumer.n=NULL; n->next=NULL; n->ts=0ll; memset(&n->pkt,0,sizeof n->pkt); av_init_packet(&n->pkt); return 0; audio: find: if (NULL!=n->f.fc->pb) { avio_close(n->f.fc->pb); n->f.fc->pb=NULL; } avformat_close_input(&n->f.fc); fc: vmt.parent->cleanup(&n->node); base: return -1; }
void Record_DS::disk_thread ( void ) { _thread.name( "Capture" ); DMESSAGE( "capture thread running..." ); const nframes_t nframes = _nframes; /* buffer to hold the interleaved data returned by the track reader */ sample_t *buf = buffer_alloc( nframes * channels() * _disk_io_blocks ); sample_t *cbuf = buffer_alloc( nframes ); const size_t block_size = nframes * sizeof( sample_t ); nframes_t blocks_read = 0; while ( wait_for_block() ) { /* pull data from the per-channel ringbuffers and interlace it */ for ( int i = channels(); i--; ) { while ( jack_ringbuffer_read_space( _rb[ i ] ) < block_size ) usleep( 10 * 1000 ); jack_ringbuffer_read( _rb[ i ], ((char*)cbuf), block_size ); buffer_interleave_one_channel( buf + ( blocks_read * nframes * channels() ), cbuf, i, channels(), nframes ); } blocks_read++; if ( blocks_read == _disk_io_blocks ) { write_block( buf, nframes * _disk_io_blocks ); blocks_read = 0; } } DMESSAGE( "capture thread terminating" ); /* flush what remains in the buffer out to disk */ { while ( blocks_read-- > 0 || ( ! sem_trywait( &_blocks ) && errno != EAGAIN ) ) { for ( int i = channels(); i--; ) { jack_ringbuffer_read( _rb[ i ], (char*)cbuf, block_size ); buffer_interleave_one_channel( buf, cbuf, i, channels(), nframes ); } const nframes_t frames_remaining = (_stop_frame - _frame ) - _frames_written; if ( frames_remaining < nframes ) { /* this is the last block, might be partial */ write_block( buf, frames_remaining ); break; } else write_block( buf, nframes ); } } free(buf); free(cbuf); DMESSAGE( "finalzing capture" ); Track::Capture *c = _capture; _capture = NULL; /* now finalize the recording */ if ( c->audio_file ) track()->finalize( c, _stop_frame ); delete c; flush(); _terminate = false; DMESSAGE( "capture thread gone" ); _thread.exit(); }
void Playback_DS::disk_thread ( void ) { _thread.name( "Playback" ); DMESSAGE( "playback thread running" ); /* buffer to hold the interleaved data returned by the track reader */ sample_t *buf = buffer_alloc( _nframes * channels() * _disk_io_blocks ); sample_t *cbuf = buffer_alloc( _nframes ); const nframes_t nframes = _nframes; nframes_t blocks_written; while ( ! _terminate ) { seek: blocks_written = 0; read_block( buf, nframes * _disk_io_blocks ); while ( blocks_written < _disk_io_blocks && wait_for_block() ) { // lock(); // for seeking if ( _pending_seek ) { /* FIXME: non-RT-safe IO */ DMESSAGE( "performing seek to frame %lu", (unsigned long)_seek_frame ); _frame = _seek_frame; _pending_seek = false; flush(); goto seek; } /* might have received terminate signal while waiting for block */ if ( _terminate ) goto done; // unlock(); // for seeking /* deinterleave the buffer and stuff it into the per-channel ringbuffers */ const size_t block_size = nframes * sizeof( sample_t ); for ( int i = 0; i < channels(); i++ ) { buffer_deinterleave_one_channel( cbuf, buf + ( blocks_written * nframes * channels() ), i, channels(), nframes ); while ( jack_ringbuffer_write_space( _rb[ i ] ) < block_size ) usleep( 100 * 1000 ); jack_ringbuffer_write( _rb[ i ], ((char*)cbuf), block_size ); } blocks_written++; } } done: DMESSAGE( "playback thread terminating" ); free(buf); free(cbuf); // flush(); _terminate = false; _thread.exit(); }
int JACK_Module::handle ( int m ) { static unsigned long _event_state = 0; unsigned long evstate = Fl::event_state(); switch ( m ) { case FL_PUSH: if ( Fl::event_inside( output_connection_handle ) || Fl::event_inside( output_connection2_handle ) || Fl::event_inside( input_connection_handle ) ) { _event_state = evstate; return 1; } return Module::handle(m) || 1; case FL_RELEASE: Fl::selection_owner(0); receptive_to_drop = NULL; if ( Fl::event_inside( output_connection_handle ) || Fl::event_inside( output_connection2_handle ) || Fl::event_inside( input_connection_handle ) ) { if ( _event_state & FL_BUTTON3 ) { /* was a right click */ // TODO: Pop up connection menu. } } return Module::handle(m) || 1; case FL_DRAG: { if ( Fl::event_is_click() ) return 1; int connection_handle = -1; if ( Fl::event_inside( output_connection_handle ) ) connection_handle = 0; if ( Fl::event_inside( output_connection2_handle ) ) connection_handle = 1; if ( Fl::event_button1() && connection_handle >= 0 && ! Fl::selection_owner() ) { DMESSAGE( "initiation of drag" ); char *s = (char*)malloc(256); s[0] = 0; for ( unsigned int i = _connection_handle_outputs[connection_handle][0]; i < aux_audio_output.size() && i < _connection_handle_outputs[connection_handle][1]; ++i ) { char *s2; asprintf(&s2, "jack.port://%s\r\n", aux_audio_output[i].jack_port()->jack_name() ); s = (char*)realloc( s, strlen( s ) + strlen( s2 ) + 1 ); strcat( s, s2 ); free( s2 ); } Fl::copy(s, strlen(s) + 1, 0); Fl::selection_owner(this); free( s ); Fl::dnd(); return 1; } return 1; } /* we have to prevent Fl_Group::handle() from getting these, otherwise it will mess up Fl::belowmouse() */ case FL_MOVE: if ( Fl::event_inside( output_connection_handle ) || Fl::event_inside( output_connection2_handle ) || Fl::event_inside( input_connection_handle ) ) { fl_cursor( FL_CURSOR_HAND ); } else fl_cursor( FL_CURSOR_DEFAULT ); Module::handle(m); return 1; case FL_ENTER: case FL_DND_ENTER: Module::handle(m); return 1; case FL_LEAVE: case FL_DND_LEAVE: Module::handle(m); if ( this == receptive_to_drop ) { receptive_to_drop = NULL; redraw(); } fl_cursor( FL_CURSOR_DEFAULT ); return 1; case FL_DND_RELEASE: Fl::selection_owner(0); receptive_to_drop = NULL; redraw(); return 1; case FL_DND_DRAG: { if ( this == receptive_to_drop ) return 1; if ( aux_audio_input.size() ) { receptive_to_drop = this; redraw(); return 1; } return 0; } case FL_PASTE: { receptive_to_drop = NULL; redraw(); if ( ! Fl::event_inside( this ) ) return 0; /* NOW we get the text... */ const char *text = Fl::event_text(); DMESSAGE( "Got drop text \"%s\"",text); if ( strncmp( text, "jack.port://", strlen( "jack.port://" ) ) ) { return 0; } std::vector<std::string> port_names; char *port_name; int end; while ( sscanf( text, "jack.port://%a[^\r\n]\r\n%n", &port_name, &end ) > 0 ) { DMESSAGE( "Scanning %s", port_name ); port_names.push_back( port_name ); free(port_name ); text += end; } for ( unsigned int i = 0; i < aux_audio_input.size() && i < port_names.size(); i++) { const char *pn = port_names[i].c_str(); JACK::Port *ji = aux_audio_input[i].jack_port(); if ( ji->connected_to( pn ) ) { DMESSAGE( "Disconnecting from \"%s\"", pn ); ji->disconnect( pn ); } else { DMESSAGE( "Connecting to %s", pn ); ji->connect( pn ); } } Fl::selection_owner(0); return 1; } } return Module::handle(m); }
bool Chain::insert ( Module *m, Module *n ) { client()->lock(); if ( !m ) { if ( modules() == 0 && n->can_support_inputs( 0 ) >= 0 ) { n->chain( this ); n->configure_inputs( 0 ); modules_pack->add( n ); } else if ( n->can_support_inputs( module( modules() - 1 )->noutputs() ) >= 0 ) { n->chain( this ); n->configure_inputs( module( modules() - 1 )->noutputs() ); modules_pack->add( n ); } else { DMESSAGE( "Module says it can't support %i inputs", module( modules() - 1 )->noutputs() ); goto err; } } else { int i = modules_pack->find( m ); n->chain( this ); if ( 0 == i ) { /* inserting to head of chain*/ if ( n->can_support_inputs( 0 ) >= 0 ) n->configure_inputs( 0 ); else goto err; } else { if ( n->can_support_inputs( module( i - 1 )->noutputs() ) >= 0 ) { n->configure_inputs( module( i - 1 )->noutputs() ); m->configure_inputs( n->noutputs() ); for ( int j = i + 1; j < modules(); ++j ) module( j )->configure_inputs( module( j - 1 )->noutputs() ); } else goto err; } modules_pack->insert( *n, i ); } strip()->handle_module_added( n ); configure_ports(); client()->unlock(); DMESSAGE( "Module \"%s\" has %i:%i audio and %i:%i control ports", n->name(), n->ninputs(), n->noutputs(), n->ncontrol_inputs(), n->ncontrol_outputs() ); n->initialize(); return true; err: client()->unlock(); DMESSAGE( "Insert failed" ); return false; }
int main ( int argc, char **argv ) { bool no_ui = false; fl_display = 0; printf( "%s %s %s -- %s\n", APP_TITLE, VERSION, "", COPYRIGHT ); Thread::init(); Thread thread( "UI" ); thread.set(); ensure_dirs(); signal( SIGTERM, sigterm_handler ); signal( SIGHUP, sigterm_handler ); signal( SIGINT, sigterm_handler ); Fl_Tooltip::color( FL_BLACK ); Fl_Tooltip::textcolor( FL_YELLOW ); Fl_Tooltip::size( 14 ); Fl_Tooltip::hoverdelay( 0.1f ); LOG_REGISTER_CREATE( Mixer_Strip ); LOG_REGISTER_CREATE( Chain ); LOG_REGISTER_CREATE( Plugin_Module ); LOG_REGISTER_CREATE( Gain_Module ); LOG_REGISTER_CREATE( Spatializer_Module ); LOG_REGISTER_CREATE( Meter_Module ); LOG_REGISTER_CREATE( JACK_Module ); LOG_REGISTER_CREATE( Mono_Pan_Module ); LOG_REGISTER_CREATE( Meter_Indicator_Module ); LOG_REGISTER_CREATE( Controller_Module ); LOG_REGISTER_CREATE( AUX_Module ); LOG_REGISTER_CREATE( Spatialization_Console ); LOG_REGISTER_CREATE( Group ); signal( SIGPIPE, SIG_IGN ); const char *osc_port = NULL; nsm = new NSM_Client; instance_name = strdup( APP_NAME ); bool instance_override = false; static struct option long_options[] = { { "help", no_argument, 0, '?' }, { "instance", required_argument, 0, 'i' }, { "osc-port", required_argument, 0, 'p' }, { "no-ui", no_argument, 0, 'u' }, { 0, 0, 0, 0 } }; int option_index = 0; int c = 0; while ( ( c = getopt_long_only( argc, argv, "", long_options, &option_index ) ) != -1 ) { switch ( c ) { case 'p': DMESSAGE( "Using OSC port %s", optarg ); osc_port = optarg; break; case 'i': DMESSAGE( "Using OSC port %s", optarg ); free( instance_name ); instance_name = strdup( optarg ); instance_override = true; break; case 'u': DMESSAGE( "Disabling user interface" ); no_ui = true; break; case '?': printf( "\nUsage: %s [--instance instance_name] [--osc-port portnum] [path_to_project]\n\n", argv[0] ); exit(0); break; } } { char *name = strdup( argv[0] ); char *n = basename( name ); if ( ! strcmp( n, "non-mixer-noui" ) ) no_ui = true; free( name ); } if ( ! no_ui ) { Fl::visual( FL_DOUBLE | FL_RGB ); Fl::visible_focus( 0 ); fl_register_images(); } Fl::lock(); Fl_Double_Window *main_window; { Fl_Double_Window *o = main_window = new Fl_Double_Window( 800, 600, "Non Mixer" ); { main_window->xclass( APP_NAME ); { Fl_Widget *o = mixer = new Mixer( 0, 0, main_window->w(), main_window->h(), NULL ); Fl_Group::current()->resizable(o); } } o->end(); o->size_range( main_window->w(), mixer->min_h(), 0, 0 ); o->callback( (Fl_Callback*)cb_main, main_window ); if ( ! no_ui ) { o->show( 0,0 ); } } Plugin_Module::spawn_discover_thread(); mixer->init_osc( osc_port ); char *nsm_url = getenv( "NSM_URL" ); if ( nsm_url ) { if ( ! nsm->init( nsm_url ) ) { if ( instance_override ) WARNING( "--instance option is not available when running under session management, ignoring." ); if ( optind < argc ) WARNING( "Loading files from the command-line is incompatible with session management, ignoring." ); nsm->announce( APP_NAME, ":switch:dirty:", argv[0] ); /* if ( ! no_ui ) */ /* { */ // poll so we can keep OSC handlers running in the GUI thread and avoid extra sync Fl::add_timeout( NSM_CHECK_INTERVAL, check_nsm, NULL ); /* } */ } } else { if ( optind < argc ) { MESSAGE( "Waiting for plugins..." ); Plugin_Module::join_discover_thread(); MESSAGE( "Loading \"%s\"", argv[optind] ); if ( ! mixer->command_load( argv[optind] ) ) { fl_alert( "Error opening project specified on commandline" ); } } } Fl::add_timeout( 0.1f, check_sigterm ); Fl::dnd_text_ops( 0 ); if ( ! no_ui ) { DMESSAGE( "Running UI..." ); Fl::run(); } else { DMESSAGE( "Not Running UI..." ); while ( ! got_sigterm ) { Fl::check(); usleep( 200 * 1000 ); } } delete main_window; main_window = NULL; MESSAGE( "Your fun is over" ); }