コード例 #1
0
def _handle_tline_key_event(event):
    """
    This is called when timeline widgets have focus and key is pressed.
    Returns True for handled key presses to stop those
    keyevents from going forward.
    """

    tool_was_selected = workflow.tline_tool_keyboard_selected(event)
    if tool_was_selected == True:
        return True
    
    action = _get_shortcut_action(event)
    prefs = editorpersistance.prefs

    if action == 'mark_in':
        monitorevent.mark_in_pressed()
        return True
    if action == 'to_mark_in':
        monitorevent.to_mark_in_pressed()
        return True
    if action == 'zoom_out':
        updater.zoom_out()
    if action == 'zoom_in':
        updater.zoom_in()
    if action == 'mark_out':
        monitorevent.mark_out_pressed()
        return True
    if action == 'to_mark_out':
        monitorevent.to_mark_out_pressed()
        return True
    if action == 'play_pause':
        if PLAYER().is_playing():
            monitorevent.stop_pressed()
        else:
            monitorevent.play_pressed()
        return True
    if action == 'switch_monitor':
        updater.switch_monitor_display()
        return True
    if action == 'add_marker':
        tlineaction.add_marker()
        return True    
    if action == 'cut':
        tlineaction.cut_pressed()
        return True
    if action == 'sequence_split':
        tlineaction.sequence_split_pressed()
        return True
    if action == 'log_range':
        medialog.log_range_clicked()
        return True
    """
    THis may need rethinking
    if action == 'toggle_ripple':
        gui.editor_window.toggle_trim_ripple_mode()
        return True
    """
    
    # Key bindings for keyboard trimming
    if editorstate.current_is_active_trim_mode() == True:
        if action == 'prev_frame':
            trimmodes.left_arrow_pressed((event.get_state() & Gdk.ModifierType.CONTROL_MASK))
            return True
        elif action == 'next_frame':
            trimmodes.right_arrow_pressed((event.get_state() & Gdk.ModifierType.CONTROL_MASK))
            return True
        elif action == 'enter_edit':
            trimmodes.enter_pressed()
            return True

    # Key bindings for MOVE MODES and _NO_EDIT modes
    if editorstate.current_is_move_mode() or editorstate.current_is_active_trim_mode() == False:
        if action == 'next_cut':
            if editorstate.timeline_visible():
                tline_frame = PLAYER().tracktor_producer.frame()
                frame = current_sequence().find_next_cut_frame(tline_frame)
                if frame != -1:
                    PLAYER().seek_frame(frame)
                    if editorpersistance.prefs.center_on_arrow_move == True:
                        updater.center_tline_to_current_frame()
                    return True
            else:
                monitorevent.up_arrow_seek_on_monitor_clip()
        if action == 'prev_cut':
            if editorstate.timeline_visible():
                tline_frame = PLAYER().tracktor_producer.frame()
                frame = current_sequence().find_prev_cut_frame(tline_frame)
                if frame != -1:
                    PLAYER().seek_frame(frame)
                    if editorpersistance.prefs.center_on_arrow_move == True:
                        updater.center_tline_to_current_frame()
                    return True
            else:
                 monitorevent.down_arrow_seek_on_monitor_clip()
                 return True
        # Apr-2017 - SvdB - Add different speeds for different modifiers
        # Allow user to select what speed belongs to what modifier, knowing that a combo of mods
        # will MULTIPLY all speeds
        # Available: SHIFT_MASK LOCK_MASK CONTROL_MASK
        if action == 'prev_frame' or action == 'next_frame':
            if action == 'prev_frame':
                seek_amount = -1
            else:
                seek_amount = 1
                
            if (event.get_state() & Gdk.ModifierType.SHIFT_MASK):
                seek_amount = seek_amount * prefs.ffwd_rev_shift
            if (event.get_state() & Gdk.ModifierType.CONTROL_MASK):
                seek_amount = seek_amount * prefs.ffwd_rev_ctrl
            if (event.get_state() & Gdk.ModifierType.LOCK_MASK):
                seek_amount = seek_amount * prefs.ffwd_rev_caps
            PLAYER().seek_delta(seek_amount)
            return True
        if action == '3_point_overwrite':
            tlineaction.three_point_overwrite_pressed()
            return True
        if action == 'insert':
            if not (event.get_state() & Gdk.ModifierType.CONTROL_MASK):
                tlineaction.insert_button_pressed()
                return True
        if action == 'append':
            tlineaction.append_button_pressed()
            return True
        if action == 'slower':
            monitorevent.j_pressed()
            return True
        if action == 'stop':
            monitorevent.k_pressed()
            return True
        if action == 'faster':
            monitorevent.l_pressed()
            return True
        if action == 'log_range':
            medialog.log_range_clicked()
            return True
        if action == 'resync':
            tlineaction.resync_button_pressed()
            return True
        if action == 'delete':
            # Clip selection and compositor selection are mutually exclusive, 
            # so max one one these will actually delete something
            tlineaction.splice_out_button_pressed()
            compositormodes.delete_current_selection()
        if action == 'to_start':
            if PLAYER().is_playing():
                monitorevent.stop_pressed()
            PLAYER().seek_frame(0)
            _move_to_beginning()
            return True
        if action == 'to_end':
            if PLAYER().is_playing():
                monitorevent.stop_pressed()
            PLAYER().seek_end()
            _move_to_end()
            return True
    else:
        if action == 'to_start':
            if PLAYER().is_playing():
                monitorevent.stop_pressed()
            gui.editor_window.set_default_edit_tool()
            PLAYER().seek_frame(0)
            _move_to_beginning()
            return True
        if action == 'to_end':
            if PLAYER().is_playing():
                monitorevent.stop_pressed()
            gui.editor_window.set_default_edit_tool()
            PLAYER().seek_end()
            _move_to_end()
            return True

    return False
