add usb_direct for shuttle, revised shuttle again, titler tweak, transportque design...
authorGood Guy <good1.2guy@gmail.com>
Mon, 11 Feb 2019 22:16:20 +0000 (15:16 -0700)
committerGood Guy <good1.2guy@gmail.com>
Mon, 11 Feb 2019 22:16:20 +0000 (15:16 -0700)
20 files changed:
cinelerra-5.1/bld.sh
cinelerra-5.1/cinelerra/canvas.C
cinelerra-5.1/cinelerra/canvas.h
cinelerra-5.1/cinelerra/cwindow.C
cinelerra-5.1/cinelerra/mwindow.C
cinelerra-5.1/cinelerra/playbackengine.C
cinelerra-5.1/cinelerra/playbackengine.h
cinelerra-5.1/cinelerra/shuttle.C
cinelerra-5.1/cinelerra/shuttle.h
cinelerra-5.1/cinelerra/transportque.C
cinelerra-5.1/cinelerra/transportque.h
cinelerra-5.1/cinelerra/vdevicex11.C
cinelerra-5.1/cinelerra/vdevicex11.h
cinelerra-5.1/cinelerra/zwindow.C
cinelerra-5.1/configure.ac
cinelerra-5.1/doc/99-ShuttlePRO.rules
cinelerra-5.1/guicast/bccapture.C
cinelerra-5.1/guicast/bccapture.h
cinelerra-5.1/plugins/titler/titlerwindow.C
cinelerra-5.1/shuttlerc

index 7c8837bfbf9a6b4443f93c38c35299aad8851b4d..f09b34a05881ca9d63b8cd2cb530f7f371b7f88f 100755 (executable)
@@ -1,6 +1,6 @@
 #!/bin/bash
 ( ./autogen.sh
-  ./configure --with-single-user --with-booby
+  ./configure --with-single-user --with-booby --with-shuttle-usb
   make && make install ) 2>&1 | tee log
 mv Makefile Makefile.cfg
 cp Makefile.devel Makefile
index 2b3953002d58cc03f8dc56321dd223baea9ede1e..0997e064dcafd393acce96fadf419b65ad3a2cd9 100644 (file)
@@ -576,6 +576,22 @@ void Canvas::get_scrollbars(EDL *edl,
 //printf("Canvas::get_scrollbars 5 %d %d\n", get_xscroll(), get_yscroll());
 }
 
+
+void Canvas::update_geometry(EDL *edl, int x, int y, int w, int h)
+{
+       int redraw = 0;
+       if( this->x != x || this->y != y ||
+           this->w != w || this->h != h ) redraw = 1;
+       if( !redraw ) {
+               int vx = x, vy = y, vw = w, vh = h;
+               get_scrollbars(edl, vx, vy, vw, vh);
+               if( vx != view_x || vy != view_y ||
+                   vw != view_w || vh != view_h ) redraw = 1;
+       }
+       if( !redraw ) return;
+       reposition_window(edl, x, y, w, y);
+}
+
 void Canvas::reposition_window(EDL *edl, int x, int y, int w, int h)
 {
        this->x = view_x = x;  this->y = view_y = y;
@@ -596,8 +612,6 @@ void Canvas::reposition_window(EDL *edl, int x, int y, int w, int h)
                        canvas_subwindow->flash(0);
                }
        }
-
-
        draw_refresh(0);
 }
 
index 9a78095eacea972c62543eafe57028edc0e39d21..1984269560882a1583377cce0ba19fcbb3bfd530 100644 (file)
@@ -131,6 +131,7 @@ public:
 // passing -1 causes automatic size detection
                int canvas_w = -1,
                int canvas_h = -1);
+       void update_geometry(EDL *edl, int x, int y, int w, int h);
        void reposition_window(EDL *edl, int x, int y, int w, int h);
        virtual void reset_translation() {};
        virtual void close_source() {};
index 6f29f27b6afc59c8181d409988453b0e76dc909e..1611f7534342100a018fdf8a6ef338ba26b11981 100644 (file)
@@ -255,20 +255,11 @@ void CWindow::update(int dir, int overlays, int tool_window, int operation, int
        gui->canvas->update_zoom(mwindow->edl->session->cwindow_xscroll,
                        mwindow->edl->session->cwindow_yscroll,
                        mwindow->edl->session->cwindow_zoom);
-       gui->canvas->reposition_window(mwindow->edl,
-                       mwindow->theme->ccanvas_x,
-                       mwindow->theme->ccanvas_y,
-                       mwindow->theme->ccanvas_w,
-                       mwindow->theme->ccanvas_h);
-
-
-
+       gui->canvas->update_geometry(mwindow->edl,
+                       mwindow->theme->ccanvas_x, mwindow->theme->ccanvas_y,
+                       mwindow->theme->ccanvas_w, mwindow->theme->ccanvas_h);
 
        gui->unlock_window();
-
-
-
-
 }
 
 int CWindow::update_position(double position)
index 3aa564d193c28e59bbfdd5500c600665ced717e0..e6a40ee551bb01059bb985e9a99f17c2b43f71f7 100644 (file)
@@ -1291,7 +1291,7 @@ void MWindow::handle_mixers(EDL *edl, int command, int wait_tracking,
                                track->record = track->play = 0;
                }
                zwindow->change_source(mixer_edl);
-               zwindow->handle_mixer(command, wait_tracking,
+               zwindow->handle_mixer(command, 0,
                                use_inout, toggle_audio, loop_play, speed);
        }
        zwindows_lock->unlock();
