00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00022
00023 #ifdef HAVE_CONFIG_H
00024 #include <config.h>
00025 #endif
00026
00027 #include <fcntl.h>
00028 #include <unistd.h>
00029 #include <errno.h>
00030 #include <linux/input.h>
00031
00032 #include "jogshuttle.h"
00033 #include "preferences.h"
00034 #include "commands.h"
00035
00036 #include <string>
00037 using std::string;
00038 #include <utility>
00039 using std::pair;
00040 using std::make_pair;
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090 extern "C"
00091 {
00092 #include "support.h"
00093 extern struct navigate_control g_nav_ctl;
00094 }
00095
00097
00099 void JogShuttle_inputCallback( gpointer data, gint source, GdkInputCondition condition )
00100 {
00101 JogShuttle * js = static_cast<JogShuttle *>( data );
00102 g_return_if_fail( js != NULL );
00103 js->inputCallback( source, condition );
00104 }
00105
00111 JogShuttle *JogShuttle::_instance = NULL;
00112
00117 JogShuttle &JogShuttle::getInstance()
00118 {
00119 if ( _instance == NULL )
00120 _instance = new JogShuttle();
00121 return *_instance;
00122 }
00123
00126 JogShuttle::JogShuttle() :
00127 _callback( NULL ),
00128 input_( -1 ),
00129 monitorTag_( -1 ),
00130 _modifier_code( 0 )
00131 {
00132 _ctrl.device = NULL;
00133 start();
00134 }
00135
00140 JogShuttle::~JogShuttle()
00141 {
00142 if ( input_ >= 0 )
00143 {
00144 gdk_input_remove( monitorTag_ );
00145 media_ctrl_close(&_ctrl);
00146 }
00147 }
00148
00154 bool JogShuttle::start()
00155 {
00156 Preferences & prefs = Preferences::getInstance();
00157
00158 if ( prefs.enableJogShuttle )
00159 {
00160 stop();
00161 media_ctrl_open( &_ctrl );
00162 if ( _ctrl.device )
00163 {
00164 monitorTag_ = gdk_input_add( _ctrl.fd, GDK_INPUT_READ,
00165 JogShuttle_inputCallback,
00166 ( gpointer ) this );
00167 return true;
00168 }
00169 }
00170 return false;
00171 }
00172
00175 void JogShuttle::stop()
00176 {
00177 if ( monitorTag_ != -1 )
00178 {
00179 gdk_input_remove( monitorTag_ );
00180 monitorTag_ = -1;
00181 }
00182 if ( _ctrl.device )
00183 media_ctrl_close( &_ctrl );
00184 }
00185
00192 void JogShuttle::registerCallback( void * user, JogShuttleCallback callback )
00193 {
00194 if ( _callback )
00195 g_warning( "JogShuttle::registerCallback - already registered\n" );
00196 _callback = callback;
00197 _callbackdata = user;
00198 }
00199
00206 void JogShuttle::deregisterCallback()
00207 {
00208 if ( _callback == NULL )
00209 g_warning( "JogShuttle::deregisterCallback - not registered\n" );
00210 _callback = NULL;
00211 }
00212
00213 struct media_ctrl_key *JogShuttle::getKeyset()
00214 {
00215 if ( _ctrl.device != NULL ) return _ctrl.device->keys;
00216 else return NULL;
00217 }
00218
00219
00220
00221
00222
00223
00229 void JogShuttle::jog( int offs )
00230 {
00231 gdk_threads_enter();
00232 if ( offs < 0 )
00233 videoBackBy(offs);
00234 else
00235 videoForwardBy(offs);
00236 gdk_threads_leave();
00237 }
00238
00243 void JogShuttle::shuttle( int angle )
00244 {
00245
00246
00247
00248
00249
00250 gdk_threads_enter();
00251 videoShuttle( angle );
00252 gdk_threads_leave();
00253 }
00254
00267 void JogShuttle::button( struct media_ctrl_event *ev )
00268 {
00269
00270 unsigned short first;
00271 unsigned short second;
00272
00273
00274
00275
00276 if ( ev->value == KEY_RELEASE && _modifier_code != 0 )
00277 {
00278 _modifier_code = 0;
00279 return;
00280 }
00281
00282
00283 if ( _callback != NULL )
00284 {
00285
00286
00287 if ( _modifier_code == 0 )
00288 _modifier_code = ev->index + 1;
00289
00290 if ( _modifier_code != ev->index + 1 )
00291 {
00292 first = _modifier_code - 1;
00293 second = ev->index + 1;
00294 }
00295 else
00296 {
00297 first = ev->index;
00298 second = 0;
00299 }
00300 _callback( _callbackdata, first, second );
00301 }
00302 else
00303 {
00304
00305
00306 if ( _modifier_code == 0 )
00307 _modifier_code = ev->code;
00308
00309 if ( _modifier_code != ev->code )
00310 {
00311 first = _modifier_code;
00312 second = ev->code;
00313 }
00314 else
00315 {
00316 first = ev->code;
00317 second = 0;
00318 }
00319
00320
00321 string action
00322 = Preferences::getInstance()._JogShuttleMappings[
00323 make_pair( first, second ) ]._action;
00324
00325 if ( "" != action )
00326 {
00327 gdk_threads_enter();
00328 processCommand( ( char * ) action.c_str() );
00329 gdk_threads_leave();
00330 }
00331 }
00332 return ;
00333
00334 }
00335
00336
00337
00338
00344 void JogShuttle::inputCallback( gint source, GdkInputCondition condition )
00345 {
00346 g_return_if_fail( this != NULL );
00347
00348
00349 if ( condition != GDK_INPUT_READ )
00350 stop();
00351 g_return_if_fail( condition == GDK_INPUT_READ );
00352
00353 struct media_ctrl_event ev;
00354
00355 ev.type = MEDIA_CTRL_EVENT_NONE;
00356 media_ctrl_read_event(&_ctrl, &ev);
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386 if ( ev.type == MEDIA_CTRL_EVENT_NONE ) return;
00387 #if 0
00388 printf( "JogShuttle: %02x %02x %02d\n", ev.type, ev.code, ev.value );
00389 #endif
00390
00391
00392 if ( ev.type == MEDIA_CTRL_EVENT_JOG )
00393 {
00394 this->jog( CLAMP( ev.value, -1, 1 ) );
00395 }
00396 else if ( ev.type == MEDIA_CTRL_EVENT_SHUTTLE )
00397 {
00398 this->shuttle( ev.value );
00399 }
00400 else if ( ev.type == MEDIA_CTRL_EVENT_KEY )
00401 {
00402 this->button( &ev );
00403 }
00404 else
00405 {
00406 return;
00407 }
00408 }