Esempio n. 1
0
class KazamApp(GObject.GObject):
    def __init__(self, datadir, dist, debug, test, sound, silent):
        GObject.GObject.__init__(self)
        logger.debug("Setting variables.")

        prefs.datadir = datadir
        prefs.get_sound_files()

        self.startup = True
        prefs.debug = debug
        prefs.test = test
        prefs.dist = dist
        prefs.silent = silent
        prefs.sound = sound

        self.setup_translations()

        if prefs.sound:
            try:
                from kazam.pulseaudio.pulseaudio import pulseaudio_q
                prefs.sound = True
            except:
                logger.warning(
                    _("Pulse Audio Failed to load. Sound recording disabled."))
                prefs.sound = False

        self.icons = Gtk.IconTheme.get_default()
        self.icons.append_search_path(datadir)
        self.default_cursor = Gdk.Cursor(Gdk.CursorType.LEFT_PTR)

        # Initialize all the variables

        self.main_x = 0
        self.main_y = 0
        self.countdown = None
        self.tempfile = ""
        self.recorder = None
        self.area_window = None
        self.select_window = None
        self.outline_window = None
        self.old_vid_path = None
        self.old_pic_path = None
        self.in_countdown = False
        self.recording_paused = False
        self.recording = False
        self.main_mode = 0
        self.record_mode = 0
        self.last_mode = None
        self.keypress_detect = False
        self.keypress_viewer = None
        self.cam = None

        if prefs.sound:
            try:
                prefs.pa_q = pulseaudio_q()
                prefs.pa_q.start()
            except:
                logger.warning(
                    "Pulse Audio Failed to load. Sound recording disabled.")
                prefs.sound = False

        prefs.get_webcam_sources()

        self.mainmenu = MainMenu()

        logger.debug("Connecting indicator signals.")
        logger.debug("Starting in silent mode: {0}".format(prefs.silent))
        self.indicator = KazamIndicator(prefs.silent)
        self.indicator.connect("indicator-quit-request", self.cb_quit_request)
        self.indicator.connect("indicator-show-request", self.cb_show_request)
        self.indicator.connect("indicator-help-request", self.cb_help_request)
        self.indicator.connect("indicator-start-request",
                               self.cb_start_request)
        self.indicator.connect("indicator-stop-request", self.cb_stop_request)
        self.indicator.connect("indicator-pause-request",
                               self.cb_pause_request)
        self.indicator.connect("indicator-unpause-request",
                               self.cb_unpause_request)
        self.indicator.connect("indicator-about-request",
                               self.cb_about_request)

        self.mainmenu.connect("file-quit", self.cb_quit_request)
        self.mainmenu.connect("file-preferences", self.cb_preferences_request)
        self.mainmenu.connect("help-help", self.cb_help_request)
        self.mainmenu.connect("help-about", self.cb_help_about)
        self.webcam = HW.webcam
        self.webcam.connect("webcam-change", self.cb_webcam_change)

        #
        # Detect Xlib, if there's no Xlib, there's no KeyViewer
        #

        try:
            imp.find_module('Xlib')
            self.keypress_viewer = KeypressViewer()
            self.keypress_viewer.connect("keypress", self.cb_got_keypress)
            self.keypress_detect = True
        except ImportError:
            logger.warning(
                _("No Xlib support in python3, unable to capture key and mouse clicks."
                  ))
            self.keypress_detect = False

        #
        # Setup UI
        #
        logger.debug("Main Window UI setup.")

        self.builder = Gtk.Builder()
        self.builder.add_from_file(
            os.path.join(prefs.datadir, "ui", "kazam.ui"))
        self.builder.connect_signals(self)
        for w in self.builder.get_objects():
            if issubclass(type(w), Gtk.Buildable):
                name = Gtk.Buildable.get_name(w)
                setattr(self, name, w)
            else:
                logger.debug("Unable to get name for '%s'" % w)

        # Retrieve gdk_win for the root window
        self.gdk_win = self.window.get_root_window()

        #
        # Attach main menu, so that
        #
        self.MainGrid.attach(self.mainmenu.menubar, 0, 0, 1, 1)

        self.main_context = self.toolbar_main.get_style_context()
        self.main_context.add_class(Gtk.STYLE_CLASS_PRIMARY_TOOLBAR)
        self.main_context.connect("changed", self.cb_main_context_change)
        self.main_fg_color = self.main_context.get_color(Gtk.StateFlags.ACTIVE)

        #
        # Screen cast mode
        #
        self.btn_screencast = Gtk.RadioToolButton(group=None)
        self.btn_screencast.set_label(_("Screencast"))
        self.btn_screencast.set_tooltip_text(
            _("Record a video of your desktop."))
        screencast_icon = self.icons.lookup_icon(
            "kazam-screencast-symbolic", 24, Gtk.IconLookupFlags.FORCE_SIZE)
        if screencast_icon:
            cast_icon_pixbuf, was_sym = screencast_icon.load_symbolic(
                self.main_fg_color, None, None, None)
            cast_img = Gtk.Image.new_from_pixbuf(cast_icon_pixbuf)
            self.btn_screencast.set_icon_widget(cast_img)
        self.btn_screencast.set_active(True)
        self.btn_screencast.set_name("MAIN_SCREENCAST")
        self.btn_screencast.connect("toggled", self.cb_main_toggled)

        #
        # Screen shot mode
        #
        self.btn_screenshot = Gtk.RadioToolButton(group=self.btn_screencast)
        self.btn_screenshot.set_label(_("Screenshot"))
        self.btn_screenshot.set_tooltip_text(
            _("Record a picture of your desktop."))
        screenshot_icon = self.icons.lookup_icon(
            "kazam-screenshot-symbolic", 24, Gtk.IconLookupFlags.FORCE_SIZE)
        if screenshot_icon:
            shot_icon_pixbuf, was_sym = screenshot_icon.load_symbolic(
                self.main_fg_color, None, None, None)
            shot_img = Gtk.Image.new_from_pixbuf(shot_icon_pixbuf)
            self.btn_screenshot.set_icon_widget(shot_img)
        self.btn_screenshot.set_name("MAIN_SCREENSHOT")
        self.btn_screenshot.connect("toggled", self.cb_main_toggled)

        #
        # Broadcast mode
        #
        self.btn_broadcast = Gtk.RadioToolButton(group=self.btn_screencast)
        self.btn_broadcast.set_label(_("Broadcast"))
        self.btn_broadcast.set_tooltip_text(_("Broadcast your desktop."))
        broadcast_icon = self.icons.lookup_icon("kazam-broadcast-symbolic", 24,
                                                Gtk.IconLookupFlags.FORCE_SIZE)
        if broadcast_icon:
            cam_icon_pixbuf, was_sym = broadcast_icon.load_symbolic(
                self.main_fg_color, None, None, None)
            cam_img = Gtk.Image.new_from_pixbuf(cam_icon_pixbuf)
            self.btn_broadcast.set_icon_widget(cam_img)
        self.btn_broadcast.set_name("MAIN_BROADCAST")
        self.btn_broadcast.connect("toggled", self.cb_main_toggled)

        #
        # Webcam mode
        #
        self.btn_webcam = Gtk.RadioToolButton(group=self.btn_screencast)
        self.btn_webcam.set_label(_("Webcam"))
        self.btn_webcam.set_tooltip_text(_("Capture form your webcam."))
        webcam_icon = self.icons.lookup_icon("kazam-webcam-symbolic", 24,
                                             Gtk.IconLookupFlags.FORCE_SIZE)
        if webcam_icon:
            cam_icon_pixbuf, was_sym = webcam_icon.load_symbolic(
                self.main_fg_color, None, None, None)
            cam_img = Gtk.Image.new_from_pixbuf(cam_icon_pixbuf)
            self.btn_webcam.set_icon_widget(cam_img)
        self.btn_webcam.set_name("MAIN_WEBCAM")
        self.btn_webcam.connect("toggled", self.cb_main_toggled)

        self.sep_1 = Gtk.SeparatorToolItem()
        self.sep_1.set_draw(False)
        self.sep_1.set_expand(True)
        self.sep_1a = Gtk.SeparatorToolItem()
        self.sep_1a.set_draw(False)
        self.sep_1a.set_expand(True)
        self.toolbar_main.insert(self.sep_1, -1)
        self.toolbar_main.insert(self.btn_screencast, -1)
        self.toolbar_main.insert(self.btn_screenshot, -1)
        self.toolbar_main.insert(self.btn_broadcast, -1)
        if prefs.webcam_sources:
            self.toolbar_main.insert(self.btn_webcam, -1)
        else:
            self.chk_webcam.set_sensitive(False)
            self.chk_webcam_broadcast.set_sensitive(False)
        self.toolbar_main.insert(self.sep_1a, -1)

        # Auxiliary toolbar
        self.aux_context = self.toolbar_aux.get_style_context()
        self.aux_context.add_class(Gtk.STYLE_CLASS_TOOLBAR)
        self.aux_fg_color = self.aux_context.get_color(Gtk.StateFlags.ACTIVE)

        self.btn_full = Gtk.RadioToolButton(group=None)
        self.btn_full.set_label(_("Fullscreen"))
        self.btn_full.set_tooltip_text(
            _("Capture contents of the current screen."))
        full_icon = self.icons.lookup_icon("kazam-fullscreen-symbolic", 24,
                                           Gtk.IconLookupFlags.FORCE_SIZE)
        if full_icon:
            full_icon_pixbuf, was_sym = full_icon.load_symbolic(
                self.aux_fg_color, None, None, None)
            full_img = Gtk.Image.new_from_pixbuf(full_icon_pixbuf)
            self.btn_full.set_icon_widget(full_img)
        self.btn_full.set_active(True)
        self.btn_full.set_name("MODE_FULL")
        self.btn_full.connect("toggled", self.cb_record_mode_toggled)

        self.btn_allscreens = Gtk.RadioToolButton(group=self.btn_full)
        self.btn_allscreens.set_label(_("All Screens"))
        self.btn_allscreens.set_tooltip_text(
            _("Capture contents of all of your screens."))
        allscreens_icon = self.icons.lookup_icon(
            "kazam-all-screens-symbolic", 24, Gtk.IconLookupFlags.FORCE_SIZE)
        if allscreens_icon:
            allscreens_icon_pixbuf, was_sym = allscreens_icon.load_symbolic(
                self.aux_fg_color, None, None, None)
            allscreens_img = Gtk.Image.new_from_pixbuf(allscreens_icon_pixbuf)
            self.btn_allscreens.set_icon_widget(allscreens_img)
        self.btn_allscreens.set_name("MODE_ALL")
        self.btn_allscreens.connect("toggled", self.cb_record_mode_toggled)
        if HW.combined_screen is None:
            self.btn_allscreens.set_sensitive(False)

        self.btn_window = Gtk.RadioToolButton(group=self.btn_full)
        self.btn_window.set_label(_("Window"))
        self.btn_window.set_tooltip_text(
            _("Capture contents of a single window."))
        window_icon = self.icons.lookup_icon("kazam-window-symbolic", 24,
                                             Gtk.IconLookupFlags.FORCE_SIZE)
        if window_icon:
            window_icon_pixbuf, was_sym = window_icon.load_symbolic(
                self.aux_fg_color, None, None, None)
            window_img = Gtk.Image.new_from_pixbuf(window_icon_pixbuf)
            self.btn_window.set_icon_widget(window_img)
        self.btn_window.set_name("MODE_WIN")
        self.btn_window.connect("toggled", self.cb_record_mode_toggled)
        self.btn_window.connect("clicked", self.cb_record_window_clicked)

        self.btn_area = Gtk.RadioToolButton(group=self.btn_full)
        self.btn_area.set_label(_("Area"))
        self.btn_area.set_tooltip_text(
            _("Capture a pre-selected area of your screen."))
        area_icon = self.icons.lookup_icon("kazam-area-symbolic", 24,
                                           Gtk.IconLookupFlags.FORCE_SIZE)
        if area_icon:
            area_icon_pixbuf, was_sym = area_icon.load_symbolic(
                self.aux_fg_color, None, None, None)
            area_img = Gtk.Image.new_from_pixbuf(area_icon_pixbuf)
            self.btn_area.set_icon_widget(area_img)
        self.btn_area.set_name("MODE_AREA")
        self.btn_area.connect("toggled", self.cb_record_mode_toggled)
        self.btn_area.connect("clicked", self.cb_record_area_clicked)

        self.sep_2 = Gtk.SeparatorToolItem()
        self.sep_2.set_draw(False)
        self.sep_2.set_expand(True)
        self.sep_2a = Gtk.SeparatorToolItem()
        self.sep_2a.set_draw(False)
        self.sep_2a.set_expand(True)
        self.toolbar_aux.insert(self.sep_2, -1)
        self.toolbar_aux.insert(self.btn_full, -1)
        self.toolbar_aux.insert(self.btn_allscreens, -1)
        self.toolbar_aux.insert(self.btn_window, -1)
        self.toolbar_aux.insert(self.btn_area, -1)
        self.toolbar_aux.insert(self.sep_2a, -1)
        self.ntb_main.set_current_page(0)
        self.btn_record.grab_focus()

        #
        # Take care of screen size changes.
        #
        self.default_screen = Gdk.Screen.get_default()
        self.default_screen.connect("size-changed",
                                    self.cb_screen_size_changed)
        self.window.connect("configure-event", self.cb_configure_event)
        #        self.window.connect("delete-event", self.cb_delete_event)

        # Fetch sources info, take care of all the widgets and saved settings and show main window
        if prefs.sound:
            prefs.get_audio_sources()

        self.instructions = ("""  SUPER-CTRL-W to toggle main window.\n"""
                             """  SUPER-CTRL-R to start recording.\n"""
                             """  SUPER-CTRL-F to finish recording.\n"""
                             """  SUPER-CTRL-P to pause/resume recording.\n"""
                             """  SUPER-CTRL-Q to quit.\n""")

        if not prefs.silent:
            self.window.show_all()
        else:
            logger.info("""Starting in silent mode:\n""" + self.instructions)

        self.restore_UI()

        if not self.keypress_detect:
            self.chk_keypresses.set_sensitive(False)
            self.chk_keypresses.set_active(False)

        #HW.get_current_screen(self.window)
        self.startup = False
        self.noSelectNextModeActive = False

        screen = HW.get_current_screen(self.window)
        prefs.current_screen = screen

        #
        # For debugging purposes only ...
        #
        # self.keypress_viewer.start()
        # self.keypress_window = KeypressWindow()

    #
    # Callbacks, go down here ...
    #
    def cb_got_keypress(self, kv, ev_type, action, value):
        """ev_type: 'KeySym', 'KeyStr', 'MouseButton'
           action: 'Press' or 'Release'
           value: A key name ('Control_L' or 'd' or 'backslash' or 1,2,3 for
                              mouse buttons.)
        """
        logger.info("GOT EVENT: {}, {}, {}".format(ev_type, action, value))
        if self.keypress_window:
            self.keypress_window.show(ev_type, value, action)

    #
    # Mode of operation toggles
    #

    def cb_main_toggled(self, widget):
        # Here be defaults
        self.toolbar_aux.set_sensitive(True)
        self.chk_borders_pic.set_sensitive(True)

        name = widget.get_name()
        if name == "MAIN_SCREENCAST" and widget.get_active():
            logger.debug("Main toggled: {0}".format(name))
            self.main_mode = MODE_SCREENCAST
            self.ntb_main.set_current_page(0)
            self.indicator.menuitem_start.set_label(_("Start recording"))
            self.btn_record.set_label(_("Capture"))

        elif name == "MAIN_SCREENSHOT" and widget.get_active():
            logger.debug("Main toggled: {0}".format(name))
            self.main_mode = MODE_SCREENSHOT
            self.ntb_main.set_current_page(1)
            if self.record_mode == MODE_WIN:
                self.last_mode.set_active(True)
            self.indicator.menuitem_start.set_label(_("Take screenshot"))
            if self.record_mode != "MODE_WIN":
                self.chk_borders_pic.set_sensitive(False)
            self.btn_record.set_label(_("Capture"))

        elif name == "MAIN_BROADCAST" and widget.get_active():
            logger.debug("Main toggled: {0}".format(name))
            self.main_mode = MODE_BROADCAST
            self.ntb_main.set_current_page(2)
            self.indicator.menuitem_start.set_label(_("Start broadcasting"))
            self.btn_record.set_label(_("Broadcast"))
            self.toolbar_aux.set_sensitive(False)

        elif name == "MAIN_WEBCAM" and widget.get_active():
            logger.debug("Main toggled: {0}".format(name))
            self.ntb_main.set_current_page(3)
            self.main_mode = MODE_WEBCAM
            self.toolbar_aux.set_sensitive(False)
            self.indicator.menuitem_start.set_label(_("Start recording"))
            self.btn_record.set_label(_("Capture"))

    #
    # Record mode toggles
    #
    def cb_record_mode_toggled(self, widget):
        noSelection = False
        if widget.get_active():
            self.current_mode = widget
            if self.noSelectNextModeActive == True:
                self.noSelectNextModeActive = False
                noSelection = True
        else:
            self.last_mode = widget

        if widget.get_name() == "MODE_AREA" and widget.get_active():
            logger.debug("Area ON.")
            if noSelection != True:
                self.area_window = AreaWindow()
                self.tmp_sig1 = self.area_window.connect(
                    "area-selected", self.cb_area_selected)
                self.tmp_sig2 = self.area_window.connect(
                    "area-canceled", self.cb_area_canceled)
            self.record_mode = MODE_AREA

        if widget.get_name() == "MODE_AREA" and not widget.get_active():
            logger.debug("Area OFF.")
            if self.area_window:
                self.area_window.disconnect(self.tmp_sig1)
                self.area_window.disconnect(self.tmp_sig2)
                self.area_window.window.destroy()
                self.area_window = None

        if widget.get_name() == "MODE_FULL" and widget.get_active():
            logger.debug("Capture full screen.")
            self.record_mode = MODE_FULL

        if widget.get_name() == "MODE_ALL" and widget.get_active():
            logger.debug("Capture all screens.")
            self.record_mode = MODE_ALL

        if widget.get_name() == "MODE_WIN" and widget.get_active():
            logger.debug("Window capture ON.")
            if noSelection != True:
                self.select_window = SelectWindow()
                self.tmp_sig3 = self.select_window.connect(
                    "window-selected", self.cb_window_selected)
                self.tmp_sig4 = self.select_window.connect(
                    "window-canceled", self.cb_window_canceled)
                self.chk_borders_pic.set_sensitive(True)
            self.record_mode = MODE_WIN

        if widget.get_name() == "MODE_WIN" and not widget.get_active():
            logger.debug("Window capture OFF.")
            self.chk_borders_pic.set_sensitive(False)
            if self.select_window:
                self.select_window.disconnect(self.tmp_sig3)
                self.select_window.disconnect(self.tmp_sig4)
                self.select_window.window.destroy()
                self.select_window = None

    def cb_main_context_change(self, widget):
        #
        # If this is the only way on how to deal with symbolic icons, then someone needs spanking ...
        #
        if widget.get_state() == Gtk.StateFlags.BACKDROP:
            self.main_fg_color = self.main_context.get_color(
                Gtk.StateFlags.ACTIVE)
            self.aux_fg_color = self.aux_context.get_color(
                Gtk.StateFlags.ACTIVE)

            #
            # Update icons on the main toolbar
            #
            cast_icon = self.icons.lookup_icon("kazam-screencast-symbolic", 24,
                                               Gtk.IconLookupFlags.FORCE_SIZE)
            if cast_icon:
                cast_icon_pixbuf, was_sym = cast_icon.load_symbolic(
                    self.main_fg_color, None, None, None)
                cast_img = Gtk.Image.new_from_pixbuf(cast_icon_pixbuf)
                self.btn_screencast.set_icon_widget(cast_img)
                cast_img.show_all()

            shot_icon = self.icons.lookup_icon("kazam-screenshot-symbolic", 24,
                                               Gtk.IconLookupFlags.FORCE_SIZE)
            if shot_icon:
                shot_icon_pixbuf, was_sym = shot_icon.load_symbolic(
                    self.main_fg_color, None, None, None)
                shot_img = Gtk.Image.new_from_pixbuf(shot_icon_pixbuf)
                self.btn_screenshot.set_icon_widget(shot_img)
                shot_img.show_all()

            webcam_icon = self.icons.lookup_icon(
                "kazam-webcam-symbolic", 24, Gtk.IconLookupFlags.FORCE_SIZE)
            if webcam_icon:
                webcam_icon_pixbuf, was_sym = webcam_icon.load_symbolic(
                    self.main_fg_color, None, None, None)
                webcam_img = Gtk.Image.new_from_pixbuf(webcam_icon_pixbuf)
                self.btn_screencast.set_icon_widget(webcam_img)
                webcam_img.show_all()

            broadcast_icon = self.icons.lookup_icon(
                "kazam-broadcast-symbolic", 24, Gtk.IconLookupFlags.FORCE_SIZE)
            if broadcast_icon:
                broadcast_icon_pixbuf, was_sym = broadcast_icon.load_symbolic(
                    self.main_fg_color, None, None, None)
                broadcast_img = Gtk.Image.new_from_pixbuf(
                    broadcast_icon_pixbuf)
                self.btn_screenshot.set_icon_widget(broadcast_img)
                broadcast_img.show_all()

            #
            # Update icons on the aux toolbar
            #
            full_icon = self.icons.lookup_icon("kazam-fullscreen-symbolic", 24,
                                               Gtk.IconLookupFlags.FORCE_SIZE)
            if full_icon:
                full_icon_pixbuf, was_sym = full_icon.load_symbolic(
                    self.aux_fg_color, None, None, None)
                full_img = Gtk.Image.new_from_pixbuf(full_icon_pixbuf)
                self.btn_full.set_icon_widget(full_img)
                full_img.show_all()

            allscreens_icon = self.icons.lookup_icon(
                "kazam-all-screens-symbolic", 24,
                Gtk.IconLookupFlags.FORCE_SIZE)
            if allscreens_icon:
                allscreens_icon_pixbuf, was_sym = allscreens_icon.load_symbolic(
                    self.aux_fg_color, None, None, None)
                allscreens_img = Gtk.Image.new_from_pixbuf(
                    allscreens_icon_pixbuf)
                self.btn_allscreens.set_icon_widget(allscreens_img)
                allscreens_img.show_all()

            window_icon = self.icons.lookup_icon(
                "kazam-window-symbolic", 24, Gtk.IconLookupFlags.FORCE_SIZE)
            if window_icon:
                window_icon_pixbuf, was_sym = window_icon.load_symbolic(
                    self.aux_fg_color, None, None, None)
                window_img = Gtk.Image.new_from_pixbuf(window_icon_pixbuf)
                self.btn_window.set_icon_widget(window_img)
                window_img.show_all()

            area_icon = self.icons.lookup_icon("kazam-area-symbolic", 24,
                                               Gtk.IconLookupFlags.FORCE_SIZE)
            if area_icon:
                area_icon_pixbuf, was_sym = area_icon.load_symbolic(
                    self.aux_fg_color, None, None, None)
                area_img = Gtk.Image.new_from_pixbuf(area_icon_pixbuf)
                self.btn_area.set_icon_widget(area_img)
                area_img.show_all()

    #
    # Unity quick list callbacks
    #

    def cb_ql_screencast(self, menu, data):
        logger.debug("Screencast quicklist activated.")
        self.btn_screencast.set_active(True)
        self.run_counter()

    def cb_ql_screenshot(self, menu, data):
        logger.debug("Screenshot quicklist activated.")
        self.btn_screenshot.set_active(True)
        self.run_counter()

    def cb_record_area_clicked(self, widget):
        if self.area_window:
            logger.debug("Area mode clicked.")
            self.area_window.show_all()
            self.window.set_sensitive(False)

    def cb_record_window_clicked(self, widget):
        if self.select_window:
            logger.debug("Window mode clicked.")
            self.select_window.show_all()
            self.window.set_sensitive(False)

    def cb_area_selected(self, widget):
        logger.debug(
            "Area selected: SX: {0}, SY: {1}, EX: {2}, EY: {3}".format(
                self.area_window.startx, self.area_window.starty,
                self.area_window.endx, self.area_window.endy))
        logger.debug(
            "Area selected: GX: {0}, GY: {1}, GX: {2}, GY: {3}".format(
                self.area_window.g_startx, self.area_window.g_starty,
                self.area_window.g_endx, self.area_window.g_endy))
        prefs.area = (self.area_window.g_startx, self.area_window.g_starty,
                      self.area_window.g_endx, self.area_window.g_endy,
                      self.area_window.width, self.area_window.height)
        self.window.set_sensitive(True)

    def cb_area_canceled(self, widget):
        logger.debug("Area selection canceled.")
        self.window.set_sensitive(True)
        self.noSelectNextModeActive = True
        self.last_mode.set_active(True)

    def cb_window_selected(self, widget):
        prefs.xid = self.select_window.xid
        prefs.xid_geometry = self.select_window.geometry
        logger.debug("Window selected: {0} - {1}".format(
            self.select_window.win_name, prefs.xid))
        logger.debug("Window geometry: {0}".format(
            self.select_window.geometry))
        self.window.set_sensitive(True)

    def cb_window_canceled(self, widget):
        logger.debug("Window selection canceled.")
        self.window.set_sensitive(True)
        self.noSelectNextModeActive = True
        self.last_mode.set_active(True)

    def cb_screen_size_changed(self, screen):
        logger.debug("Screen size changed.")
        HW.get_screens()
        #
        # If combined screen was set to none, turn off the button for all screens
        #
        if HW.combined_screen:
            self.btn_allscreens.set_sensitive(True)
        else:
            self.btn_allscreens.set_sensitive(False)

    def cb_configure_event(self, widget, event):
        if event.type == Gdk.EventType.CONFIGURE:
            prefs.main_x = event.x
            prefs.main_y = event.y

    def cb_quit_request(self, indicator):
        logger.debug("Quit requested.")
        # Restore cursor, just in case if by some chance stays set to cross-hairs
        self.gdk_win.set_cursor(self.default_cursor)
        (prefs.main_x, prefs.main_y) = self.window.get_position()
        try:
            os.remove(self.recorder.tempfile)
            os.remove("{0}.mux".format(self.recorder.tempfile))
        except OSError:
            logger.info(
                "Unable to delete one of the temporary files. Check your temporary directory."
            )
        except AttributeError:
            pass

        prefs.save_config()

        if prefs.sound and prefs.pa_q != None:
            prefs.pa_q.end()
            prefs.pa_q = None

        #
        # Just in case, try to shutdown keylogger
        #
        if self.keypress_viewer:
            self.keypress_viewer.stop()
        Gtk.main_quit()

    def cb_preferences_request(self, indicator):
        logger.debug("Preferences requested.")
        self.preferences_window = Preferences()
        self.preferences_window.open()

    def cb_help_request(self, indicator):
        messagedialog = Gtk.MessageDialog(parent=self.window,
                                          flags=Gtk.DialogFlags.MODAL,
                                          type=Gtk.MessageType.WARNING,
                                          buttons=Gtk.ButtonsType.OK,
                                          message_format=self.instructions)
        messagedialog.run()
        messagedialog.destroy()

    def cb_show_request(self, indicator):
        if not self.window.get_property("visible"):
            logger.debug("Show requested, raising window.")
            self.window.show_all()
            self.window.present()
            self.window.move(prefs.main_x, prefs.main_y)
        else:
            self.window.hide()

    def cb_close_clicked(self, indicator):
        (prefs.main_x, prefs.main_y) = self.window.get_position()
        self.window.hide()

    def cb_about_request(self, activated):
        AboutDialog(self.icons)

    def cb_delete_event(self, widget, user_data):
        self.cb_quit_request(None)

    def cb_start_request(self, widget):
        logger.debug("Start recording selected.")
        self.run_counter()

    def cb_record_clicked(self, widget):
        logger.debug("Record clicked, invoking Screencast.")
        self.run_counter()

    def cb_counter_finished(self, widget):
        logger.debug("Counter finished.")
        self.in_countdown = False
        self.countdown = None
        self.indicator.blink_set_state(BLINK_STOP)
        if self.main_mode in [MODE_SCREENCAST, MODE_WEBCAM, MODE_BROADCAST]:
            if self.main_mode == MODE_BROADCAST:
                self.indicator.menuitem_finish.set_label(
                    _("Finish broadcasting"))
            else:
                self.indicator.menuitem_finish.set_label(_("Finish recording"))
            self.indicator.menuitem_pause.set_sensitive(True)
            self.indicator.start_recording()
            self.recorder.start_recording()
            if (self.main_mode == MODE_SCREENCAST and
                    prefs.capture_keys) or (self.main_mode == MODE_BROADCAST
                                            and prefs.capture_keys_broadcast):
                self.keypress_window = KeypressWindow()
                if self.keypress_viewer:
                    self.keypress_viewer.start()
        elif self.main_mode == MODE_SCREENSHOT:
            self.indicator.hide_it()
            self.grabber.grab()
            self.indicator.show_it()

    def cb_stop_request(self, widget):
        self.recording = False

        if self.outline_window:
            self.outline_window.hide()
            self.outline_window.window.destroy()
            self.outline_window = None

        if self.in_countdown:
            logger.debug("Cancel countdown request.")
            self.countdown.cancel_countdown()
            self.countdown = None
            self.indicator.menuitem_finish.set_label(_("Finish recording"))
            self.window.set_sensitive(True)
            self.window.show()
            self.window.present()
        else:
            if self.recording_paused:
                self.recorder.unpause_recording()
            logger.debug("Stop request.")
            self.recorder.stop_recording()
            if (self.main_mode == MODE_SCREENCAST and
                    prefs.capture_keys) or (self.main_mode == MODE_BROADCAST
                                            and prefs.capture_keys_broadcast):
                if self.keypress_viewer:
                    self.keypress_viewer.stop()
                self.keypress_window.window.destroy()
                self.keypress_window = None
                self.keypress_viewer = None

            self.tempfile = self.recorder.get_tempfile()
            logger.debug("Recorded tmp file: {0}".format(self.tempfile))
            logger.debug("Waiting for data to flush.")

    def cb_flush_done(self, widget):
        if self.main_mode == MODE_SCREENCAST and prefs.autosave_video:
            logger.debug("Autosaving enabled.")
            fname = get_next_filename(prefs.autosave_video_dir,
                                      prefs.autosave_video_file,
                                      CODEC_LIST[prefs.codec][3])

            shutil.move(self.tempfile, fname)

            self.window.set_sensitive(True)
            self.window.show()
            self.window.present()
        elif self.main_mode == MODE_SCREENCAST or self.main_mode == MODE_WEBCAM:
            self.done_recording = DoneRecording(self.icons, self.tempfile,
                                                prefs.codec, self.old_vid_path)
            logger.debug("Done Recording initialized.")
            self.done_recording.connect("save-done", self.cb_save_done)
            self.done_recording.connect("save-cancel", self.cb_save_cancel)
            self.done_recording.connect("edit-request", self.cb_edit_request)
            logger.debug("Done recording signals connected.")
            self.done_recording.show_all()
            self.window.set_sensitive(False)

        elif self.main_mode == MODE_BROADCAST:
            self.window.set_sensitive(True)
            self.window.show_all()
            self.window.present()
            self.window.move(prefs.main_x, prefs.main_y)

        elif self.main_mode == MODE_SCREENSHOT:
            if self.outline_window:
                self.outline_window.hide()
                self.outline_window.window.destroy()
                self.outline_window = None

            self.grabber.connect("save-done", self.cb_save_done)
            self.indicator.recording = False
            self.indicator.menuitem_start.set_sensitive(True)
            self.indicator.menuitem_pause.set_sensitive(False)
            self.indicator.menuitem_pause.set_active(False)
            self.indicator.menuitem_finish.set_sensitive(False)
            self.indicator.menuitem_quit.set_sensitive(True)

            if prefs.autosave_picture:
                fname = get_next_filename(prefs.autosave_picture_dir,
                                          prefs.autosave_picture_file, ".png")
                self.grabber.autosave(fname)
            else:
                self.grabber.save_capture(self.old_pic_path)

    def cb_pause_request(self, widget):
        logger.debug("Pause requested.")
        self.recording_paused = True
        self.recorder.pause_recording()

    def cb_unpause_request(self, widget):
        logger.debug("Unpause requested.")
        self.recording_paused = False
        self.recorder.unpause_recording()

    def cb_save_done(self, widget, result):
        logger.debug("Save Done, result: {0}".format(result))
        if self.main_mode == MODE_SCREENCAST:
            self.old_vid_path = result
        else:
            self.old_pic_path = result

        self.window.set_sensitive(True)
        self.window.show_all()
        self.window.present()
        self.window.move(prefs.main_x, prefs.main_y)

    def cb_save_cancel(self, widget):
        try:
            logger.debug("Save canceled, removing {0}".format(self.tempfile))
            os.remove(self.tempfile)
        except OSError:
            logger.info("Failed to remove tempfile {0}".format(self.tempfile))
        except AttributeError:
            logger.info("Failed to remove tempfile {0}".format(self.tempfile))
            pass

        self.window.set_sensitive(True)
        self.window.show_all()
        self.window.present()
        self.window.move(prefs.main_x, prefs.main_y)

    def cb_help_about(self, widget):
        AboutDialog(self.icons)

    def cb_edit_request(self, widget, data):
        (command, arg_list) = data
        arg_list.insert(0, command)
        #
        # Use the current autosave filename for edit file.
        #
        fname = get_next_filename(prefs.video_dest, prefs.autosave_video_file,
                                  CODEC_LIST[prefs.codec][3])

        shutil.move(self.tempfile, fname)
        arg_list.append(fname)
        logger.debug("Edit request, cmd: {0}".format(arg_list))
        try:
            Popen(arg_list)
        except:
            logger.warning("Failed to open selected editor.")
        self.window.set_sensitive(True)
        self.window.show_all()

    def cb_check_cursor(self, widget):
        name = Gtk.Buildable.get_name(widget)
        if name == "chk_cursor":
            prefs.capture_cursor = widget.get_active()
        elif name == "chk_cursor_pic":
            prefs.capture_cursor_pic = widget.get_active()
        elif name == "chk_cursor_broadcast":
            prefs.capture_cursor_broadcast = widget.get_active()
        logger.debug("Toggled {}: {}.".format(name, widget.get_active()))

    def cb_check_borders_pic(self, widget):
        prefs.capture_borders_pic = widget.get_active()
        logger.debug("Capture borders_pic: {0}.".format(
            prefs.capture_borders_pic))

    def cb_check_speakers(self, widget):
        name = Gtk.Buildable.get_name(widget)
        if name == "chk_speakers":
            prefs.capture_speakers = widget.get_active()
        elif name == "chk_speakers_webcam":
            prefs.capture_speakers_webcam = widget.get_active()
        elif name == "chk_speakers_broadcast":
            prefs.capture_speakers_broadcast = widget.get_active()
        logger.debug("Toggled {}: {}.".format(name, widget.get_active()))

    def cb_check_microphone(self, widget):
        name = Gtk.Buildable.get_name(widget)
        if name == "chk_microphone":
            prefs.capture_microphone = widget.get_active()
        elif name == "chk_microphone_webcam":
            prefs.capture_microphone_webcam = widget.get_active()
        elif name == "chk_microphone_broadcast":
            prefs.capture_microphone_broadcast = widget.get_active()
        logger.debug("Toggled {}: {}.".format(name, widget.get_active()))

    def cb_spinbutton_delay_change(self, widget):
        prefs.countdown_timer = widget.get_value_as_int()
        logger.debug("Start delay now: {0}".format(prefs.countdown_timer))

    def cb_check_webcam(self, widget):
        name = Gtk.Buildable.get_name(widget)
        if widget.get_active() is True:
            if self.cam is None:
                logger.debug("Turning ON webcam window.")
                self.cam = GWebcam()
                self.cam.start()
                if name == "chk_webcam_broadcast":
                    self.chk_webcam.set_active(True)
                else:
                    self.chk_webcam_broadcast.set_active(True)
        else:
            if self.cam is not None:
                logger.debug("Turning OFF webcam window.")
                self.cam.close()
                self.cam = None
                if name == "chk_webcam_broadcast":
                    self.chk_webcam.set_active(False)
                else:
                    self.chk_webcam_broadcast.set_active(False)

    def cb_check_keypresses(self, widget):
        name = Gtk.Buildable.get_name(widget)
        if name == "chk_keypresses":
            prefs.capture_keys = widget.get_active()
        elif name == "chk_keypresses_broadcast":
            prefs.capture_keys_broadcast = widget.get_active()
        logger.debug("Toggled {}: {}.".format(name, widget.get_active()))

    #
    # Other somewhat useful stuff ...
    #

    def run_counter(self):
        if self.recording:
            logger.debug("Already recording, not starting again.")
            return
        #
        # Annoyances with the menus
        #
        logger.debug("Running Counter.")
        (main_x, main_y) = self.window.get_position()
        if main_x and main_y:
            prefs.main_x = main_x
            prefs.main_y = main_y

        self.indicator.recording = True
        self.indicator.menuitem_start.set_sensitive(False)
        self.indicator.menuitem_pause.set_sensitive(False)
        self.indicator.menuitem_finish.set_sensitive(True)
        self.indicator.menuitem_quit.set_sensitive(False)
        self.indicator.menuitem_finish.set_label(_("Cancel countdown"))
        self.in_countdown = True

        self.indicator.blink_set_state(BLINK_START)

        if prefs.sound:
            if (self.main_mode == MODE_SCREENCAST and prefs.capture_speakers) or \
               (self.main_mode == MODE_BROADCAST and prefs.capture_speakers_broadcast) or \
               (self.main_mode == MODE_WEBCAM and prefs.capture_speakers_webcam):
                try:
                    audio_source = prefs.speaker_sources[prefs.audio_source][1]
                    try:
                        audio_channels = prefs.pa_q.get_source_info_by_index(
                            prefs.speaker_sources[
                                prefs.audio_source][0])[2].channels
                    except:
                        audio_channels = 1
                    logger.debug(
                        "Detected audio channels: {}".format(audio_channels))
                except IndexError:
                    logger.warning(
                        "It appears that speakers audio source isn't set up correctly."
                    )
                    audio_source = None
            else:
                audio_source = None
                audio_channels = 1

            if (self.main_mode == MODE_SCREENCAST and prefs.capture_microphone) or \
               (self.main_mode == MODE_BROADCAST and prefs.capture_microphone_broadcast) or \
               (self.main_mode == MODE_WEBCAM and prefs.capture_microphone_webcam):
                try:
                    audio2_source = prefs.mic_sources[prefs.audio2_source][1]
                    try:
                        audio2_channels = prefs.pa_q.get_source_info_by_index(
                            prefs.speaker_sources[
                                prefs.audio2_source][0])[2].channels
                    except:
                        audio2_channels = 1
                    logger.debug(
                        "Detected audio2 channels: {}".format(audio2_channels))
                except IndexError:
                    logger.warning(
                        "It appears that microphone audio source isn't set up correctly."
                    )
                    audio2_source = None
            else:
                audio2_source = None
                audio2_channels = 1
        else:
            audio_source = None
            audio_channels = 1
            audio2_source = None
            audio2_channels = 1

        #
        # Get appropriate coordinates for recording
        #

        video_source = None

        screen = HW.get_current_screen(self.window)
        prefs.current_screen = screen

        if self.main_mode == MODE_WEBCAM:
            video_source = CAM_RESOLUTIONS[prefs.webcam_source]
        elif self.record_mode == MODE_ALL:
            video_source = HW.combined_screen
        else:
            video_source = HW.screens[screen]

        if self.main_mode in [MODE_SCREENCAST, MODE_WEBCAM, MODE_BROADCAST]:
            self.recorder = Screencast(self.main_mode)
            self.recorder.setup_sources(
                video_source, audio_source, audio2_source,
                prefs.area if self.record_mode == MODE_AREA
                and self.main_mode not in [MODE_WEBCAM, MODE_BROADCAST] else
                None, prefs.xid if self.record_mode == MODE_WIN
                and self.main_mode not in [MODE_WEBCAM, MODE_BROADCAST] else
                None, audio_channels, audio2_channels)

            self.recorder.connect("flush-done", self.cb_flush_done)

        elif self.main_mode == MODE_SCREENSHOT:
            self.grabber = Grabber()
            self.grabber.setup_sources(
                video_source,
                prefs.area if self.record_mode == MODE_AREA else None,
                prefs.xid if self.record_mode == MODE_WIN else None)
            self.grabber.connect("flush-done", self.cb_flush_done)

        self.countdown = CountdownWindow(self.indicator,
                                         show_window=prefs.countdown_splash)
        self.countdown.connect("counter-finished", self.cb_counter_finished)
        logger.debug("Starting counter.")
        self.countdown.run(prefs.countdown_timer)
        self.recording = True
        logger.debug("Hiding main window.")
        self.window.hide()
        if self.main_mode == MODE_SCREENCAST or self.main_mode == MODE_SCREENSHOT:
            try:
                if self.record_mode == MODE_AREA and prefs.area:
                    logger.debug("Showing recording outline.")
                    self.outline_window = OutlineWindow(
                        prefs.area[0], prefs.area[1], prefs.area[4],
                        prefs.area[5])
                    self.outline_window.show()
                else:
                    logger.debug(
                        "Ubuntu 13.04 or higher not detected, recording outline not shown."
                    )
            except:
                logger.debug("Unable to show recording outline.")

    def setup_translations(self):
        gettext.bindtextdomain("kazam", "/usr/share/locale")
        gettext.textdomain("kazam")
        locale.bindtextdomain("kazam", "/usr/share/locale")
        locale.textdomain("kazam")
        currentLocale = locale.getlocale()
        try:
            locale.setlocale(locale.LC_ALL, currentLocale)
        except Exception as e:
            logger.exception(
                "EXCEPTION: Setlocale failed, no language support.")

    def restore_UI(self):
        self.window.move(prefs.main_x, prefs.main_y)
        self.chk_cursor.set_active(prefs.capture_cursor)
        self.chk_speakers.set_active(prefs.capture_speakers)
        self.chk_microphone.set_active(prefs.capture_microphone)
        self.chk_keypresses.set_active(prefs.capture_keys)

        self.chk_cursor_pic.set_active(prefs.capture_cursor_pic)
        self.chk_borders_pic.set_active(prefs.capture_borders_pic)
        self.spinbutton_delay.set_value(prefs.countdown_timer)

        self.chk_speakers_webcam.set_active(prefs.capture_speakers_webcam)
        self.chk_microphone_webcam.set_active(prefs.capture_microphone_webcam)

        self.chk_cursor_broadcast.set_active(prefs.capture_cursor_broadcast)
        self.chk_speakers_broadcast.set_active(
            prefs.capture_speakers_broadcast)
        self.chk_microphone_broadcast.set_active(
            prefs.capture_microphone_broadcast)
        self.chk_keypresses_broadcast.set_active(prefs.capture_keys_broadcast)

        #
        # Turn off the combined screen icon if we don't have more than one screen.
        #
        if HW.combined_screen:
            self.btn_allscreens.set_sensitive(True)
        else:
            self.btn_allscreens.set_sensitive(False)

    def cb_webcam_change(self, widget):
        prefs.get_webcam_sources()
        logger.debug("Webcams: {}".format(prefs.webcam_sources))
        if prefs.webcam_sources:
            logger.debug("Adding Webcam UI items.")
            self.toolbar_main.insert(self.btn_webcam, -1)
            self.toolbar_main.show_all()
            self.chk_webcam.set_active(False)
            self.chk_webcam.set_sensitive(True)
        else:
            logger.debug("Removing Webcam UI items.")
            self.toolbar_main.remove(self.btn_webcam)
            self.chk_webcam.set_sensitive(False)
            self.chk_webcam.set_active(False)
            if self.btn_webcam.get_active():
                self.btn_screencast.set_active(True)