コード例 #2
0
ファイル: editorwindow.py プロジェクト: BogusCurry/flowblade
    def _init_view_menu(self, menu_item):
        menu_item.set_submenu(None)
        menu = Gtk.Menu()

        mb_menu_item = Gtk.MenuItem(_("Middlebar Layout").encode('utf-8'))
        mb_menu = Gtk.Menu()
        tc_left = Gtk.RadioMenuItem()
        tc_left.set_label(_("Timecode Left").encode('utf-8'))
        tc_left.set_active(True)
        tc_left.connect("activate", lambda w: middlebar._show_buttons_TC_LEFT_layout(w))
        mb_menu.append(tc_left)

        tc_middle = Gtk.RadioMenuItem.new_with_label([tc_left], _("Timecode Center").encode('utf-8'))
        tc_middle.connect("activate", lambda w: middlebar._show_buttons_TC_MIDDLE_layout(w))
        mb_menu.append(tc_middle)

        if editorpersistance.prefs.midbar_tc_left == True:
            tc_left.set_active(True)
        else:
            tc_middle.set_active(True)

        mb_menu_item.set_submenu(mb_menu)
        menu.append(mb_menu_item)

        tabs_menu_item = Gtk.MenuItem(_("Tabs Position").encode('utf-8'))
        tabs_menu =  Gtk.Menu()
        tabs_up = Gtk.RadioMenuItem()
        tabs_up.set_label( _("Up").encode('utf-8'))
        tabs_up.connect("activate", lambda w: self._show_tabs_up(w))
        tabs_menu.append(tabs_up)
        
        tabs_down = Gtk.RadioMenuItem.new_with_label([tabs_up], _("Down").encode('utf-8'))
        tabs_down.connect("activate", lambda w: self._show_tabs_down(w))

        if editorpersistance.prefs.tabs_on_top == True:
            tabs_up.set_active(True)
        else:
            tabs_down.set_active(True)

        tabs_menu.append(tabs_down)
        tabs_menu_item.set_submenu(tabs_menu)
        menu.append(tabs_menu_item)

        sep = Gtk.SeparatorMenuItem()
        menu.append(sep)

        if not (editorstate.screen_size_small_height() == True or editorstate.screen_size_small_height() == True):
            
            show_monitor_info_item = Gtk.CheckMenuItem(_("Show Monitor Sequence Profile").encode('utf-8'))
            show_monitor_info_item.set_active(editorpersistance.prefs.show_sequence_profile)
            show_monitor_info_item.connect("toggled", lambda w: middlebar._show_monitor_info_toggled(w))
            menu.append(show_monitor_info_item)

            show_vu_item = Gtk.CheckMenuItem(_("Show Master Volume Meter").encode('utf-8'))
            show_vu_item.set_active(editorpersistance.prefs.show_vu_meter)
            show_vu_item.connect("toggled", lambda w: self._show_vu_meter(w))
            menu.append(show_vu_item)

            sep = Gtk.SeparatorMenuItem()
            menu.append(sep)

        interp_menu_item = Gtk.MenuItem(_("Monitor Playback Interpolation").encode('utf-8'))
        interp_menu = Gtk.Menu()
        
        interp_nearest = Gtk.RadioMenuItem()
        interp_nearest.set_label(_("Nearest Neighbour (fast)").encode('utf-8'))
        interp_nearest.connect("activate", lambda w: monitorevent.set_monitor_playback_interpolation("nearest"))
        interp_menu.append(interp_nearest)
        
        interp_bilinear = Gtk.RadioMenuItem.new_with_label([interp_nearest], _("Bilinear (good)").encode('utf-8'))
        interp_bilinear.connect("activate", lambda w: monitorevent.set_monitor_playback_interpolation("bilinear"))
        interp_menu.append(interp_bilinear)

        interp_bicubic = Gtk.RadioMenuItem.new_with_label([interp_nearest], _("Bicubic (better)").encode('utf-8'))
        interp_bicubic.set_active(True)
        interp_bicubic.connect("activate", lambda w: monitorevent.set_monitor_playback_interpolation("bicubic"))
        interp_menu.append(interp_bicubic)

        interp_hyper = Gtk.RadioMenuItem.new_with_label([interp_nearest], _("Hyper/Lanczos (best)").encode('utf-8'))
        interp_hyper.connect("activate", lambda w: monitorevent.set_monitor_playback_interpolation("hyper"))
        interp_menu.append(interp_hyper)

        interp_menu_item.set_submenu(interp_menu)
        menu.append(interp_menu_item)

        sep = Gtk.SeparatorMenuItem()
        menu.append(sep)        
        
        zoom_in_menu_item = Gtk.MenuItem(_("Zoom In").encode('utf-8'))
        zoom_in_menu_item.connect("activate", lambda w: updater.zoom_in())
        menu.append(zoom_in_menu_item)
        zoom_out_menu_item = Gtk.MenuItem(_("Zoom Out").encode('utf-8'))
        zoom_out_menu_item.connect("activate", lambda w: updater.zoom_out())
        menu.append(zoom_out_menu_item)
        zoom_fit_menu_item = Gtk.MenuItem(_("Zoom Fit").encode('utf-8'))
        zoom_fit_menu_item.connect("activate", lambda w: updater.zoom_project_length())
        menu.append(zoom_fit_menu_item)
        
        menu_item.set_submenu(menu)
