Esempio n. 1
0
class ANoise:
    """Control the sound indicator"""
    def __init__(self):
        # These 3 are needed
        GObject.threads_init()
        DBusGMainLoop(set_as_default=True)
        Gst.init(None)
        GLib.set_application_name(_('Ambient Noise'))
        self.sound_menu = SoundMenuControls('Ambient Noise', 'anoise')
        self.noise = Noise()
        self.win_preferences = Preferences(self)

        try:
            self.keybinder = Keybinder
            self.keybinder.init()
            if self.keybinder.bind('AudioPlay', self._sound_menu_play_toggle,
                                   None):
                self.keybinder.bind('AudioStop', self._sound_menu_stop, None)
                self.keybinder.bind('AudioPause', self._sound_menu_pause, None)
                self.keybinder.bind('AudioNext', self._sound_menu_next, None)
                self.keybinder.bind('AudioPrev', self._sound_menu_previous,
                                    None)
            else:
                self.keybinder = None

        except (ValueError, ImportError):
            self.keybinder = None

        # Need in a few DE
        try:
            self.window = GUI(self)
        except:
            pass

        self.player = Gst.ElementFactory.make(PLAYBIN, "player")
        self.player.connect("about-to-finish", self._loop)

        dummy_i18n = (_("Coffee Shop"), _("Fire"), _("Forest"), _("Night"),
                      _("Rain"), _("River"), _("Sea"), _("Storm"), _("Wind")
                      )  # Need i18n

        # Overwrite libraty methods
        self.sound_menu._sound_menu_is_playing = self._sound_menu_is_playing
        self.sound_menu._sound_menu_play = self._sound_menu_play
        self.sound_menu._sound_menu_pause = self._sound_menu_pause
        self.sound_menu._sound_menu_next = self._sound_menu_next
        self.sound_menu._sound_menu_previous = self._sound_menu_previous
        self.sound_menu._sound_menu_raise = self._sound_menu_raise
        self.sound_menu._sound_menu_play_toggle = self._sound_menu_play_toggle

        # Autostart when click on sound indicator icon
        threading.Timer(1, self._sound_menu_play).start()

    def _loop(self, message):
        """Start again the same sound in the EOS"""
        self.player.set_property('uri', self.noise.get_current_filename_uri())

    def _sound_menu_is_playing(self):
        """Called in the first click"""
        return self.is_playing

    def _sound_menu_play_toggle(self, keypress=None, data=None):
        """Play toggle, media keys have an expectation that play is a toggle"""
        if self.is_playing:
            self._sound_menu_pause('AudioPause')
        else:
            self._sound_menu_play('AudioPlay')

    def _sound_menu_play(self, keypress=None, data=None):
        """Play"""
        self.is_playing = True  # Need to overwrite this for an issue with autstart
        self.sound_menu.song_changed(
            self.noise.get_current_index(), '', '', self.noise.get_name(),
            urllib.parse.quote(self.noise.get_icon_uri(), ':/'),
            urllib.parse.quote(self.noise.get_current_filename_uri(), ':/'))
        self.player.set_property('uri', self.noise.get_current_filename_uri())
        self.player.set_state(Gst.State.PLAYING)
        self.sound_menu.signal_playing()

    def _sound_menu_stop(self, keypress=None, data=None):
        """Stop, different from pause in that it sets the pointer of the track to the start again"""
        self.is_playing = False
        self.player.set_state(
            Gst.State.READY)  # assuming this is akin to stop?
        self.sound_menu.signal_stopped()

    def _sound_menu_pause(self, keypress=None, data=None):
        """Pause"""
        self.is_playing = False  # Need to overwrite this for an issue with autstart
        self.player.set_state(Gst.State.PAUSED)
        self.sound_menu.signal_paused()

    def _set_new_play(self, what):
        """Next or Previous"""
        # Get Next/Previous
        if what == 'next':
            self.noise.set_next()
        if what == 'previous':
            self.noise.set_previous()
        # From pause?
        self.player.set_state(Gst.State.READY)
        # Play
        if self.is_playing:
            self._sound_menu_play()
        else:
            self.sound_menu.song_changed(
                self.noise.get_current_index(), '', '', self.noise.get_name(),
                urllib.parse.quote(self.noise.get_icon_uri(), ':/'),
                urllib.parse.quote(self.noise.get_current_filename_uri(),
                                   ':/'))

    def _sound_menu_previous(self, keypress=None, data=None):
        """Previous"""
        self._set_new_play('previous')

    def _sound_menu_next(self, keypress=None, data=None):
        """Next"""
        self._set_new_play('next')

    def _sound_menu_raise(self):
        """Click on player"""
        self.win_preferences.show()

    def set_timer(self, enable, seconds):
        if enable:
            self.timer = threading.Timer(seconds, self._set_future_pause)
            self.timer.start()
        else:
            self.timer.cancel()

    def _set_future_pause(self):
        self.win_preferences.set_show_timer()
        self._sound_menu_pause()
