(Drag jack output module and drop on jack input module of another strip) In Non Mixer, all JACK modules (including Aux) will now list their connections.tags/non-daw-v1.2.0
@@ -157,7 +157,6 @@ public: | |||||
{ | { | ||||
static int _button; | static int _button; | ||||
int r = 0; | |||||
switch ( m ) | switch ( m ) | ||||
{ | { | ||||
case FL_PUSH: | case FL_PUSH: | ||||
@@ -217,6 +216,6 @@ public: | |||||
} | } | ||||
} | } | ||||
return Fl_Group::handle( m ) | r; | |||||
return Fl_Group::handle( m ); | |||||
} | } | ||||
}; | }; |
@@ -69,7 +69,7 @@ public: | |||||
virtual int | virtual int | ||||
handle ( int m ) | handle ( int m ) | ||||
{ | { | ||||
int r = Fl_Input::handle( m ); | |||||
int r = 0; | |||||
switch ( m ) | switch ( m ) | ||||
{ | { | ||||
@@ -79,23 +79,31 @@ public: | |||||
Fl::event_key() == FL_Tab ) ) | Fl::event_key() == FL_Tab ) ) | ||||
{ | { | ||||
Fl::focus( NULL ); | Fl::focus( NULL ); | ||||
return 1; | |||||
r = 1; | |||||
} | } | ||||
else | |||||
return r; | |||||
break; | |||||
} | } | ||||
case FL_FOCUS: | case FL_FOCUS: | ||||
redraw(); | redraw(); | ||||
return 1; | |||||
r = 1; | |||||
break; | |||||
case FL_UNFOCUS: | case FL_UNFOCUS: | ||||
do_callback(); | do_callback(); | ||||
return 1; | |||||
r = 1; | |||||
break; | |||||
case FL_PUSH: | case FL_PUSH: | ||||
take_focus(); | take_focus(); | ||||
redraw(); | redraw(); | ||||
return 1; | |||||
r = 1; | |||||
break; | |||||
case FL_DND_ENTER: | |||||
return 0; | |||||
case FL_PASTE: | |||||
return 0; | |||||
default: | default: | ||||
return r; | |||||
break; | |||||
} | } | ||||
return Fl_Input::handle( m ) | r; | |||||
} | } | ||||
}; | }; |
@@ -0,0 +1,61 @@ | |||||
/*******************************************************************************/ | |||||
/* Copyright (C) 2013 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. */ | |||||
/*******************************************************************************/ | |||||
static unsigned char img_io_input_connector_10x10_png[] = { | |||||
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, | |||||
0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0a, | |||||
0x08, 0x06, 0x00, 0x00, 0x00, 0x8d, 0x32, 0xcf, 0xbd, 0x00, 0x00, 0x00, | |||||
0x04, 0x73, 0x42, 0x49, 0x54, 0x08, 0x08, 0x08, 0x08, 0x7c, 0x08, 0x64, | |||||
0x88, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x00, | |||||
0x9e, 0x00, 0x00, 0x00, 0x9e, 0x01, 0x22, 0xcb, 0xc6, 0x03, 0x00, 0x00, | |||||
0x00, 0x19, 0x74, 0x45, 0x58, 0x74, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, | |||||
0x72, 0x65, 0x00, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x6e, 0x6b, 0x73, 0x63, | |||||
0x61, 0x70, 0x65, 0x2e, 0x6f, 0x72, 0x67, 0x9b, 0xee, 0x3c, 0x1a, 0x00, | |||||
0x00, 0x01, 0x51, 0x49, 0x44, 0x41, 0x54, 0x18, 0x95, 0x3d, 0xd0, 0xb1, | |||||
0x6a, 0xdb, 0x40, 0x1c, 0xc0, 0xe1, 0x9f, 0x72, 0x7f, 0xcc, 0x21, 0xbc, | |||||
0xc5, 0x87, 0xb0, 0xb7, 0x18, 0x6c, 0xa8, 0x49, 0x37, 0x1b, 0x8c, 0x26, | |||||
0xdb, 0x19, 0xfb, 0x0e, 0x7e, 0x82, 0xee, 0x21, 0x53, 0xe9, 0x14, 0x42, | |||||
0x37, 0x37, 0x7b, 0x9e, 0xa2, 0x63, 0x07, 0x6b, 0xd6, 0xec, 0xc5, 0xe0, | |||||
0x80, 0xc1, 0x08, 0xac, 0x66, 0xf0, 0xa0, 0xb3, 0x90, 0x4e, 0xa7, 0x4e, | |||||
0xed, 0xf6, 0xcd, 0x5f, 0xd0, 0xb6, 0x2d, 0x00, 0xfb, 0xfd, 0xfe, 0x4b, | |||||
0x59, 0x96, 0x8f, 0x4d, 0xd3, 0xdc, 0x01, 0x4e, 0x44, 0xf2, 0x30, 0x0c, | |||||
0x9f, 0x86, 0xc3, 0xe1, 0x6f, 0x80, 0xa0, 0x6d, 0x5b, 0x76, 0xbb, 0xdd, | |||||
0xb7, 0xf3, 0xf9, 0xfc, 0x35, 0x4d, 0xd3, 0x5e, 0x96, 0x65, 0x78, 0xef, | |||||
0x19, 0x0c, 0x06, 0x4c, 0xa7, 0xd3, 0x8f, 0x28, 0x8a, 0x7e, 0x4e, 0x26, | |||||
0x93, 0xef, 0x6a, 0xbd, 0x5e, 0x3f, 0x9c, 0x4e, 0xa7, 0x1f, 0x49, 0x92, | |||||
0xf4, 0x2e, 0x97, 0x0b, 0xdb, 0xed, 0x96, 0xe3, 0xf1, 0x88, 0x31, 0x86, | |||||
0x2c, 0xcb, 0x42, 0x63, 0xcc, 0x7d, 0x5d, 0xd7, 0xbb, 0x1b, 0x6b, 0xed, | |||||
0x73, 0x9a, 0xa6, 0xb7, 0x00, 0x4a, 0x29, 0x44, 0x04, 0x11, 0x41, 0x29, | |||||
0x05, 0x40, 0x9a, 0xa6, 0xbd, 0xb2, 0x2c, 0x1f, 0xc5, 0x39, 0x67, 0xac, | |||||
0xb5, 0x78, 0xef, 0x09, 0x82, 0x80, 0xd5, 0x6a, 0x45, 0x10, 0x04, 0xb4, | |||||
0x6d, 0x8b, 0x73, 0x8e, 0xa2, 0x28, 0x68, 0x9a, 0xe6, 0x4e, 0x00, 0xf1, | |||||
0xde, 0x93, 0x24, 0x09, 0x45, 0x51, 0x10, 0xc7, 0x31, 0x22, 0x42, 0x92, | |||||
0x24, 0x68, 0xad, 0x59, 0x2e, 0x97, 0x00, 0xee, 0x46, 0x29, 0xf5, 0xde, | |||||
0xed, 0x76, 0xb9, 0x5e, 0xaf, 0x78, 0xef, 0xa9, 0xaa, 0x8a, 0xaa, 0xaa, | |||||
0xfe, 0x5b, 0x6b, 0x8d, 0x88, 0xe4, 0xa2, 0xb5, 0x7e, 0x99, 0xcd, 0x66, | |||||
0x9f, 0xf2, 0x3c, 0xef, 0x59, 0x6b, 0x31, 0xc6, 0x00, 0x10, 0xc7, 0x31, | |||||
0x9d, 0x4e, 0x87, 0xf9, 0x7c, 0xfe, 0x11, 0x86, 0xe1, 0x93, 0xda, 0x6c, | |||||
0x36, 0x7b, 0x6b, 0x6d, 0xd8, 0xef, 0xf7, 0x3f, 0x5b, 0x6b, 0xc3, 0xba, | |||||
0xae, 0x01, 0x30, 0xc6, 0xb0, 0x58, 0x2c, 0xfe, 0x44, 0x51, 0xf4, 0x3a, | |||||
0x1e, 0x8f, 0xdf, 0x82, 0x7f, 0xe1, 0x87, 0xc3, 0xe1, 0xc1, 0x5a, 0xfb, | |||||
0xec, 0x9c, 0x33, 0x80, 0x28, 0xa5, 0xde, 0xb5, 0xd6, 0x2f, 0xa3, 0xd1, | |||||
0xe8, 0x17, 0xc0, 0x5f, 0xd1, 0x17, 0xa6, 0x12, 0x83, 0xc3, 0x30, 0x9b, | |||||
0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 | |||||
}; | |||||
static unsigned int img_io_input_connector_10x10_png_len = 468; |
@@ -0,0 +1,63 @@ | |||||
/*******************************************************************************/ | |||||
/* Copyright (C) 2013 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. */ | |||||
/*******************************************************************************/ | |||||
static unsigned char img_io_output_connector_10x10_png[] = { | |||||
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, | |||||
0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0a, | |||||
0x08, 0x06, 0x00, 0x00, 0x00, 0x8d, 0x32, 0xcf, 0xbd, 0x00, 0x00, 0x00, | |||||
0x04, 0x73, 0x42, 0x49, 0x54, 0x08, 0x08, 0x08, 0x08, 0x7c, 0x08, 0x64, | |||||
0x88, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x00, | |||||
0x9e, 0x00, 0x00, 0x00, 0x9e, 0x01, 0x22, 0xcb, 0xc6, 0x03, 0x00, 0x00, | |||||
0x00, 0x19, 0x74, 0x45, 0x58, 0x74, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, | |||||
0x72, 0x65, 0x00, 0x77, 0x77, 0x77, 0x2e, 0x69, 0x6e, 0x6b, 0x73, 0x63, | |||||
0x61, 0x70, 0x65, 0x2e, 0x6f, 0x72, 0x67, 0x9b, 0xee, 0x3c, 0x1a, 0x00, | |||||
0x00, 0x01, 0x61, 0x49, 0x44, 0x41, 0x54, 0x18, 0x95, 0x35, 0xd0, 0xbf, | |||||
0x6a, 0xc2, 0x40, 0x00, 0x07, 0xe0, 0xdf, 0xfd, 0x89, 0xe4, 0x32, 0xc4, | |||||
0x40, 0xed, 0x22, 0x9c, 0x50, 0x24, 0x99, 0x1c, 0xdc, 0x33, 0x38, 0x64, | |||||
0xec, 0x03, 0x14, 0x9c, 0xd4, 0xb9, 0x7b, 0xe9, 0x54, 0x3a, 0x95, 0xd2, | |||||
0xb1, 0x1d, 0x74, 0xeb, 0xe4, 0xec, 0xd2, 0x31, 0x01, 0x9f, 0x40, 0x04, | |||||
0xe9, 0x10, 0x85, 0x06, 0x1c, 0x6d, 0x40, 0x34, 0xe4, 0xd0, 0x0b, 0x5e, | |||||
0xa7, 0x7e, 0x8f, 0xf0, 0x11, 0x63, 0x0c, 0x00, 0x60, 0xbd, 0x5e, 0xdf, | |||||
0x96, 0x65, 0xf9, 0xa0, 0xb5, 0xbe, 0x21, 0x84, 0x54, 0x9c, 0xf3, 0x9d, | |||||
0x10, 0xe2, 0x31, 0x08, 0x82, 0x18, 0x00, 0x88, 0x31, 0x06, 0xab, 0xd5, | |||||
0xea, 0x69, 0xbb, 0xdd, 0xde, 0x27, 0x49, 0xd2, 0xb0, 0x6d, 0x1b, 0x8c, | |||||
0x31, 0x14, 0x45, 0x81, 0x28, 0x8a, 0x72, 0x29, 0xe5, 0x7b, 0xa7, 0xd3, | |||||
0x79, 0x66, 0xfd, 0x7e, 0x3f, 0xca, 0xb2, 0xec, 0x6d, 0x36, 0x9b, 0x35, | |||||
0x84, 0x10, 0x18, 0x8d, 0x46, 0xe8, 0x76, 0xbb, 0x58, 0x2e, 0x97, 0x58, | |||||
0x2c, 0x16, 0x4e, 0xb3, 0xd9, 0xec, 0x00, 0xf8, 0xa6, 0x4a, 0xa9, 0x97, | |||||
0x38, 0x8e, 0xaf, 0x00, 0x40, 0x6b, 0x8d, 0xf3, 0xf9, 0x8c, 0xd3, 0xe9, | |||||
0x04, 0xad, 0x35, 0x00, 0x20, 0x49, 0x92, 0x46, 0x59, 0x96, 0x0f, 0xbc, | |||||
0xaa, 0xaa, 0xeb, 0xe3, 0xf1, 0x08, 0xc6, 0x18, 0x2e, 0x97, 0x0b, 0xc6, | |||||
0xe3, 0x31, 0x8c, 0x31, 0xa0, 0x94, 0xa2, 0x56, 0xab, 0xe1, 0x70, 0x38, | |||||
0x40, 0x6b, 0x7d, 0xc3, 0x8d, 0x31, 0x9c, 0x52, 0x8a, 0xe1, 0x70, 0x08, | |||||
0xcf, 0xf3, 0x30, 0x9d, 0x4e, 0xa1, 0xb5, 0xc6, 0x60, 0x30, 0x40, 0x51, | |||||
0x14, 0x98, 0x4c, 0x26, 0x20, 0x84, 0x54, 0xd4, 0xb2, 0xac, 0x1f, 0xd7, | |||||
0x75, 0xe1, 0xba, 0x2e, 0x38, 0xe7, 0x70, 0x1c, 0x07, 0x42, 0x08, 0x30, | |||||
0xc6, 0x60, 0xdb, 0x36, 0x3c, 0xcf, 0x03, 0xe7, 0x7c, 0x47, 0xd2, 0x34, | |||||
0xbd, 0xdd, 0x6c, 0x36, 0x9f, 0xf3, 0xf9, 0xbc, 0x51, 0xaf, 0xd7, 0x91, | |||||
0x65, 0x19, 0x00, 0xa0, 0xd5, 0x6a, 0x41, 0x29, 0x85, 0x30, 0x0c, 0xf3, | |||||
0x76, 0xbb, 0x7d, 0x47, 0x7d, 0xdf, 0xff, 0x92, 0x52, 0x7e, 0xf4, 0x7a, | |||||
0xbd, 0x3c, 0xcf, 0x73, 0xfc, 0xdb, 0xef, 0xf7, 0x08, 0xc3, 0xf0, 0x57, | |||||
0x4a, 0xf9, 0x1e, 0x04, 0x41, 0x4c, 0xfe, 0xc3, 0xd3, 0x34, 0x8d, 0x94, | |||||
0x52, 0x2f, 0x55, 0x55, 0x5d, 0x1b, 0x63, 0xb8, 0x65, 0x59, 0x3f, 0x8e, | |||||
0xe3, 0xbc, 0xfa, 0xbe, 0xff, 0x05, 0x00, 0x7f, 0xb0, 0xa3, 0x9e, 0x20, | |||||
0x9c, 0xde, 0x99, 0x8e, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, | |||||
0xae, 0x42, 0x60, 0x82 | |||||
}; | |||||
static unsigned int img_io_output_connector_10x10_png_len = 484; |
@@ -1 +1 @@ | |||||
Subproject commit fe832d3cbc807c475f4b6a51facf543aa7d9882d | |||||
Subproject commit ed50ecc551d5e490f4acb1ec673c9e8f43e23fb0 |
@@ -123,6 +123,7 @@ AUX_Module::draw ( void ) | |||||
{ | { | ||||
int W = 5; | int W = 5; | ||||
child(0)->size( w() - W, 18 ); | |||||
Module::draw_box(x(),y(),w() - W,h()); | Module::draw_box(x(),y(),w() - W,h()); | ||||
Module::draw_label(x(),y(),w() - W,h()); | Module::draw_label(x(),y(),w() - W,h()); | ||||
@@ -458,6 +458,7 @@ Chain::name ( const char *name ) | |||||
_engine = new Engine( &Chain::process, this ); | _engine = new Engine( &Chain::process, this ); | ||||
engine()->buffer_size_callback( &Chain::buffer_size, this ); | engine()->buffer_size_callback( &Chain::buffer_size, this ); | ||||
engine()->port_connect_callback( &Chain::port_connect, this ); | |||||
const char *jack_name = engine()->init( ename ); | const char *jack_name = engine()->init( ename ); | ||||
@@ -824,3 +825,43 @@ Chain::buffer_size ( nframes_t nframes ) | |||||
m->resize_buffers( nframes ); | m->resize_buffers( nframes ); | ||||
} | } | ||||
} | } | ||||
void | |||||
Chain::port_connect ( jack_port_id_t a, jack_port_id_t b, int connect, void *v ) | |||||
{ | |||||
((Chain*)v)->port_connect( a, b, connect ); | |||||
} | |||||
/* handle jack port connection change */ | |||||
void | |||||
Chain::port_connect ( jack_port_id_t a, jack_port_id_t b, int connect ) | |||||
{ | |||||
/* this is called from JACK non-RT thread... */ | |||||
if ( jack_port_is_mine( engine()->jack_client(), jack_port_by_id( engine()->jack_client(), a ) ) || | |||||
jack_port_is_mine( engine()->jack_client(), jack_port_by_id( engine()->jack_client(), b ) )) | |||||
{ | |||||
Fl::awake( Chain::update_connection_status, this ); | |||||
} | |||||
} | |||||
void | |||||
Chain::update_connection_status ( void *v ) | |||||
{ | |||||
((Chain*)v)->update_connection_status(); | |||||
} | |||||
void | |||||
Chain::update_connection_status ( void ) | |||||
{ | |||||
for ( int i = 0; i < modules(); i++ ) | |||||
{ | |||||
Module *m = module(i); | |||||
if ( !strcmp( m->name(), "JACK" ) || | |||||
!strcmp( m->name(), "AUX" )) | |||||
{ | |||||
((JACK_Module*)m)->update_connection_status(); | |||||
} | |||||
} | |||||
} |
@@ -73,6 +73,13 @@ private: | |||||
static void buffer_size ( nframes_t nframes, void *v ); | static void buffer_size ( nframes_t nframes, void *v ); | ||||
void buffer_size ( nframes_t nframes ); | void buffer_size ( nframes_t nframes ); | ||||
static void port_connect ( jack_port_id_t a, jack_port_id_t b, int connect, void *v ); | |||||
void port_connect ( jack_port_id_t a, jack_port_id_t b, int connect ); | |||||
static void update_connection_status ( void *v ); | |||||
void update_connection_status ( void ); | |||||
protected: | protected: | ||||
void get ( Log_Entry &e ) const; | void get ( Log_Entry &e ) const; | ||||
@@ -36,6 +36,7 @@ Engine::Engine ( void (*process_callback)(nframes_t nframes, void *), void *user | |||||
_process_callback_user_data = user_data; | _process_callback_user_data = user_data; | ||||
_buffer_size_callback = 0; | _buffer_size_callback = 0; | ||||
_buffers_dropped = 0; | _buffers_dropped = 0; | ||||
_port_connect_callback = 0; | |||||
} | } | ||||
Engine::~Engine ( ) | Engine::~Engine ( ) | ||||
@@ -52,6 +53,13 @@ Engine::buffer_size_callback ( void ( *buffer_size_callback ) ( nframes_t, void | |||||
_buffer_size_callback_user_data = user_data; | _buffer_size_callback_user_data = user_data; | ||||
} | } | ||||
void | |||||
Engine::port_connect_callback ( void ( *port_connect_callback ) ( jack_port_id_t a, jack_port_id_t b, int connect, void *arg), void *user_data ) | |||||
{ | |||||
_port_connect_callback = port_connect_callback; | |||||
_port_connect_callback_user_data = user_data; | |||||
} | |||||
/*************/ | /*************/ | ||||
/* Callbacks */ | /* Callbacks */ | ||||
/*************/ | /*************/ | ||||
@@ -91,6 +99,15 @@ Engine::buffer_size ( nframes_t nframes ) | |||||
return 0; | return 0; | ||||
} | } | ||||
/* THREAD: ?? */ | |||||
void | |||||
Engine::port_connect( jack_port_id_t a, jack_port_id_t b, int connect ) | |||||
{ | |||||
if ( _port_connect_callback ) | |||||
_port_connect_callback( a, b, connect, _port_connect_callback_user_data ); | |||||
} | |||||
/* THREAD: RT */ | /* THREAD: RT */ | ||||
int | int | ||||
Engine::process ( nframes_t nframes ) | Engine::process ( nframes_t nframes ) | ||||
@@ -40,13 +40,16 @@ class Engine : public JACK::Client, public Mutex | |||||
void ( * _buffer_size_callback ) ( nframes_t, void * ); | void ( * _buffer_size_callback ) ( nframes_t, void * ); | ||||
void *_buffer_size_callback_user_data; | void *_buffer_size_callback_user_data; | ||||
void ( * _port_connect_callback ) ( jack_port_id_t a, jack_port_id_t b, int connect, void * ); | |||||
void *_port_connect_callback_user_data; | |||||
void shutdown ( void ); | void shutdown ( void ); | ||||
int process ( nframes_t nframes ); | int process ( nframes_t nframes ); | ||||
int xrun ( void ); | int xrun ( void ); | ||||
void freewheel ( bool yes ); | void freewheel ( bool yes ); | ||||
int buffer_size ( nframes_t nframes ); | int buffer_size ( nframes_t nframes ); | ||||
void thread_init ( void ); | void thread_init ( void ); | ||||
void port_connect ( jack_port_id_t a, jack_port_id_t b, int connect ); | |||||
Engine ( const Engine &rhs ); | Engine ( const Engine &rhs ); | ||||
Engine & operator = ( const Engine &rhs ); | Engine & operator = ( const Engine &rhs ); | ||||
@@ -64,4 +67,5 @@ public: | |||||
int dropped ( void ) const { return _buffers_dropped; } | int dropped ( void ) const { return _buffers_dropped; } | ||||
void buffer_size_callback ( void ( *buffer_size_callback ) ( nframes_t, void * ), void *user_data ); | void buffer_size_callback ( void ( *buffer_size_callback ) ( nframes_t, void * ), void *user_data ); | ||||
void port_connect_callback ( void ( *port_connect_callback ) ( jack_port_id_t a, jack_port_id_t b, int connect, void *arg), void *user_data ); | |||||
}; | }; |
@@ -22,6 +22,9 @@ | |||||
#include <string.h> | #include <string.h> | ||||
#include <FL/fl_ask.H> | #include <FL/fl_ask.H> | ||||
#include <FL/Fl_Box.H> | |||||
#include <FL/Fl_Pack.H> | |||||
#include <FL/Fl_Scalepack.H> | |||||
#include "dsp.h" | #include "dsp.h" | ||||
@@ -29,14 +32,30 @@ | |||||
#include "Chain.H" | #include "Chain.H" | ||||
#include "JACK_Module.H" | #include "JACK_Module.H" | ||||
#include <FL/fl_draw.H> | |||||
#include <FL/Fl.H> | |||||
#include <FL/Fl_Browser.H> | |||||
#include <FL/Fl_PNG_Image.H> | |||||
#include <FL/img_io_input_connector_10x10_png.h> | |||||
#include <FL/img_io_output_connector_10x10_png.h> | |||||
static Fl_PNG_Image *input_connector_image = NULL; | |||||
static Fl_PNG_Image *output_connector_image = NULL; | |||||
extern char *instance_name; | |||||
static JACK_Module *receptive_to_drop = NULL; | |||||
JACK_Module::JACK_Module ( bool log ) | JACK_Module::JACK_Module ( bool log ) | ||||
: Module ( 50, 24, name() ) | |||||
: Module ( 25, 25, name() ) | |||||
{ | { | ||||
_prefix = 0; | _prefix = 0; | ||||
align( FL_ALIGN_TOP | FL_ALIGN_INSIDE ); | |||||
if ( log ) | if ( log ) | ||||
{ | { | ||||
/* FIXME: how do Controls find out that a connected value has changed? How does this work in ladspa? */ | /* FIXME: how do Controls find out that a connected value has changed? How does this work in ladspa? */ | ||||
@@ -72,6 +91,60 @@ JACK_Module::JACK_Module ( bool log ) | |||||
log_create(); | log_create(); | ||||
} | } | ||||
{ Fl_Scalepack *o = new Fl_Scalepack( x() + Fl::box_dx(box()), | |||||
y() + Fl::box_dy(box()), | |||||
w(), | |||||
24 - Fl::box_dh(box()) ); | |||||
o->type( Fl_Pack::HORIZONTAL ); | |||||
o->spacing( 0 ); | |||||
{ Fl_Box *o = input_connection_handle = new Fl_Box( x(), y(), 18, 18 ); | |||||
o->tooltip( "Drag and drop to make and break JACK connections."); | |||||
o->hide(); | |||||
o->image( input_connector_image ? input_connector_image : input_connector_image = new Fl_PNG_Image( "input_connector", img_io_input_connector_10x10_png, img_io_input_connector_10x10_png_len ) ); | |||||
} | |||||
{ Fl_Box *o = new Fl_Box( x() + 10, y(), w() - 20, h() ); | |||||
Fl_Group::current()->resizable(o); | |||||
} | |||||
{ Fl_Button *o = dec_button = new Fl_Button( 0, 0, 12, h(), "-" ); | |||||
o->callback( cb_button, this ); | |||||
o->labelsize(10); | |||||
o->labelfont( FL_HELVETICA_BOLD ); | |||||
o->hide(); | |||||
} | |||||
{ Fl_Button *o = inc_button = new Fl_Button( 0,0, 12, h(), "+" ); | |||||
o->labelsize(10); | |||||
o->labelfont( FL_HELVETICA_BOLD ); | |||||
o->callback( cb_button, this ); | |||||
o->hide(); | |||||
} | |||||
{ Fl_Box *o = output_connection_handle = new Fl_Box( x(), y(), 18, 18 ); | |||||
o->tooltip( "Drag and drop to make and break JACK connections."); | |||||
o->image( output_connector_image ? output_connector_image : output_connector_image = new Fl_PNG_Image( "output_connector", img_io_output_connector_10x10_png, img_io_output_connector_10x10_png_len ) ); | |||||
o->hide(); | |||||
} | |||||
o->end(); | |||||
resizable(o); | |||||
} | |||||
{ | |||||
Fl_Browser *o = connection_display = new Fl_Browser( x() + Fl::box_dx(box()), y() + 25, w() - Fl::box_dw(box()), 300 ); | |||||
o->textsize( 11 ); | |||||
o->textcolor( FL_LIGHT3 ); | |||||
o->textfont( FL_COURIER ); | |||||
o->box( FL_FLAT_BOX ); | |||||
o->color( fl_color_add_alpha( fl_rgb_color( 10, 10, 10 ), 25 )); | |||||
} | |||||
end(); | end(); | ||||
} | } | ||||
@@ -86,6 +159,155 @@ JACK_Module::~JACK_Module ( ) | |||||
void | |||||
JACK_Module::draw ( void ) | |||||
{ | |||||
Module::draw(); | |||||
if ( this == receptive_to_drop ) | |||||
{ | |||||
Fl_Widget *o = input_connection_handle; | |||||
fl_draw_box( FL_OVAL_BOX, o->x(), o->y(), o->w(), o->h(), fl_color_add_alpha( FL_GREEN, 127 ) ); | |||||
} | |||||
} | |||||
static std::list<std::string> | |||||
get_connections_for_ports ( std::vector<JACK::Port> ports ) | |||||
{ | |||||
std::list<std::string> names; | |||||
for ( unsigned int i = 0; i < ports.size(); ++i ) | |||||
{ | |||||
const char **connections = ports[i].connections(); | |||||
if ( ! connections ) | |||||
return names; | |||||
bool is_output = ports[i].type() == JACK::Port::Output; | |||||
for ( const char **c = connections; *c; c++ ) | |||||
{ | |||||
char *client_id = 0; | |||||
char *strip_name = 0; | |||||
// char *client_name = 0; | |||||
if ( 2 == sscanf( *c, "Non-Mixer.%a[^:/]/%a[^:]:", &client_id, &strip_name ) ) | |||||
{ | |||||
free( client_id ); | |||||
char *s = NULL; | |||||
asprintf( &s, "%s%s", is_output ? "@r" : "", strip_name ); | |||||
free( strip_name ); | |||||
strip_name = s; | |||||
} | |||||
else | |||||
if ( 2 == sscanf( *c, "Non-Timeline.%a[^:/]:%a[^/]/", &client_id, &strip_name ) ) | |||||
{ | |||||
free( client_id ); | |||||
char *s = NULL; | |||||
asprintf( &s, "@C2%s%s", is_output ? "@r" : "", strip_name ); | |||||
free( strip_name ); | |||||
strip_name = s; | |||||
} | |||||
else | |||||
if ( 2 == sscanf( *c, "Non-DAW.%a[^:/]:%a[^/]/", &client_id, &strip_name ) ) | |||||
{ | |||||
free( client_id ); | |||||
char *s = NULL; | |||||
asprintf( &s, "@C2%s%s", is_output ? "@r" : "", strip_name ); | |||||
free( strip_name ); | |||||
strip_name = s; | |||||
} | |||||
else if ( 1 == sscanf( *c, "%a[^:]:", &strip_name ) ) | |||||
{ | |||||
char *s = NULL; | |||||
asprintf( &s, "@C3%s%s", is_output ? "@r" : "", strip_name ); | |||||
free( strip_name ); | |||||
strip_name = s; | |||||
} | |||||
else | |||||
{ | |||||
continue; | |||||
} | |||||
for ( std::list<std::string>::const_iterator j = names.begin(); | |||||
j != names.end(); | |||||
j++ ) | |||||
{ | |||||
if ( !strcmp( j->c_str(), strip_name ) ) | |||||
{ | |||||
goto skip; | |||||
} | |||||
} | |||||
names.push_back( strip_name ); | |||||
skip: | |||||
free( strip_name ); | |||||
; | |||||
} | |||||
} | |||||
names.sort(); | |||||
return names; | |||||
} | |||||
void | |||||
JACK_Module::update_connection_status ( void ) | |||||
{ | |||||
std::list<std::string> output_names = get_connections_for_ports( jack_output ); | |||||
std::list<std::string> input_names = get_connections_for_ports( jack_input ); | |||||
connection_display->clear(); | |||||
int n = 0; | |||||
for ( std::list<std::string>::const_iterator j = input_names.begin(); | |||||
j != input_names.end(); | |||||
j++ ) | |||||
{ | |||||
connection_display->add( j->c_str() ); | |||||
n++; | |||||
} | |||||
for ( std::list<std::string>::const_iterator j = output_names.begin(); | |||||
j != output_names.end(); | |||||
j++ ) | |||||
{ | |||||
connection_display->add( j->c_str() ); | |||||
n++; | |||||
} | |||||
h( 25 + ( n * 13 ) ); | |||||
parent()->parent()->redraw(); | |||||
} | |||||
void | |||||
JACK_Module::cb_button ( Fl_Widget *w, void *v ) | |||||
{ | |||||
((JACK_Module*)v)->cb_button( w ); | |||||
} | |||||
void | |||||
JACK_Module::cb_button( Fl_Widget *w ) | |||||
{ | |||||
int n = audio_output.size(); | |||||
if ( w == dec_button ) | |||||
{ | |||||
--n; | |||||
} | |||||
else if ( w == inc_button ) | |||||
{ | |||||
++n; | |||||
} | |||||
if ( chain()->can_configure_outputs( this, n ) ) | |||||
{ | |||||
configure_outputs( n ); | |||||
chain()->configure_ports(); | |||||
} | |||||
} | |||||
int | int | ||||
JACK_Module::can_support_inputs ( int ) | JACK_Module::can_support_inputs ( int ) | ||||
{ | { | ||||
@@ -95,6 +317,15 @@ JACK_Module::can_support_inputs ( int ) | |||||
bool | bool | ||||
JACK_Module::configure_inputs ( int n ) | JACK_Module::configure_inputs ( int n ) | ||||
{ | { | ||||
if ( n > 0 ) | |||||
{ | |||||
if ( is_default() ) | |||||
control_input[0].hints.minimum = 1; | |||||
output_connection_handle->show(); | |||||
} | |||||
int on = audio_input.size(); | int on = audio_input.size(); | ||||
if ( n > on ) | if ( n > on ) | ||||
@@ -150,7 +381,12 @@ bool | |||||
JACK_Module::configure_outputs ( int n ) | JACK_Module::configure_outputs ( int n ) | ||||
{ | { | ||||
int on = audio_output.size(); | int on = audio_output.size(); | ||||
if ( n > 0 ) | |||||
{ | |||||
input_connection_handle->show(); | |||||
} | |||||
if ( n > on ) | if ( n > on ) | ||||
{ | { | ||||
for ( int i = on; i < n; ++i ) | for ( int i = on; i < n; ++i ) | ||||
@@ -191,6 +427,11 @@ JACK_Module::configure_outputs ( int n ) | |||||
if ( is_default() ) | if ( is_default() ) | ||||
control_input[1].control_value_no_callback( n ); | control_input[1].control_value_no_callback( n ); | ||||
if ( n > 0 && is_default() ) | |||||
{ | |||||
dec_button->show(); | |||||
inc_button->show(); | |||||
} | |||||
return true; | return true; | ||||
} | } | ||||
@@ -244,6 +485,142 @@ JACK_Module::handle_chain_name_changed ( void ) | |||||
Module::handle_chain_name_changed(); | Module::handle_chain_name_changed(); | ||||
} | } | ||||
int | |||||
JACK_Module::handle ( int m ) | |||||
{ | |||||
static JACK_Module *drag_source = 0; | |||||
switch ( m ) | |||||
{ | |||||
case FL_PUSH: | |||||
return Module::handle(m) || 1; | |||||
case FL_RELEASE: | |||||
return Module::handle(m) || 1; | |||||
case FL_DRAG: | |||||
{ | |||||
if ( ! Fl::event_inside( this ) && this != drag_source ) | |||||
{ | |||||
DMESSAGE( "initiation of drag" ); | |||||
char *s = (char*)malloc(256); | |||||
s[0] = 0; | |||||
for ( unsigned int i = 0; i < jack_output.size(); ++i ) | |||||
{ | |||||
char *s2; | |||||
asprintf(&s2, "jack.port://%s/%s:%s\r\n", instance_name, chain()->name(), jack_output[i].name() ); | |||||
s = (char*)realloc( s, strlen( s ) + strlen( s2 ) + 1 ); | |||||
strcat( s, s2 ); | |||||
free( s2 ); | |||||
} | |||||
Fl::copy(s, strlen(s) + 1, 0); | |||||
free( s ); | |||||
Fl::dnd(); | |||||
drag_source = this; | |||||
return 1; | |||||
} | |||||
return 1; | |||||
} | |||||
/* we have to prevent Fl_Group::handle() from getting these, otherwise it will mess up Fl::belowmouse() */ | |||||
case FL_MOVE: | |||||
return 0; | |||||
case FL_ENTER: | |||||
case FL_DND_ENTER: | |||||
return 1; | |||||
case FL_LEAVE: | |||||
case FL_DND_LEAVE: | |||||
if ( this == receptive_to_drop ) | |||||
{ | |||||
receptive_to_drop = NULL; | |||||
redraw(); | |||||
} | |||||
return 1; | |||||
case FL_DND_RELEASE: | |||||
receptive_to_drop = NULL; | |||||
redraw(); | |||||
return 1; | |||||
case FL_DND_DRAG: | |||||
{ | |||||
if ( this == drag_source ) | |||||
return 0; | |||||
if ( this == receptive_to_drop ) | |||||
return 1; | |||||
if ( jack_input.size() ) | |||||
{ | |||||
receptive_to_drop = this; | |||||
redraw(); | |||||
return 1; | |||||
} | |||||
return 0; | |||||
} | |||||
case FL_PASTE: | |||||
{ | |||||
receptive_to_drop = NULL; | |||||
redraw(); | |||||
drag_source = NULL; | |||||
/* 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 < jack_input.size() && i < port_names.size(); i++) | |||||
{ | |||||
const char *pn = port_names[i].c_str(); | |||||
JACK::Port *ji = &jack_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; | |||||
} | |||||
} | |||||
return Module::handle(m); | |||||
} | |||||
/**********/ | /**********/ | ||||
@@ -19,6 +19,8 @@ | |||||
#pragma once | #pragma once | ||||
class Fl_Box; | |||||
class Fl_Browser; | |||||
#include "Module.H" | #include "Module.H" | ||||
#include "JACK/Port.H" | #include "JACK/Port.H" | ||||
#include <vector> | #include <vector> | ||||
@@ -45,15 +47,28 @@ protected: | |||||
static void jack_port_activation_error ( JACK::Port *p ); | static void jack_port_activation_error ( JACK::Port *p ); | ||||
Fl_Button * dec_button; | |||||
Fl_Button * inc_button; | |||||
Fl_Browser * connection_display; | |||||
Fl_Box * input_connection_handle; | |||||
Fl_Box * output_connection_handle; | |||||
static void cb_button ( Fl_Widget *w, void *v ); | |||||
void cb_button ( Fl_Widget *w ); | |||||
public: | public: | ||||
void update_connection_status ( void ); | |||||
JACK_Module ( bool log = true ); | JACK_Module ( bool log = true ); | ||||
virtual ~JACK_Module ( ); | virtual ~JACK_Module ( ); | ||||
virtual const char *name ( void ) const { return "JACK"; } | virtual const char *name ( void ) const { return "JACK"; } | ||||
virtual bool initialize ( void ); | virtual bool initialize ( void ); | ||||
virtual void draw ( void ); | |||||
virtual int handle ( int m ); | |||||
virtual int can_support_inputs ( int ); | virtual int can_support_inputs ( int ); | ||||
virtual bool configure_inputs ( int n ); | virtual bool configure_inputs ( int n ); | ||||
virtual bool configure_outputs ( int n ); | virtual bool configure_outputs ( int n ); | ||||
@@ -730,22 +730,6 @@ Mixer::update_menu ( void ) | |||||
project_name->label( Project::name() ); | project_name->label( Project::name() ); | ||||
} | } | ||||
int | |||||
Mixer::handle ( int m ) | |||||
{ | |||||
if ( Fl_Group::handle( m ) ) | |||||
return 1; | |||||
switch ( m ) | |||||
{ | |||||
case FL_ENTER: | |||||
case FL_LEAVE: | |||||
return 1; | |||||
} | |||||
return 0; | |||||
} | |||||
/************/ | /************/ | ||||
@@ -73,10 +73,6 @@ private: | |||||
static int osc_non_hello ( const char *, const char *, lo_arg **, int , lo_message msg, void * ); | static int osc_non_hello ( const char *, const char *, lo_arg **, int , lo_message msg, void * ); | ||||
protected: | |||||
int handle ( int m ); | |||||
public: | public: | ||||
char * get_unique_track_name ( const char *name ); | char * get_unique_track_name ( const char *name ); | ||||
@@ -211,7 +211,7 @@ Mixer_Strip::chain ( Chain *c ) | |||||
void Mixer_Strip::cb_handle(Fl_Widget* o) { | void Mixer_Strip::cb_handle(Fl_Widget* o) { | ||||
// parent()->parent()->damage( FL_DAMAGE_ALL, x(), y(), w(), h() ); | // parent()->parent()->damage( FL_DAMAGE_ALL, x(), y(), w(), h() ); | ||||
DMESSAGE( "Callback for %s", o->label() ); | |||||
// DMESSAGE( "Callback for %s", o->label() ); | |||||
if ( o == tab_button ) | if ( o == tab_button ) | ||||
{ | { | ||||
@@ -440,8 +440,7 @@ Mixer_Strip::init ( ) | |||||
} // Fl_Button* o | } // Fl_Button* o | ||||
o->end(); | o->end(); | ||||
} // Fl_Group* o | |||||
} // Fl_Group* o | |||||
{ Fl_Flip_Button* o = tab_button = new Fl_Flip_Button(61, 183, 45, 22, "fader/signal"); | { Fl_Flip_Button* o = tab_button = new Fl_Flip_Button(61, 183, 45, 22, "fader/signal"); | ||||
o->type(1); | o->type(1); | ||||
o->labelsize( 14 ); | o->labelsize( 14 ); | ||||
@@ -481,7 +480,6 @@ Mixer_Strip::init ( ) | |||||
o->pad( false ); | o->pad( false ); | ||||
o->size( 33, 100 ); | o->size( 33, 100 ); | ||||
} | } | ||||
{ Meter_Indicator_Module *o = meter_indicator = new Meter_Indicator_Module( true ); | { Meter_Indicator_Module *o = meter_indicator = new Meter_Indicator_Module( true ); | ||||
o->disable_context_menu( true ); | o->disable_context_menu( true ); | ||||
o->pad( false ); | o->pad( false ); | ||||
@@ -693,15 +691,30 @@ Mixer_Strip::menu ( void ) const | |||||
int | int | ||||
Mixer_Strip::handle ( int m ) | Mixer_Strip::handle ( int m ) | ||||
{ | { | ||||
static int _button = 0; | |||||
Logger log( this ); | Logger log( this ); | ||||
if ( Fl_Group::handle( m ) ) | |||||
return 1; | |||||
switch ( m ) | |||||
{ | |||||
case FL_FOCUS: | |||||
damage( FL_DAMAGE_USER1 ); | |||||
return 1; | |||||
case FL_UNFOCUS: | |||||
damage( FL_DAMAGE_USER1 ); | |||||
return 1; | |||||
} | |||||
/* if ( m == FL_PUSH ) */ | |||||
/* take_focus(); */ | |||||
switch ( m ) | switch ( m ) | ||||
{ | { | ||||
case FL_KEYBOARD: | case FL_KEYBOARD: | ||||
{ | { | ||||
if ( Fl_Group::handle( m ) ) | |||||
return 1; | |||||
if ( Fl::event_key() == FL_Menu ) | if ( Fl::event_key() == FL_Menu ) | ||||
{ | { | ||||
menu_popup( &menu(), x(), y() ); | menu_popup( &menu(), x(), y() ); | ||||
@@ -712,34 +725,27 @@ Mixer_Strip::handle ( int m ) | |||||
break; | break; | ||||
} | } | ||||
case FL_PUSH: | case FL_PUSH: | ||||
_button = Fl::event_button(); | |||||
case FL_RELEASE: | |||||
{ | { | ||||
int r = 0; | |||||
if ( Fl::event_button1() ) | |||||
{ | |||||
take_focus(); | |||||
r = 1; | |||||
} | |||||
if ( Fl_Group::handle( m ) ) | |||||
return 1; | |||||
else if ( test_press( FL_BUTTON3 ) ) | |||||
int b = _button; | |||||
_button = 0; | |||||
/* if ( 1 == b ) */ | |||||
/* { */ | |||||
/* take_focus(); */ | |||||
/* } */ | |||||
/* else */ | |||||
if ( 3 == b ) | |||||
{ | { | ||||
menu_popup( &menu() ); | menu_popup( &menu() ); | ||||
return 1; | return 1; | ||||
} | } | ||||
else | |||||
return r; | |||||
break; | break; | ||||
} | } | ||||
case FL_FOCUS: | |||||
damage( FL_DAMAGE_USER1 ); | |||||
return Fl_Group::handle( m ) || 1; | |||||
case FL_UNFOCUS: | |||||
damage( FL_DAMAGE_USER1 ); | |||||
return Fl_Group::handle( m ) || 1; | |||||
} | } | ||||
return Fl_Group::handle( m ); | |||||
return 0; | |||||
} | } | ||||
@@ -133,6 +133,7 @@ Module::init ( void ) | |||||
box( FL_UP_BOX ); | box( FL_UP_BOX ); | ||||
labeltype( FL_NO_LABEL ); | labeltype( FL_NO_LABEL ); | ||||
align( FL_ALIGN_CENTER | FL_ALIGN_INSIDE ); | |||||
set_visible_focus(); | set_visible_focus(); | ||||
selection_color( FL_RED ); | selection_color( FL_RED ); | ||||
color( fl_color_average( FL_WHITE, FL_CYAN, 0.40 ) ); | color( fl_color_average( FL_WHITE, FL_CYAN, 0.40 ) ); | ||||
@@ -599,7 +600,7 @@ Module::draw_label ( int tx, int ty, int tw, int th ) | |||||
} | } | ||||
fl_draw( s ? s : lp, tx, ty, tw, th, (Fl_Align)(FL_ALIGN_CENTER | FL_ALIGN_INSIDE | FL_ALIGN_CLIP ) ); | |||||
fl_draw( s ? s : lp, tx, ty, tw, th, align() | FL_ALIGN_CLIP ); | |||||
if ( s ) | if ( s ) | ||||
delete[] s; | delete[] s; | ||||
@@ -777,13 +778,15 @@ Module::handle_chain_name_changed ( ) | |||||
int | int | ||||
Module::handle ( int m ) | Module::handle ( int m ) | ||||
{ | { | ||||
static int _button = 0; | |||||
if ( Fl_Group::handle( m ) ) | |||||
return 1; | |||||
switch ( m ) | switch ( m ) | ||||
{ | { | ||||
case FL_KEYBOARD: | case FL_KEYBOARD: | ||||
{ | { | ||||
if ( Fl_Group::handle( m ) ) | |||||
return 1; | |||||
if ( Fl::event_key() == FL_Menu ) | if ( Fl::event_key() == FL_Menu ) | ||||
{ | { | ||||
menu_popup( &menu(), x(), y() ); | menu_popup( &menu(), x(), y() ); | ||||
@@ -792,28 +795,35 @@ Module::handle ( int m ) | |||||
else | else | ||||
return menu().test_shortcut() != 0; | return menu().test_shortcut() != 0; | ||||
} | } | ||||
case FL_PUSH: | |||||
{ | |||||
case FL_PUSH: | |||||
take_focus(); | take_focus(); | ||||
if ( Fl_Group::handle( m ) ) | |||||
return 1; | |||||
else if ( test_press( FL_BUTTON3 ) ) | |||||
_button = Fl::event_button(); | |||||
return 1; | |||||
// if ( Fl::visible_focus() && handle( FL_FOCUS )) Fl::focus(this); | |||||
case FL_DRAG: | |||||
_button = Fl::event_button(); | |||||
return 1; | |||||
case FL_RELEASE: | |||||
{ | |||||
int b = _button; | |||||
_button = 0; | |||||
DMESSAGE( "Button %i", b); | |||||
if ( 3 == b ) | |||||
{ | { | ||||
menu_popup( &menu() ); | menu_popup( &menu() ); | ||||
return 1; | return 1; | ||||
} | } | ||||
else if ( test_press( FL_BUTTON1 ) ) | |||||
else if ( 1 == b ) | |||||
{ | { | ||||
command_open_parameter_editor(); | command_open_parameter_editor(); | ||||
return 1; | return 1; | ||||
} | } | ||||
else if ( test_press( FL_BUTTON3 | FL_CTRL ) ) | |||||
else if ( 3 == b && Fl::event_ctrl() ) | |||||
{ | { | ||||
command_remove(); | command_remove(); | ||||
return 1; | return 1; | ||||
} | } | ||||
else if ( test_press( FL_BUTTON2 ) ) | |||||
else if ( 2 == b ) | |||||
{ | { | ||||
if ( !bypassable() ) | if ( !bypassable() ) | ||||
{ | { | ||||
@@ -826,6 +836,10 @@ Module::handle ( int m ) | |||||
} | } | ||||
return 1; | return 1; | ||||
} | } | ||||
/* else */ | |||||
/* { */ | |||||
/* take_focus(); */ | |||||
/* } */ | |||||
return 0; | return 0; | ||||
} | } | ||||
@@ -835,7 +849,7 @@ Module::handle ( int m ) | |||||
return 1; | return 1; | ||||
} | } | ||||
return Fl_Group::handle( m ); | |||||
return 0; | |||||
} | } | ||||
@@ -295,7 +295,8 @@ main ( int argc, char **argv ) | |||||
} | } | ||||
Fl::add_timeout( 0.1f, check_sigterm ); | Fl::add_timeout( 0.1f, check_sigterm ); | ||||
Fl::dnd_text_ops( 0 ); | |||||
if ( ! no_ui ) | if ( ! no_ui ) | ||||
{ | { | ||||
DMESSAGE( "Running UI..." ); | DMESSAGE( "Running UI..." ); | ||||
@@ -108,7 +108,11 @@ namespace JACK | |||||
((Client*)arg)->shutdown(); | ((Client*)arg)->shutdown(); | ||||
} | } | ||||
void | |||||
Client::port_connect ( jack_port_id_t a, jack_port_id_t b, int connect, void *arg ) | |||||
{ | |||||
((Client*)arg)->port_connect( a, b, connect ); | |||||
} | |||||
/** Connect to JACK using client name /client_name/. Return a static | /** Connect to JACK using client name /client_name/. Return a static | ||||
* pointer to actual name as reported by JACK */ | * pointer to actual name as reported by JACK */ | ||||
@@ -125,6 +129,7 @@ namespace JACK | |||||
set_callback( xrun ); | set_callback( xrun ); | ||||
set_callback( freewheel ); | set_callback( freewheel ); | ||||
set_callback( buffer_size ); | set_callback( buffer_size ); | ||||
set_callback( port_connect ); | |||||
/* FIXME: should we wait to register this until after the project | /* FIXME: should we wait to register this until after the project | ||||
has been loaded (and we have disk threads running)? */ | has been loaded (and we have disk threads running)? */ | ||||
@@ -40,6 +40,8 @@ namespace JACK | |||||
volatile bool _freewheeling; | volatile bool _freewheeling; | ||||
volatile bool _zombified; | volatile bool _zombified; | ||||
static void port_connect ( jack_port_id_t a, jack_port_id_t b, int connect, void *arg ); | |||||
virtual void port_connect ( jack_port_id_t a, jack_port_id_t b, int connect ) { } | |||||
static void shutdown ( void *arg ); | static void shutdown ( void *arg ); | ||||
virtual void shutdown ( void ) = 0; | virtual void shutdown ( void ) = 0; | ||||
static int process ( nframes_t nframes, void *arg ); | static int process ( nframes_t nframes, void *arg ); | ||||
@@ -298,6 +298,42 @@ namespace JACK | |||||
return true; | return true; | ||||
} | } | ||||
int | |||||
Port::connect ( const char *to ) | |||||
{ | |||||
const char *name = jack_port_name( _port ); | |||||
if ( _direction == Output ) | |||||
{ | |||||
return jack_connect( _client->jack_client(), name, to ); | |||||
} | |||||
else | |||||
{ | |||||
return jack_connect( _client->jack_client(), to, name ); | |||||
} | |||||
} | |||||
int | |||||
Port::disconnect ( const char *from ) | |||||
{ | |||||
const char *name = jack_port_name( _port ); | |||||
if ( _direction == Output ) | |||||
{ | |||||
return jack_disconnect( _client->jack_client(), name, from ); | |||||
} | |||||
else | |||||
{ | |||||
return jack_disconnect( _client->jack_client(), from, name ); | |||||
} | |||||
} | |||||
bool | |||||
Port::connected_to ( const char *to ) | |||||
{ | |||||
return jack_port_connected_to( _port, to ); | |||||
} | |||||
void | void | ||||
Port::freeze ( void ) | Port::freeze ( void ) | ||||
@@ -74,6 +74,9 @@ namespace JACK | |||||
void *buffer ( nframes_t nframes ); | void *buffer ( nframes_t nframes ); | ||||
void silence ( nframes_t nframes ); | void silence ( nframes_t nframes ); | ||||
int connect ( const char *to ); | |||||
int disconnect ( const char *from ); | |||||
bool connected_to ( const char *to ); | |||||
/* */ | /* */ | ||||
const char ** connections ( void ); | const char ** connections ( void ); | ||||
bool connections ( const char **port_names ); | bool connections ( const char **port_names ); | ||||
@@ -253,6 +253,8 @@ Audio_Sequence::handle ( int m ) | |||||
{ | { | ||||
case FL_PASTE: | case FL_PASTE: | ||||
{ | { | ||||
if ( ! Fl::event_inside( this ) ) | |||||
return 0; | |||||
const char *text = Fl::event_text(); | const char *text = Fl::event_text(); | ||||
if ( ! strcmp( text, "Audio_Region" ) ) | if ( ! strcmp( text, "Audio_Region" ) ) | ||||
@@ -262,7 +264,7 @@ Audio_Sequence::handle ( int m ) | |||||
if ( ! sscanf( text, "file://%a[^\r\n]\n", &file ) ) | if ( ! sscanf( text, "file://%a[^\r\n]\n", &file ) ) | ||||
{ | { | ||||
printf( "invalid drop \"%s\"\n", text ); | |||||
WARNING( "invalid drop \"%s\"\n", text ); | |||||
return 0; | return 0; | ||||
} | } | ||||
@@ -43,7 +43,6 @@ protected: | |||||
void handle_widget_change ( nframes_t start, nframes_t length ); | void handle_widget_change ( nframes_t start, nframes_t length ); | ||||
void draw ( void ); | void draw ( void ); | ||||
int handle ( int m ); | |||||
static void cb_button ( Fl_Widget *w, void *v ); | static void cb_button ( Fl_Widget *w, void *v ); | ||||
void cb_button ( Fl_Widget *w ); | void cb_button ( Fl_Widget *w ); | ||||
@@ -52,6 +51,8 @@ protected: | |||||
public: | public: | ||||
int handle ( int m ); | |||||
LOG_CREATE_FUNC( Audio_Sequence ); | LOG_CREATE_FUNC( Audio_Sequence ); | ||||
Audio_Sequence_Header * header ( void ) { return (Audio_Sequence_Header*)child(0); } | Audio_Sequence_Header * header ( void ) { return (Audio_Sequence_Header*)child(0); } | ||||
@@ -389,9 +389,7 @@ Sequence::handle ( int m ) | |||||
fl_cursor( FL_CURSOR_DEFAULT ); | fl_cursor( FL_CURSOR_DEFAULT ); | ||||
Fl_Group::handle( m ); | Fl_Group::handle( m ); | ||||
return 1; | return 1; | ||||
case FL_DND_DRAG: | |||||
return 1; | |||||
case FL_ENTER: | |||||
case FL_ENTER: | |||||
// DMESSAGE( "enter" ); | // DMESSAGE( "enter" ); | ||||
if ( Fl::event_x() >= drawable_x() ) | if ( Fl::event_x() >= drawable_x() ) | ||||
{ | { | ||||
@@ -424,10 +422,14 @@ Sequence::handle ( int m ) | |||||
{ | { | ||||
return Fl_Group::handle(m); | return Fl_Group::handle(m); | ||||
} | } | ||||
case FL_DND_DRAG: | |||||
case FL_DND_ENTER: | case FL_DND_ENTER: | ||||
case FL_DND_LEAVE: | case FL_DND_LEAVE: | ||||
case FL_DND_RELEASE: | case FL_DND_RELEASE: | ||||
return 1; | |||||
if ( Fl::event_x() >= drawable_x() ) | |||||
return 1; | |||||
else | |||||
return 0; | |||||
case FL_MOVE: | case FL_MOVE: | ||||
{ | { | ||||
if ( Fl::event_x() >= drawable_x() ) | if ( Fl::event_x() >= drawable_x() ) | ||||
@@ -47,6 +47,7 @@ | |||||
#include <FL/Fl_Menu_Button.H> | #include <FL/Fl_Menu_Button.H> | ||||
#include "FL/menu_popup.H" | #include "FL/menu_popup.H" | ||||
extern char *instance_name; | |||||
@@ -997,6 +998,8 @@ Track::menu ( void ) const | |||||
#include "FL/event_name.H" | #include "FL/event_name.H" | ||||
#include "FL/test_press.H" | #include "FL/test_press.H" | ||||
static Fl_Widget *receptive_to_drop = NULL; | |||||
void | void | ||||
Track::draw ( void ) | Track::draw ( void ) | ||||
{ | { | ||||
@@ -1020,6 +1023,12 @@ Track::draw ( void ) | |||||
else | else | ||||
Fl_Group::draw(); | Fl_Group::draw(); | ||||
if ( ((Track_Header*)child(0))->input_connector_handle == receptive_to_drop ) | |||||
{ | |||||
Fl_Widget *o = ((Track_Header*)child(0))->input_connector_handle; | |||||
fl_draw_box( FL_OVAL_BOX, o->x(), o->y(), o->w(), o->h(), fl_color_add_alpha( FL_GREEN, 127 ) ); | |||||
} | |||||
if ( ! Track::colored_tracks ) | if ( ! Track::colored_tracks ) | ||||
color( saved_color ); | color( saved_color ); | ||||
@@ -1032,6 +1041,19 @@ Track::handle ( int m ) | |||||
/* if ( m != FL_NO_EVENT ) */ | /* if ( m != FL_NO_EVENT ) */ | ||||
/* DMESSAGE( "%s", event_name( m ) ); */ | /* DMESSAGE( "%s", event_name( m ) ); */ | ||||
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 ) | switch ( m ) | ||||
{ | { | ||||
@@ -1065,6 +1087,9 @@ Track::handle ( int m ) | |||||
} | } | ||||
case FL_PUSH: | case FL_PUSH: | ||||
{ | { | ||||
if ( Fl::event_inside( ((Track_Header*)child(0))->output_connector_handle ) ) | |||||
return 1; | |||||
Logger log( this ); | Logger log( this ); | ||||
if ( Fl_Group::handle( m ) ) | if ( Fl_Group::handle( m ) ) | ||||
@@ -1078,6 +1103,140 @@ Track::handle ( int m ) | |||||
return 0; | 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 sequence()->handle(m); | |||||
} | |||||
return 0; | |||||
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_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 0; | |||||
} | |||||
default: | default: | ||||
return Fl_Group::handle( m ); | return Fl_Group::handle( m ); | ||||
} | } | ||||
@@ -8,20 +8,35 @@ decl {\#include "FL/Fl_Sometimes_Input.H"} {public global | |||||
decl {\#include "FL/Fl_Blink_Button.H"} {public global | decl {\#include "FL/Fl_Blink_Button.H"} {public global | ||||
} | } | ||||
decl {\#include <FL/Fl_PNG_Image.H>} {private local | |||||
} | |||||
decl {\#include <FL/img_io_input_connector_10x10_png.h>} {private local | |||||
} | |||||
decl {\#include <FL/img_io_output_connector_10x10_png.h>} {private local | |||||
} | |||||
decl {Fl_PNG_Image *output_connector_image = NULL;} {private local | |||||
} | |||||
decl {Fl_PNG_Image *input_connector_image = NULL;} {private local | |||||
} | |||||
widget_class Track_Header {open | widget_class Track_Header {open | ||||
xywh {897 224 525 60} type Double box NO_BOX resizable visible | |||||
xywh {680 695 525 60} type Double box NO_BOX resizable visible | |||||
} { | } { | ||||
Fl_Group box_group {open | Fl_Group box_group {open | ||||
private xywh {0 0 200 60} box THIN_UP_BOX color 63 | private xywh {0 0 200 60} box THIN_UP_BOX color 63 | ||||
code0 {o->resizable(0);} | code0 {o->resizable(0);} | ||||
} { | } { | ||||
Fl_Group {} {open | Fl_Group {} {open | ||||
xywh {0 0 200 51} | |||||
xywh {0 0 200 55} | |||||
code0 {o->resizable(0);} | code0 {o->resizable(0);} | ||||
} { | } { | ||||
Fl_Input name_input { | Fl_Input name_input { | ||||
label {input:} | label {input:} | ||||
xywh {0 2 200 23} labeltype NO_LABEL align 20 when 8 | |||||
xywh {4 2 151 22} labeltype NO_LABEL align 20 when 8 | |||||
class Fl_Sometimes_Input | class Fl_Sometimes_Input | ||||
} | } | ||||
Fl_Button track_inputs_indicator { | Fl_Button track_inputs_indicator { | ||||
@@ -56,6 +71,16 @@ widget_class Track_Header {open | |||||
label s | label s | ||||
tooltip solo xywh {172 26 24 24} type Toggle selection_color 91 labelfont 5 labelsize 12 | tooltip solo xywh {172 26 24 24} type Toggle selection_color 91 labelfont 5 labelsize 12 | ||||
} | } | ||||
Fl_Box input_connector_handle { | |||||
tooltip {Drag and drop this input connector to make or break JACK connections} xywh {157 4 18 18} box FLAT_BOX | |||||
code0 {o->image( input_connector_image ? input_connector_image : input_connector_image = new Fl_PNG_Image( "input-connector", img_io_input_connector_10x10_png, img_io_input_connector_10x10_png_len ) );} | |||||
code1 {o->box(FL_NO_BOX);} | |||||
} | |||||
Fl_Box output_connector_handle {selected | |||||
tooltip {Drag and drop this output connector to make or break JACK connections} xywh {177 4 18 18} box FLAT_BOX | |||||
code0 {o->image( output_connector_image ? output_connector_image : output_connector_image = new Fl_PNG_Image( "output-connector", img_io_output_connector_10x10_png, img_io_output_connector_10x10_png_len ) );} | |||||
code1 {o->box(FL_NO_BOX);} | |||||
} | |||||
} | } | ||||
} | } | ||||
Fl_Box {} { | Fl_Box {} { | ||||
@@ -72,7 +97,7 @@ Fl_Group::draw();} {} | |||||
} | } | ||||
widget_class Control_Sequence_Header {open | widget_class Control_Sequence_Header {open | ||||
xywh {315 771 200 55} type Double box NO_BOX visible | |||||
xywh {325 886 200 55} type Double box NO_BOX visible | |||||
} { | } { | ||||
Fl_Input name_input { | Fl_Input name_input { | ||||
label {input:} | label {input:} | ||||
@@ -80,7 +105,7 @@ widget_class Control_Sequence_Header {open | |||||
class Fl_Sometimes_Input | class Fl_Sometimes_Input | ||||
} | } | ||||
Fl_Button menu_button { | Fl_Button menu_button { | ||||
label menu selected | |||||
label menu | |||||
tooltip {Expand controls} xywh {5 26 31 24} selection_color 3 labelfont 4 labelsize 10 | tooltip {Expand controls} xywh {5 26 31 24} selection_color 3 labelfont 4 labelsize 10 | ||||
} | } | ||||
Fl_Button outputs_indicator { | Fl_Button outputs_indicator { | ||||
@@ -103,7 +128,7 @@ widget_class Control_Sequence_Header {open | |||||
} | } | ||||
widget_class Audio_Sequence_Header {open | widget_class Audio_Sequence_Header {open | ||||
xywh {332 613 200 50} type Double box NO_BOX resizable visible | |||||
xywh {404 670 200 50} type Double box NO_BOX resizable visible | |||||
} { | } { | ||||
Fl_Group {} {open | Fl_Group {} {open | ||||
xywh {0 0 200 55} | xywh {0 0 200 55} | ||||