コード例 #3
0
    def _init_view_menu(self, menu_item):
        menu_item.remove_submenu()
        menu = gtk.Menu()

        mb_menu_item = gtk.MenuItem(_("Middlebar Layout").encode('utf-8'))
        mb_menu = gtk.Menu()
        tc_left = gtk.RadioMenuItem(None, _("Timecode Left").encode('utf-8'))
        tc_left.set_active(True)
        tc_left.connect("activate",
                        lambda w: middlebar._show_buttons_TC_LEFT_layout(w))
        mb_menu.append(tc_left)

        tc_middle = gtk.RadioMenuItem(tc_left,
                                      _("Timecode Center").encode('utf-8'))
        tc_middle.connect(
            "activate", lambda w: middlebar._show_buttons_TC_MIDDLE_layout(w))
        mb_menu.append(tc_middle)

        if editorpersistance.prefs.midbar_tc_left == True:
            tc_left.set_active(True)
        else:
            tc_middle.set_active(True)

        mb_menu_item.set_submenu(mb_menu)
        menu.append(mb_menu_item)

        tabs_menu_item = gtk.MenuItem(_("Tabs Position").encode('utf-8'))
        tabs_menu = gtk.Menu()
        tabs_up = gtk.RadioMenuItem(None, _("Up").encode('utf-8'))
        tabs_up.connect("activate", lambda w: self._show_tabs_up(w))
        tabs_menu.append(tabs_up)

        tabs_down = gtk.RadioMenuItem(tabs_up, _("Down").encode('utf-8'))
        tabs_down.connect("activate", lambda w: self._show_tabs_down(w))

        if editorpersistance.prefs.tabs_on_top == True:
            tabs_up.set_active(True)
        else:
            tabs_down.set_active(True)

        tabs_menu.append(tabs_down)
        tabs_menu_item.set_submenu(tabs_menu)
        menu.append(tabs_menu_item)

        sep = gtk.SeparatorMenuItem()
        menu.append(sep)

        show_monitor_info_item = gtk.CheckMenuItem(
            _("Show Monitor Sequence Profile").encode('utf-8'))
        show_monitor_info_item.set_active(
            editorpersistance.prefs.show_sequence_profile)
        show_monitor_info_item.connect(
            "toggled", lambda w: middlebar._show_monitor_info_toggled(w))
        menu.append(show_monitor_info_item)

        show_vu_item = gtk.CheckMenuItem(
            _("Show Master Volume Meter").encode('utf-8'))
        show_vu_item.set_active(editorpersistance.prefs.show_vu_meter)
        show_vu_item.connect("toggled", lambda w: self._show_vu_meter(w))
        menu.append(show_vu_item)

        sep = gtk.SeparatorMenuItem()
        menu.append(sep)

        interp_menu_item = gtk.MenuItem(
            _("Monitor Playback Interpolation").encode('utf-8'))
        interp_menu = gtk.Menu()

        interp_nearest = gtk.RadioMenuItem(
            None,
            _("Nearest Neighbour").encode('utf-8'))
        interp_nearest.connect(
            "activate", lambda w: monitorevent.
            set_monitor_playback_interpolation("nearest"))
        interp_menu.append(interp_nearest)

        interp_bilinear = gtk.RadioMenuItem(interp_nearest,
                                            _("Bilinear").encode('utf-8'))
        interp_bilinear.connect(
            "activate", lambda w: monitorevent.
            set_monitor_playback_interpolation("bilinear"))
        interp_menu.append(interp_bilinear)

        interp_bicubic = gtk.RadioMenuItem(interp_nearest,
                                           _("Bicubic").encode('utf-8'))
        interp_bicubic.set_active(True)
        interp_bicubic.connect(
            "activate", lambda w: monitorevent.
            set_monitor_playback_interpolation("bicubic"))

        interp_menu.append(interp_bicubic)

        interp_hyper = gtk.RadioMenuItem(interp_nearest,
                                         _("Hyper/Lanczos").encode('utf-8'))
        interp_hyper.connect(
            "activate",
            lambda w: monitorevent.set_monitor_playback_interpolation("hyper"))
        interp_menu.append(interp_hyper)

        interp_menu_item.set_submenu(interp_menu)
        menu.append(interp_menu_item)

        sep = gtk.SeparatorMenuItem()
        menu.append(sep)

        zoom_in_menu_item = gtk.MenuItem(_("Zoom In").encode('utf-8'))
        zoom_in_menu_item.connect("activate", lambda w: updater.zoom_in())
        menu.append(zoom_in_menu_item)
        zoom_out_menu_item = gtk.MenuItem(_("Zoom Out").encode('utf-8'))
        zoom_out_menu_item.connect("activate", lambda w: updater.zoom_out())
        menu.append(zoom_out_menu_item)
        zoom_fit_menu_item = gtk.MenuItem(_("Zoom Fit").encode('utf-8'))
        zoom_fit_menu_item.connect("activate",
                                   lambda w: updater.zoom_project_length())
        menu.append(zoom_fit_menu_item)

        menu_item.set_submenu(menu)