@@ -1589,10 +1589,15 @@ void MWindow::init_exportedl()
 void MWindow::init_shuttle()
 {
 #ifdef HAVE_SHUTTLE
-       const char *dev_name = Shuttle::probe();
-       if( dev_name ) {
+       int ret = Shuttle::probe();
+       if( ret >= 0 ) {
                shuttle = new Shuttle(this);
-               shuttle->start(dev_name);
+               if( shuttle->read_config_file() > 0 ) {
+                       printf("shuttle: bad config file\n");
+                       delete shuttle;  shuttle = 0;
+                       return;
+               }
+               shuttle->start(ret);
        }
 #endif
 }
index 42f77cfd0e33a8f8b140a6e6bc66cd4ee614499b..39fdaa96e2527a67d20c603a7b66dd4abdb5a6a2 100644 (file)
@@ -56,9 +56,12 @@ PlaybackEngine::PlaybackEngine(MWindow *mwindow, Canvas *output)
        command->command = STOP;
        next_command = new TransportCommand();
        next_command->change_type = CHANGE_ALL;
-       curr_command = new TransportCommand();
        stop_command = new TransportCommand();
        stop_command->command = STOP;
+       stop_command->realtime = 1;
+       sent_command = new TransportCommand();
+       sent_command->command = -1;
+       sent_lock = new Mutex("PlaybackEngine::sent");
        tracking_lock = new Mutex("PlaybackEngine::tracking_lock");
        renderengine_lock = new Mutex("PlaybackEngine::renderengine_lock");
        tracking_done = new Condition(1, "PlaybackEngine::tracking_done");
@@ -74,7 +77,7 @@ PlaybackEngine::PlaybackEngine(MWindow *mwindow, Canvas *output)
 PlaybackEngine::~PlaybackEngine()
 {
        done = 1;
-       transport_stop(0);
+       output_lock->unlock();
        Thread::join();
        delete preferences;
        delete_render_engine();
@@ -88,7 +91,8 @@ PlaybackEngine::~PlaybackEngine()
        delete command;
        delete next_command;
        delete stop_command;
-       delete curr_command;
+       delete sent_command;
+       delete sent_lock;
        delete input_lock;
        delete output_lock;
 }
@@ -161,16 +165,14 @@ void PlaybackEngine::create_cache()
 
 void PlaybackEngine::perform_change()
 {
-       switch( command->change_type )
-       {
+       switch( command->change_type ) {
                case CHANGE_ALL:
                        create_cache();
                case CHANGE_EDL:
                        create_render_engine();
+                       break;
                case CHANGE_PARAMS:
-                       if(command->change_type != CHANGE_EDL &&
-                               (uint32_t)command->change_type != CHANGE_ALL)
-                               render_engine->get_edl()->synchronize_params(command->get_edl());
+                       render_engine->get_edl()->synchronize_params(command->get_edl());
                case CHANGE_NONE:
                        break;
        }
@@ -364,23 +366,27 @@ void PlaybackEngine::run()
        while( !done ) {
 // Wait for current command to finish
                output_lock->lock("PlaybackEngine::run");
-//printf("PlaybackEngine::run 0 %d\n", curr_command->command);
-               if( curr_command->command < 0 ) continue;
-// this covers a glitch that occurs when stop is asserted
-// when the render_engine starting, but not initialized
-               if( curr_command->command == STOP && render_engine )
-                       render_engine->interrupt_playback();
-               wait_render_engine();
+               if( done ) break;
 
 // Read the new command
-               input_lock->lock("PlaybackEngine::run");
-               command->copy_from(curr_command);
-               curr_command->command = -1;
-               input_lock->unlock();
-               if( done ) break;
+               sent_lock->lock("PlaybackEngine::run");
+               int command = sent_command->command;
+               if( command >= 0 ) {
+                       this->command->copy_from(sent_command);
+//printf("sent command=%d\n", sent_command->command);
+                       sent_command->command = -1;
+                       if( sent_command->locked )
+                               input_lock->unlock();
+               }
+               sent_lock->unlock();
+               if( command < 0 ) continue;
+
+               interrupt_playback(0);
+               wait_render_engine();
+
 //printf("PlaybackEngine::run 1 %d\n", command->command);
 
-               switch( command->command ) {
+               switch( command ) {
 // Parameter change only
                case COMMAND_NONE:
                        perform_change();
@@ -442,9 +448,11 @@ void PlaybackEngine::send_command(int command, EDL *edl, int wait_tracking, int
        int do_stop = 0, do_resume = 0;
        int curr_command = this->command->command;
        int curr_single_frame = TransportCommand::single_frame(curr_command);
+       int curr_direction = TransportCommand::get_direction(curr_command);
        int curr_audio = this->command->toggle_audio ?
                !curr_single_frame : curr_single_frame;
        int single_frame = TransportCommand::single_frame(command);
+       int direction = TransportCommand::get_direction(command);
        int next_audio = next_command->toggle_audio ? !single_frame : single_frame;
 
 // Dispatch command
@@ -468,7 +476,7 @@ void PlaybackEngine::send_command(int command, EDL *edl, int wait_tracking, int
 // Resume or change direction
                switch( curr_command ) {
                default:
-                       transport_stop(wait_tracking);
+                       transport_stop(curr_direction != direction ? 1 : 0);
                        do_resume = 1;
 // fall through
                case STOP:
@@ -500,18 +508,25 @@ void PlaybackEngine::send_command(int command, EDL *edl, int wait_tracking, int
 
 int PlaybackEngine::transport_stop(int wait_tracking)
 {
-       input_lock->lock("PlaybackEngine::transport_stop 1");
-       curr_command->copy_from(stop_command);
-       interrupt_playback(wait_tracking);
-//printf("send: %d (STOP)\n", STOP);
-       input_lock->unlock();
+       interrupt_playback(0);
+       input_lock->lock("PlaybackEngine::transport_stop");
+       sent_lock->lock("PlaybackEngine::transport_stop");
+       sent_command->copy_from(stop_command);
+       sent_command->locked = wait_tracking ? 1 : 0;
+               if( !sent_command->locked )
+               input_lock->unlock();
+       sent_lock->unlock();
        output_lock->unlock();
+       if( wait_tracking ) {
+               tracking_done->lock("PlaybackEngine::transport_stop");
+               tracking_done->unlock();
+       }
+//printf("send: %d (STOP) 0\n", STOP);
        return 0;
 }
 
 int PlaybackEngine::transport_command(int command, int change_type, EDL *new_edl, int use_inout)
 {
-       input_lock->lock("PlaybackEngine::transport_command 1");
        next_command->command = command;
        next_command->change_type |= change_type;
        if( new_edl ) {
@@ -530,15 +545,24 @@ int PlaybackEngine::transport_command(int command, int change_type, EDL *new_edl
                next_command->set_playback_range(new_edl, use_inout,
                                preferences->forward_render_displacement);
        }
-       curr_command->copy_from(next_command);
+
+       input_lock->lock("PlaybackEngine::transport_command");
+       next_command->locked =
+               next_command->change_type == CHANGE_NONE ||
+               next_command->change_type == CHANGE_PARAMS ? 0 : 1;
+       sent_lock->lock("PlaybackEngine::transport_command");
+       sent_command->copy_from(next_command);
+       if( !sent_command->locked )
+               input_lock->unlock();
        next_command->reset();
+       sent_lock->unlock();
+       output_lock->unlock();
 //static const char *types[] = { "NONE",
 // "FRAME_FWD", "NORMAL_FWD", "FAST_FWD", "FRAME_REV", "NORMAL_REV", "FAST_REV",
 // "STOP",  "PAUSE", "SLOW_FWD", "SLOW_REV", "REWIND", "GOTO_END", "CURRENT_FRAME",
 // "LAST_FRAME" };
-//printf("send= %d (%s)\n", command, types[command]);
-       input_lock->unlock();
-       output_lock->unlock();
+//printf("send= %d (%s) %d\n", sent_command->command,
+// types[sent_command->command], sent_command->locked);
        return 0;
 }
 
index 73ef329cd9064301b8646e884579c3924be8eae3..85fc00ad9aeae06b3e498dfd3a91193a559c3b87 100644 (file)
@@ -115,10 +115,11 @@ public:
                        EDL *new_edl=0, int use_inout=0);
 
        Condition *input_lock, *output_lock;
-// active command
-       TransportCommand *command;
-// stop, next, queued commands
-       TransportCommand *stop_command, *next_command, *curr_command;
+       Mutex *sent_lock;
+// active command, stop command
+       TransportCommand *command, *stop_command;
+// next command under construction, last sent command
+       TransportCommand *next_command, *sent_command;
 
 // Render engine
        RenderEngine *render_engine;
index b3049c5dcd01ddb660e60510e414e3a3fae317e4..22adeaf01180c29609e9d3280870313bc84ad403 100644 (file)
@@ -52,7 +52,28 @@ KeySymMapping KeySymMapping::key_sym_mapping[] = {
        { NULL, 0 }
 };
 
-KeySym KeySymMapping::to_keysym(const char *str)
+int KeySymMapping::get_mask(const char *&str)
+{
+       int mask = 0;
+       while( *str ) {
+               if( !strncmp("Shift-",str,6) ) {
+                       mask |= ShiftMask;
+                       str += 6;  continue;
+               }
+               if( !strncmp("Ctrl-",str,5) ) {
+                       mask |= ControlMask;
+                       str += 5;  continue;
+               }
+               else if( !strncmp("Alt-",str,4) ) {
+                       mask |= Mod1Mask;
+                       str += 4;  continue;
+               }
+               break;
+       }
+       return mask;
+}
+
+SKeySym KeySymMapping::to_keysym(const char *str)
 {
        if( !strncmp("FWD_",str, 4) ) {
                float speed = atof(str+4) / SHUTTLE_MAX_SPEED;
@@ -70,15 +91,26 @@ KeySym KeySymMapping::to_keysym(const char *str)
                if( key_code < SKEY_MIN ) key_code = SKEY_MIN;
                return key_code;
        }
+       int mask = get_mask(str);
        for( KeySymMapping *ksp = &key_sym_mapping[0]; ksp->str; ++ksp )
-               if( !strcmp(str, ksp->str) ) return ksp->sym;
+               if( !strcmp(str, ksp->str) )
+                       return SKeySym(ksp->sym, mask);
        return 0;
 }
 
-const char *KeySymMapping::to_string(KeySym ks)
+const char *KeySymMapping::to_string(SKeySym ks)
 {
-       for( KeySymMapping *ksp = &key_sym_mapping[0]; ksp->sym; ++ksp )
-               if( ksp->sym == ks ) return ksp->str;
+       for( KeySymMapping *ksp = &key_sym_mapping[0]; ksp->sym.key; ++ksp ) {
+               if( ksp->sym.key == ks.key ) {
+                       static char string[BCSTRLEN];
+                       char *sp = string, *ep = sp+sizeof(string);
+                       if( ks.msk & Mod1Mask ) sp += snprintf(sp, ep-sp, "Alt-");
+                       if( ks.msk & ControlMask ) sp += snprintf(sp, ep-sp, "Ctrl-");
+                       if( ks.msk & ShiftMask ) sp += snprintf(sp, ep-sp, "Shift-");
+                       snprintf(sp, ep-sp, "%s", ksp->str);
+                       return string;
+               }
+       }
        if( ks >= SKEY_MIN && ks <= SKEY_MAX ) {
                double speed = SHUTTLE_MAX_SPEED *
                        (ks-(SKEY_MAX+SKEY_MIN)/2.) / ((SKEY_MAX-SKEY_MIN)/2.);
@@ -157,14 +189,14 @@ void Translation::clear()
        for( int i=0; i<NUM_JOGS; ++i ) jog[i].clear();
 }
 
-void Translation::append_stroke(KeySym sym, int press)
+void Translation::append_stroke(SKeySym sym, int press)
 {
        Stroke *s = pressed_strokes->append();
        s->keysym = sym;
        s->press = press;
 }
 
-void Translation::add_keysym(KeySym sym, int press_release)
+void Translation::add_keysym(SKeySym sym, int press_release)
 {
 //printf("add_keysym(0x%x, %d)\n", (int)sym, press_release);
        switch( press_release ) {
@@ -199,9 +231,8 @@ void Translation::add_release(int all_keys)
 {
 //printf("add_release(%d)\n", all_keys);
        modifiers.release(all_keys);
-       if( !all_keys ) {
+       if( !all_keys )
                pressed_strokes = released_strokes;
-       }
        if( keysym_down ) {
                append_stroke(keysym_down, 0);
                keysym_down = 0;
@@ -211,7 +242,7 @@ void Translation::add_release(int all_keys)
 
 void Translation::add_keystroke(const char *keySymName, int press_release)
 {
-       KeySym sym;
+       SKeySym sym;
 
        if( is_key && !strncmp(keySymName, "RELEASE", 8) ) {
                add_release(0);
@@ -225,13 +256,18 @@ void Translation::add_keystroke(const char *keySymName, int press_release)
                fprintf(stderr, "unrecognized KeySym: %s\n", keySymName);
 }
 
-void Translation::add_string(const char *str)
+void Translation::add_string(char *&str)
 {
-       while( str && *str ) {
-               if( *str >= ' ' && *str <= '~' )
-                       add_keysym((KeySym)(*str), PRESS_RELEASE);
-               ++str;
+       int delim = *str++;
+       if( !delim ) return;
+       while( str && *str && *str!=delim ) {
+               if( *str < ' ' || *str > '~' ) continue;
+               int mask = KeySymMapping::get_mask((const char *&)str);
+               if( str[0] == '\\' && str[1] ) ++str;
+               add_keysym(SKeySym(*str++, mask), PRESS_RELEASE);
+               mask = 0;
        }
+       if( *str == delim ) ++str;
 }
 
 int Translation::start_line(const char *key)
@@ -306,11 +342,11 @@ void Translation::finish_line()
 void Translation::print_line(const char *key)
 {
        if( is_key ) {
-               print_strokes(key, "D", pressed_strokes);
-               print_strokes(key, "U", released_strokes);
+               print_strokes(key, "D", pressed);
+               print_strokes(key, "U", released);
        }
        else {
-               print_strokes(key, "", pressed_strokes);
+               print_strokes(key, "", pressed);
        }
        printf("\n");
 }
@@ -321,7 +357,7 @@ void Translation::print_line(const char *key)
 // PRESS_RELEASE -> released, but to be re-pressed if necessary
 // RELEASE -> up
 
-void Modifiers::mark_as_down(KeySym sym, int hold)
+void Modifiers::mark_as_down(SKeySym sym, int hold)
 {
        Modifiers &modifiers = *this;
        for( int i=0; i<size(); ++i ) {
@@ -336,7 +372,7 @@ void Modifiers::mark_as_down(KeySym sym, int hold)
        s.press = hold ? HOLD : PRESS;
 }
 
-void Modifiers::mark_as_up(KeySym sym)
+void Modifiers::mark_as_up(SKeySym sym)
 {
        Modifiers &modifiers = *this;
        for( int i=0; i<size(); ++i ) {
@@ -378,7 +414,7 @@ void Modifiers::re_press()
 
 
 Shuttle::Shuttle(MWindow *mwindow)
- : Thread(0, 0, 0)
+ : Thread(1, 0, 0)
 {
        this->mwindow = mwindow;
 
@@ -390,15 +426,26 @@ Shuttle::Shuttle(MWindow *mwindow)
        wx = wy = 0;
        jogvalue = 0xffff;
        shuttlevalue = 0xffff;
-       dev_name = 0;
+       dev_index = -1;
 
        done = -1;
        failed = 0;
        first_time = 1;
        tr = 0;
+       debug = 0;
+       usb_direct = 0;
+
        last_translation = 0;
        last_focused = 0;
 
+#ifdef HAVE_SHUTTLE_USB
+       devsh = 0;
+       claimed = -1;
+       last_jog = 0;
+       last_shuttle = 0;
+       last_btns = 0;
+#endif
+
        default_translation = new Translation(this);
        config_path = 0;
        config_mtime = 0;
@@ -434,15 +481,15 @@ int Shuttle::send_button(unsigned int button, int press)
        wdw->top_level->put_event((XEvent *) b);
        return 0;
 }
-int Shuttle::send_keycode(unsigned int keycode, int press, int send)
+int Shuttle::send_keycode(unsigned key, unsigned msk, int press, int send)
 {
        if( debug ) {
                const char *cp = !send ? 0 :
-                       KeySymMapping::to_string(keycode);
+                       KeySymMapping::to_string(SKeySym(key, msk));
                if( cp )
                        printf("key: %s %d\n", cp, press);
                else
-                       printf("key: %04x %d\n", keycode, press);
+                       printf("key: %04x/%04x %d\n", key, msk, press);
        }
        XKeyEvent *k = new XKeyEvent();
        memset(k, 0, sizeof(*k));
@@ -457,17 +504,17 @@ int Shuttle::send_keycode(unsigned int keycode, int press, int send)
        k->x = wx;
        k->y = wy;
        k->state = msk;
-       k->keycode = keycode;
+       k->keycode = key;
        k->same_screen = 1;
        wdw->top_level->put_event((XEvent *) k);
        return 0;
 }
 
-int Shuttle::send_keysym(KeySym keysym, int press)
+int Shuttle::send_keysym(SKeySym keysym, int press)
 {
        return keysym >= XK_Button_1 && keysym <= XK_Scroll_Down ?
                send_button((unsigned int)keysym - XK_Button_0, press) :
-               send_keycode((unsigned int)keysym, press, 1);
+               send_keycode(keysym.key, keysym.msk, press, 1);
 //     unsigned int keycode = XKeysymToKeycode(wdw->top_level->display, keysym);
 //     return send_keycode(keycode, press, 0);
 }
@@ -562,22 +609,66 @@ void Shuttle::jogshuttle(unsigned short code, unsigned int value)
        }
 }
 
-const char *Shuttle::probe()
+static const struct shuttle_dev {
+       const char *path;
+       unsigned vendor, product;
+} shuttle_devs[] = {
+       { "/dev/input/by-id/usb-Contour_Design_ShuttleXpress-event-if00",
+               0x0b33, 0x0020 },
+       { "/dev/input/by-id/usb-Contour_Design_ShuttlePRO_v2-event-if00",
+               0x0b33, 0x0030 },
+       { "/dev/input/by-id/usb-Contour_Design_ShuttlePro-event-if00",
+               0x0b33, 0x0030 },
+};
+
+#ifdef HAVE_SHUTTLE_USB
+void Shuttle::usb_probe(int idx)
+{
+       int ret = libusb_init(0);
+       if( ret < 0 ) return;
+       claimed = 0;
+       const struct shuttle_dev *s = &shuttle_devs[idx];
+       devsh = libusb_open_device_with_vid_pid(0, s->vendor, s->product);
+       if( devsh ) {
+               int sh_iface = SHUTTLE_INTERFACE;
+               libusb_detach_kernel_driver(devsh, sh_iface);
+               ret = libusb_claim_interface(devsh, sh_iface);
+               if( ret >= 0 ) claimed = 1;
+       }
+       if( !claimed )
+               usb_done();
+}
+
+void Shuttle::usb_done()
+{
+       if( devsh ) {
+               if( claimed > 0 ) {
+                       int sh_iface = SHUTTLE_INTERFACE;
+                       libusb_release_interface(devsh, sh_iface);
+                       libusb_attach_kernel_driver(devsh, sh_iface);
+                       claimed = 0;
+               }
+               libusb_close(devsh);
+               devsh = 0;
+       }
+       if( claimed >= 0 ) {
+               libusb_exit(0);
+               claimed = -1;
+       }
+}
+#endif
+
+int Shuttle::probe()
 {
        struct stat st;
-       static const char *shuttle_devs[] = {
-               "/dev/input/by-id/usb-Contour_Design_ShuttleXpress-event-if00",
-               "/dev/input/by-id/usb-Contour_Design_ShuttlePRO_v2-event-if00",
-               "/dev/input/by-id/usb-Contour_Design_ShuttlePro-event-if00",
-       };
        int ret = sizeof(shuttle_devs) / sizeof(shuttle_devs[0]);
-       while( --ret >= 0 && stat(shuttle_devs[ret] , &st) );
-       return ret >= 0 ? shuttle_devs[ret] : 0;
+       while( --ret >= 0 && stat(shuttle_devs[ret].path , &st) );
+       return ret;
 }
 
-void Shuttle::start(const char *dev_name)
+void Shuttle::start(int idx)
 {
-       this->dev_name = dev_name;
+       this->dev_index = idx;
        first_time = 1;
        done = 0;
        Thread::start();
@@ -708,19 +799,23 @@ int Shuttle::get_focused_window_translation()
        return 0;
 }
 
-void Shuttle::handle_event()
+int Shuttle::load_translation()
 {
-       if( read_config_file() > 0 ) {
-               done = 1;
-               return;
-       }
+       if( read_config_file() > 0 )
+               return done = 1;
        if( get_focused_window_translation() < 0 )
-               return;
+               return 0;
        if( last_translation != tr ) {
                last_translation = tr;
                if( debug )
                        printf("new translation: %s\n", tr->name);
        }
+       return 0;
+}
+
+void Shuttle::handle_event()
+{
+       if( load_translation() ) return;
 //     if( debug )
 //             printf("event: (%d, %d, 0x%x)\n", ev.type, ev.code, ev.value);
        switch( ev.type ) {
@@ -741,7 +836,55 @@ void Shuttle::handle_event()
 
 void Shuttle::run()
 {
-       for( enable_cancel(); !done; sleep(1) ) {
+       if( dev_index < 0 ) return;
+       const char *dev_name = shuttle_devs[dev_index].path;
+
+#ifdef HAVE_SHUTTLE_USB
+       if( usb_direct )
+               usb_probe(dev_index);
+
+       disable_cancel();
+       while( devsh && !done ) {
+               int len = 0;
+               static const int IN_ENDPOINT = 0x81;
+               unsigned char dat[BCSTRLEN];
+               int ret = libusb_interrupt_transfer(devsh,
+                               IN_ENDPOINT, dat, sizeof(dat), &len, 100);
+               if( ret != 0 ) {
+                       if( ret == LIBUSB_ERROR_TIMEOUT ) continue;
+                       printf("shuttle: %s\n  %s\n",
+                               dev_name, libusb_strerror((libusb_error)ret));
+                       sleep(1);  continue;
+               }
+               if( load_translation() ) break;
+               if( debug ) {
+                       printf("shuttle: ");
+                       for( int i=0; i<len; ++i ) printf(" %02x", dat[i]);
+                       printf("\n");
+               }
+               if( last_shuttle != dat[0] )
+                       shuttle((char)(last_shuttle = dat[0]));
+
+               if( last_jog != dat[1] )
+                       jog(last_jog = dat[1]);
+
+               unsigned btns = (dat[4]<<8) | dat[3];
+               unsigned dif = last_btns ^ btns;
+               if( dif ) {
+                       last_btns = btns;
+                       for( int i=0; i<15; ++i ) {
+                               unsigned msk = 1 << i;
+                               if( !(dif & msk) ) continue;
+                               key(i+EVENT_CODE_KEY1, btns & msk ? 1 : 0);
+                       }
+               }
+       }
+       usb_done();
+#endif
+       usb_direct = 0;
+       enable_cancel();
+
+       for( ; !done; sleep(1) ) {
                fd = open(dev_name, O_RDONLY);
                if( fd < 0 ) {
                        perror(dev_name);
@@ -800,6 +943,7 @@ int Shuttle::read_config_file()
        config_mtime = st.st_mtime;
        translations.clear();
        debug = 0;
+       usb_direct = 0;
 #define ws(ch) (ch==' ' || ch=='\t')
        char line[BCTEXTLEN], *cp;
        Translation *trans = 0;
@@ -871,6 +1015,9 @@ int Shuttle::read_config_file()
                        if( !strcmp(tok, "DEBUG") ) {
                                debug = 1;  goto skip;
                        }
+                       if( !strcmp(tok, "USB_DIRECT") ) {
+                               usb_direct = 1;  goto skip;
+                       }
                        key = tok;
                        if( !trans ) {
                                fprintf(stderr, "no translation section defining key: %s\n", key);
@@ -882,13 +1029,21 @@ int Shuttle::read_config_file()
                                while( ws(*cp) ) ++cp;
                                if( !*cp || *cp == '#' || *cp == '\n' ) break;
                                if( *cp == '"' ) {
-                                       tok = ++cp;
-                                       while( *cp && *cp != '"' && *cp != '\n' ) {
-                                               if( *cp != '\\' ) { ++cp;  continue; }
-                                               for( char *bp=cp; *bp; ++bp ) bp[0] = bp[1];
+                                       while( *cp ) {
+                                               if( *cp == '"' )
+                                                       trans->add_string(cp);
+                                               while( ws(*cp) ) ++cp;
+                                               if( !*cp || *cp == '#' || *cp == '\n' ) break;
+                                               tok = cp;
+                                               while( *cp && !ws(*cp) && *cp != '\n' ) ++cp;
+                                               *cp = 0;
+                                               SKeySym sym = KeySymMapping::to_keysym(tok);
+                                               if( !sym ) {
+                                                       fprintf(stderr, "unknown keysym: %s\n", tok);
+                                                       ret = 1;  break;
+                                               }
+                                               trans->add_keysym(sym, PRESS_RELEASE);
                                        }
-                                       *cp++ = 0;
-                                       trans->add_string(tok);
                                        continue;
                                }
                                tok = cp;
index 0f07e8eaf9fc9f93566fee5dcfa37dc29431fd1c..46283dfc82b9f1a1ec2065d3335f2ea69dea88ac 100644 (file)
 #include <linux/input.h>
 #include <sys/types.h>
 
+#ifdef HAVE_SHUTTLE_USB
+#include <libusb-1.0/libusb.h>
+#endif
+
 // Copyright 2013 Eric Messick (FixedImagePhoto.com/Contact)
 // reworked 2019 for cinelerra-gg by William Morrow (aka goodguy)
 
@@ -18,6 +22,7 @@
 #define DELAY CurrentTime
 // playback max speed -64x .. 64x
 #define SHUTTLE_MAX_SPEED 64.
+#define SHUTTLE_INTERFACE 0
 
 // protocol for events from the shuttlepro HUD device
 //
@@ -78,19 +83,34 @@ enum { JL=0,JR };
 #define FOCUS_VIEWER  4
 #define FOCUS_LOAD    5
 
+class SKeySym {
+public:
+       union {
+               struct { uint32_t key, msk; };
+               uint64_t v;
+       };
+       SKeySym() { v = 0; }
+       SKeySym(int k) { key = k;  msk = 0; }
+       SKeySym(unsigned k, unsigned m) { key = k;  msk = m; }
+       bool operator ==(SKeySym &ks) { return ks.v == v; }
+       operator int() { return key; }
+};
+
 class KeySymMapping {
 public:
-       static KeySym to_keysym(const char *str);
-       static const char *to_string(KeySym ks);
+       static int get_mask(const char *&str);
+       static SKeySym to_keysym(const char *str);
+       static const char *to_string(SKeySym ks);
        static KeySymMapping key_sym_mapping[];
+
        const char *str;
-       KeySym sym;
+       SKeySym sym;
 };
 
 class Stroke : public ListItem<Stroke>
 {
 public:
-       KeySym keysym;
+       SKeySym keysym;
        int press; // 1:press, 0:release
 };
 
@@ -100,7 +120,7 @@ public:
        Strokes() {}
        ~Strokes() {}
        void clear() { while( last ) delete last; }
-       void add_stroke(KeySym keysym, int press=1) {
+       void add_stroke(SKeySym keysym, int press=1) {
                Stroke *s = append();
                s->keysym = keysym; s->press = press;
        }
@@ -113,8 +133,8 @@ public:
        Modifiers(Translation *trans) { this->trans = trans; }
        ~Modifiers() {}
 
-       void mark_as_down(KeySym sym, int hold);
-       void mark_as_up(KeySym sym);
+       void mark_as_down(SKeySym sym, int hold);
+       void mark_as_up(SKeySym sym);
        void release(int allkeys);
        void re_press();
 };
@@ -144,11 +164,11 @@ public:
        ~Translation();
        void init(int def);
        void clear();
-       void append_stroke(KeySym sym, int press);
+       void append_stroke(SKeySym sym, int press);
        void add_release(int all_keys);
        void add_keystroke(const char *keySymName, int press_release);
-       void add_keysym(KeySym sym, int press_release);
-       void add_string(const char *str);
+       void add_keysym(SKeySym sym, int press_release);
+       void add_string(char *&str);
        int start_line(const char *key);
        void print_strokes(const char *name, const char *up_dn, Strokes *strokes);
        void print_stroke(Stroke *s);
@@ -162,7 +182,7 @@ public:
        int first_release_stroke;
        Strokes *pressed, *released;
        Strokes *pressed_strokes, *released_strokes;
-       KeySym keysym_down;
+       SKeySym keysym_down;
 
        Strokes key_down[NUM_KEYS];
        Strokes key_up[NUM_KEYS];
@@ -183,7 +203,15 @@ class Shuttle : public Thread
 {
        int fd;
        unsigned short jogvalue, shuttlevalue;
-       const char *dev_name;
+       int dev_index;
+#ifdef HAVE_SHUTTLE_USB
+       struct libusb_device_handle *devsh;
+       void usb_probe(int idx);
+       void usb_done();
+       unsigned last_jog, last_shuttle, last_btns;
+       int claimed;
+#endif
+
        Translation *default_translation;
        Translations translations;
 public:
@@ -191,18 +219,19 @@ public:
        ~Shuttle();
 
        int send_button(unsigned int button, int press);
-       int send_keycode(unsigned int keycode, int press, int send);
-       int send_keysym(KeySym keysym, int press);
+       int send_keycode(unsigned key, unsigned msk, int press, int send);
+       int send_keysym(SKeySym keysym, int press);
        void send_stroke_sequence(int kjs, int index);
        void key(unsigned short code, unsigned int value);
        void shuttle(int value);
        void jog(unsigned int value);
        void jogshuttle(unsigned short code, unsigned int value);
-       void start(const char *dev_name);
+       void start(int idx);
        void stop();
        void handle_event();
+       int load_translation();
        int get_focused_window_translation();
-       static const char *probe();
+       static int probe();
        void run();
        int read_config_file();
        static BC_WindowBase *owns(BC_WindowBase *wdw, Window win);
@@ -211,6 +240,7 @@ public:
        int failed;
        int first_time;
        int debug;
+       int usb_direct;
 
        MWindow *mwindow;
        Translation *tr, *last_translation;
index 318b400bb892c2f0d42c60bdacd64a6c687ae625..5021f462d06e535633d8b08cd828464e8f901998 100644 (file)
@@ -47,19 +47,19 @@ TransportCommand::~TransportCommand()
 
 void TransportCommand::reset()
 {
+       command = COMMAND_NONE;
+       change_type = 0;
        playbackstart = 0;
        start_position = 0;
        end_position = 0;
        infinite = 0;
        realtime = 0;
        resume = 0;
+       locked = 0;
        toggle_audio = 0;
        loop_play = 0;
        displacement = 0;
        speed = 0;
-// Don't reset the change type for commands which don't perform the change
-       if(command != STOP) change_type = 0;
-       command = COMMAND_NONE;
 }
 
 EDL* TransportCommand::get_edl()
@@ -90,6 +90,7 @@ void TransportCommand::copy_from(TransportCommand *command)
        this->playbackstart = command->playbackstart;
        this->realtime = command->realtime;
        this->resume = command->resume;
+       this->locked = command->locked;
        this->toggle_audio = command->toggle_audio;
        this->loop_play = command->loop_play;
        this->displacement = command->displacement;
index 351cf6825ea7bddd2844db901d8227fe7e93b512..fd5a5cc4732e181591500ad7e0ecc1fc8d090901 100644 (file)
@@ -55,7 +55,6 @@ public:
        void delete_edl();
        void new_edl();
 
-       PlaybackEngine *engine;
        int command;
        int change_type;
 // playback range
@@ -67,6 +66,8 @@ public:
        int displacement;
 // Send output to device
        int realtime;
+// command must execute
+       int locked;
 // Use persistant starting point
        int resume;
 // reverse audio duty
index ea8720dbf2f777eea591644eba51bd3a1c13d4ae..362777ff534d8f6117efa5b8f07d21f4071e2b9d 100644 (file)
@@ -77,10 +77,6 @@ int VDeviceX11::reset_parameters()
        capture_bitmap = 0;
        color_model_selected = 0;
        is_cleared = 0;
-
-       for( int i = 0; i < SCREENCAP_BORDERS; i++ ) {
-               screencap_border[i] = 0;
-       }
        return 0;
 }
 
@@ -91,33 +87,9 @@ int VDeviceX11::open_input()
                device->in_config->h,
                device->in_config->screencapture_display);
 //printf("VDeviceX11::open_input 2\n");
-
-// create overlay
-       device->mwindow->gui->lock_window("VDeviceX11::close_all");
-
-       screencap_border[0] = new BC_Popup(device->mwindow->gui,
-                       device->input_x - SCREENCAP_PIXELS, device->input_y - SCREENCAP_PIXELS,
-                       device->in_config->w + SCREENCAP_PIXELS * 2, SCREENCAP_PIXELS,
-                       SCREENCAP_COLOR, 1);
-       screencap_border[1] = new BC_Popup(device->mwindow->gui,
-                       device->input_x - SCREENCAP_PIXELS, device->input_y,
-                       SCREENCAP_PIXELS, device->in_config->h,
-                       SCREENCAP_COLOR, 1);
-       screencap_border[2] = new BC_Popup(device->mwindow->gui,
-                       device->input_x - SCREENCAP_PIXELS, device->input_y + device->in_config->h,
-                       device->in_config->w + SCREENCAP_PIXELS * 2, SCREENCAP_PIXELS,
-                       SCREENCAP_COLOR, 1);
-       screencap_border[3] = new BC_Popup(device->mwindow->gui,
-                       device->input_x + device->in_config->w, device->input_y,
-                       SCREENCAP_PIXELS, device->in_config->h,
-                       SCREENCAP_COLOR, 1);
-usleep(500000);        // avoids a bug in gnome-shell 2017/10/19
-
-       for( int i=0; i<SCREENCAP_BORDERS; ++i )
-               screencap_border[i]->show_window(0);
-
-       device->mwindow->gui->flush();
-       device->mwindow->gui->unlock_window();
+       capture_bitmap->bars_on(SCREENCAP_PIXELS, SCREENCAP_COLOR,
+               device->input_x, device->input_y,
+               device->in_config->w, device->in_config->h);
 
        return 0;
 }
@@ -186,15 +158,6 @@ int VDeviceX11::close_all()
                output->unlock_canvas();
        }
 
-       if( device->mwindow ) {
-               device->mwindow->gui->lock_window("VDeviceX11::close_all");
-               for( int i=0; i<SCREENCAP_BORDERS; ++i ) {
-                       delete screencap_border[i];
-                       screencap_border[i] = 0;
-               }
-               device->mwindow->gui->unlock_window();
-       }
-
        reset_parameters();
 
        return 0;
@@ -202,20 +165,9 @@ int VDeviceX11::close_all()
 
 int VDeviceX11::read_buffer(VFrame *frame)
 {
-//printf("VDeviceX11::read_buffer %d colormodel=%d\n", __LINE__, frame->get_color_model());
-       device->mwindow->gui->lock_window("VDeviceX11::close_all");
-
-       screencap_border[0]->reposition_window(device->input_x - SCREENCAP_PIXELS,
-                       device->input_y - SCREENCAP_PIXELS);
-       screencap_border[1]->reposition_window(device->input_x - SCREENCAP_PIXELS,
-                       device->input_y);
-       screencap_border[2]->reposition_window(device->input_x - SCREENCAP_PIXELS,
-                       device->input_y + device->in_config->h);
-       screencap_border[3]->reposition_window(device->input_x + device->in_config->w,
-                       device->input_y);
-       device->mwindow->gui->flush();
-       device->mwindow->gui->unlock_window();
-
+       capture_bitmap->bars_reposition(
+               device->input_x, device->input_y,
+               device->in_config->w, device->in_config->h);
 
        capture_bitmap->capture_frame(frame,
                device->input_x, device->input_y, device->do_cursor);
index afc21edb27db2aac2f53b9f5431a0e88ef3ead0d..223c474b4f9170cf7881dd981cc9a4de64f9921d 100644 (file)
@@ -133,10 +133,8 @@ private:
        int get_display_colormodel(int file_colormodel);
 
 // windows which overlay the screencap area
-#define SCREENCAP_BORDERS 4
 #define SCREENCAP_PIXELS 5
 #define SCREENCAP_COLOR GREEN
-       BC_Popup *screencap_border[SCREENCAP_BORDERS];
 
 // Bitmap to be written to device
        BC_Bitmap *bitmap;
index 6508b9e457673f05853e4bc9258d15cfdc8db445..a6f6d73f8119c29120291817e891178de5ac86cc 100644 (file)
@@ -218,12 +218,12 @@ void ZWindow::handle_close_event(int result)
 
 void ZWindow::change_source(EDL *edl)
 {
-       if( this->edl && edl != this->edl )
+       if( this->edl == edl ) return;
+       if( !edl || !this->edl || this->edl->equivalent_output(edl) >= 0 )
+               zgui->playback_engine->refresh_frame(CHANGE_ALL, edl);
+       if( this->edl )
                this->edl->remove_user();
        this->edl = edl;
-       if( edl != 0 ) {
-               zgui->playback_engine->refresh_frame(CHANGE_ALL, edl);
-       }
 }
 
 void ZWindow::stop_playback(int wait)
index c2211b32012f9d35eafd8e86d1d5e5b21d3d869b..0a6cd86b70efe0f95720ed8304bf5dd1fb17cb40 100644 (file)
@@ -54,6 +54,7 @@ CHECK_WITH([libzmpeg],[build libzmpeg],[LIBZMPEG],[yes])
 CHECK_WITH([commercial],[enable commercial capture],[COMMERCIAL],[yes])
 CHECK_WITH([thirdparty],[use thirdparty build],[CIN_3RDPARTY],[yes])
 CHECK_WITH([shuttle],[shuttle device],[SHUTTLE],[yes])
+CHECK_WITH([shuttle-usb],[use libusb for shuttle],[SHUTTLE_USB],[no])
 
 if test "x$WANT_LV2" != "xno"; then
   GTK2_LIBS=`pkg-config --libs gtk+-2.0`
@@ -823,7 +824,7 @@ if test "x$WANT_CIN_3RDPARTY" != "xno"; then
 fi
 for v in GL XFT XXF86VM OSS ALSA FIREWIRE DV DVB \
         VIDEO4LINUX2 ESOUND PACTL OPENEXR LV2 \
-        COMMERCIAL LIBZMPEG SHUTTLE; do
+        COMMERCIAL LIBZMPEG SHUTTLE SHUTTLE_USB; do
   eval vv="\$WANT_$v"
   if test "x$vv" != "xno"; then
     CFG_CFLAGS+=" -DHAVE_$v"
@@ -850,6 +851,7 @@ echo "  using: with-booby = $WANT_BOOBY"
 echo "  using: with-libzmpeg = $WANT_LIBZMPEG"
 echo "  using: with-commerical = $WANT_COMMERCIAL"
 echo "  using: with-shuttle = $WANT_SHUTTLE"
+echo "  using: with-shuttle-usb = $WANT_SHUTTLE_USB"
 echo ""
 echo "  using: thirdparty build = $WANT_CIN_3RDPARTY"
 echo "  using: single-user  = $WANT_CINBIN_BUILD"
@@ -873,6 +875,9 @@ fi
 if test "x$WANT_BOOBY" != "xno"; then
   CFG_CFLAGS+=" -DBOOBY"
 fi
+if test "x$WANT_SHUTTLE_USB" != "xno"; then
+  EXTRA_LIBS+=' -lusb-1.0'
+fi
 
 # intel lock elision bugs
 if test "x$WANT_NOELISION" != "xno"; then
index 90584f4b32adb7eaa87900ed3b7fb45924f2aa02..7362fbe31a04ff9292bd5e631e4fe40f0c4cb926 100644 (file)
@@ -6,3 +6,5 @@
 ATTRS{name}=="Contour Design ShuttlePRO v2" MODE="0644"
 ATTRS{name}=="Contour Design ShuttleXpress" MODE="0644"
 ATTRS{name}=="Contour Design ShuttlePro" MODE="0644"
+SUBSYSTEMS=="usb", ATTRS{idVendor}=="0b33", ATTRS{idProduct}=="0020", MODE="0666"
+SUBSYSTEMS=="usb", ATTRS{idVendor}=="0b33", ATTRS{idProduct}=="0030", MODE="0666"
index e955a52730b03ed51f80c60dd21c5baa722cb1fc..d8a555906a7bd505ea9249c70774c8a844860ca4 100644 (file)
@@ -44,26 +44,29 @@ BC_Capture::BC_Capture(int w, int h, const char *display_path)
 
        data = 0;
        use_shm = 1;
+       for( int i=0; i<4; ++i ) border[i] = 0;
+       bar_w = 0;  bar_color = 0;
        init_window(display_path);
        allocate_data();
 }
 
-
 BC_Capture::~BC_Capture()
 {
+       bars_off();
        delete_data();
        XCloseDisplay(display);
 }
 
+
 int BC_Capture::init_window(const char *display_path)
 {
        int bits_per_pixel;
        if( display_path && display_path[0] == 0 ) display_path = NULL;
        if( (display = XOpenDisplay(display_path)) == NULL ) {
-               printf(_("cannot connect to X server.\n"));
-               if( getenv("DISPLAY") == NULL )
-               printf(_("'DISPLAY' environment variable not set.\n"));
-               exit(-1);
+               printf(_("cannot connect to X server.\n"));
+               if( getenv("DISPLAY") == NULL )
+               printf(_("'DISPLAY' environment variable not set.\n"));
+               exit(-1);
                return 1;
        }
 
@@ -75,35 +78,82 @@ int BC_Capture::init_window(const char *display_path)
        server_byte_order = (XImageByteOrder(display) == MSBFirst) ? 0 : 1;
        char *data = 0;
        XImage *ximage;
-       ximage = XCreateImage(display,
-                                       vis,
-                                       default_depth,
-                                       ZPixmap,
-                                       0,
-                                       data,
-                                       16,
-                                       16,
-                                       8,
-                                       0);
+       ximage = XCreateImage(display, vis, default_depth,
+                       ZPixmap, 0, data, 16, 16, 8, 0);
        bits_per_pixel = ximage->bits_per_pixel;
        XDestroyImage(ximage);
        bitmap_color_model = BC_WindowBase::evaluate_color_model(client_byte_order, server_byte_order, bits_per_pixel);
 
 // test shared memory
 // This doesn't ensure the X Server is on the local host
-    if( use_shm && !XShmQueryExtension(display) ) {
-        use_shm = 0;
-    }
+       if( use_shm && !XShmQueryExtension(display) )
+               use_shm = 0;
        return 0;
 }
 
+Window BC_Capture::bar(int x, int y, int w, int h, int color)
+{
+       unsigned long mask = CWEventMask | CWBackPixel |
+                       CWOverrideRedirect | CWSaveUnder;
+       XSetWindowAttributes attr;
+       memset(&attr, 0, sizeof(attr));
+       Screen *scr = XDefaultScreenOfDisplay(display);
+       Window root = RootWindowOfScreen(scr);
+       Visual *vis = DefaultVisualOfScreen(scr);
+       int depth = DefaultDepthOfScreen(scr);
+       attr.background_pixel = color;
+       attr.override_redirect = True;
+       attr.save_under = True;
+       Window win = XCreateWindow(display, root, x,y,w,h, 0,depth,
+                       InputOutput, vis, mask, &attr);
+       XMapWindow(display, win);
+       return win;
+}
+
+void BC_Capture::bars_on(int bw, int color, int x, int y, int w, int h)
+{
+       this->bar_w = bw;
+       this->bar_color = color;
+       border[0] = bar(x-bw, y-bw, w+2*bw, bw, color);
+       border[1] = bar(x-bw, y,    bw,     h,  color);
+       border[2] = bar(x-bw, y+h,  w+2*bw, bw, color);
+       border[3] = bar(x+w,  y,    bw,     h,  color);
+       XFlush(display);
+}
+
+void BC_Capture::bars_off()
+{
+       for( int i=0; i<4; ++i ) {
+               if( !border[i] ) continue;
+               XUnmapWindow(display, border[i]);
+       }
+       for( int i=0; i<4; ++i ) {
+               if( !border[i] ) continue;
+               XDestroyWindow(display, border[i]);
+               border[i] = 0;
+       }
+       XFlush(display);
+}
+
+void BC_Capture::bars_reposition(int x, int y, int w, int h)
+{
+       int bw = this->bar_w;
+       if( border[0] )
+               XMoveResizeWindow(display, border[0], x-bw, y-bw, w+2*bw, bw);
+       if( border[1] )
+               XMoveResizeWindow(display, border[1], x-bw, y,    bw,     h );
+       if( border[2] )
+               XMoveResizeWindow(display, border[2], x-bw, y+h,  w+2*bw, bw);
+       if( border[3] )
+               XMoveResizeWindow(display, border[3], x+w,  y,    bw,     h );
+}
 
 int BC_Capture::allocate_data()
 {
 // try shared memory
        if( !display ) return 1;
-    if( use_shm ) {
-           ximage = XShmCreateImage(display, vis, default_depth, ZPixmap, (char*)NULL, &shm_info, w, h);
+       if( use_shm ) {
+               ximage = XShmCreateImage(display, vis, default_depth, ZPixmap, (char*)NULL, &shm_info, w, h);
 
                shm_info.shmid = shmget(IPC_PRIVATE, h * ximage->bytes_per_line, IPC_CREAT | 0600);
                if( shm_info.shmid == -1 ) {
@@ -118,7 +168,7 @@ int BC_Capture::allocate_data()
 // Crashes here if remote server.
                BC_Resources::error = 0;
                XShmAttach(display, &shm_info);
-       XSync(display, False);
+               XSync(display, False);
                if( BC_Resources::error ) {
                        XDestroyImage(ximage);
                        shmdt(shm_info.shmaddr);
index 787fb4a6455fb94d429235b780580ff598604621..817eeb676ceeba1add1c55099ec8de5d0ac71999 100644 (file)
@@ -44,6 +44,13 @@ public:
        int get_w();
        int get_h();
 
+       Window border[4];
+       int bar_w, bar_color;
+       Window bar(int x, int y, int w, int h, int color);
+       void bars_on(int bw, int color, int x, int y, int w, int h);
+       void bars_off();
+       void bars_reposition(int x, int y, int w, int h);
+
        int w, h, default_depth;
        unsigned char **row_data;
 
index 25f456df059fb8070b98a547aaf195c335b230d2..6ad7e48d258dbeffe171f5193d8b7eaa8a78dc69 100644 (file)
@@ -934,7 +934,7 @@ void TitleWindow::check_style(const char *font_name, int update)
 
 TitleFont::TitleFont(TitleMain *client, TitleWindow *window, int x, int y)
  : BC_PopupTextBox(window, &window->fonts, client->config.font,
-               x, y, 300, 300, LISTBOX_ICON_LIST)
+               x, y, 340, 300, LISTBOX_ICON_LIST)
 {
        this->client = client;
        this->window = window;
index ecec4d0badd93e2e922e11af6d369024dddeefbf..1f5758f9d389d88668c709a65c24c8904c5392e5 100644 (file)
@@ -1,6 +1,8 @@
 
 # uncomment to enable diagnostics
 #DEBUG
+# uncommet to use direct usb
+#USB_DIRECT
 
 # redefine default, use
 # also used for resources,load windows
 
 [Cinelerra]
 
- K5 XK_KP_0     # Stop
- K9 XK_KP_3     # Play
+# Most useful functions have to be on K5-K9 because Xpress only has 5 keys
+ K5 XK_Home    # Beginning
+ K6 XK_KP_3    # Play, or if playing Stop
+ K7 XK_KP_0    # Stop
+ K8 XK_KP_6    # Reverse, or if playing Stop
+ K9 XK_End     # End
+
+# K10 "["      # Switch if K14 not working
+# K11 "]"      # Switch if K15 not working
+ K10 Alt-XK_Left
+ K11 Alt-XK_Right
  K12 XK_Home    # Beginning
  K13 XK_End     # End
  K14 "["        # Toggle in
  K15 "]"        # Toggle out
 
- K1 "i"                # Pro Only - Clip
- K2 "x"                # Pro Only - Cut
- K3 "c"                # Pro Only - Copy
- K4 "v"                # Pro Only - Paste
+ K1 "i"                # Clip
+ K2 "x"                # Cut
+ K3 "c"                # Copy
+ K4 "v"                # Paste
 
  S-7 REV_16    # Next 6 are reverse keys
  S-6 REV_8     #  the number on the end represents speed
  S5  FWD_4
  S6  FWD_8
  S7  FWD_16
+
  JL XK_KP_4     # Frame reverse
  JR XK_KP_1     # Frame forward
 
 [Composer]
 
- K5 XK_KP_0     # Stop
- K9 XK_KP_3     # Play
+# Most useful functions have to be on K5-K9 because Xpress only has 5 keys
+ K5 XK_Home    # Beginning
+ K6 XK_KP_3    # Play, or if playing Stop
+ K7 "f"                # Go in or out of Fullscreen mode
+ K8 XK_KP_6    # Reverse, of if playing Stop
+ K9 XK_End     # End
+
+ K10 "["       # Temporary until K14 Pro fixed
+ K11 "]"       # Temporary until K15 Pro fixed
  K12 XK_Home    # Beginning
  K13 XK_End     # End
  K14 "["        # Toggle in
  K15 "]"        # Toggle out
 
- K1 "i"                # Pro Only - Clip
- K2 "x"                # Pro Only - Cut
- K3 "c"                # Pro Only - Copy
- K4 "v"                # Pro Only - Paste
+ K1 "i"                # Clip
+ K2 "x"                # Cut
+ K3 "c"                # Copy
+ K4 "v"                # Paste
 
  S-7 REV_16
  S-6 REV_8
  S5  FWD_4
  S6  FWD_8
  S7  FWD_16
+
  JL XK_KP_4     # Frame reverse
  JR XK_KP_1     # Frame forward
 
 [Viewer]
 
- K5 "v"                # Splice (Viewer only - button is on Xpress)
- K9 "b"                # Overwrite (Viewer only - button is on Xpress)
+# Most useful functions have to be on K6-K9 because Xpress only has 5 keys
+ K5 XK_Home    # Beginning
+ K6 XK_KP_3    # Play, or if playing Stop
+ K7 "f"                # Go in or out of Fullscreen mode
+ K8 XK_KP_6    # Reverse, or if playing Stop
+ K9 XK_End     # End
+
+ K10 "["       # Temporary until K14 Pro fixed
+ K11 "]"       # Temporary until K15 Pro fixed
  K12 XK_Home    # Beginning
  K13 XK_End     # End
  K14 "["        # Toggle in
  K15 "]"        # Toggle out
 
- K1 "i"                # Pro Only - Clip
- K2 XK_Home    # Pro Only - Beginning 
- K3 "c"                # Pro Only - Copy
- K4 XK_End     # Pro Only - End
+ K1 "i"                # Clip
+ K2 "v"                # Splice
+ K3 "c"                # Copy
+ K4 "b"                # Overwrite
+
  S-7 REV_16
  S-6 REV_8
  S-5 REV_4