Esempio n. 2
0
class GUI:
    """This will be for DE as MATE 14.10+ which hasn't sound indicator with Gtk3"""
    def __init__(self, player):
        self.player = player
        self.win_preferences = Preferences(self)

        builder = Gtk.Builder()
        builder.add_from_file('/usr/share/anoise/anoise.ui')
        self.win_icon = builder.get_object('icon_noise')
        self.btn_play = builder.get_object('btn_play')
        self.lbl_title = builder.get_object('lbl_title')
        builder.connect_signals(self)
        self.window = builder.get_object('main_win')
        self.window.show_all()
        self._set_window_icon()

    def _set_window_icon(self):
        try:
            self.window.set_icon_from_file(
                self.player.noise.get_icon().replace('file://', ''))
            self.win_icon.set_from_file(self.player.noise.get_icon().replace(
                'file://', ''))
        except:
            self.window.set_icon_from_file(
                '/usr/share/icons/hicolor/48x48/apps/anoise.png')
            self.win_icon.set_from_file(
                '/usr/share/icons/hicolor/48x48/apps/anoise.png')
        self.lbl_title.set_text(self.player.noise.get_name())

    def on_btn_previous_clicked(self, widget, data=None):
        self.player._set_new_play('previous')
        image = Gtk.Image(stock=Gtk.STOCK_MEDIA_PAUSE)
        self.btn_play.set_image(image)
        self._set_window_icon()

    def on_btn_next_clicked(self, widget, data=None):
        self.player._set_new_play('next')
        image = Gtk.Image(stock=Gtk.STOCK_MEDIA_PAUSE)
        self.btn_play.set_image(image)
        self._set_window_icon()

    def _play(self):
        self.player.is_playing = True
        self.player._sound_menu_play()
        image = Gtk.Image(stock=Gtk.STOCK_MEDIA_PAUSE)
        self.btn_play.set_image(image)

    def _pause(self):
        if self.player.is_playing:
            self.player.is_playing = False
        self.player._sound_menu_pause()
        image = Gtk.Image(stock=Gtk.STOCK_MEDIA_PLAY)
        self.btn_play.set_image(image)

    def on_btn_play_pause_clicked(self, widget, data=None):
        if self.player.is_playing:
            self._pause()
        else:
            self._play()

    def on_menu_preferences_activate(self, widget, data=None):
        self.win_preferences.show()

    def set_timer(self, enable, seconds):
        if enable:
            self.timer = threading.Timer(seconds, self._set_future_pause)
            self.timer.start()
        else:
            self.timer.cancel()

    def _set_future_pause(self):
        self.win_preferences.set_show_timer()
        self._pause()

    def on_menu_about_activate(self, widget, data=None):
        webbrowser.open_new('http://anoise.tuxfamily.org')

    def on_main_win_delete_event(self, widget, data=None):
        try:
            self.timer.cancel()
        except:
            pass
        Gtk.main_quit()