コード例 #4
0
ファイル: keyevents.py プロジェクト: dvdlvr/flowblade
def _handle_tline_key_event(event):
    """
    This is called when timeline widgets have focus and key is pressed.
    Returns True for handled key presses to stop those
    keyevents from going forward.
    """

    tool_was_selected = workflow.tline_tool_keyboard_selected(event)
    if tool_was_selected == True:
        return True
    
    action = _get_shortcut_action(event)
    prefs = editorpersistance.prefs

    if action == 'mark_in':
        monitorevent.mark_in_pressed()
        return True
    if action == 'to_mark_in':
        monitorevent.to_mark_in_pressed()
        return True
    if action == 'zoom_out':
        updater.zoom_out()
    if action == 'zoom_in':
        updater.zoom_in()
    if action == 'mark_out':
        monitorevent.mark_out_pressed()
        return True
    if action == 'to_mark_out':
        monitorevent.to_mark_out_pressed()
        return True
    if action == 'play_pause':
        if PLAYER().is_playing():
            monitorevent.stop_pressed()
        else:
            monitorevent.play_pressed()
        return True
    if action == 'switch_monitor':
        updater.switch_monitor_display()
        return True
    if action == 'add_marker':
        tlineaction.add_marker()
        return True    
    if action == 'cut':
        tlineaction.cut_pressed()
        return True
    if action == 'sequence_split':
        tlineaction.sequence_split_pressed()
        return True
    if action == 'log_range':
        medialog.log_range_clicked()
        return True
    """
    THis may need rethinking
    if action == 'toggle_ripple':
        gui.editor_window.toggle_trim_ripple_mode()
        return True
    """
    
    # Key bindings for keyboard trimming
    if editorstate.current_is_active_trim_mode() == True:
        if action == 'prev_frame':
            trimmodes.left_arrow_pressed((event.get_state() & Gdk.ModifierType.CONTROL_MASK))
            return True
        elif action == 'next_frame':
            trimmodes.right_arrow_pressed((event.get_state() & Gdk.ModifierType.CONTROL_MASK))
            return True
        elif action == 'enter_edit':
            trimmodes.enter_pressed()
            return True

    # Key bindings for MOVE MODES and _NO_EDIT modes
    if editorstate.current_is_move_mode() or editorstate.current_is_active_trim_mode() == False:
        if action == 'next_cut':
            if editorstate.timeline_visible():
                tline_frame = PLAYER().tracktor_producer.frame()
                frame = current_sequence().find_next_cut_frame(tline_frame)
                if frame != -1:
                    PLAYER().seek_frame(frame)
                    if editorpersistance.prefs.center_on_arrow_move == True:
                        updater.center_tline_to_current_frame()
                    return True
            else:
                monitorevent.up_arrow_seek_on_monitor_clip()
        if action == 'prev_cut':
            if editorstate.timeline_visible():
                tline_frame = PLAYER().tracktor_producer.frame()
                frame = current_sequence().find_prev_cut_frame(tline_frame)
                if frame != -1:
                    PLAYER().seek_frame(frame)
                    if editorpersistance.prefs.center_on_arrow_move == True:
                        updater.center_tline_to_current_frame()
                    return True
            else:
                 monitorevent.down_arrow_seek_on_monitor_clip()
                 return True
        # Apr-2017 - SvdB - Add different speeds for different modifiers
        # Allow user to select what speed belongs to what modifier, knowing that a combo of mods
        # will MULTIPLY all speeds
        # Available: SHIFT_MASK LOCK_MASK CONTROL_MASK
        if action == 'prev_frame' or action == 'next_frame':
            if action == 'prev_frame':
                seek_amount = -1
            else:
                seek_amount = 1
                
            if (event.get_state() & Gdk.ModifierType.SHIFT_MASK):
                seek_amount = seek_amount * prefs.ffwd_rev_shift
            if (event.get_state() & Gdk.ModifierType.CONTROL_MASK):
                seek_amount = seek_amount * prefs.ffwd_rev_ctrl
            if (event.get_state() & Gdk.ModifierType.LOCK_MASK):
                seek_amount = seek_amount * prefs.ffwd_rev_caps
            PLAYER().seek_delta(seek_amount)
            return True
        if action == '3_point_overwrite':
            tlineaction.three_point_overwrite_pressed()
            return True
        if action == 'insert':
            if not (event.get_state() & Gdk.ModifierType.CONTROL_MASK):
                tlineaction.insert_button_pressed()
                return True
        if action == 'append':
            tlineaction.append_button_pressed()
            return True
        if action == 'slower':
            monitorevent.j_pressed()
            return True
        if action == 'stop':
            monitorevent.k_pressed()
            return True
        if action == 'faster':
            monitorevent.l_pressed()
            return True
        if action == 'log_range':
            medialog.log_range_clicked()
            return True
        if action == 'resync':
            tlineaction.resync_button_pressed()
            return True
        if action == 'delete':
            # Clip selection and compositor selection are mutually exclusive, 
            # so max one one these will actually delete something
            tlineaction.splice_out_button_pressed()
            compositormodes.delete_current_selection()
        if action == 'to_start':
            if PLAYER().is_playing():
                monitorevent.stop_pressed()
            PLAYER().seek_frame(0)
            _move_to_beginning()
            return True
        if action == 'to_end':
            if PLAYER().is_playing():
                monitorevent.stop_pressed()
            PLAYER().seek_end()
            _move_to_end()
            return True
    else:
        if action == 'to_start':
            if PLAYER().is_playing():
                monitorevent.stop_pressed()
            gui.editor_window.set_default_edit_tool()
            PLAYER().seek_frame(0)
            _move_to_beginning()
            return True
        if action == 'to_end':
            if PLAYER().is_playing():
                monitorevent.stop_pressed()
            gui.editor_window.set_default_edit_tool()
            PLAYER().seek_end()
            _move_to_end()
            return True

    return False