Esempio n. 2
0
class KazamApp(GObject.GObject):

    def __init__(self, datadir, dist, debug, test, sound, silent):
        GObject.GObject.__init__(self)
        logger.debug("Setting variables.")

        prefs.datadir = datadir
        prefs.get_sound_files()

        self.startup = True
        prefs.debug = debug
        prefs.test = test
        prefs.dist = dist
        prefs.silent = silent
        prefs.sound = sound

        self.setup_translations()

        if prefs.sound:
            try:
                from kazam.pulseaudio.pulseaudio import pulseaudio_q
                prefs.sound = True
            except:
                logger.warning("Pulse Audio Failed to load. Sound recording disabled.")
                prefs.sound = False

        self.icons = Gtk.IconTheme.get_default()
        self.default_cursor = Gdk.Cursor(Gdk.CursorType.LEFT_PTR)

        # Initialize all the variables

        self.main_x = 0
        self.main_y = 0
        self.countdown = None
        self.tempfile = ""
        self.recorder = None
        self.area_window = None
        self.select_window = None
        self.outline_window = None
        self.old_vid_path = None
        self.old_pic_path = None
        self.in_countdown = False
        self.recording_paused = False
        self.recording = False
        self.main_mode = 0
        self.record_mode = 0
        self.last_mode = None

        if prefs.sound:
            prefs.pa_q = pulseaudio_q()
            prefs.pa_q.start()

        self.mainmenu = MainMenu()

        logger.debug("Connecting indicator signals.")
        logger.debug("Starting in silent mode: {0}".format(prefs.silent))
        self.indicator = KazamIndicator(prefs.silent)
        self.indicator.connect("indicator-quit-request", self.cb_quit_request)
        self.indicator.connect("indicator-show-request", self.cb_show_request)
        self.indicator.connect("indicator-start-request", self.cb_start_request)
        self.indicator.connect("indicator-stop-request", self.cb_stop_request)
        self.indicator.connect("indicator-pause-request", self.cb_pause_request)
        self.indicator.connect("indicator-unpause-request", self.cb_unpause_request)
        self.indicator.connect("indicator-about-request", self.cb_about_request)

        self.mainmenu.connect("file-quit", self.cb_quit_request)
        self.mainmenu.connect("file-preferences", self.cb_preferences_request)
        self.mainmenu.connect("help-about", self.cb_help_about)

        #
        # Setup UI
        #
        logger.debug("Main Window UI setup.")

        self.builder = Gtk.Builder()
        self.builder.add_from_file(os.path.join(prefs.datadir, "ui", "kazam.ui"))
        self.builder.connect_signals(self)
        for w in self.builder.get_objects():
            if issubclass(type(w), Gtk.Buildable):
                name = Gtk.Buildable.get_name(w)
                setattr(self, name, w)
            else:
                logger.debug("Unable to get name for '%s'" % w)

        # Retrieve gdk_win for the root window
        self.gdk_win = self.window.get_root_window()

        #
        # Attach main menu, so that
        #
        self.MainGrid.attach(self.mainmenu.menubar, 0, 0, 1, 1)

        self.main_context = self.toolbar_main.get_style_context()
        self.main_context.add_class(Gtk.STYLE_CLASS_PRIMARY_TOOLBAR)
        self.main_context.connect("changed", self.cb_main_context_change)
        self.main_fg_color = self.main_context.get_color(Gtk.StateFlags.ACTIVE)

        self.btn_cast = Gtk.RadioToolButton(group=None)
        self.btn_cast.set_label(_("Screencast"))
        self.btn_cast.set_tooltip_text(_("Record a video of your desktop."))
        cast_icon = self.icons.lookup_icon("kazam-screencast-symbolic", 24, Gtk.IconLookupFlags.FORCE_SIZE)
        if cast_icon:
            cast_icon_pixbuf, was_sym = cast_icon.load_symbolic(self.main_fg_color, None, None, None)
            cast_img  = Gtk.Image.new_from_pixbuf(cast_icon_pixbuf)
            self.btn_cast.set_icon_widget(cast_img)
        self.btn_cast.set_active(True)
        self.btn_cast.set_name("MAIN_SCREENCAST")
        self.btn_cast.connect("toggled", self.cb_main_toggled)

        self.btn_shot = Gtk.RadioToolButton(group=self.btn_cast)
        self.btn_shot.set_label(_("Screenshot"))
        self.btn_shot.set_tooltip_text(_("Record a picture of your desktop."))
        shot_icon = self.icons.lookup_icon("kazam-screenshot-symbolic", 24, Gtk.IconLookupFlags.FORCE_SIZE)
        if shot_icon:
            shot_icon_pixbuf, was_sym = shot_icon.load_symbolic(self.main_fg_color, None, None, None)
            shot_img  = Gtk.Image.new_from_pixbuf(shot_icon_pixbuf)
            self.btn_shot.set_icon_widget(shot_img)
        self.btn_shot.set_name("MAIN_SCREENSHOT")
        self.btn_shot.connect("toggled", self.cb_main_toggled)

        self.sep_1 = Gtk.SeparatorToolItem()
        self.sep_1.set_draw(False)
        self.sep_1.set_expand(True)
        self.toolbar_main.insert(self.sep_1, -1)
        self.toolbar_main.insert(self.btn_cast, -1)
        self.toolbar_main.insert(self.btn_shot, -1)
        self.toolbar_main.insert(self.sep_1, -1)

        # Auxiliary toolbar
        self.aux_context = self.toolbar_aux.get_style_context()
        self.aux_context.add_class(Gtk.STYLE_CLASS_TOOLBAR)
        self.aux_fg_color = self.aux_context.get_color(Gtk.StateFlags.ACTIVE)

        self.btn_full = Gtk.RadioToolButton(group=None)
        self.btn_full.set_label(_("Fullscreen"))
        self.btn_full.set_tooltip_text(_("Capture contents of the current screen."))
        full_icon = self.icons.lookup_icon("kazam-fullscreen-symbolic", 24, Gtk.IconLookupFlags.FORCE_SIZE)
        if full_icon:
            full_icon_pixbuf, was_sym = full_icon.load_symbolic(self.aux_fg_color, None, None, None)
            full_img  = Gtk.Image.new_from_pixbuf(full_icon_pixbuf)
            self.btn_full.set_icon_widget(full_img)
        self.btn_full.set_active(True)
        self.btn_full.set_name("MODE_FULL")
        self.btn_full.connect("toggled", self.cb_record_mode_toggled)

        self.btn_allscreens = Gtk.RadioToolButton(group=self.btn_full)
        self.btn_allscreens.set_label(_("All Screens"))
        self.btn_allscreens.set_tooltip_text(_("Capture contents of all of your screens."))
        allscreens_icon = self.icons.lookup_icon("kazam-all-screens-symbolic", 24, Gtk.IconLookupFlags.FORCE_SIZE)
        if allscreens_icon:
            allscreens_icon_pixbuf, was_sym = allscreens_icon.load_symbolic(self.aux_fg_color, None, None, None)
            allscreens_img  = Gtk.Image.new_from_pixbuf(allscreens_icon_pixbuf)
            self.btn_allscreens.set_icon_widget(allscreens_img)
        self.btn_allscreens.set_name("MODE_ALL")
        self.btn_allscreens.connect("toggled", self.cb_record_mode_toggled)
        if HW.combined_screen is None:
            self.btn_allscreens.set_sensitive(False)

        self.btn_window = Gtk.RadioToolButton(group=self.btn_full)
        self.btn_window.set_label(_("Window"))
        self.btn_window.set_tooltip_text(_("Capture contents of a single window."))
        window_icon = self.icons.lookup_icon("kazam-window-symbolic", 24, Gtk.IconLookupFlags.FORCE_SIZE)
        if window_icon:
            window_icon_pixbuf, was_sym = window_icon.load_symbolic(self.aux_fg_color, None, None, None)
            window_img  = Gtk.Image.new_from_pixbuf(window_icon_pixbuf)
            self.btn_window.set_icon_widget(window_img)
        self.btn_window.set_name("MODE_WIN")
        self.btn_window.connect("toggled", self.cb_record_mode_toggled)
        self.btn_window.connect("clicked", self.cb_record_window_clicked)

        self.btn_area = Gtk.RadioToolButton(group=self.btn_full)
        self.btn_area.set_label(_("Area"))
        self.btn_area.set_tooltip_text(_("Capture a pre-selected area of your screen."))
        area_icon = self.icons.lookup_icon("kazam-area-symbolic", 24, Gtk.IconLookupFlags.FORCE_SIZE)
        if area_icon:
            area_icon_pixbuf, was_sym = area_icon.load_symbolic(self.aux_fg_color, None, None, None)
            area_img  = Gtk.Image.new_from_pixbuf(area_icon_pixbuf)
            self.btn_area.set_icon_widget(area_img)
        self.btn_area.set_name("MODE_AREA")
        self.btn_area.connect("toggled", self.cb_record_mode_toggled)
        self.btn_area.connect("clicked", self.cb_record_area_clicked)

        self.sep_2 = Gtk.SeparatorToolItem()
        self.sep_2.set_draw(False)
        self.sep_2.set_expand(True)
        self.toolbar_aux.insert(self.sep_2, -1)
        self.toolbar_aux.insert(self.btn_full, -1)
        self.toolbar_aux.insert(self.btn_allscreens, -1)
        self.toolbar_aux.insert(self.btn_window, -1)
        self.toolbar_aux.insert(self.btn_area, -1)
        self.toolbar_aux.insert(self.sep_2, -1)

        self.ntb_main.set_current_page(0)
        self.btn_record.grab_focus()

        #
        # Take care of screen size changes.
        #
        self.default_screen = Gdk.Screen.get_default()
        self.default_screen.connect("size-changed", self.cb_screen_size_changed)
        self.window.connect("configure-event", self.cb_configure_event)

        # Fetch sources info, take care of all the widgets and saved settings and show main window
        if prefs.sound:
            prefs.get_audio_sources()

        if not prefs.silent:
            self.window.show_all()
        else:
            logger.info("""Starting in silent mode:\n"""
                        """  SUPER-CTRL-W to toggle main window.\n"""
                        """  SUPER-CTRL-R to start recording.\n"""
                        """  SUPER-CTRL-F to finish recording.\n"""
                        """  SUPER-CTRL-P to pause/resume recording.\n"""
                        """  SUPER-CTRL-Q to quit.\n"""
                        )

        self.restore_UI()

        HW.get_current_screen(self.window)
        self.startup = False

    #
    # Callbacks, go down here ...
    #

    #
    # Mode of operation toggles
    #

    def cb_main_toggled(self, widget):
        name = widget.get_name()
        if name == "MAIN_SCREENCAST" and widget.get_active():
            logger.debug("Main toggled: {0}".format(name))
            self.main_mode = MODE_SCREENCAST
            self.ntb_main.set_current_page(0)
            self.indicator.menuitem_start.set_label(_("Start recording"))

        elif name == "MAIN_SCREENSHOT" and widget.get_active():
            logger.debug("Main toggled: {0}".format(name))
            self.main_mode = MODE_SCREENSHOT
            self.ntb_main.set_current_page(1)
            if self.record_mode == MODE_WIN:
                self.last_mode.set_active(True)
            self.indicator.menuitem_start.set_label(_("Take screenshot"))
            if self.record_mode == "MODE_WIN":
                self.chk_borders_pic.set_sensitive(True)
            else:
                self.chk_borders_pic.set_sensitive(False)

    #
    # Record mode toggles
    #
    def cb_record_mode_toggled(self, widget):
        if widget.get_active():
            self.current_mode = widget
        else:
            self.last_mode = widget

        if widget.get_name() == "MODE_AREA" and widget.get_active():
            logger.debug("Area ON.")
            self.area_window = AreaWindow()
            self.tmp_sig1 = self.area_window.connect("area-selected", self.cb_area_selected)
            self.tmp_sig2 = self.area_window.connect("area-canceled", self.cb_area_canceled)
            self.record_mode = MODE_AREA

        if widget.get_name() == "MODE_AREA" and not widget.get_active():
            logger.debug("Area OFF.")
            if self.area_window:
                self.area_window.disconnect(self.tmp_sig1)
                self.area_window.disconnect(self.tmp_sig2)
                self.area_window.window.destroy()
                self.area_window = None

        if widget.get_name() == "MODE_FULL" and widget.get_active():
            logger.debug("Capture full screen.")
            self.record_mode = MODE_FULL

        if widget.get_name() == "MODE_ALL" and widget.get_active():
            logger.debug("Capture all screens.")
            self.record_mode = MODE_ALL

        if widget.get_name() == "MODE_WIN" and widget.get_active():
            logger.debug("Window capture ON.")
            self.select_window = SelectWindow()
            self.tmp_sig3 = self.select_window.connect("window-selected", self.cb_window_selected)
            self.tmp_sig4 = self.select_window.connect("window-canceled", self.cb_window_canceled)
            self.record_mode = MODE_WIN
            self.chk_borders_pic.set_sensitive(True)

        if widget.get_name() == "MODE_WIN" and not widget.get_active():
            logger.debug("Window capture OFF.")
            self.chk_borders_pic.set_sensitive(False)
            if self.select_window:
                self.select_window.disconnect(self.tmp_sig3)
                self.select_window.disconnect(self.tmp_sig4)
                self.select_window.window.destroy()
                self.select_window = None

    def cb_main_context_change(self, widget):
        #
        # If this is the only way on how to deal with symbolic icons, then someone needs spanking ...
        #
        if widget.get_state() == Gtk.StateFlags.BACKDROP:
            self.main_fg_color = self.main_context.get_color(Gtk.StateFlags.ACTIVE)
            self.aux_fg_color = self.aux_context.get_color(Gtk.StateFlags.ACTIVE)

            #
            # Update icons on the main toolbar
            #
            cast_icon = self.icons.lookup_icon("kazam-screencast-symbolic", 24, Gtk.IconLookupFlags.FORCE_SIZE)
            if cast_icon:
                cast_icon_pixbuf, was_sym = cast_icon.load_symbolic(self.main_fg_color, None, None, None)
                cast_img = Gtk.Image.new_from_pixbuf(cast_icon_pixbuf)
                self.btn_cast.set_icon_widget(cast_img)
                cast_img.show_all()

            shot_icon = self.icons.lookup_icon("kazam-screenshot-symbolic", 24, Gtk.IconLookupFlags.FORCE_SIZE)
            if shot_icon:
                shot_icon_pixbuf, was_sym = shot_icon.load_symbolic(self.main_fg_color, None, None, None)
                shot_img = Gtk.Image.new_from_pixbuf(shot_icon_pixbuf)
                self.btn_shot.set_icon_widget(shot_img)
                shot_img.show_all()

            #
            # Update icons on the aux toolbar
            #
            full_icon = self.icons.lookup_icon("kazam-fullscreen-symbolic", 24, Gtk.IconLookupFlags.FORCE_SIZE)
            if full_icon:
                full_icon_pixbuf, was_sym = full_icon.load_symbolic(self.aux_fg_color, None, None, None)
                full_img = Gtk.Image.new_from_pixbuf(full_icon_pixbuf)
                self.btn_full.set_icon_widget(full_img)
                full_img.show_all()

            allscreens_icon = self.icons.lookup_icon("kazam-all-screens-symbolic", 24, Gtk.IconLookupFlags.FORCE_SIZE)
            if allscreens_icon:
                allscreens_icon_pixbuf, was_sym = allscreens_icon.load_symbolic(self.aux_fg_color, None, None, None)
                allscreens_img = Gtk.Image.new_from_pixbuf(allscreens_icon_pixbuf)
                self.btn_allscreens.set_icon_widget(allscreens_img)
                allscreens_img.show_all()

            window_icon = self.icons.lookup_icon("kazam-window-symbolic", 24, Gtk.IconLookupFlags.FORCE_SIZE)
            if window_icon:
                window_icon_pixbuf, was_sym = window_icon.load_symbolic(self.aux_fg_color, None, None, None)
                window_img = Gtk.Image.new_from_pixbuf(window_icon_pixbuf)
                self.btn_window.set_icon_widget(window_img)
                window_img.show_all()

            area_icon = self.icons.lookup_icon("kazam-area-symbolic", 24, Gtk.IconLookupFlags.FORCE_SIZE)
            if area_icon:
                area_icon_pixbuf, was_sym = area_icon.load_symbolic(self.aux_fg_color, None, None, None)
                area_img = Gtk.Image.new_from_pixbuf(area_icon_pixbuf)
                self.btn_area.set_icon_widget(area_img)
                area_img.show_all()

    #
    # Unity quick list callbacks
    #

    def cb_ql_screencast(self, menu, data):
        logger.debug("Screencast quicklist activated.")
        self.btn_cast.set_active(True)
        self.run_counter()

    def cb_ql_screenshot(self, menu, data):
        logger.debug("Screenshot quicklist activated.")
        self.btn_shot.set_active(True)
        self.run_counter()

    def cb_record_area_clicked(self, widget):
        if self.area_window:
            logger.debug("Area mode clicked.")
            self.area_window.window.show_all()
            self.window.set_sensitive(False)

    def cb_record_window_clicked(self, widget):
        if self.select_window:
            logger.debug("Window mode clicked.")
            self.select_window.window.show_all()
            self.window.set_sensitive(False)

    def cb_area_selected(self, widget):
        logger.debug("Area selected: SX: {0}, SY: {1}, EX: {2}, EY: {3}".format(
            self.area_window.startx,
            self.area_window.starty,
            self.area_window.endx,
            self.area_window.endy))
        logger.debug("Area selected: GX: {0}, GY: {1}, GX: {2}, GY: {3}".format(
            self.area_window.g_startx,
            self.area_window.g_starty,
            self.area_window.g_endx,
            self.area_window.g_endy))
        prefs.area = (self.area_window.g_startx,
                      self.area_window.g_starty,
                      self.area_window.g_endx,
                      self.area_window.g_endy,
                      self.area_window.width,
                      self.area_window.height)
        self.window.set_sensitive(True)

    def cb_area_canceled(self, widget):
        logger.debug("Area selection canceled.")
        self.window.set_sensitive(True)
        self.last_mode.set_active(True)

    def cb_window_selected(self, widget):
        prefs.xid = self.select_window.xid
        prefs.xid_geometry = self.select_window.geometry
        logger.debug("Window selected: {0} - {1}".format(self.select_window.win_name, prefs.xid))
        logger.debug("Window geometry: {0}".format(self.select_window.geometry))
        self.window.set_sensitive(True)

    def cb_window_canceled(self, widget):
        logger.debug("Window selection canceled.")
        self.window.set_sensitive(True)
        self.last_mode.set_active(True)

    def cb_screen_size_changed(self, screen):
        logger.debug("Screen size changed.")
        HW.get_screens()
        #
        # If combined screen was set to none, turn off the button for all screens
        #
        if HW.combined_screen:
            self.btn_allscreens.set_sensitive(True)
        else:
            self.btn_allscreens.set_sensitive(False)

    def cb_configure_event(self, widget, event):
        if event.type == Gdk.EventType.CONFIGURE:
            prefs.main_x = event.x
            prefs.main_y = event.y

    def cb_quit_request(self, indicator):
        logger.debug("Quit requested.")
        # Restore cursor, just in case if by some chance stays set to cross-hairs
        self.gdk_win.set_cursor(self.default_cursor)
        (prefs.main_x, prefs.main_y) = self.window.get_position()
        try:
            os.remove(self.recorder.tempfile)
            os.remove("{0}.mux".format(self.recorder.tempfile))
        except OSError:
            logger.info("Unable to delete one of the temporary files. Check your temporary directory.")
        except AttributeError:
            pass

        prefs.save_config()

        if prefs.sound:
            prefs.pa_q.end()

        Gtk.main_quit()

    def cb_preferences_request(self, indicator):
        logger.debug("Preferences requested.")
        self.preferences_window = Preferences()
        self.preferences_window.open()

    def cb_show_request(self, indicator):
        if not self.window.get_property("visible"):
            logger.debug("Show requested, raising window.")
            self.window.show_all()
            self.window.present()
            self.window.move(prefs.main_x, prefs.main_y)
        else:
            self.window.hide()

    def cb_close_clicked(self, indicator):
        (prefs.main_x, prefs.main_y) = self.window.get_position()
        self.window.hide()

    def cb_about_request(self, activated):
        AboutDialog(self.icons)

    def cb_delete_event(self, widget, user_data):
        self.cb_quit_request(None)

    def cb_start_request(self, widget):
        logger.debug("Start recording selected.")
        self.run_counter()

    def cb_record_clicked(self, widget):
        logger.debug("Record clicked, invoking Screencast.")
        self.run_counter()

    def cb_counter_finished(self, widget):
        logger.debug("Counter finished.")
        self.in_countdown = False
        self.countdown = None
        self.indicator.blink_set_state(BLINK_STOP)
        if self.main_mode == MODE_SCREENCAST:
            self.indicator.menuitem_finish.set_label(_("Finish recording"))
            self.indicator.menuitem_pause.set_sensitive(True)
            self.indicator.start_recording()
            self.recorder.start_recording()
        elif self.main_mode == MODE_SCREENSHOT:
            self.indicator.hide_it()
            self.grabber.grab()
            self.indicator.show_it()

    def cb_stop_request(self, widget):
        self.recording = False

        if self.outline_window:
            self.outline_window.hide()
            self.outline_window.window.destroy()
            self.outline_window = None

        if self.in_countdown:
            logger.debug("Cancel countdown request.")
            self.countdown.cancel_countdown()
            self.countdown = None
            self.indicator.menuitem_finish.set_label(_("Finish recording"))
            self.window.set_sensitive(True)
            self.window.show()
            self.window.present()
        else:
            if self.recording_paused:
                self.recorder.unpause_recording()
            logger.debug("Stop request.")
            self.recorder.stop_recording()
            self.tempfile = self.recorder.get_tempfile()
            logger.debug("Recorded tmp file: {0}".format(self.tempfile))
            logger.debug("Waiting for data to flush.")

    def cb_flush_done(self, widget):
        if self.main_mode == MODE_SCREENCAST and prefs.autosave_video:
            logger.debug("Autosaving enabled.")
            fname = get_next_filename(prefs.autosave_video_dir,
                                      prefs.autosave_video_file,
                                      CODEC_LIST[prefs.codec][3])

            shutil.move(self.tempfile, fname)

            self.window.set_sensitive(True)
            self.window.show()
            self.window.present()
        elif self.main_mode == MODE_SCREENCAST:
            self.done_recording = DoneRecording(self.icons,
                                            self.tempfile,
                                            prefs.codec,
                                            self.old_vid_path)
            logger.debug("Done Recording initialized.")
            self.done_recording.connect("save-done", self.cb_save_done)
            self.done_recording.connect("save-cancel", self.cb_save_cancel)
            self.done_recording.connect("edit-request", self.cb_edit_request)
            logger.debug("Done recording signals connected.")
            self.done_recording.show_all()
            self.window.set_sensitive(False)

        elif self.main_mode == MODE_SCREENSHOT:
            if self.outline_window:
                self.outline_window.hide()
                self.outline_window.window.destroy()
                self.outline_window = None

            self.grabber.connect("save-done", self.cb_save_done)
            self.indicator.recording = False
            self.indicator.menuitem_start.set_sensitive(True)
            self.indicator.menuitem_pause.set_sensitive(False)
            self.indicator.menuitem_pause.set_active(False)
            self.indicator.menuitem_finish.set_sensitive(False)
            self.indicator.menuitem_quit.set_sensitive(True)

            if prefs.autosave_picture:
                fname = get_next_filename(prefs.autosave_picture_dir,
                                          prefs.autosave_picture_file,
                                          ".png")
                self.grabber.autosave(fname)
            else:
                self.grabber.save_capture(self.old_pic_path)

    def cb_pause_request(self, widget):
        logger.debug("Pause requested.")
        self.recording_paused = True
        self.recorder.pause_recording()

    def cb_unpause_request(self, widget):
        logger.debug("Unpause requested.")
        self.recording_paused = False
        self.recorder.unpause_recording()

    def cb_save_done(self, widget, result):
        logger.debug("Save Done, result: {0}".format(result))
        if self.main_mode == MODE_SCREENCAST:
            self.old_vid_path = result
        else:
            self.old_pic_path = result

        self.window.set_sensitive(True)
        self.window.show_all()
        self.window.present()
        self.window.move(prefs.main_x, prefs.main_y)

    def cb_save_cancel(self, widget):
        try:
            logger.debug("Save canceled, removing {0}".format(self.tempfile))
            os.remove(self.tempfile)
        except OSError:
            logger.info("Failed to remove tempfile {0}".format(self.tempfile))
        except AttributeError:
            logger.info("Failed to remove tempfile {0}".format(self.tempfile))
            pass

        self.window.set_sensitive(True)
        self.window.show_all()
        self.window.present()
        self.window.move(prefs.main_x, prefs.main_y)

    def cb_help_about(self, widget):
        AboutDialog(self.icons)

    def cb_edit_request(self, widget, data):
        (command, arg_list) = data
        arg_list.insert(0, command)
        #
        # Use the current autosave filename for edit file.
        #
        fname = get_next_filename(prefs.video_dest,
                                  prefs.autosave_video_file,
                                  CODEC_LIST[prefs.codec][3])

        shutil.move(self.tempfile, fname)
        arg_list.append(fname)
        logger.debug("Edit request, cmd: {0}".format(arg_list))
        try:
            Popen(arg_list)
        except:
            logger.warning("Failed to open selected editor.")
        self.window.set_sensitive(True)
        self.window.show_all()

    def cb_check_cursor(self, widget):
        prefs.capture_cursor = widget.get_active()
        logger.debug("Capture cursor: {0}.".format(prefs.capture_cursor))

    def cb_check_cursor_pic(self, widget):
        prefs.capture_cursor_pic = widget.get_active()
        logger.debug("Capture cursor_pic: {0}.".format(prefs.capture_cursor_pic))

    def cb_check_borders_pic(self, widget):
        prefs.capture_borders_pic = widget.get_active()
        logger.debug("Capture borders_pic: {0}.".format(prefs.capture_borders_pic))

    def cb_check_speakers(self, widget):
        prefs.capture_speakers = widget.get_active()
        logger.debug("Capture speakers: {0}.".format(prefs.capture_speakers))

    def cb_check_microphone(self, widget):
        prefs.capture_microphone = widget.get_active()
        logger.debug("Capture microphone: {0}.".format(prefs.capture_microphone))

    def cb_spinbutton_delay_change(self, widget):
        prefs.countdown_timer = widget.get_value_as_int()
        logger.debug("Start delay now: {0}".format(prefs.countdown_timer))

    #
    # Other somewhat useful stuff ...
    #

    def run_counter(self):
        #
        # Annoyances with the menus
        #
        (main_x, main_y) = self.window.get_position()
        if main_x and main_y:
            prefs.main_x = main_x
            prefs.main_y = main_y

        self.indicator.recording = True
        self.indicator.menuitem_start.set_sensitive(False)
        self.indicator.menuitem_pause.set_sensitive(False)
        self.indicator.menuitem_finish.set_sensitive(True)
        self.indicator.menuitem_quit.set_sensitive(False)
        self.indicator.menuitem_finish.set_label(_("Cancel countdown"))
        self.in_countdown = True

        self.indicator.blink_set_state(BLINK_START)

        if self.main_mode == MODE_SCREENCAST and prefs.sound:
            if prefs.capture_speakers:
                try:
                    audio_source = prefs.speaker_sources[prefs.audio_source][1]
                except  IndexError:
                    logger.warning("It appears that speakers audio source isn't set up correctly.")
                    audio_source = None
            else:
                audio_source = None

            if prefs.capture_microphone:
                try:
                    audio2_source = prefs.mic_sources[prefs.audio2_source][1]
                except IndexError:
                    logger.warning("It appears that microphone audio source isn't set up correctly.")
                    audio2_source = None
            else:
                audio2_source = None

        else:
            audio_source = None
            audio2_source = None

        #
        # Get appropriate coordinates for recording
        #

        video_source = None

        if self.record_mode == MODE_ALL:
            video_source = HW.combined_screen
        else:
            screen = HW.get_current_screen(self.window)
            video_source = HW.screens[screen]

        if self.main_mode == MODE_SCREENCAST:
            self.recorder = Screencast()
            self.recorder.setup_sources(video_source,
                                        audio_source,
                                        audio2_source,
                                        prefs.area if self.record_mode == MODE_AREA else None,
                                        prefs.xid if self.record_mode == MODE_WIN else None)

            self.recorder.connect("flush-done", self.cb_flush_done)

        elif self.main_mode == MODE_SCREENSHOT:
            self.grabber = Grabber()
            self.grabber.setup_sources(video_source,
                                       prefs.area if self.record_mode == MODE_AREA else None,
                                       prefs.xid if self.record_mode == MODE_WIN else None)
            self.grabber.connect("flush-done", self.cb_flush_done)

        self.countdown = CountdownWindow(self.indicator, show_window = prefs.countdown_splash)
        self.countdown.connect("counter-finished", self.cb_counter_finished)
        self.countdown.run(prefs.countdown_timer)
        self.recording = True
        logger.debug("Hiding main window.")
        self.window.hide()
        try:
            if self.record_mode == MODE_AREA and prefs.area:
                if prefs.dist[0] == 'Ubuntu' and int(prefs.dist[1].split(".")[0]) > 12:
                    logger.debug("Showing recording outline.")
                    self.outline_window = OutlineWindow(prefs.area[0],
                                                        prefs.area[1],
                                                        prefs.area[4],
                                                        prefs.area[5])
                    self.outline_window.show()
                else:
                    logger.debug("Ubuntu 13.04 or higher not detected, recording outline not shown.")
        except:
                logger.debug("Unable to show recording outline.")

    def setup_translations(self):
        gettext.bindtextdomain("kazam", "/usr/share/locale")
        gettext.textdomain("kazam")
        try:
            locale.setlocale(locale.LC_ALL, "")
        except Exception as e:
            logger.exception("EXCEPTION: Setlocale failed, no language support.")

    def restore_UI (self):
        self.window.move(prefs.main_x, prefs.main_y)
        self.chk_cursor.set_active(prefs.capture_cursor)
        self.chk_speakers.set_active(prefs.capture_speakers)
        self.chk_microphone.set_active(prefs.capture_microphone)
        self.chk_cursor_pic.set_active(prefs.capture_cursor_pic)
        self.chk_borders_pic.set_active(prefs.capture_borders_pic)
        self.spinbutton_delay.set_value(prefs.countdown_timer)

        #
        # Turn off the combined screen icon if we don't have more than one screen.
        #
        if HW.combined_screen:
            self.btn_allscreens.set_sensitive(True)
        else:
            self.btn_allscreens.set_sensitive(False)