Esempio n. 3
0
class ANoise:
    """Control the sound indicator"""
    def __init__(self):
        # These 3 are need
        GObject.threads_init()
        DBusGMainLoop(set_as_default=True)
        Gst.init(None)
        
        self.sound_menu = SoundMenuControls('anoise')
        self.noise = Noise()
        self.win_preferences = Preferences(self)
        
        # Need in a few DE
        try:
            self.window = GUI(self)
        except:
            pass
        
        self.player = Gst.ElementFactory.make(PLAYBIN, "player")
        self.player.connect("about-to-finish", self._loop)
        
        self.player.set_property('uri', self.noise.get_current_filename())
        self.is_playing = True
        
        dummy_i18n = (_("Coffee Shop"), _("Fire"), _("Forest"), _("Night"), _("Rain"), _("River"), _("Sea"), _("Storm"), _("Wind")) # Need i18n
        
        # Overwrite libraty methods
        self.sound_menu._sound_menu_is_playing = self._sound_menu_is_playing
        self.sound_menu._sound_menu_play       = self._sound_menu_play
        self.sound_menu._sound_menu_pause      = self._sound_menu_pause
        self.sound_menu._sound_menu_next       = self._sound_menu_next
        self.sound_menu._sound_menu_previous   = self._sound_menu_previous
        self.sound_menu._sound_menu_raise      = self._sound_menu_raise
        
        # Autostart when click on sound indicator icon
        threading.Timer(2, self._sound_menu_play).start()
    
    def _loop(self, message):
        """Start again the same sound in the EOS"""
        self.player.set_property('uri', self.noise.get_current_filename())
    
    def _sound_menu_is_playing(self):
        """Called in the first click"""
        return self.is_playing
    
    def _sound_menu_play(self):
        """Play"""
        self.is_playing = True # Need to overwrite this for an issue with autstart
        self.sound_menu.song_changed('', '', self.noise.get_name(), self.noise.get_icon())
        self.player.set_state(Gst.State.PLAYING)
        self.sound_menu.signal_playing()
    
    def _sound_menu_pause(self):
        """Pause"""
        self.is_playing = False # Need to overwrite this for an issue with autstart
        self.player.set_state(Gst.State.PAUSED)
        self.sound_menu.signal_paused()
    
    def _set_new_play(self, what):
        """Next or Previous"""
        self.noise.refresh_all_ogg()
        # Get Next/Previous
        if what == 'next':
            self.noise.set_next()
        if what == 'previous':
            self.noise.set_previous()
        # From pause?
        self.player.set_state(Gst.State.READY)
        if not self.is_playing:
            self.is_playing = True
        # Set new sound
        self.player.set_property('uri', self.noise.get_current_filename())
        # Play
        self._sound_menu_play()
    
    def _sound_menu_previous(self):
        """Previous"""
        self._set_new_play('previous')
    
    def _sound_menu_next(self):
        """Next"""
        self._set_new_play('next')
    
    def _sound_menu_raise(self):
        """Click on player"""
        self.win_preferences.show()
    
    def set_timer(self, enable, seconds):
        if enable:
            self.timer = threading.Timer(seconds, self._set_future_pause)
            self.timer.start()
        else:
            self.timer.cancel()
    
    def _set_future_pause(self):
        self.win_preferences.set_show_timer()
        self._sound_menu_pause()