コード例 #5
0
ファイル: editorwindow.py プロジェクト: admonkey/flowblade
    def _init_view_menu(self, menu_item):
        menu = menu_item.get_submenu()

        # Full Screen -tem is already in menu, we need separator here
        sep = Gtk.SeparatorMenuItem()
        menu.append(sep)

        mb_menu_item = Gtk.MenuItem(_("Middlebar Layout").encode('utf-8'))
        mb_menu = Gtk.Menu()
        tc_left = Gtk.RadioMenuItem()
        tc_left.set_label(_("Timecode Left").encode('utf-8'))
        tc_left.set_active(True)
        tc_left.connect("activate", lambda w: middlebar._show_buttons_TC_LEFT_layout(w))
        mb_menu.append(tc_left)

        tc_middle = Gtk.RadioMenuItem.new_with_label([tc_left], _("Timecode Center").encode('utf-8'))
        tc_middle.connect("activate", lambda w: middlebar._show_buttons_TC_MIDDLE_layout(w))
        mb_menu.append(tc_middle)

        if editorpersistance.prefs.midbar_tc_left == True:
            tc_left.set_active(True)
        else:
            tc_middle.set_active(True)

        mb_menu_item.set_submenu(mb_menu)
        menu.append(mb_menu_item)

        tabs_menu_item = Gtk.MenuItem(_("Tabs Position").encode('utf-8'))
        tabs_menu =  Gtk.Menu()
        tabs_up = Gtk.RadioMenuItem()
        tabs_up.set_label( _("Up").encode('utf-8'))
        tabs_up.connect("activate", lambda w: self._show_tabs_up(w))
        tabs_menu.append(tabs_up)
        
        tabs_down = Gtk.RadioMenuItem.new_with_label([tabs_up], _("Down").encode('utf-8'))
        tabs_down.connect("activate", lambda w: self._show_tabs_down(w))

        if editorpersistance.prefs.tabs_on_top == True:
            tabs_up.set_active(True)
        else:
            tabs_down.set_active(True)

        tabs_menu.append(tabs_down)
        tabs_menu_item.set_submenu(tabs_menu)
        menu.append(tabs_menu_item)

        sep = Gtk.SeparatorMenuItem()
        menu.append(sep)

        if not (editorstate.screen_size_small_height() == True or editorstate.screen_size_small_height() == True):
            
            show_monitor_info_item = Gtk.CheckMenuItem(_("Show Monitor Sequence Profile").encode('utf-8'))
            show_monitor_info_item.set_active(editorpersistance.prefs.show_sequence_profile)
            show_monitor_info_item.connect("toggled", lambda w: middlebar._show_monitor_info_toggled(w))
            menu.append(show_monitor_info_item)

            show_vu_item = Gtk.CheckMenuItem(_("Show Master Volume Meter").encode('utf-8'))
            show_vu_item.set_active(editorpersistance.prefs.show_vu_meter)
            show_vu_item.connect("toggled", lambda w: self._show_vu_meter(w))
            menu.append(show_vu_item)

            sep = Gtk.SeparatorMenuItem()
            menu.append(sep)

        interp_menu_item = Gtk.MenuItem(_("Monitor Playback Interpolation").encode('utf-8'))
        interp_menu = Gtk.Menu()
        
        interp_nearest = Gtk.RadioMenuItem()
        interp_nearest.set_label(_("Nearest Neighbour (fast)").encode('utf-8'))
        interp_nearest.connect("activate", lambda w: monitorevent.set_monitor_playback_interpolation("nearest"))
        interp_menu.append(interp_nearest)
        
        interp_bilinear = Gtk.RadioMenuItem.new_with_label([interp_nearest], _("Bilinear (good)").encode('utf-8'))
        interp_bilinear.connect("activate", lambda w: monitorevent.set_monitor_playback_interpolation("bilinear"))
        interp_menu.append(interp_bilinear)

        interp_bicubic = Gtk.RadioMenuItem.new_with_label([interp_nearest], _("Bicubic (better)").encode('utf-8'))
        interp_bicubic.set_active(True)
        interp_bicubic.connect("activate", lambda w: monitorevent.set_monitor_playback_interpolation("bicubic"))
        interp_menu.append(interp_bicubic)

        interp_hyper = Gtk.RadioMenuItem.new_with_label([interp_nearest], _("Hyper/Lanczos (best)").encode('utf-8'))
        interp_hyper.connect("activate", lambda w: monitorevent.set_monitor_playback_interpolation("hyper"))
        interp_menu.append(interp_hyper)

        interp_menu_item.set_submenu(interp_menu)
        menu.append(interp_menu_item)

        sep = Gtk.SeparatorMenuItem()
        menu.append(sep)        
        
        zoom_in_menu_item = Gtk.MenuItem(_("Zoom In").encode('utf-8'))
        zoom_in_menu_item.connect("activate", lambda w: updater.zoom_in())
        menu.append(zoom_in_menu_item)
        zoom_out_menu_item = Gtk.MenuItem(_("Zoom Out").encode('utf-8'))
        zoom_out_menu_item.connect("activate", lambda w: updater.zoom_out())
        menu.append(zoom_out_menu_item)
        zoom_fit_menu_item = Gtk.MenuItem(_("Zoom Fit").encode('utf-8'))
        zoom_fit_menu_item.connect("activate", lambda w: updater.zoom_project_length())
        menu.append(zoom_fit_menu_item)