Esempio n. 3
0
class KazamApp(GObject.GObject):
    def __init__(self, datadir, dist, debug, test, sound, silent):
        GObject.GObject.__init__(self)
        logger.debug("Setting variables.")

        prefs.datadir = datadir
        prefs.get_sound_files()

        self.startup = True
        prefs.debug = debug
        prefs.test = test
        prefs.dist = dist
        prefs.silent = silent
        prefs.sound = sound

        self.setup_translations()

        if prefs.sound:
            try:
                from kazam.pulseaudio.pulseaudio import pulseaudio_q
                prefs.sound = True
            except:
                logger.warning(
                    "Pulse Audio Failed to load. Sound recording disabled.")
                prefs.sound = False

        self.icons = Gtk.IconTheme.get_default()
        self.default_cursor = Gdk.Cursor(Gdk.CursorType.LEFT_PTR)

        # Initialize all the variables

        self.main_x = 0
        self.main_y = 0
        self.countdown = None
        self.tempfile = ""
        self.recorder = None
        self.area_window = None
        self.select_window = None
        self.outline_window = None
        self.old_vid_path = None
        self.old_pic_path = None
        self.in_countdown = False
        self.recording_paused = False
        self.recording = False
        self.main_mode = 0
        self.record_mode = 0
        self.last_mode = None

        if prefs.sound:
            prefs.pa_q = pulseaudio_q()
            prefs.pa_q.start()

        self.mainmenu = MainMenu()

        logger.debug("Connecting indicator signals.")
        logger.debug("Starting in silent mode: {0}".format(prefs.silent))
        self.indicator = KazamIndicator(prefs.silent)
        self.indicator.connect("indicator-quit-request", self.cb_quit_request)
        self.indicator.connect("indicator-show-request", self.cb_show_request)
        self.indicator.connect("indicator-start-request",
                               self.cb_start_request)
        self.indicator.connect("indicator-stop-request", self.cb_stop_request)
        self.indicator.connect("indicator-pause-request",
                               self.cb_pause_request)
        self.indicator.connect("indicator-unpause-request",
                               self.cb_unpause_request)
        self.indicator.connect("indicator-about-request",
                               self.cb_about_request)

        self.mainmenu.connect("file-quit", self.cb_quit_request)
        self.mainmenu.connect("file-preferences", self.cb_preferences_request)
        self.mainmenu.connect("help-about", self.cb_help_about)

        #
        # Setup UI
        #
        logger.debug("Main Window UI setup.")

        self.builder = Gtk.Builder()
        self.builder.add_from_file(
            os.path.join(prefs.datadir, "ui", "kazam.ui"))
        self.builder.connect_signals(self)
        for w in self.builder.get_objects():
            if issubclass(type(w), Gtk.Buildable):
                name = Gtk.Buildable.get_name(w)
                setattr(self, name, w)
            else:
                logger.debug("Unable to get name for '%s'" % w)

        # Retrieve gdk_win for the root window
        self.gdk_win = self.window.get_root_window()

        #
        # Attach main menu, so that
        #
        self.MainGrid.attach(self.mainmenu.menubar, 0, 0, 1, 1)

        self.main_context = self.toolbar_main.get_style_context()
        self.main_context.add_class(Gtk.STYLE_CLASS_PRIMARY_TOOLBAR)
        self.main_context.connect("changed", self.cb_main_context_change)
        self.main_fg_color = self.main_context.get_color(Gtk.StateFlags.ACTIVE)

        self.btn_cast = Gtk.RadioToolButton(group=None)
        self.btn_cast.set_label(_("Screencast"))
        self.btn_cast.set_tooltip_text(_("Record a video of your desktop."))
        cast_icon = self.icons.lookup_icon("kazam-screencast-symbolic", 24,
                                           Gtk.IconLookupFlags.FORCE_SIZE)
        if cast_icon:
            cast_icon_pixbuf, was_sym = cast_icon.load_symbolic(
                self.main_fg_color, None, None, None)
            cast_img = Gtk.Image.new_from_pixbuf(cast_icon_pixbuf)
            self.btn_cast.set_icon_widget(cast_img)
        self.btn_cast.set_active(True)
        self.btn_cast.set_name("MAIN_SCREENCAST")
        self.btn_cast.connect("toggled", self.cb_main_toggled)

        self.btn_shot = Gtk.RadioToolButton(group=self.btn_cast)
        self.btn_shot.set_label(_("Screenshot"))
        self.btn_shot.set_tooltip_text(_("Record a picture of your desktop."))
        shot_icon = self.icons.lookup_icon("kazam-screenshot-symbolic", 24,
                                           Gtk.IconLookupFlags.FORCE_SIZE)
        if shot_icon:
            shot_icon_pixbuf, was_sym = shot_icon.load_symbolic(
                self.main_fg_color, None, None, None)
            shot_img = Gtk.Image.new_from_pixbuf(shot_icon_pixbuf)
            self.btn_shot.set_icon_widget(shot_img)
        self.btn_shot.set_name("MAIN_SCREENSHOT")
        self.btn_shot.connect("toggled", self.cb_main_toggled)

        self.sep_1 = Gtk.SeparatorToolItem()
        self.sep_1.set_draw(False)
        self.sep_1.set_expand(True)
        self.toolbar_main.insert(self.sep_1, -1)
        self.toolbar_main.insert(self.btn_cast, -1)
        self.toolbar_main.insert(self.btn_shot, -1)
        self.toolbar_main.insert(self.sep_1, -1)

        # Auxiliary toolbar
        self.aux_context = self.toolbar_aux.get_style_context()
        self.aux_context.add_class(Gtk.STYLE_CLASS_TOOLBAR)
        self.aux_fg_color = self.aux_context.get_color(Gtk.StateFlags.ACTIVE)

        self.btn_full = Gtk.RadioToolButton(group=None)
        self.btn_full.set_label(_("Fullscreen"))
        self.btn_full.set_tooltip_text(
            _("Capture contents of the current screen."))
        full_icon = self.icons.lookup_icon("kazam-fullscreen-symbolic", 24,
                                           Gtk.IconLookupFlags.FORCE_SIZE)
        if full_icon:
            full_icon_pixbuf, was_sym = full_icon.load_symbolic(
                self.aux_fg_color, None, None, None)
            full_img = Gtk.Image.new_from_pixbuf(full_icon_pixbuf)
            self.btn_full.set_icon_widget(full_img)
        self.btn_full.set_active(True)
        self.btn_full.set_name("MODE_FULL")
        self.btn_full.connect("toggled", self.cb_record_mode_toggled)

        self.btn_allscreens = Gtk.RadioToolButton(group=self.btn_full)
        self.btn_allscreens.set_label(_("All Screens"))
        self.btn_allscreens.set_tooltip_text(
            _("Capture contents of all of your screens."))
        allscreens_icon = self.icons.lookup_icon(
            "kazam-all-screens-symbolic", 24, Gtk.IconLookupFlags.FORCE_SIZE)
        if allscreens_icon:
            allscreens_icon_pixbuf, was_sym = allscreens_icon.load_symbolic(
                self.aux_fg_color, None, None, None)
            allscreens_img = Gtk.Image.new_from_pixbuf(allscreens_icon_pixbuf)
            self.btn_allscreens.set_icon_widget(allscreens_img)
        self.btn_allscreens.set_name("MODE_ALL")
        self.btn_allscreens.connect("toggled", self.cb_record_mode_toggled)
        if HW.combined_screen is None:
            self.btn_allscreens.set_sensitive(False)

        self.btn_window = Gtk.RadioToolButton(group=self.btn_full)
        self.btn_window.set_label(_("Window"))
        self.btn_window.set_tooltip_text(
            _("Capture contents of a single window."))
        window_icon = self.icons.lookup_icon("kazam-window-symbolic", 24,
                                             Gtk.IconLookupFlags.FORCE_SIZE)
        if window_icon:
            window_icon_pixbuf, was_sym = window_icon.load_symbolic(
                self.aux_fg_color, None, None, None)
            window_img = Gtk.Image.new_from_pixbuf(window_icon_pixbuf)
            self.btn_window.set_icon_widget(window_img)
        self.btn_window.set_name("MODE_WIN")
        self.btn_window.connect("toggled", self.cb_record_mode_toggled)
        self.btn_window.connect("clicked", self.cb_record_window_clicked)

        self.btn_area = Gtk.RadioToolButton(group=self.btn_full)
        self.btn_area.set_label(_("Area"))
        self.btn_area.set_tooltip_text(
            _("Capture a pre-selected area of your screen."))
        area_icon = self.icons.lookup_icon("kazam-area-symbolic", 24,
                                           Gtk.IconLookupFlags.FORCE_SIZE)
        if area_icon:
            area_icon_pixbuf, was_sym = area_icon.load_symbolic(
                self.aux_fg_color, None, None, None)
            area_img = Gtk.Image.new_from_pixbuf(area_icon_pixbuf)
            self.btn_area.set_icon_widget(area_img)
        self.btn_area.set_name("MODE_AREA")
        self.btn_area.connect("toggled", self.cb_record_mode_toggled)
        self.btn_area.connect("clicked", self.cb_record_area_clicked)

        self.sep_2 = Gtk.SeparatorToolItem()
        self.sep_2.set_draw(False)
        self.sep_2.set_expand(True)
        self.toolbar_aux.insert(self.sep_2, -1)
        self.toolbar_aux.insert(self.btn_full, -1)
        self.toolbar_aux.insert(self.btn_allscreens, -1)
        self.toolbar_aux.insert(self.btn_window, -1)
        self.toolbar_aux.insert(self.btn_area, -1)
        self.toolbar_aux.insert(self.sep_2, -1)

        self.ntb_main.set_current_page(0)
        self.btn_record.grab_focus()

        #
        # Take care of screen size changes.
        #
        self.default_screen = Gdk.Screen.get_default()
        self.default_screen.connect("size-changed",
                                    self.cb_screen_size_changed)
        self.window.connect("configure-event", self.cb_configure_event)

        # Fetch sources info, take care of all the widgets and saved settings and show main window
        if prefs.sound:
            prefs.get_audio_sources()

        if not prefs.silent:
            self.window.show_all()
        else:
            logger.info("""Starting in silent mode:\n"""
                        """  SUPER-CTRL-W to toggle main window.\n"""
                        """  SUPER-CTRL-R to start recording.\n"""
                        """  SUPER-CTRL-F to finish recording.\n"""
                        """  SUPER-CTRL-P to pause/resume recording.\n"""
                        """  SUPER-CTRL-Q to quit.\n""")

        self.restore_UI()

        HW.get_current_screen(self.window)
        #self.set_mode(prefs.last_mode)
        self.set_default_mode()
        self.startup = False

    #
    # Callbacks, go down here ...
    #

    #
    # Mode of operation toggles
    #

    def cb_main_toggled(self, widget):
        name = widget.get_name()
        if widget.get_active():
            self.set_mode(name)

    def set_mode(self, mode, setToggle=False):
        logger.debug("Mode toggled: {0}".format(mode))

        if mode == "MAIN_SCREENCAST":
            self.main_mode = MODE_SCREENCAST
            self.ntb_main.set_current_page(0)
            self.indicator.menuitem_start.set_label(_("Start recording"))
        elif mode == "MAIN_SCREENSHOT":
            self.main_mode = MODE_SCREENSHOT
            self.ntb_main.set_current_page(1)
            if self.record_mode == MODE_WIN:
                self.last_mode.set_active(True)
            self.indicator.menuitem_start.set_label(_("Take screenshot"))
            if self.record_mode == "MODE_WIN":
                self.chk_borders_pic.set_sensitive(True)
            else:
                self.chk_borders_pic.set_sensitive(False)
        prefs.last_mode = mode

    def set_default_mode(self):
        if prefs.last_mode == "MAIN_SCREENCAST":
            self.btn_shot.set_active(False)
            self.btn_cast.set_active(True)
        elif prefs.last_mode == "MAIN_SCREENSHOT":
            self.btn_cast.set_active(False)
            self.btn_shot.set_active(True)

    #
    # Record mode toggles
    #
    def cb_record_mode_toggled(self, widget):
        if widget.get_active():
            self.current_mode = widget
        else:
            self.last_mode = widget

        if widget.get_name() == "MODE_AREA" and widget.get_active():
            logger.debug("Area ON.")
            self.area_window = AreaWindow()
            self.tmp_sig1 = self.area_window.connect("area-selected",
                                                     self.cb_area_selected)
            self.tmp_sig2 = self.area_window.connect("area-canceled",
                                                     self.cb_area_canceled)
            self.record_mode = MODE_AREA

        if widget.get_name() == "MODE_AREA" and not widget.get_active():
            logger.debug("Area OFF.")
            if self.area_window:
                self.area_window.disconnect(self.tmp_sig1)
                self.area_window.disconnect(self.tmp_sig2)
                self.area_window.window.destroy()
                self.area_window = None

        if widget.get_name() == "MODE_FULL" and widget.get_active():
            logger.debug("Capture full screen.")
            self.record_mode = MODE_FULL

        if widget.get_name() == "MODE_ALL" and widget.get_active():
            logger.debug("Capture all screens.")
            self.record_mode = MODE_ALL

        if widget.get_name() == "MODE_WIN" and widget.get_active():
            logger.debug("Window capture ON.")
            self.select_window = SelectWindow()
            self.tmp_sig3 = self.select_window.connect("window-selected",
                                                       self.cb_window_selected)
            self.tmp_sig4 = self.select_window.connect("window-canceled",
                                                       self.cb_window_canceled)
            self.record_mode = MODE_WIN
            self.chk_borders_pic.set_sensitive(True)

        if widget.get_name() == "MODE_WIN" and not widget.get_active():
            logger.debug("Window capture OFF.")
            self.chk_borders_pic.set_sensitive(False)
            if self.select_window:
                self.select_window.disconnect(self.tmp_sig3)
                self.select_window.disconnect(self.tmp_sig4)
                self.select_window.window.destroy()
                self.select_window = None

    def cb_main_context_change(self, widget):
        #
        # If this is the only way on how to deal with symbolic icons, then someone needs spanking ...
        #
        if widget.get_state() == Gtk.StateFlags.BACKDROP:
            self.main_fg_color = self.main_context.get_color(
                Gtk.StateFlags.ACTIVE)
            self.aux_fg_color = self.aux_context.get_color(
                Gtk.StateFlags.ACTIVE)

            #
            # Update icons on the main toolbar
            #
            cast_icon = self.icons.lookup_icon("kazam-screencast-symbolic", 24,
                                               Gtk.IconLookupFlags.FORCE_SIZE)
            if cast_icon:
                cast_icon_pixbuf, was_sym = cast_icon.load_symbolic(
                    self.main_fg_color, None, None, None)
                cast_img = Gtk.Image.new_from_pixbuf(cast_icon_pixbuf)
                self.btn_cast.set_icon_widget(cast_img)
                cast_img.show_all()

            shot_icon = self.icons.lookup_icon("kazam-screenshot-symbolic", 24,
                                               Gtk.IconLookupFlags.FORCE_SIZE)
            if shot_icon:
                shot_icon_pixbuf, was_sym = shot_icon.load_symbolic(
                    self.main_fg_color, None, None, None)
                shot_img = Gtk.Image.new_from_pixbuf(shot_icon_pixbuf)
                self.btn_shot.set_icon_widget(shot_img)
                shot_img.show_all()

            #
            # Update icons on the aux toolbar
            #
            full_icon = self.icons.lookup_icon("kazam-fullscreen-symbolic", 24,
                                               Gtk.IconLookupFlags.FORCE_SIZE)
            if full_icon:
                full_icon_pixbuf, was_sym = full_icon.load_symbolic(
                    self.aux_fg_color, None, None, None)
                full_img = Gtk.Image.new_from_pixbuf(full_icon_pixbuf)
                self.btn_full.set_icon_widget(full_img)
                full_img.show_all()

            allscreens_icon = self.icons.lookup_icon(
                "kazam-all-screens-symbolic", 24,
                Gtk.IconLookupFlags.FORCE_SIZE)
            if allscreens_icon:
                allscreens_icon_pixbuf, was_sym = allscreens_icon.load_symbolic(
                    self.aux_fg_color, None, None, None)
                allscreens_img = Gtk.Image.new_from_pixbuf(
                    allscreens_icon_pixbuf)
                self.btn_allscreens.set_icon_widget(allscreens_img)
                allscreens_img.show_all()

            window_icon = self.icons.lookup_icon(
                "kazam-window-symbolic", 24, Gtk.IconLookupFlags.FORCE_SIZE)
            if window_icon:
                window_icon_pixbuf, was_sym = window_icon.load_symbolic(
                    self.aux_fg_color, None, None, None)
                window_img = Gtk.Image.new_from_pixbuf(window_icon_pixbuf)
                self.btn_window.set_icon_widget(window_img)
                window_img.show_all()

            area_icon = self.icons.lookup_icon("kazam-area-symbolic", 24,
                                               Gtk.IconLookupFlags.FORCE_SIZE)
            if area_icon:
                area_icon_pixbuf, was_sym = area_icon.load_symbolic(
                    self.aux_fg_color, None, None, None)
                area_img = Gtk.Image.new_from_pixbuf(area_icon_pixbuf)
                self.btn_area.set_icon_widget(area_img)
                area_img.show_all()

    #
    # Unity quick list callbacks
    #

    def cb_ql_screencast(self, menu, data):
        logger.debug("Screencast quicklist activated.")
        self.btn_cast.set_active(True)
        self.run_counter()

    def cb_ql_screenshot(self, menu, data):
        logger.debug("Screenshot quicklist activated.")
        self.btn_shot.set_active(True)
        self.run_counter()

    def cb_record_area_clicked(self, widget):
        if self.area_window:
            logger.debug("Area mode clicked.")
            self.area_window.window.show_all()
            self.window.set_sensitive(False)

    def cb_record_window_clicked(self, widget):
        if self.select_window:
            logger.debug("Window mode clicked.")
            self.select_window.window.show_all()
            self.window.set_sensitive(False)

    def cb_area_selected(self, widget):
        logger.debug(
            "Area selected: SX: {0}, SY: {1}, EX: {2}, EY: {3}".format(
                self.area_window.startx, self.area_window.starty,
                self.area_window.endx, self.area_window.endy))
        logger.debug(
            "Area selected: GX: {0}, GY: {1}, GX: {2}, GY: {3}".format(
                self.area_window.g_startx, self.area_window.g_starty,
                self.area_window.g_endx, self.area_window.g_endy))
        prefs.area = (self.area_window.g_startx, self.area_window.g_starty,
                      self.area_window.g_endx, self.area_window.g_endy,
                      self.area_window.width, self.area_window.height)
        self.window.set_sensitive(True)

    def cb_area_canceled(self, widget):
        logger.debug("Area selection canceled.")
        self.window.set_sensitive(True)
        self.last_mode.set_active(True)

    def cb_window_selected(self, widget):
        prefs.xid = self.select_window.xid
        prefs.xid_geometry = self.select_window.geometry
        logger.debug("Window selected: {0} - {1}".format(
            self.select_window.win_name, prefs.xid))
        logger.debug("Window geometry: {0}".format(
            self.select_window.geometry))
        self.window.set_sensitive(True)

    def cb_window_canceled(self, widget):
        logger.debug("Window selection canceled.")
        self.window.set_sensitive(True)
        self.last_mode.set_active(True)

    def cb_screen_size_changed(self, screen):
        logger.debug("Screen size changed.")
        HW.get_screens()
        #
        # If combined screen was set to none, turn off the button for all screens
        #
        if HW.combined_screen:
            self.btn_allscreens.set_sensitive(True)
        else:
            self.btn_allscreens.set_sensitive(False)

    def cb_configure_event(self, widget, event):
        if event.type == Gdk.EventType.CONFIGURE:
            prefs.main_x = event.x
            prefs.main_y = event.y

    def cb_quit_request(self, indicator):
        logger.debug("Quit requested.")
        # Restore cursor, just in case if by some chance stays set to cross-hairs
        self.gdk_win.set_cursor(self.default_cursor)
        (prefs.main_x, prefs.main_y) = self.window.get_position()
        try:
            os.remove(self.recorder.tempfile)
            os.remove("{0}.mux".format(self.recorder.tempfile))
        except OSError:
            logger.info(
                "Unable to delete one of the temporary files. Check your temporary directory."
            )
        except AttributeError:
            pass

        prefs.save_config()

        if prefs.sound:
            prefs.pa_q.end()

        Gtk.main_quit()

    def cb_preferences_request(self, indicator):
        logger.debug("Preferences requested.")
        self.preferences_window = Preferences()
        self.preferences_window.open()

    def cb_show_request(self, indicator):
        if not self.window.get_property("visible"):
            logger.debug("Show requested, raising window.")
            self.window.show_all()
            self.window.present()
            self.window.move(prefs.main_x, prefs.main_y)
        else:
            self.window.hide()

    def cb_close_clicked(self, indicator):
        (prefs.main_x, prefs.main_y) = self.window.get_position()
        self.window.hide()

    def cb_about_request(self, activated):
        AboutDialog(self.icons)

    def cb_delete_event(self, widget, user_data):
        self.cb_quit_request(None)

    def cb_start_request(self, widget):
        logger.debug("Start recording selected.")
        self.run_counter()

    def cb_record_clicked(self, widget):
        logger.debug("Record clicked, invoking Screencast.")
        self.run_counter()

    def cb_counter_finished(self, widget):
        logger.debug("Counter finished.")
        self.in_countdown = False
        self.countdown = None
        self.indicator.blink_set_state(BLINK_STOP)
        if self.main_mode == MODE_SCREENCAST:
            self.indicator.menuitem_finish.set_label(_("Finish recording"))
            self.indicator.menuitem_pause.set_sensitive(True)
            self.indicator.start_recording()
            self.recorder.start_recording()
        elif self.main_mode == MODE_SCREENSHOT:
            self.indicator.hide_it()
            self.grabber.grab()
            self.indicator.show_it()

    def cb_stop_request(self, widget):
        self.recording = False

        if self.outline_window:
            self.outline_window.hide()
            self.outline_window.window.destroy()
            self.outline_window = None

        if self.in_countdown:
            logger.debug("Cancel countdown request.")
            self.countdown.cancel_countdown()
            self.countdown = None
            self.indicator.menuitem_finish.set_label(_("Finish recording"))
            self.window.set_sensitive(True)
            self.window.show()
            self.window.present()
        else:
            if self.recording_paused:
                self.recorder.unpause_recording()
            logger.debug("Stop request.")
            self.recorder.stop_recording()
            self.tempfile = self.recorder.get_tempfile()
            logger.debug("Recorded tmp file: {0}".format(self.tempfile))
            logger.debug("Waiting for data to flush.")

    def cb_flush_done(self, widget):
        if self.main_mode == MODE_SCREENCAST and prefs.autosave_video:
            logger.debug("Autosaving enabled.")
            fname = get_next_filename(prefs.autosave_video_dir,
                                      prefs.autosave_video_file,
                                      CODEC_LIST[prefs.codec][3])

            shutil.move(self.tempfile, fname)

            self.window.set_sensitive(True)
            self.window.show()
            self.window.present()
        elif self.main_mode == MODE_SCREENCAST:
            self.done_recording = DoneRecording(self.icons, self.tempfile,
                                                prefs.codec, self.old_vid_path)
            logger.debug("Done Recording initialized.")
            self.done_recording.connect("save-done", self.cb_save_done)
            self.done_recording.connect("save-cancel", self.cb_save_cancel)
            self.done_recording.connect("edit-request", self.cb_edit_request)
            logger.debug("Done recording signals connected.")
            self.done_recording.show_all()
            self.window.set_sensitive(False)

        elif self.main_mode == MODE_SCREENSHOT:
            if self.outline_window:
                self.outline_window.hide()
                self.outline_window.window.destroy()
                self.outline_window = None

            self.grabber.connect("save-done", self.cb_save_done)
            self.indicator.recording = False
            self.indicator.menuitem_start.set_sensitive(True)
            self.indicator.menuitem_pause.set_sensitive(False)
            self.indicator.menuitem_pause.set_active(False)
            self.indicator.menuitem_finish.set_sensitive(False)
            self.indicator.menuitem_quit.set_sensitive(True)

            flags = self.grabber.SAVE_FLAGS_FILE
            filename = self.old_pic_path

            if prefs.capture_editor:
                flags |= self.grabber.SAVE_FLAGS_EDIT_FIRST

            if prefs.autosave_picture:
                flags |= self.grabber.SAVE_FLAGS_FILE_AUTO
                filename = get_next_filename(prefs.autosave_picture_dir,
                                             prefs.autosave_picture_file,
                                             ".png")
            if prefs.capture_clipboard_pic:
                flags |= self.grabber.SAVE_FLAGS_CLIPBOARD
                if prefs.capture_clipboard_only:
                    flags &= ~self.grabber.SAVE_FLAGS_FILE

            self.grabber.save_capture(filename, flags)

    def cb_pause_request(self, widget):
        logger.debug("Pause requested.")
        self.recording_paused = True
        self.recorder.pause_recording()

    def cb_unpause_request(self, widget):
        logger.debug("Unpause requested.")
        self.recording_paused = False
        self.recorder.unpause_recording()

    def cb_save_done(self, widget, result):
        logger.debug("Save Done, result: {0}".format(
            result if result is not None else "<no file>"))
        if self.main_mode == MODE_SCREENCAST:
            self.old_vid_path = result
        else:
            if result is not None:
                self.old_pic_path = result

        self.window.set_sensitive(True)
        self.window.show_all()
        self.window.present()
        self.window.move(prefs.main_x, prefs.main_y)

    def cb_save_cancel(self, widget):
        try:
            logger.debug("Save canceled, removing {0}".format(self.tempfile))
            os.remove(self.tempfile)
        except OSError:
            logger.info("Failed to remove tempfile {0}".format(self.tempfile))
        except AttributeError:
            logger.info("Failed to remove tempfile {0}".format(self.tempfile))
            pass

        self.window.set_sensitive(True)
        self.window.show_all()
        self.window.present()
        self.window.move(prefs.main_x, prefs.main_y)

    def cb_help_about(self, widget):
        AboutDialog(self.icons)

    def cb_edit_request(self, widget, data):
        (command, arg_list) = data
        arg_list.insert(0, command)
        #
        # Use the current autosave filename for edit file.
        #
        fname = get_next_filename(prefs.video_dest, prefs.autosave_video_file,
                                  CODEC_LIST[prefs.codec][3])

        shutil.move(self.tempfile, fname)
        arg_list.append(fname)
        logger.debug("Edit request, cmd: {0}".format(arg_list))
        try:
            Popen(arg_list)
        except:
            logger.warning("Failed to open selected editor.")
        self.window.set_sensitive(True)
        self.window.show_all()

    def cb_check_cursor(self, widget):
        prefs.capture_cursor = widget.get_active()
        logger.debug("Capture cursor: {0}.".format(prefs.capture_cursor))

    def cb_check_cursor_pic(self, widget):
        prefs.capture_cursor_pic = widget.get_active()
        logger.debug("Capture cursor_pic: {0}.".format(
            prefs.capture_cursor_pic))

    def cb_check_editor(self, widget):
        prefs.capture_editor = widget.get_active()
        logger.debug("Capture editor: {0}.".format(prefs.capture_editor))

    def cb_check_clipboard(self, widget):
        prefs.capture_clipboard_pic = widget.get_active()
        logger.debug("Capture to clipboard: {0}.".format(
            prefs.capture_clipboard_pic))
        self.chk_clipboard_skipsave.set_sensitive(prefs.capture_clipboard_pic)

    def cb_check_clipboard_skipsave(self, widget):
        prefs.capture_clipboard_only = widget.get_active()
        logger.debug(
            "Capture to clipboard only (skip save option): {0}.".format(
                prefs.capture_clipboard_only))

    def cb_check_borders_pic(self, widget):
        prefs.capture_borders_pic = widget.get_active()
        logger.debug("Capture borders_pic: {0}.".format(
            prefs.capture_borders_pic))

    def cb_check_speakers(self, widget):
        prefs.capture_speakers = widget.get_active()
        logger.debug("Capture speakers: {0}.".format(prefs.capture_speakers))

    def cb_check_microphone(self, widget):
        prefs.capture_microphone = widget.get_active()
        logger.debug("Capture microphone: {0}.".format(
            prefs.capture_microphone))

    def cb_spinbutton_delay_change(self, widget):
        prefs.countdown_timer = widget.get_value_as_int()
        logger.debug("Start delay now: {0}".format(prefs.countdown_timer))

    #
    # Other somewhat useful stuff ...
    #

    def run_counter(self):
        #
        # Annoyances with the menus
        #
        (main_x, main_y) = self.window.get_position()
        if main_x and main_y:
            prefs.main_x = main_x
            prefs.main_y = main_y

        self.indicator.recording = True
        self.indicator.menuitem_start.set_sensitive(False)
        self.indicator.menuitem_pause.set_sensitive(False)
        self.indicator.menuitem_finish.set_sensitive(True)
        self.indicator.menuitem_quit.set_sensitive(False)
        self.indicator.menuitem_finish.set_label(_("Cancel countdown"))
        self.in_countdown = True

        self.indicator.blink_set_state(BLINK_START)

        if self.main_mode == MODE_SCREENCAST and prefs.sound:
            if prefs.capture_speakers:
                try:
                    audio_source = prefs.speaker_sources[prefs.audio_source][1]
                except IndexError:
                    logger.warning(
                        "It appears that speakers audio source isn't set up correctly."
                    )
                    audio_source = None
            else:
                audio_source = None

            if prefs.capture_microphone:
                try:
                    audio2_source = prefs.mic_sources[prefs.audio2_source][1]
                except IndexError:
                    logger.warning(
                        "It appears that microphone audio source isn't set up correctly."
                    )
                    audio2_source = None
            else:
                audio2_source = None

        else:
            audio_source = None
            audio2_source = None

        #
        # Get appropriate coordinates for recording
        #

        video_source = None

        if self.record_mode == MODE_ALL:
            video_source = HW.combined_screen
        else:
            screen = HW.get_current_screen(self.window)
            video_source = HW.screens[screen]

        if self.main_mode == MODE_SCREENCAST:
            self.recorder = Screencast()
            self.recorder.setup_sources(
                video_source, audio_source, audio2_source,
                prefs.area if self.record_mode == MODE_AREA else None,
                prefs.xid if self.record_mode == MODE_WIN else None)

            self.recorder.connect("flush-done", self.cb_flush_done)

        elif self.main_mode == MODE_SCREENSHOT:
            self.grabber = Grabber()
            self.grabber.setup_sources(
                video_source,
                prefs.area if self.record_mode == MODE_AREA else None,
                prefs.xid if self.record_mode == MODE_WIN else None)
            self.grabber.connect("flush-done", self.cb_flush_done)

        self.countdown = CountdownWindow(self.indicator,
                                         show_window=prefs.countdown_splash)
        self.countdown.connect("counter-finished", self.cb_counter_finished)
        self.countdown.run(prefs.countdown_timer)
        self.recording = True
        logger.debug("Hiding main window.")
        self.window.hide()
        try:
            if self.record_mode == MODE_AREA and prefs.area:
                if prefs.dist[0] == 'Ubuntu' and int(
                        prefs.dist[1].split(".")[0]) > 12:
                    logger.debug("Showing recording outline.")
                    self.outline_window = OutlineWindow(
                        prefs.area[0], prefs.area[1], prefs.area[4],
                        prefs.area[5])
                    self.outline_window.show()
                else:
                    logger.debug(
                        "Ubuntu 13.04 or higher not detected, recording outline not shown."
                    )
        except:
            logger.debug("Unable to show recording outline.")

    def setup_translations(self):
        gettext.bindtextdomain("kazam", "/usr/share/locale")
        gettext.textdomain("kazam")
        try:
            locale.setlocale(locale.LC_ALL, "")
        except Exception as e:
            logger.exception(
                "EXCEPTION: Setlocale failed, no language support.")

    def restore_UI(self):
        self.window.move(prefs.main_x, prefs.main_y)
        self.chk_cursor.set_active(prefs.capture_cursor)
        self.chk_speakers.set_active(prefs.capture_speakers)
        self.chk_microphone.set_active(prefs.capture_microphone)
        self.chk_cursor_pic.set_active(prefs.capture_cursor_pic)
        self.chk_clipboard.set_active(prefs.capture_clipboard_pic)
        self.chk_clipboard_skipsave.set_active(prefs.capture_clipboard_only)
        self.chk_clipboard_skipsave.set_sensitive(prefs.capture_clipboard_pic)
        self.chk_borders_pic.set_active(prefs.capture_borders_pic)
        self.spinbutton_delay.set_value(prefs.countdown_timer)
        self.chk_editor.set_active(prefs.capture_editor)

        #
        # Turn off the combined screen icon if we don't have more than one screen.
        #
        if HW.combined_screen:
            self.btn_allscreens.set_sensitive(True)
        else:
            self.btn_allscreens.set_sensitive(False)