Esempio n. 4
0
class Indicator:

    # ----------------------------------------------------------------------- #
    def __init__(self, player):

        # apparently appindicator will not quit on Ctrl-C by default. fix
        # bellow allows it to do so in Ctrl-C run the default action kernel
        # action which allows indicator to exit
        signal.signal(signal.SIGINT, signal.SIG_DFL)

        # expose the passing player to tht class
        self._player = player

        # remove registration to dbus, disabling MPRIS integration, mainly this
        # is done because current anoise MPRIS integration does not notify the
        # GUI element of play/pause/next/forward changes internally an attempt
        # at dbus manager that listens for anoise mpris notification fails due
        # to double signaling and handling of multiple MPRIS subscribed clients
        # and inability to distinguish which come from anoise
        self._player.sound_menu.remove_from_connection()

        #: DEBUG SETTING, used during development
        #: hide window ui, if it's the GUI class (rather then Indicator class)
        # if self._player.window.__class__.__name__ == 'GUI':
        #     self._player.window.window.hide()

        # build the preferences window
        self._preferences_window = Preferences(self)

        # expose the default gtk settings
        self._gtk_settings = Gtk.Settings.get_default()

        # expose the default icon theme
        self._default_icon_theme = Gtk.IconTheme.get_default()

        # expose "hicolor" theme as fallback theme
        self._fallback_icon_theme = Gtk.IconTheme()
        self._fallback_icon_theme.set_custom_theme('hicolor')

        # expose found appindicator and appindicator-pause icons
        self._appindicator_icon, self._appindicator_icon_pause = \
            self._get_indicator_icons()

        # build the appindicator
        self._appindicator, builder = self._make_appindicator()

        # expose the play/pause menu item to the class
        self._menuitem_play = builder.get_object('play_pause_toggle')
        # expose now playing menu item
        self._menuitem_now_playing = builder.get_object('now_playing')

        # expose now playing image
        self._image_now_playing = builder.get_object('image_now_playing')
        # expose play image
        self._image_play = builder.get_object('image_play')
        # expose pause image
        self._image_pause = builder.get_object('image_pause')

        # disable startup autoplay (ugh, terrible approach)
        # runs before indicator is made visible to show the "paused" icon
        self._disable_startup_autoplay()

        # set the indicator status to active
        self._appindicator.set_status(AppIndicator3.IndicatorStatus.ACTIVE)

        # update the noise icon in the ui and the appindicator
        self._update_now_playing()

    # ----------------------------------------------------------------------- #
    def set_timer(self, enable, seconds):
        # method is run by preferences window code, which is why it's public

        # it's strange that this code is run in the UI code.
        # if window ui and appindicator will both install you will end up with
        # two timers, so seems like runing both "ui"s is not a good idea
        # exclusive, unless preferences can be a singleton

        if enable:
            self.timer = threading.Timer(seconds, self._set_future_pause)
            self.timer.start()
        else:
            self.timer.cancel()

    # ----------------------------------------------------------------------- #
    def _disable_startup_autoplay(self):
        """
        Disable auto play on aplication startup. This is done by patching
        the self._player._sound_menu_play with function that pauses the player
        insteady of playing it, and the restores the original function after it
        was ran once. Unfortunately this is the only way to do this at this
        point.
        """

        # set all the gui statuses to "pause"
        self._pause()
        # preserve the original function
        original_func = self._player._sound_menu_play

        # create a patched function which pauses the play when run the FIRST
        # time and then restores the original _sound_menu_play to the player
        # object (sad, should not need to patch)
        def _sound_menu_play(*args, **kwargs):
            # pause
            self._player._sound_menu_pause()
            self._player._sound_menu_play = original_func

        # now patch the play function with our patched function
        self._player._sound_menu_play = _sound_menu_play

    # ----------------------------------------------------------------------- #
    def _make_appindicator(self):
        """
        Return constructed AppIndicator and it's menu.
        Also return the menu builder so we can update few of it's items
        """

        # get full glade file. assumption here is that the ui file in the same
        # folder as this script
        ui_file_path = os.path.join(
            os.path.realpath(os.path.dirname(__file__)), 'appindicator.ui')

        # force showing of images despite whatever the global setting is
        self._gtk_settings.props.gtk_button_images = True

        # build the apindicator menu from the glade file
        builder = Gtk.Builder()
        builder.add_from_file(ui_file_path)

        # create the appindicator
        appindicator = AppIndicator3.Indicator.new(
            APPINDICATOR_ID, self._appindicator_icon,
            AppIndicator3.IndicatorCategory.APPLICATION_STATUS)

        # get the appindicator menu
        menu = builder.get_object('appindicator_menu')

        # setup the signals for the appindicator menu items
        builder.connect_signals(self)

        # get the play/pause menu iterm
        menuitem_play = builder.get_object('play_pause_toggle')

        # setup to trigger play/pause menu action on appindicator middle click
        appindicator.set_secondary_activate_target(menuitem_play)

        # set all menu items visible
        menu.show_all()

        # attach to the menu to the appindicator
        appindicator.set_menu(menu)

        return appindicator, builder

    # ----------------------------------------------------------------------- #
    def _get_indicator_icons(self):

        icons = []

        # for over both default and fallback theme to get icons
        for theme in [self._default_icon_theme, self._fallback_icon_theme]:
            # try to find both regular and pause icons
            for icon_name in [APPINDICATOR_ICON, APPINDICATOR_ICON_PAUSE]:
                # break out of the loop if we failed to find any of the icons
                # and set the icon collection to an empty list
                if theme.has_icon(icon_name) is True:
                    icon_info = theme.lookup_icon(icon_name, Gtk.IconSize.MENU,
                                                  0)
                    # get icon file path
                    icons.append(icon_info.get_filename())
                else:
                    icons = []
                    break

            # if we found both icons break out
            if len(icons) == 2 or all(icons) is True:
                break

        # if we could not find 2 icons fallback to very generic icons
        if len(icons) != 2 or all(icons) is False:
            icons = APPINDICATOR_ICONS_FALLBACK

        return icons

    # ----------------------------------------------------------------------- #
    def _on_toggle_play_pause_activate(self, widget):
        if self._player.is_playing:
            self._player._sound_menu_pause()
            self._pause()
        else:
            self._player._sound_menu_play()
            self._play()

    # ----------------------------------------------------------------------- #
    def _on_next_activate(self, widget):
        # tell the player to play next track
        self._player._set_new_play('next')
        # update noise status
        self._update_now_playing()

    # ----------------------------------------------------------------------- #
    def _on_previous_activate(self, widget):
        # tell the player to play track
        self._player._set_new_play('previous')
        # update noise status
        self._update_now_playing()

    # ----------------------------------------------------------------------- #
    def _on_preferences_window_show_activate(self, widget):
        self._preferences_window.show()

    # ----------------------------------------------------------------------- #
    def _on_about_activate(self, widget):
        # open default web browser to the homepage
        webbrowser.open_new('http://anoise.tuxfamily.org')

    # ----------------------------------------------------------------------- #
    def _on_quit_activate(self, widget):
        # try to cancel the timer catching all (really?) exceptions
        try:
            self.timer.cancel()
        except Exception:
            pass

        # tell gtk main loop to quit
        Gtk.main_quit()

    # ----------------------------------------------------------------------- #
    def _update_now_playing(self):
        # try to get the noise icon file, otherwise fallback to the default
        # note: it does not throw a specific error we can test for so
        #       we are testing for Exception
        try:
            # get the icon file name for the existing noise
            icon_file = self._player.noise.get_icon().replace('file://', '')
            fallback_icon_name = None
        except Exception:
            # retrieve the default application icon from the icon as a pixbuf
            icon_file = APPINDICATOR_ICON
            fallback_icon_name = PLAYING_NOW_FALLBACK_ICON

        # get the now playing noise
        now_playing = self._player.noise.get_name()
        # form "Not Playing: <noise>" string for the indicator
        new_label = "Now Playing: %s" % now_playing
        # update the indicator now playing label to the noise name
        self._menuitem_now_playing.set_label(new_label)

        # update the now playing menu icon
        #
        # if fallback icon name is not set then we set the found noise icon
        # otherwise we set the set the image to the fallback icons
        if fallback_icon_name is None:
            self._image_now_playing.set_from_file(icon_file)
        else:
            self._image_now_playing.set_from_icon_name(fallback_icon_name,
                                                       Gtk.IconSize.MENU)

        # update the now playing menu item with the now playing image
        self._menuitem_now_playing.set_image(self._image_now_playing)

    # ----------------------------------------------------------------------- #
    def _play(self):
        # tell player to play
        self._menuitem_play.set_label("P_ause")
        self._menuitem_play.set_image(self._image_pause)
        self._appindicator.set_icon(self._appindicator_icon)
        self._update_now_playing()

    # ----------------------------------------------------------------------- #
    def _pause(self):
        # pause the player
        self._menuitem_play.set_label("_Play")
        self._menuitem_play.set_image(self._image_play)
        self._appindicator.set_icon(self._appindicator_icon_pause)
        self._update_now_playing()

    # ----------------------------------------------------------------------- #
    def _set_future_pause(self):
        self._preferences_window.set_show_timer()
        self._player._sound_menu_pause()
        self._pause()