Ejemplo n.º 1
0
    def __init__(self, parent, args):
        QtCore.QThread.__init__(self, parent)
        self._running = False
        self.args = args
        self.settings = Settings()
        self.net = Networking(self)
        BufferUtils.set_app(self)
        self.scene = Scene(self)
        self.plugins = PluginLoader()
        self.mixer = Mixer(self)
        self.playlist = Playlist(self)
        self.qt_app = parent

        self.scene.warmup()

        self.aubio_connector = None
        if not self.args.noaudio:
            self.aubio_thread = QtCore.QThread()
            self.aubio_thread.start()
            self.aubio_connector = AubioConnector()
            self.aubio_connector.onset_detected.connect(
                self.mixer.onset_detected)
            self.aubio_connector.fft_data.connect(
                self.mixer.audio.update_fft_data)
            self.aubio_connector.pitch_data.connect(
                self.mixer.audio.update_pitch_data)
            self.aubio_connector.moveToThread(self.aubio_thread)

        self.mixer.set_playlist(self.playlist)

        if self.args.preset:
            log.info("Setting constant preset %s" % args.preset)
            self.mixer.set_constant_preset(args.preset)
Ejemplo n.º 2
0
    def __init__(self, request, port):

        self.playlist = Playlist(port, pool=None)
        self.request = request
        self.byte_count = 0

        if Config.scrobble:

            self.scrobble_queue = Queue.Queue()
            self.scrobbler = Scrobbler(self.scrobble_queue)
            self.scrobbler.daemon = True
            self.scrobbler.start()
Ejemplo n.º 3
0
class FireMixApp(QtCore.QThread):
    """
    Main logic of FireMix.  Operates the mixer tick loop.
    """
    playlist_changed = QtCore.Signal()

    def __init__(self, parent, args):
        QtCore.QThread.__init__(self, parent)
        self._running = False
        self.args = args
        self.settings = Settings()
        self.net = Networking(self)
        BufferUtils.set_app(self)
        self.scene = Scene(self)
        self.plugins = PluginLoader()
        self.mixer = Mixer(self)
        self.playlist = Playlist(self)
        self.qt_app = parent

        self.scene.warmup()

        self.aubio_connector = None
        if not self.args.noaudio:
            self.aubio_thread = QtCore.QThread()
            self.aubio_thread.start()
            self.aubio_connector = AubioConnector()
            self.aubio_connector.onset_detected.connect(
                self.mixer.onset_detected)
            self.aubio_connector.fft_data.connect(
                self.mixer.audio.update_fft_data)
            self.aubio_connector.pitch_data.connect(
                self.mixer.audio.update_pitch_data)
            self.aubio_connector.moveToThread(self.aubio_thread)

        self.mixer.set_playlist(self.playlist)

        if self.args.preset:
            log.info("Setting constant preset %s" % args.preset)
            self.mixer.set_constant_preset(args.preset)

    def run(self):
        self._running = True
        self.mixer.run()

    def stop(self):
        self._running = False
        self.aubio_thread.quit()
        self.mixer.stop()
        self.playlist.save()
        self.settings.save()
Ejemplo n.º 4
0
class FireMixApp(QtCore.QThread):
    """
    Main logic of FireMix.  Operates the mixer tick loop.
    """
    playlist_changed = QtCore.Signal()

    def __init__(self, parent, args):
        QtCore.QThread.__init__(self, parent)
        self._running = False
        self.args = args
        self.settings = Settings()
        self.net = Networking(self)
        BufferUtils.set_app(self)
        self.scene = Scene(self)
        self.plugins = PluginLoader()
        self.mixer = Mixer(self)
        self.playlist = Playlist(self)
        self.qt_app = parent

        self.scene.warmup()

        self.aubio_connector = None
        if not self.args.noaudio:
            self.aubio_thread = QtCore.QThread()
            self.aubio_thread.start()
            self.aubio_connector = AubioConnector()
            self.aubio_connector.onset_detected.connect(self.mixer.onset_detected)
            self.aubio_connector.fft_data.connect(self.mixer.audio.update_fft_data)
            self.aubio_connector.pitch_data.connect(self.mixer.audio.update_pitch_data)
            self.aubio_connector.moveToThread(self.aubio_thread)

        self.mixer.set_playlist(self.playlist)

        if self.args.preset:
            log.info("Setting constant preset %s" % args.preset)
            self.mixer.set_constant_preset(args.preset)

    def run(self):
        self._running = True
        self.mixer.run()

    def stop(self):
        self._running = False
        self.aubio_thread.quit()
        self.mixer.stop()
        self.playlist.save()
        self.settings["last-preset"] = self.playlist.active_preset.name()
        self.settings.save()
Ejemplo n.º 5
0
    def __init__(self, parent, args):
        QtCore.QThread.__init__(self, parent)
        self._running = False
        self.args = args
        self.settings = Settings()
        self.net = Networking(self)
        BufferUtils.set_app(self)
        self.scene = Scene(self)
        self.plugins = PluginLoader()
        self.mixer = Mixer(self)
        self.playlist = Playlist(self)
        self.qt_app = parent

        self.scene.warmup()

        self.aubio_connector = None
        if not self.args.noaudio:
            self.aubio_thread = QtCore.QThread()
            self.aubio_thread.start()
            self.aubio_connector = AubioConnector()
            self.aubio_connector.onset_detected.connect(self.mixer.onset_detected)
            self.aubio_connector.fft_data.connect(self.mixer.audio.update_fft_data)
            self.aubio_connector.pitch_data.connect(self.mixer.audio.update_pitch_data)
            self.aubio_connector.moveToThread(self.aubio_thread)

        self.mixer.set_playlist(self.playlist)

        if self.args.preset:
            log.info("Setting constant preset %s" % args.preset)
            self.mixer.set_constant_preset(args.preset)
Ejemplo n.º 6
0
    def __makePlaylist(self, playlistData):
        if playlistData["deleted"] == "True":
            return None

        title = playlistData["name"]
        description = playlistData[
            "description"] if "description" in playlistData else None
        serviceId = playlistData["id"]
        songs = self.__makeSongSet(playlistData["tracks"])
        return Playlist(title, description, songs, serviceId)
Ejemplo n.º 7
0
    def __init__(self, args, parent=None):
        self._running = False
        self.args = args
        self.settings = Settings()
        self.net = Networking(self)
        BufferUtils.set_app(self)
        self.scene = Scene(self)
        self.plugins = PluginLoader()
        self.mixer = Mixer(self)

        # Create the default layer.
        default_playlist = Playlist(self, self.args.playlist, 'last_playlist')
        default_layer = Layer(self, 'default')
        default_layer.set_playlist(default_playlist)
        self.mixer.add_layer(default_layer)

        if self.args.speech_layer:
            speech_playlist = Playlist(self, self.args.speech_playlist,
                                       'last_speech_playlist')
            speech_layer = Layer(self, 'speech')
            speech_layer.set_playlist(speech_playlist)
            self.mixer.add_layer(speech_layer)

        self.scene.warmup()

        self.aubio_connector = None
        if not self.args.noaudio:
            self.aubio_connector = AubioConnector()
            self.aubio_connector.onset_detected.connect(
                self.mixer.onset_detected)

        self.osc_server = None
        if not self.args.noosc:
            self.osc_server = OscServer(self.args.osc_port,
                                        self.args.mixxx_osc_port, self.mixer)
            self.osc_server.start()

        if self.args.preset:
            log.info("Setting constant preset %s" % args.preset)
            self.mixer.set_constant_preset(args.preset)

        QtCore.QThread.__init__(self, parent)
Ejemplo n.º 8
0
    def __init__(self, parent, args):
        QtCore.QThread.__init__(self, parent)
        self._running = False
        self.args = args
        self.settings = Settings()
        self.net = Networking(self)
        BufferUtils.set_app(self)
        self.scene = Scene(self)
        self.plugins = PluginLoader()
        self.mixer = Mixer(self)
        self.playlist = Playlist(self)
        self.qt_app = parent
        self.gui = None

        self.scene.warmup()

        self.mixer.set_playlist(self.playlist)

        if self.args.preset:
            log.info("Setting constant preset %s" % args.preset)
            self.mixer.set_constant_preset(args.preset)
Ejemplo n.º 9
0
    def __init__(self, request, port):

        self.playlist       = Playlist(port, pool=None)
        self.request        = request
        self.byte_count     = 0

        if Config.scrobble:

            self.scrobble_queue = Queue.Queue()
            self.scrobbler      = Scrobbler( self.scrobble_queue )
            self.scrobbler.daemon = True
            self.scrobbler.start()
Ejemplo n.º 10
0
class FireMixApp(QtCore.QThread):
    """
    Main logic of FireMix.  Operates the mixer tick loop.
    """
    playlist_changed = QtCore.Signal()

    def __init__(self, args, parent=None):
        self._running = False
        self.args = args
        self.settings = Settings()
        self.net = Networking(self)
        self.scene = Scene(self)
        self.plugins = PluginLoader()
        self.mixer = Mixer(self)
        self.playlist = Playlist(self)

        self.aubio_connector = None
        if self.args.audio:
            self.aubio_connector = AubioConnector()
            self.aubio_connector.onset_detected.connect(self.mixer.onset_detected)

        self.mixer.set_playlist(self.playlist)

        if self.args.preset:
            log.info("Setting constant preset %s" % args.preset)
            self.mixer.set_constant_preset(args.preset)

        QtCore.QThread.__init__(self, parent)

    def run(self):
        self._running = True
        self.mixer.run()

    def stop(self):
        self._running = False
        self.mixer.stop()
        self.playlist.save()
        self.settings.save()
        self.scene.save()
Ejemplo n.º 11
0
    def __init__(self, args, parent=None):
        self._running = False
        self.args = args
        self.settings = Settings()
        self.net = Networking(self)
        self.scene = Scene(SceneLoader(self))
        self.plugins = PluginLoader()
        self.mixer = Mixer(self)
        self.playlist = Playlist(self)

        self.aubio_connector = None
        if self.args.audio:
            self.aubio_connector = AubioConnector()
            self.aubio_connector.onset_detected.connect(self.mixer.onset_detected)

        self.mixer.set_playlist(self.playlist)

        if self.args.preset:
            log.info("Setting constant preset %s" % args.preset)
            self.mixer.set_constant_preset(args.preset)

        QtCore.QThread.__init__(self, parent)
Ejemplo n.º 12
0
class FireMixApp(QtCore.QThread):
    """
    Main logic of FireMix.  Operates the mixer tick loop.
    """
    playlist_changed = QtCore.Signal()

    def __init__(self, args, parent=None):
        self._running = False
        self.args = args
        self.settings = Settings()
        self.net = Networking(self)
        self.scene = Scene(SceneLoader(self))
        self.plugins = PluginLoader()
        self.mixer = Mixer(self)
        self.playlist = Playlist(self)

        self.aubio_connector = None
        if self.args.audio:
            self.aubio_connector = AubioConnector()
            self.aubio_connector.onset_detected.connect(self.mixer.onset_detected)

        self.mixer.set_playlist(self.playlist)

        if self.args.preset:
            log.info("Setting constant preset %s" % args.preset)
            self.mixer.set_constant_preset(args.preset)

        QtCore.QThread.__init__(self, parent)

    def run(self):
        self._running = True
        self.mixer.run()

    def stop(self):
        self._running = False
        self.mixer.stop()
        self.playlist.save()
        self.settings.save()
Ejemplo n.º 13
0
class FireMixApp(QtCore.QThread):
    """
    Main logic of FireMix.  Operates the mixer tick loop.
    """
    playlist_changed = QtCore.pyqtSignal()

    def __init__(self, parent, args):
        QtCore.QThread.__init__(self, parent)
        self._running = False
        self.args = args
        self.settings = Settings()
        self.net = Networking(self)
        BufferUtils.set_app(self)
        self.scene = Scene(self)
        self.plugins = PluginLoader()
        self.mixer = Mixer(self)
        self.playlist = Playlist(self)
        self.qt_app = parent
        self.gui = None

        self.scene.warmup()

        self.mixer.set_playlist(self.playlist)

        if self.args.preset:
            log.info("Setting constant preset %s" % args.preset)
            self.mixer.set_constant_preset(args.preset)

    def run(self):
        self._running = True
        self.mixer.start()

    def stop(self):
        self._running = False
        self.mixer.stop()
        self.playlist.save()
        self.settings.save()
Ejemplo n.º 14
0
class FireMixApp(QtCore.QThread):
    """
    Main logic of FireMix.  Operates the mixer tick loop.
    """
    playlist_changed = QtCore.pyqtSignal()

    def __init__(self, parent, args):
        QtCore.QThread.__init__(self, parent)
        self._running = False
        self.args = args
        self.settings = Settings()
        self.net = Networking(self)
        BufferUtils.set_app(self)
        self.scene = Scene(self)
        self.plugins = PluginLoader()
        self.mixer = Mixer(self)
        self.playlist = Playlist(self)
        self.qt_app = parent
        self.gui = None

        self.scene.warmup()

        self.mixer.set_playlist(self.playlist)

        if self.args.preset:
            log.info("Setting constant preset %s" % args.preset)
            self.mixer.set_constant_preset(args.preset)

    def run(self):
        self._running = True
        self.mixer.start()

    def stop(self):
        self._running = False
        self.mixer.stop()
        self.playlist.save()
        self.settings.save()
Ejemplo n.º 15
0
    def loadTakeoutPlaylist(exportPath):
        title = os.path.basename(exportPath)
        description = ""
        isDeleted = False

        metadataPath = os.path.join(exportPath, "Metadata.csv")
        with open(metadataPath) as metadataFile:
            metadata = next(csv.DictReader(metadataFile))
            title = metadata["Title"]
            description = metadata["Description"]
            isDeleted = (metadata["Deleted"] == "Yes")

        if isDeleted:
            return None

        songs = Gpm.loadTakeoutSongSet(os.path.join(exportPath, "Tracks"))
        return Playlist(title, description, songs, None)
Ejemplo n.º 16
0
    def __init__(self, parent, args):
        QtCore.QThread.__init__(self, parent)
        self._running = False
        self.args = args
        self.settings = Settings()
        self.net = Networking(self)
        BufferUtils.set_app(self)
        self.scene = Scene(self)
        self.plugins = PluginLoader()
        self.mixer = Mixer(self)
        self.playlist = Playlist(self)
        self.qt_app = parent
        self.gui = None

        self.scene.warmup()

        self.mixer.set_playlist(self.playlist)

        if self.args.preset:
            log.info("Setting constant preset %s" % args.preset)
            self.mixer.set_constant_preset(args.preset)
Ejemplo n.º 17
0
 def addPlaylist(self, title, description):
     playlistId = self.client.create_playlist(title, description)
     return Playlist(title, description, list(), playlistId)
Ejemplo n.º 18
0
class Streamer(object):

    def __init__(self, request, port):

        self.playlist       = Playlist(port, pool=None)
        self.request        = request
        self.byte_count     = 0

        if Config.scrobble:

            self.scrobble_queue = Queue.Queue()
            self.scrobbler      = Scrobbler( self.scrobble_queue )
            self.scrobbler.daemon = True
            self.scrobbler.start()

    # It's always a good day for smoking crack at Nullsoft!
    #   See the Amarok source for ideas on the (crappy) icecast metadata "protocol"
    #           This explains the whole cockamamie thing:
    #           http://www.smackfu.com/stuff/programming/shoutcast.html

    def get_meta(self, song):
        # lifted from amarok
        metadata    = u"%cStreamTitle='%s';StreamUrl='%s';%s"
        padding     = u'\x00' * 16
        meta        = None
        if self.dirty_meta:
            songs           = unicode(song)
            stream_title    = songs.encode(u'ascii', u'ignore')
            stream_url      = Config.url

            # 28 is the number of static characters in metadata (!)
            length          = len(stream_title) + len(stream_url) + 28
            pad             = 16 - length % 16
            what            = padding[:pad]
            meta            = metadata % (((length + pad) / 16), stream_title, stream_url, what)
            self.dirty_meta = False
        else:
            meta = u'\x00'

        return meta

    def empty_scrobble_queue(self):
        if Config.scrobble:
            with self.scrobble_queue.mutex:
                self.scrobble_queue.queue.clear()

    def stream(self, icy_client=False):
        song = None
        while self.playlist.data[u'running']:
            if Config.scrobble and song:
                    # just played one . . . scrobble it
                    self.scrobble_queue.put(ScrobbleItem(PLAYED, song))
                    #log.debug("enqueued played")
                    #log.debug(song)

            # new song
            song            = self.playlist.get_song()
            song_start_time = time.time()
            self.playlist.data[u"progress"] = 0

            if not song:
                log.warn(u"no playlist, won't stream")
                self.playlist.data[u'status'] = u'stopped'
                self.byte_count = 0
                self.empty_scrobble_queue()
                return

            if Config.scrobble:
                #log.debug("enqueued now playing")
                self.scrobble_queue.put(ScrobbleItem(NOW_PLAYING, song))

            log.info(u'> %s' % unicode(song))

            transcode = None
            try:
                # this loop gets some of its ideas about the shoutcast protocol from Amarok
                buffer              = 0
                buffer_size         = Config.buffer_size
                metadata_interval   = Config.metaint

                try:
                    transcode.stdout.close()
                except:
                    pass

                #cif song.mimetype[0:5] in ["audio", "video"]:
                transcode = subprocess.Popen([u"/usr/bin/ffmpeg",
                                              u"-i", song.path,
                                              u"-vn",
                                              u"-loglevel", u"warning",
                                              u"-qscale:a", u"0",
                                              u"-f", u"mp3",
                                              u"-"],
                                             stdout=subprocess.PIPE,
                                             shell=False)
                self.dirty_meta = True

                skip = False
                while self.playlist.data[u'running'] and transcode:
                    bytes_until_meta = (metadata_interval - self.byte_count)
                    if bytes_until_meta == 0:
                        if icy_client:
                            metadata = self.get_meta(song)
                            self.request.send(metadata.encode(u'ascii', u'ignore'))
                        self.byte_count = 0
                    else:
                        if bytes_until_meta < buffer_size:
                            chunk_bytes = bytes_until_meta
                        else:
                            chunk_bytes = buffer_size
                        buffer = transcode.stdout.read(chunk_bytes)

                        self.request.send(buffer)
                        buflen = len(buffer)
                        self.byte_count                     += buflen
                        self.playlist.data[u"sum_bytes"]     += buflen
                        elapsed = time.time() - song_start_time
                        self.playlist.data[u'elapsed'] = elapsed
                        # set percentage elapsed
                        try:
                            self.playlist.data[u"progress"] = float(elapsed * 100) / song.length
                        except ZeroDivisionError:
                            self.playlist.data[u"progress"] = 0

                        if len(buffer) == 0: break

                    if self.playlist.data[u'skip']:
                        log.info(u">>")
                        skip = True
                        song = None  # don't scrobble
                        self.playlist.data[u"elapsed"] = 0
                        self.playlist.data[u"progress"] = 0
                        break

                    if self.playlist.data[u'status'] == u'stopped':
                        log.info(u".")
                        skip = True
                        song = None  # don't scrobble
                        self.playlist.data[u"elapsed"] = 0
                        break

                if not skip:
                    # increment the counter if we're not ffwding
                    self.playlist.next()
                else:
                    self.playlist.data[u'skip'] = False
                self.dirty_meta = True
            except error, e:
                if isinstance(e.args, tuple):
                    print "errno is %d" % e[0]
                    if e[0] == errno.EPIPE:
                        # remote peer disconnected
                        print "Detected remote disconnect"

                    elif e.errno == errno.ECONNRESET:
                        self.empty_scrobble_queue()
                        log.info(u"Client disconnected")
                    else:
                        log.info(u"Unknown socket error")
                        self.empty_scrobble_queue()
                        log.exception(errno.errorcode[e.errno])
                else:
                    print "socket error ", e
                self.request.close()
                self.playlist.data[u'status'] = 'stopped'
                break # while
            except IOError, e:
                log.info("IO ERROR")
            except KeyboardInterrupt:
                self.playlist.data[u'running']   = False
Ejemplo n.º 19
0
class GsongFinder(object):
    def __init__(self):
        ## default search options
        self.is_playing = False
        self.is_paused = False
        self.nbresults = 100
        self.user_search = ""
        self.showed = True ## trayicon
        self.settings_folder = None
        self.conf_file = None
        self.active_downloads = 0
        self.thread_num = 0
        self.engine_list = {}
        self.engine = None
        self.conf=conf
        self.latest_engine = ""
        self.change_page_request = False
        self.tray = None
        self.download_pool = []
        self.media_bitrate= None
        self.media_codec= None
        self.playlist_mode = False
        self.play = False
        self.draw_text = False
        self.url_checker = checkLink.CheckLinkIntegrity()
        self.url_debrid = debrider.Debrid(self)
        self.player_thread=None
        
        ## main gui
        self.gladeGui = Gtk.Builder()
        self.gladeGui.add_from_file(data_path+"/glade/mainGui.ui")
        Gtk.Builder.set_translation_domain(self.gladeGui, APP_NAME)
        self.window = self.gladeGui.get_object("main_window")
        self.window.set_title("Gmediafinder")
        self.window.set_resizable(1)
        self.set_window_position()
        self.show_thumbs_opt_toggle = self.gladeGui.get_object("show_thumbs_opt")
        if self.conf['show_thumbs'] == "True" :
            self.show_thumbs_opt_toggle.set_active(1)
        self.img_path = img_path
        self.window.set_icon_from_file(os.path.join(self.img_path,'gmediafinder.png'))
        self.window.connect('key-press-event', self.onKeyPress)
    
        
        # options menu
        self.options_bar = self.gladeGui.get_object("options_bar")
        self.search_box = self.gladeGui.get_object("search_box")
        self.results_box = self.gladeGui.get_object("results_box")
        self.quality_box = self.gladeGui.get_object("quality_box")

        ## throbber
        self.throbber = self.gladeGui.get_object("throbber_img")
        animation = GdkPixbuf.PixbufAnimation.new_from_file(self.img_path+'/throbber.gif')
        self.throbber.set_from_animation(animation)

        ## notebooks
        self.notebook = self.gladeGui.get_object("notebook")
        self.results_notebook = self.gladeGui.get_object("results_notebook")
        self.video_cont = self.gladeGui.get_object("video_cont")

        self.search_entry = self.gladeGui.get_object("search_entry")
        self.stop_search_btn = self.gladeGui.get_object("stop_search_btn")
        ## playlist
        self.playlists_xml = playlists_xml
        self.playlist_scrollbox = self.gladeGui.get_object("playlist_scrollbox")
        ## history
        self.search_entry.connect('changed',self.__search_history)
        self.history_view = Gtk.EntryCompletion()
        self.history_view.set_minimum_key_length(1)
        self.search_entry.set_completion(self.history_view)
        self.history_model = Gtk.ListStore(GObject.TYPE_STRING)
        self.history_view.set_model(self.history_model)
        self.history_view.set_text_column(0)
        ## options box
        self.search_opt_box = self.gladeGui.get_object("search_options_box")

        ## statbar
        self.statbar = self.gladeGui.get_object("statusbar")
        ## info
        self.info_label = self.gladeGui.get_object("info_label")


        ##extras options
        self.downloads_check = self.gladeGui.get_object("downloads_enabled")
        self.convert_check = self.gladeGui.get_object("convert_enabled")
        self.warn_dialog = self.gladeGui.get_object("warn_dialog")
        self.systray_check = self.gladeGui.get_object("systray_enabled")
        self.down_dir = down_dir
        self.down_btn = self.gladeGui.get_object("down_btn")
        self.down_menu_btn = self.gladeGui.get_object("down_menu_btn")
        if downloads == 'True':
            self.downloads_check.set_active(1)
        if convert == 'True':
            self.convert_check.set_active(1)
        if systray == 'True':
            self.systray_check.set_active(1)

        ## SIGNALS
        dic = {"on_main_window_destroy_event" : self.exit,
        "on_quit_menu_activate" : self.exit,
        "on_nextpage_btn_clicked" : self.change_page,
        "on_pageback_btn_clicked" : self.change_page,
        "on_search_entry_activate" : self.prepare_search,
        "on_about_menu_clicked" : self.on_about_btn_pressed,
        "on_settings_menu_clicked" : self.on_settings_btn_pressed,
        "on_main_window_configure_event" : self.save_position,
        "on_search_entry_icon_press" : self.clear_search_entry,
        "on_show_thumbs_opt_toggled" : self.on_gui_opt_toggled,
        "on_stop_search_btn_clicked": self.stop_threads,
        "on_downloads_enabled_toggled" : self.set_extras_options,
        "on_convert_enabled_toggled" : self.set_extras_options,
        "on_systray_enabled_toggled" : self.set_extras_options,
        "on_clear_history_btn_clicked" : self.clear_history,
         }
        self.gladeGui.connect_signals(dic)
        self.window.connect('destroy', self.exit)

        ## create main results treeview
        self.model = Gtk.ListStore(GdkPixbuf.Pixbuf,str,object,object,object,str,str,GdkPixbuf.Pixbuf,bool)
        self.treeview = Gtk.TreeView()
        self.window.realize()
        self.window_style=self.window.get_style_context()
        self.odd = Gdk.color_parse(self.window_style.lookup_color('theme_bg_color')[1].to_string())
        self.even = Gdk.color_parse(self.window_style.lookup_color('theme_base_color')[1].to_string())
        self.front = Gdk.color_parse(self.window_style.lookup_color('theme_fg_color')[1].to_string())
        self.treeview.set_model(self.model)

        rendererp = Gtk.CellRendererPixbuf()
        pixcolumn = Gtk.TreeViewColumn("",rendererp,  pixbuf=0)
        self.treeview.append_column(pixcolumn)

        rendertxt = Gtk.CellRendererText()
        txtcolumn = Gtk.TreeViewColumn("txt",rendertxt, markup=1)
        txtcolumn.set_cell_data_func(rendertxt, self.alternate_color)
        txtcolumn.set_title(_(' Results : '))
        self.treeview.append_column(txtcolumn)

        renderer = Gtk.CellRendererText()
        pathColumn = Gtk.TreeViewColumn("Link", renderer)
        self.treeview.append_column(pathColumn)

        qualityColumn = Gtk.TreeViewColumn("Quality", renderer)
        self.treeview.append_column(qualityColumn)
        
        nameColumn = Gtk.TreeViewColumn("Name", renderer)
        self.treeview.append_column(nameColumn)

        plugnameColumn = Gtk.TreeViewColumn("Name", renderer)
        self.treeview.append_column(plugnameColumn)
        
        
        ## setup the scrollview
        self.results_scroll = self.gladeGui.get_object("results_scrollbox")
        self.columns = self.treeview.get_columns()
        if self.conf['show_thumbs'] == "False":
            self.columns[0].set_visible(0)
        self.columns[1].set_sort_column_id(1)
        self.columns[2].set_visible(0)
        self.columns[3].set_visible(0)
        self.columns[4].set_visible(0)
        self.columns[5].set_visible(0)
        self.results_scroll.add(self.treeview)
        self.results_scroll.connect_after('size-allocate', self.resize_wrap, self.treeview, self.columns[1], rendertxt)
        
        ## right click menu
        self.search_playlist_menu = Gtk.Menu()
        getlink_item = Gtk.ImageMenuItem(Gtk.STOCK_COPY)
        getlink_item.get_children()[0].set_label(_('Copy file link'))
        addplaylist_item = Gtk.ImageMenuItem(Gtk.STOCK_EDIT)
        addplaylist_item.get_children()[0].set_label(_('Add to Library'))
        self.search_playlist_menu.append(getlink_item)
        self.search_playlist_menu.append(addplaylist_item)
        getlink_item.connect('activate', self._copy_link)
        addplaylist_item.connect('activate', self._add_to_playlist)
        ## connect treeview signals
        self.search_playlist_menu_active = False
        self.treeview.connect('row-activated',self.get_model)
        self.treeview.connect('cursor-changed',self.on_treeview_clicked)
        self.treeview.connect('button-press-event',self._show_search_playlist_menu)

        ## engines
        self.dlg = self.gladeGui.get_object("settings_dialog")
        self.engines_box = self.gladeGui.get_object("engines_box")
        
        ## create engines selector combobox
        box = self.gladeGui.get_object("engine_selector_box")
        self.active_engines = create_comboBox()
        self.active_engines.connect("changed", self.set_engine)
        box.pack_start(self.active_engines, False,False,5)
        self.engine_selector = ComboBox(self.active_engines)
        self.engine_selector.append("")
        ## load playlists
        self.Playlist = Playlist(self)
        ## init player
        self.player = Player(self)
        
        ## check extra options
        if downloads == 'False':            
            self.down_btn.hide()
            self.down_menu_btn.hide()
        else:
            ## init downloader
            self.downloader = downloader.Downloader(self)
            self.downloader.download_treeview.columns_autosize()
        
        ## tray icon
        if systray == 'True':
            self.__create_trayicon()
        
        
        ## browser notebook
        self.media_notebook = self.gladeGui.get_object("media_notebook")
        self.browser_box = self.gladeGui.get_object("browser_cont")
        #self.browser = browser(self)
        #self.browser.load_uri('http://video.google.com/')
        
        ## start gui
        GObject.idle_add(self.media_notebook.set_current_page,1)
        self.window.show_all()
        self.throbber.hide()
        ## start engines
        self.engines_client = Engines(self)

        ## engine selector (engines only with direct links)
        self.global_search = _("All")
        self.global_audio_search = _("All audios")
        self.global_video_search = _("All videos")

        for engine in sorted(self.engine_list):
            try:
                if getattr(self.engines_client, '%s' % engine).adult_content:
                    self.engine_selector.append(engine,True)
            except:
                self.engine_selector.append(engine)

        if ("Youtube" in self.engine_list):
            self.engine_selector.setIndexFromString("Youtube")
        else:
            self.engine_selector.select(0)
        self.engine_selector.append(self.global_search)
        self.engine_selector.append(self.global_audio_search)
        self.engine_selector.append(self.global_video_search)
        self.search_entry.grab_focus()
        self.statbar.hide()
        
        ## hide some icons by default
        self.stop_search_btn.set_sensitive(0)
            
        #THE ACTUAL THREAD BIT
        self.manager = FooThreadManager(20)
        self.resume_downloads()
        self.mainloop = GObject.MainLoop(is_running=True)
    
   
    def set_window_position(self):
        self.window.set_default_size(int(self.conf['window_state'][0]),int(self.conf['window_state'][1]))
        try:
            x,y = int(self.conf['window_state'][2]),int(self.conf['window_state'][3])
            if x == 0 or y == 0:
                self.window.set_position(Gtk.WindowPosition.CENTER_ALWAYS)
            else:
                self.window.move(x,y)
        except:
            self.window.set_position(Gtk.WindowPosition.CENTER_ALWAYS)
    
    def set_extras_options(self, widget):
        if ('convert' in widget.name):
            if widget.get_active():
                accept = warn_dialog(self.warn_dialog)
                if accept == 0:
                    convert = 'True'
                    self.conf['convert'] = True
                else:
                    widget.set_active(0)
            else:
                convert = 'False'
                self.conf['convert'] = False
                
        elif ('systray' in widget.name):
            if widget.get_active():
                systray = 'True'
                self.conf['systray'] = True
                if not self.tray:
                    self.__create_trayicon()
                else:
                    self.tray.set_visible(1)
            else:
                systray = 'False'
                self.conf['systray'] = False
                self.tray.set_visible(0)
        else:
            if widget.get_active():
                accept = warn_dialog(self.warn_dialog)
                if accept == 0:
                    self.down_btn.show()
                    self.down_menu_btn.show()
                    self.conf['downloads'] = True
                else:
                    widget.set_active(0)
            else:
                self.down_btn.hide()
                self.down_menu_btn.hide()
                self.conf['downloads'] = False
        ## save config
        self.conf.write()
    
    def on_gui_opt_toggled(self, widget):
        if widget.get_active():
            self.show_thumbs_opt = "True"
            self.columns[0].set_visible(1)
        else:
            self.show_thumbs_opt = "False"
            self.columns[0].set_visible(0)
        self.conf["show_thumbs"] = self.show_thumbs_opt
        self.conf.write()
    
    def clear_search_entry(self,widget,e,r):
        if e == Gtk.EntryIconPosition.SECONDARY:
            self.search_entry.set_text("")
        elif e == Gtk.EntryIconPosition.PRIMARY:
            self.prepare_search()
        self.search_entry.grab_focus()

    def alternate_color(self, column, cell, model, iter,truc):
        if int((model.get_string_from_iter(iter).split(":")[0])) % 2:
            cell.set_property('background-gdk', self.odd)
            cell.set_property('cell-background-gdk', self.odd)
            cell.set_property('foreground-gdk', self.front)
        else:
            cell.set_property('background-gdk', self.even)
            cell.set_property('cell-background-gdk', self.even)
            cell.set_property('foreground-gdk', self.front)

    def save_position(self,widget,e):
        self.x,self.y=self.window.get_position()

    def resize_wrap(self, scroll, allocation, treeview, column, cell):
        value = GObject.Value()
        value.init(GObject.TYPE_INT)
        otherColumns = (c for c in treeview.get_columns() if c != column)
        newWidth = allocation.width - sum(c.get_width() for c in otherColumns) - 8
        #newWidth -= treeview.style_get_property("horizontal-separator",value) * 4
        if cell.props.wrap_width == newWidth or newWidth <= 0:
                return
        if newWidth < 250:
                newWidth = 225
        cell.props.wrap_width = newWidth
        column.set_property('min-width', newWidth + 10)
        column.set_property('max-width', newWidth + 10)
        store = treeview.get_model()
        iter = store.get_iter_first()
        while iter and store.iter_is_valid(iter):
                store.row_changed(store.get_path(iter), iter)
                iter = store.iter_next(iter)
                treeview.set_size_request(0,-1)


    def set_engine(self,widget=None,engine=None):
        self.quality_box.hide()
        global_search = False
        iter = self.engine_selector.getSelectedIndex()
        if iter == 0:
            self.engine = None
            return
        ## clean the gui options box and load the plugin gui
        for w in self.search_opt_box:
            self.search_opt_box.remove(w)
        ## get engine infos
        selected = self.engine_selector.getSelected()
 
        ## load the plugin
        if engine:
            self.engine = engine
            self.engine_selector.setIndexFromString(self.engine)
        else:
            if selected == self.global_search or selected == self.global_video_search or selected == self.global_audio_search:
                global_search = True
            ## do not set the engine if global search
            if global_search:
                return
            self.engine = selected
            self.search_engine = getattr(self.engines_client,'%s' % self.engine)
            self.search_engine.load_gui()

    def get_model(self,widget=None,path=None,column=None):
        self.media_bitrate = ""
        self.media_codec = ""
        current_page = self.results_notebook.get_current_page()
        if int(current_page) == 1:
            self.playlist_mode = True
        else:
            self.playlist_mode = False
        if widget or not self.playlist_mode:
            selected = self.treeview.get_selection()
            self.selected_iter = selected.get_selected()[1]
            self.path = self.model.get_path(self.selected_iter)
            ## else extract needed metacity's infos
            self.media_thumb = self.model.get_value(self.selected_iter, 0)
            name = self.model.get_value(self.selected_iter, 4)
            self.media_name = self.clean_markup(name)
            self.file_tags = {}
            self.media_markup = self.model.get_value(self.selected_iter, 1)
            self.media_plugname = self.model.get_value(self.selected_iter, 5)
            ## for global search
            if not self.engine_selector.getSelected() == self.media_plugname:
                GObject.idle_add(self.set_engine,None,self.media_plugname)
            try:
                self.search_engine.updateBrowser=self.model.get_value(self.selected_iter, 8)
            except:
                self.search_engine.updateBrowser=False
            ## return only theme name and description then extract infos from hash
            self.media_link = self.model.get_value(self.selected_iter, 2)
            self.media_img = self.model.get_value(self.selected_iter, 0)
        else:
            selected = self.Playlist.treeview.get_selection()
            self.selected_iter = selected.get_selected()[1]
            self.path = self.Playlist.treestore.get_path(self.selected_iter)
            ## else extract needed metacity's infos
            self.media_thumb = self.Playlist.treestore.get_value(self.selected_iter, 0)
            name = self.Playlist.treestore.get_value(self.selected_iter, 0)
            self.media_name = self.clean_markup(name)
            self.file_tags = {}
            self.media_markup = self.Playlist.treestore.get_value(self.selected_iter, 0)
            self.media_plugname = self.Playlist.treestore.get_value(self.selected_iter, 0)
            self.Playlist.on_selected(self.Playlist.treeview)
            ## for youtube...
            self.search_engine.updateBrowser=True
                
        ## play in engines
        self.player_thread = thread.start_new_thread(self.search_engine.play,(self.media_link,))
        #self.search_engine.play(self.media_link)
        
    def prepare_search(self,widget=None):
        self.user_search = self.search_entry.get_text()
        self.latest_engine = self.engine_selector.getSelectedIndex()
        if self.latest_engine == 0:
            self.info_label.set_text(_("Please select a search engine..."))
            return
        if not self.user_search:
            if not self.search_engine.has_browser_mode:
                self.info_label.set_text(_("Please enter an artist/album or song name..."))
                return
        if not self.engine:
            self.info_label.set_text(_("Please select an engine..."))
            return
        self.change_page_request = False
        self.stop_threads()
        self.model.clear()
        self.player.changepage_btn.set_sensitive(0)
        self.player.pageback_btn.set_sensitive(0)
        self.__add_to_history()
        self.engine_list = self.engine_selector.get_list()
        if self.engine_selector.getSelected() == self.global_search:
            for engine in self.engine_list:
                try:
                    self.search_engine = getattr(self.engines_client,'%s' % engine)
                    self.search()
                except:
                    continue
            self.engine_selector.setIndexFromString(self.global_search)
        elif self.engine_selector.getSelected() == self.global_video_search:
            for engine in self.engine_list:
                try:
                    self.search_engine = getattr(self.engines_client,'%s' % engine)
                except:
                    continue
                if not self.search_engine.engine_type == "video":
                    continue
                try:
                    self.search()
                except:
                    continue
            self.engine_selector.setIndexFromString(self.global_video_search)
        elif self.engine_selector.getSelected() == self.global_audio_search:
            for engine in self.engine_list:
                try:
                    self.search_engine = getattr(self.engines_client,'%s' % engine)
                except:
                    continue
                if not self.search_engine.engine_type == "audio" or self.search_engine.name == "Jamendo":
                    continue
                try:
                    self.search()
                except:
                    continue
            self.engine_selector.setIndexFromString(self.global_audio_search)
        else:
            return self.search()

    def change_page(self,widget=None):
        if not self.player.changepage_btn.get_property("visible"):
            return
        try:
            name = widget.name
        except:
            name = ""
        GObject.idle_add(self.model.clear)
        user_search = self.search_entry.get_text()
        engine = self.latest_engine
        if not user_search or user_search != self.user_search or not engine or engine != self.latest_engine:
            ## if engine doesn t have browser mode, start a new search
            if not self.search_engine.has_browser_mode:
                return self.prepare_search()
            else:
                return self.prepare_change_page(engine, user_search, name)
        else:
            return self.prepare_change_page(engine, user_search, name)
            
    def prepare_change_page(self, engine, user_search, name):
            self.engine_selector.select(self.latest_engine)
            if self.engine_selector.getSelected() == self.global_search:
                for engine in self.engine_list:
                    try:
                        self.search_engine = getattr(self.engines_client,'%s' % engine)
                    except:
                        continue
                    if self.search_engine.name == "Jamendo":
                        continue
                    try:
                        self.do_change_page(name)
                    except:
                        continue
            elif self.engine_selector.getSelected() == self.global_audio_search:
                for engine in self.engine_list:
                    try:
                        self.search_engine = getattr(self.engines_client,'%s' % engine)
                    except:
                        continue
                    if self.search_engine.engine_type == "video" or self.search_engine.name == "Jamendo":
                        continue
                    try:
                        self.do_change_page(name)
                    except:
                        continue
            elif self.engine_selector.getSelected() == self.global_video_search:
                for engine in self.engine_list:
                    try:
                        self.search_engine = getattr(self.engines_client,'%s' % engine)
                    except:
                        continue
                    if self.search_engine.engine_type == "audio":
                        continue
                    try:
                        self.do_change_page(name)
                    except:
                        continue
            return self.do_change_page(name)

    def do_change_page(self,name):
        if self.engine_selector.getSelected() == self.global_audio_search:
            if self.search_engine.engine_type == "video":
                return
        if name == "pageback_btn":
            if self.search_engine.current_page != 1:
                try:
                    self.search_engine.num_start = self.search_engine.num_start - self.search_engine.results_by_page
                except:
                    pass
                self.search_engine.current_page = self.search_engine.current_page - 1
        else:
            try:
                self.search_engine.num_start = self.search_engine.num_start + self.search_engine.results_by_page
            except:
                pass
            self.search_engine.current_page = self.search_engine.current_page + 1
        self.search(self.search_engine.current_page)

    def search(self,page=None):
        self.engine_selector.select(self.latest_engine)
        ## send request to the module, can pass type and order too...reset page start to inital state
        if not page:
            page = self.search_engine.main_start_page
            self.search_engine.current_page = self.search_engine.main_start_page
        ## check if first page then desactivate back page
        if page > 1:
            self.player.pageback_btn.set_sensitive(1)
        else:
            self.player.pageback_btn.set_sensitive(0)
            #thread.start_new_thread(self.search_engine.search,(self.user_search,page))
        self.add_thread(self.search_engine,self.user_search,page)

    def add_sound(self, name, media_link, img=None, quality_list=None, plugname=None,markup_src=None, synop=None, select=False):
        print name, media_link, img, quality_list, plugname,markup_src, synop
        orig_pixbuf = img
        if not img:
            img = GdkPixbuf.Pixbuf.new_from_file_at_scale(os.path.join(self.img_path,'video.png'), 64,64, 1)
            orig_pixbuf = GdkPixbuf.Pixbuf.new_from_file(os.path.join(self.img_path,'video.png'))
        else:
			if img.get_width() != 100:
				img = self.update_image(img,100,100)
        if not name or not media_link or not img:
            return
        ## clean markup...
        try:
            n = decode_htmlentities(name)
            m = GLib.markup_escape_text(n)
            markup = '<small><b>%s</b></small>' % m
        except:
            return
            
        if markup_src:
            markup = markup + markup_src
        miter = self.model.append()
        self.model.set(miter,
                        0, img,
                        1, markup,
                        2, media_link,
                        3, quality_list,
                        4, name,
                        5, plugname,
                        6, synop,
                        7, orig_pixbuf,
                        8, select
                        )
        if select:
            self.selected_iter = miter
            self.path = self.model.get_path(self.selected_iter)
            GObject.idle_add(self.treeview.set_cursor,self.path)
            GObject.idle_add(self.get_model)

    def clean_markup(self,string):
        n = decode_htmlentities(string)
        m = GLib.markup_escape_text(n)
        return m
    
    def stop_play(self,widget=None):
        self.active_link = None
        self.player.stop()
    
    def start_play(self,url):
        try:
            self.stop_play()
        except:
            print ""
        self.active_link = url
        self.player.play_toggled(None,url)
		
    def load_new_page(self):
        self.change_page_request=True
        self.change_page()
        
		
    def update_image(self,img, w, h):
		# Get the size of the source pixmap
		src_width, src_height = img.get_width(), img.get_height()
		# Scale preserving ratio
		scale = min(float(w)/src_width, float(h)/src_height)
		new_width = int(scale*src_width)
		new_height = int(scale*src_height)
		pixbuf = img.scale_simple(new_width, new_height, GdkPixbuf.InterpType.BILINEAR)
		return pixbuf
    

    def resume_downloads(self):
        for media in os.listdir(self.down_dir):
            try:
                if '.conf' in media:
                    conf = os.path.join(self.down_dir, media)
                    f = open('''%s''' % conf, 'r')
                    data = f.read()
                    f.close()
                    link = data.split(':::')[0]
                    name = data.split(':::')[1]
                    codec = data.split(':::')[2]
                    engine_type = data.split(':::')[3]
                    engine_name = data.split(':::')[4]
                    if str(engine_type) == 'files':
                        self.download_debrid(link)
                    else:
                        self.download_file(None,link, name, codec, None, engine_type, engine_name)
            except:
                continue
    
    
    def onKeyPress(self, widget, event):
        if self.search_entry.is_focus() or self.browser.url_bar.is_focus() or self.browser.view.has_focus():
            return
        key = Gdk.keyval_name(event.keyval)
        if key == 'f':
            return self.player.set_fullscreen()
        elif key == 'space':
            return self.pause_resume()
        elif key == 's':
            return self.stop_play()
        elif key == 'BackSpace':
            self.search_entry.set_text("")
            return self.search_entry.grab_focus()
        elif key == 'd':
            if self.notebook.get_current_page() == 0:
                GObject.idle_add(self.notebook.set_current_page,1)
            else:
                GObject.idle_add(self.notebook.set_current_page,0)

        # If user press Esc button in fullscreen mode
        if event.keyval == Gdk.KEY_Escape and self.player.fullscreen:
            return self.player.set_fullscreen()

    def on_treeview_clicked(self,widget):
        '''prepare media infos from engine if available'''
        try:
            self.search_engine.get_media_infos()
        except:
            return
    
    
    def download_file(self, widget=None,link=None,name=None,codec = None,data=None,engine_type=None,engine_name=None,receive=False):
        try:
            if receive == False:
                try:
                    self.search_engine.download_file()
                except:
                    print '%s no download_file func' % self.engine.name
                return
        except:
            print ''
        if not link:
            try:
                link = self.active_link
            except:
                link = link
        if not name:
            name = self.media_name
        if not codec:
            codec = self.player.player.media_codec
        print link, name, codec, data, engine_name, engine_type
        download = downloader.FileDownloader(self, link, name, codec, data, engine_name, engine_type)
        download.start()
                
    def download_debrid(self, link):
        check = self.url_checker.check([link])
        if check != [link]:
            if check[0][1] == 0:
                self.info_label.set_text(_("This link has been removed or is expired...!"))
                return
            link   = check[0][0]
        thread = threading.Thread(target=self.url_debrid.debrid ,args=(link,))
        thread.start()

    def on_about_btn_pressed(self, widget):
        dlg = self.gladeGui.get_object("aboutdialog")
        dlg.set_version(VERSION)
        response = dlg.run()
        if response == Gtk.ResponseType.DELETE_EVENT or response == Gtk.ResponseType.CANCEL:
            dlg.hide()

    def on_settings_btn_pressed(self, widget):
        self.dlg.set_position(Gtk.WindowPosition.CENTER_ALWAYS)
        response = self.dlg.run()
        if response == False or response == True or response == Gtk.ResponseType.DELETE_EVENT:
            self.dlg.hide()

    def save_window_state(self):
        try:
            r,s,w,h = self.window.get_allocation()
            self.window.grab_focus()
            self.conf['window_state'] = (w,h,self.x,self.y)
            self.conf.write()
        except:
            return

    def exit(self,widget=None):
        """Stop method, sets the event to terminate the thread's main loop"""
        self.player.stop()
        try:
            self.player.shutdown()
        except:
            print 'player stopped'
        ## save window state
        self.save_window_state()
        self.manager.stop_all_threads(block=True)
        for th in self.download_pool:
            if not th._stopevent.isSet():
                print 'call stop download %s' % th.name
                th.stop(abort=True)
        self.mainloop.quit()

    def stop_threads(self, *args):
        #THE ACTUAL THREAD BIT
        self.manager.stop_all_threads()

    def add_thread(self, engine, query, page):
        #make a thread and start it
        thread_name = "Search thread %s,%s,%s" % (engine.name, query, page)
        args = (thread_name,self.info_label,engine,query,page,self.throbber,self.stop_search_btn)
        #THE ACTUAL THREAD BIT
        self.manager.make_thread(
                        self.thread_finished,
                        self.thread_progress,
                        *args)

    def thread_finished(self, thread):
        ## check automatic page change
        self.stop_search_btn.set_sensitive(0)
        if len(self.model) > 0:
            self.player.changepage_btn.set_sensitive(1)
            if self.change_page_request:
                ## wait for 10 seconds or exit
                try:
                    self.selected_iter = self.model.get_iter_first()
                    path = self.model.get_path(self.selected_iter)
                    self.treeview.set_cursor(path)
                    GObject.idle_add(self.get_model)
                    self.change_page_request=False
                except:
                    self.change_page_request=False
                    return
        else:
            self.player.changepage_btn.set_sensitive(0)
        self.info_label.set_text("")


    def thread_progress(self, thread):
        pass
        
    
    def select_first_media(self):
        ## wait for 10 seconds or exit
        try:
            self.selected_iter = self.model.get_iter_first()
            path = self.model.get_path(self.selected_iter)
            GObject.idle_add(self.treeview.set_cursor,path)
            GObject.idle_add(self.get_model)
        except:
            return
    
    def _show_search_playlist_menu(self,widget,event):
        if event.button == 3:
            self.search_playlist_menu_active = True
            self.search_playlist_menu.show_all()
            self.search_playlist_menu.popup(None, None, None, event.button, event.time)
        
    def _copy_link(self,widget=None,vid=None):
        self.search_playlist_menu_active = False
        link = self.media_link
        if self.search_engine.name == 'Youtube' and not vid:
            link = 'http://www.youtube.com/watch?v=%s' % self.media_link
        clipboard = Gtk.Clipboard(Gdk.Display.get_default(), "CLIPBOARD")
        clipboard.set_text(link)
        print '%s copied to clipboard' % link
        
    def _add_to_playlist(self,widget):
        self.search_playlist_menu_active = False
        link = self.media_link
        if self.search_engine.name == 'Youtube':
            link = 'http://www.youtube.com/watch?v=%s' % self.media_link
        self.Playlist.add(self.media_name, link, self.active_link, self.media_plugname)
    
    def __create_trayicon(self):
        if Gtk.check_version(2, 10, 0) is not None:
            self.log.debug("Disabled Tray Icon. It needs PyGtk >= 2.10.0")
            return
        self.tray = Gtk.StatusIcon()
        self.tray.set_from_file(os.path.join(self.img_path,'gmediafinder.png'))
        self.tray.set_tooltip('Gmediafinder')
        self.tray.connect("activate", self.__on_trayicon_click)
        self.tray.connect("popup-menu", self.__show_tray_menu)
  
  
    def __on_trayicon_click(self, widget):
        if(self.showed is True):
            self.showed = False
            self.window.hide()
            self.save_window_state()
        else:
            self.showed = True
            self.window.show()
            self.set_window_position()
  
    def __show_tray_menu(self, widget, button, activate_time):
        menu = Gtk.Menu()
        exit_item = Gtk.ImageMenuItem(Gtk.STOCK_QUIT)
        menu.append(exit_item)
        exit_item.connect('activate', self.exit)
  
        menu.show_all()
        menu.popup(None, None, None, button, activate_time)
        
    def __add_to_history(self):
        search = self.search_entry.get_text()
        c = open(history_file,'r')
        t = c.readlines()
        c.close()
        inlist = False
        for i in t:
            if re.match(search, i.replace('\n','')):
                inlist = True
                break
        if inlist:
            return
        if len(t) >= int(max_history):
            u = open(history_file,'w')
            del t[0]
            u.writelines(t)
            u.close()
        f = open(history_file,'a')
        f.write("%s\n" % search)
        f.close()
    
    def __search_history(self, widget):
        search = self.search_entry.get_text()
        self.history_model.clear()
        for l in open(history_file,'r'):
            try:
                s = re.search('.*%s.*' % search,l).group()
                self.history_model.append([s])
            except:
                pass
    
    def clear_history(self, widget):
        search = self.search_entry.get_text()
        self.history_model.clear()
        f = open(history_file,'w')
        f.write(' ')
        f.close()

  
    def __close(self, widget, event=None):
        if self.minimize == 'on':
            self.showed = False
            self.hide()
            self.save_window_state()
        else:
            self.quit(widget)
        return True
        
    def run(self):
        Gtk.main
Ejemplo n.º 20
0
# needed if LANG=en_US.UTF-8
sys.stdout = codecs.getwriter('utf8')(sys.stdout)

if __name__ == "__main__":

    args = Args()

    if args.signal:
        c = Control(args.port)
        if   args.signal == "start"     : c.start()
        elif args.signal == "stop"      : c.stop()
        elif args.signal == "restart"   : c.restart()

    else:
        playlist = Playlist(args.port)
        if   args.query                 :
            try:            print playlist.query()
            except IOError: pass # don't puke if quitting less(1)
        elif args.shuffle               : print playlist.shuffle()
        elif args.repeat                : print playlist.repeat()
        elif args.kontinue              : print playlist.kontinue()
        elif args.next_album            : print playlist.next_album()
        elif args.next_artist           : print playlist.next_artist()
        else:
            for action, arg in args.args_dict.items():
                try:
                    print {
                        "clear"         : playlist.clear,
                        "index"         : playlist.index,
                        "enqueue"       : playlist.enqueue
Ejemplo n.º 21
0
    def __init__(self):
        ## default search options
        self.is_playing = False
        self.is_paused = False
        self.nbresults = 100
        self.user_search = ""
        self.showed = True ## trayicon
        self.settings_folder = None
        self.conf_file = None
        self.active_downloads = 0
        self.thread_num = 0
        self.engine_list = {}
        self.engine = None
        self.conf=conf
        self.latest_engine = ""
        self.change_page_request = False
        self.tray = None
        self.download_pool = []
        self.media_bitrate= None
        self.media_codec= None
        self.playlist_mode = False
        self.play = False
        self.draw_text = False
        self.url_checker = checkLink.CheckLinkIntegrity()
        self.url_debrid = debrider.Debrid(self)
        self.player_thread=None
        
        ## main gui
        self.gladeGui = Gtk.Builder()
        self.gladeGui.add_from_file(data_path+"/glade/mainGui.ui")
        Gtk.Builder.set_translation_domain(self.gladeGui, APP_NAME)
        self.window = self.gladeGui.get_object("main_window")
        self.window.set_title("Gmediafinder")
        self.window.set_resizable(1)
        self.set_window_position()
        self.show_thumbs_opt_toggle = self.gladeGui.get_object("show_thumbs_opt")
        if self.conf['show_thumbs'] == "True" :
            self.show_thumbs_opt_toggle.set_active(1)
        self.img_path = img_path
        self.window.set_icon_from_file(os.path.join(self.img_path,'gmediafinder.png'))
        self.window.connect('key-press-event', self.onKeyPress)
    
        
        # options menu
        self.options_bar = self.gladeGui.get_object("options_bar")
        self.search_box = self.gladeGui.get_object("search_box")
        self.results_box = self.gladeGui.get_object("results_box")
        self.quality_box = self.gladeGui.get_object("quality_box")

        ## throbber
        self.throbber = self.gladeGui.get_object("throbber_img")
        animation = GdkPixbuf.PixbufAnimation.new_from_file(self.img_path+'/throbber.gif')
        self.throbber.set_from_animation(animation)

        ## notebooks
        self.notebook = self.gladeGui.get_object("notebook")
        self.results_notebook = self.gladeGui.get_object("results_notebook")
        self.video_cont = self.gladeGui.get_object("video_cont")

        self.search_entry = self.gladeGui.get_object("search_entry")
        self.stop_search_btn = self.gladeGui.get_object("stop_search_btn")
        ## playlist
        self.playlists_xml = playlists_xml
        self.playlist_scrollbox = self.gladeGui.get_object("playlist_scrollbox")
        ## history
        self.search_entry.connect('changed',self.__search_history)
        self.history_view = Gtk.EntryCompletion()
        self.history_view.set_minimum_key_length(1)
        self.search_entry.set_completion(self.history_view)
        self.history_model = Gtk.ListStore(GObject.TYPE_STRING)
        self.history_view.set_model(self.history_model)
        self.history_view.set_text_column(0)
        ## options box
        self.search_opt_box = self.gladeGui.get_object("search_options_box")

        ## statbar
        self.statbar = self.gladeGui.get_object("statusbar")
        ## info
        self.info_label = self.gladeGui.get_object("info_label")


        ##extras options
        self.downloads_check = self.gladeGui.get_object("downloads_enabled")
        self.convert_check = self.gladeGui.get_object("convert_enabled")
        self.warn_dialog = self.gladeGui.get_object("warn_dialog")
        self.systray_check = self.gladeGui.get_object("systray_enabled")
        self.down_dir = down_dir
        self.down_btn = self.gladeGui.get_object("down_btn")
        self.down_menu_btn = self.gladeGui.get_object("down_menu_btn")
        if downloads == 'True':
            self.downloads_check.set_active(1)
        if convert == 'True':
            self.convert_check.set_active(1)
        if systray == 'True':
            self.systray_check.set_active(1)

        ## SIGNALS
        dic = {"on_main_window_destroy_event" : self.exit,
        "on_quit_menu_activate" : self.exit,
        "on_nextpage_btn_clicked" : self.change_page,
        "on_pageback_btn_clicked" : self.change_page,
        "on_search_entry_activate" : self.prepare_search,
        "on_about_menu_clicked" : self.on_about_btn_pressed,
        "on_settings_menu_clicked" : self.on_settings_btn_pressed,
        "on_main_window_configure_event" : self.save_position,
        "on_search_entry_icon_press" : self.clear_search_entry,
        "on_show_thumbs_opt_toggled" : self.on_gui_opt_toggled,
        "on_stop_search_btn_clicked": self.stop_threads,
        "on_downloads_enabled_toggled" : self.set_extras_options,
        "on_convert_enabled_toggled" : self.set_extras_options,
        "on_systray_enabled_toggled" : self.set_extras_options,
        "on_clear_history_btn_clicked" : self.clear_history,
         }
        self.gladeGui.connect_signals(dic)
        self.window.connect('destroy', self.exit)

        ## create main results treeview
        self.model = Gtk.ListStore(GdkPixbuf.Pixbuf,str,object,object,object,str,str,GdkPixbuf.Pixbuf,bool)
        self.treeview = Gtk.TreeView()
        self.window.realize()
        self.window_style=self.window.get_style_context()
        self.odd = Gdk.color_parse(self.window_style.lookup_color('theme_bg_color')[1].to_string())
        self.even = Gdk.color_parse(self.window_style.lookup_color('theme_base_color')[1].to_string())
        self.front = Gdk.color_parse(self.window_style.lookup_color('theme_fg_color')[1].to_string())
        self.treeview.set_model(self.model)

        rendererp = Gtk.CellRendererPixbuf()
        pixcolumn = Gtk.TreeViewColumn("",rendererp,  pixbuf=0)
        self.treeview.append_column(pixcolumn)

        rendertxt = Gtk.CellRendererText()
        txtcolumn = Gtk.TreeViewColumn("txt",rendertxt, markup=1)
        txtcolumn.set_cell_data_func(rendertxt, self.alternate_color)
        txtcolumn.set_title(_(' Results : '))
        self.treeview.append_column(txtcolumn)

        renderer = Gtk.CellRendererText()
        pathColumn = Gtk.TreeViewColumn("Link", renderer)
        self.treeview.append_column(pathColumn)

        qualityColumn = Gtk.TreeViewColumn("Quality", renderer)
        self.treeview.append_column(qualityColumn)
        
        nameColumn = Gtk.TreeViewColumn("Name", renderer)
        self.treeview.append_column(nameColumn)

        plugnameColumn = Gtk.TreeViewColumn("Name", renderer)
        self.treeview.append_column(plugnameColumn)
        
        
        ## setup the scrollview
        self.results_scroll = self.gladeGui.get_object("results_scrollbox")
        self.columns = self.treeview.get_columns()
        if self.conf['show_thumbs'] == "False":
            self.columns[0].set_visible(0)
        self.columns[1].set_sort_column_id(1)
        self.columns[2].set_visible(0)
        self.columns[3].set_visible(0)
        self.columns[4].set_visible(0)
        self.columns[5].set_visible(0)
        self.results_scroll.add(self.treeview)
        self.results_scroll.connect_after('size-allocate', self.resize_wrap, self.treeview, self.columns[1], rendertxt)
        
        ## right click menu
        self.search_playlist_menu = Gtk.Menu()
        getlink_item = Gtk.ImageMenuItem(Gtk.STOCK_COPY)
        getlink_item.get_children()[0].set_label(_('Copy file link'))
        addplaylist_item = Gtk.ImageMenuItem(Gtk.STOCK_EDIT)
        addplaylist_item.get_children()[0].set_label(_('Add to Library'))
        self.search_playlist_menu.append(getlink_item)
        self.search_playlist_menu.append(addplaylist_item)
        getlink_item.connect('activate', self._copy_link)
        addplaylist_item.connect('activate', self._add_to_playlist)
        ## connect treeview signals
        self.search_playlist_menu_active = False
        self.treeview.connect('row-activated',self.get_model)
        self.treeview.connect('cursor-changed',self.on_treeview_clicked)
        self.treeview.connect('button-press-event',self._show_search_playlist_menu)

        ## engines
        self.dlg = self.gladeGui.get_object("settings_dialog")
        self.engines_box = self.gladeGui.get_object("engines_box")
        
        ## create engines selector combobox
        box = self.gladeGui.get_object("engine_selector_box")
        self.active_engines = create_comboBox()
        self.active_engines.connect("changed", self.set_engine)
        box.pack_start(self.active_engines, False,False,5)
        self.engine_selector = ComboBox(self.active_engines)
        self.engine_selector.append("")
        ## load playlists
        self.Playlist = Playlist(self)
        ## init player
        self.player = Player(self)
        
        ## check extra options
        if downloads == 'False':            
            self.down_btn.hide()
            self.down_menu_btn.hide()
        else:
            ## init downloader
            self.downloader = downloader.Downloader(self)
            self.downloader.download_treeview.columns_autosize()
        
        ## tray icon
        if systray == 'True':
            self.__create_trayicon()
        
        
        ## browser notebook
        self.media_notebook = self.gladeGui.get_object("media_notebook")
        self.browser_box = self.gladeGui.get_object("browser_cont")
        #self.browser = browser(self)
        #self.browser.load_uri('http://video.google.com/')
        
        ## start gui
        GObject.idle_add(self.media_notebook.set_current_page,1)
        self.window.show_all()
        self.throbber.hide()
        ## start engines
        self.engines_client = Engines(self)

        ## engine selector (engines only with direct links)
        self.global_search = _("All")
        self.global_audio_search = _("All audios")
        self.global_video_search = _("All videos")

        for engine in sorted(self.engine_list):
            try:
                if getattr(self.engines_client, '%s' % engine).adult_content:
                    self.engine_selector.append(engine,True)
            except:
                self.engine_selector.append(engine)

        if ("Youtube" in self.engine_list):
            self.engine_selector.setIndexFromString("Youtube")
        else:
            self.engine_selector.select(0)
        self.engine_selector.append(self.global_search)
        self.engine_selector.append(self.global_audio_search)
        self.engine_selector.append(self.global_video_search)
        self.search_entry.grab_focus()
        self.statbar.hide()
        
        ## hide some icons by default
        self.stop_search_btn.set_sensitive(0)
            
        #THE ACTUAL THREAD BIT
        self.manager = FooThreadManager(20)
        self.resume_downloads()
        self.mainloop = GObject.MainLoop(is_running=True)
Ejemplo n.º 22
0
def main():
    args = Args()

    if args.signal:
        c = Control(args.port)
        if   args.signal == u"start"     : c.start()
        elif args.signal == u"stop"      : c.stop()
        elif args.signal == u"restart"   : c.restart()
    else:
        pool        = Pool(Config.pool_size, init_worker)
        playlist    = Playlist(args.port, pool)
        if   args.query                 :
            try:            print playlist.query()
            except IOError: pass # don't puke if quitting less(1)
        elif args.shuffle               : print playlist.shuffle()
        elif args.repeat                : print playlist.repeat()
        elif args.kontinue              : print playlist.kontinue()
        elif args.next_album            : print playlist.next_album()
        elif args.next_artist           : print playlist.next_artist()
        else:
Ejemplo n.º 23
0
class Streamer(object):
    def __init__(self, request, port):

        self.playlist = Playlist(port, pool=None)
        self.request = request
        self.byte_count = 0

        if Config.scrobble:

            self.scrobble_queue = Queue.Queue()
            self.scrobbler = Scrobbler(self.scrobble_queue)
            self.scrobbler.daemon = True
            self.scrobbler.start()

    # It's always a good day for smoking crack at Nullsoft!
    #   See the Amarok source for ideas on the (crappy) icecast metadata "protocol"
    #           This explains the whole cockamamie thing:
    #           http://www.smackfu.com/stuff/programming/shoutcast.html

    def get_meta(self, song):
        # lifted from amarok
        metadata = u"%cStreamTitle='%s';StreamUrl='%s';%s"
        padding = u'\x00' * 16
        meta = None
        if self.dirty_meta:
            songs = unicode(song)
            stream_title = songs.encode(u'ascii', u'ignore')
            stream_url = Config.url

            # 28 is the number of static characters in metadata (!)
            length = len(stream_title) + len(stream_url) + 28
            pad = 16 - length % 16
            what = padding[:pad]
            meta = metadata % ((
                (length + pad) / 16), stream_title, stream_url, what)
            self.dirty_meta = False
        else:
            meta = u'\x00'

        return meta

    def empty_scrobble_queue(self):
        if Config.scrobble:
            with self.scrobble_queue.mutex:
                self.scrobble_queue.queue.clear()

    def stream(self, icy_client=False):
        song = None
        while self.playlist.data[u'running']:
            if Config.scrobble and song:
                # just played one . . . scrobble it
                self.scrobble_queue.put(ScrobbleItem(PLAYED, song))
                #log.debug("enqueued played")
                #log.debug(song)

            # new song
            song = self.playlist.get_song()
            song_start_time = time.time()
            self.playlist.data[u"progress"] = 0

            if not song:
                log.warn(u"no playlist, won't stream")
                self.playlist.data[u'status'] = u'stopped'
                self.byte_count = 0
                self.empty_scrobble_queue()
                return

            if Config.scrobble:
                #log.debug("enqueued now playing")
                self.scrobble_queue.put(ScrobbleItem(NOW_PLAYING, song))

            log.info(u'> %s' % unicode(song))

            transcode = None
            try:
                # this loop gets some of its ideas about the shoutcast protocol from Amarok
                buffer = 0
                buffer_size = Config.buffer_size
                metadata_interval = Config.metaint

                try:
                    transcode.stdout.close()
                except:
                    pass

                #cif song.mimetype[0:5] in ["audio", "video"]:
                transcode = subprocess.Popen([
                    u"/usr/bin/ffmpeg", u"-i", song.path, u"-vn", u"-loglevel",
                    u"warning", u"-qscale:a", u"0", u"-f", u"mp3", u"-"
                ],
                                             stdout=subprocess.PIPE,
                                             shell=False)
                self.dirty_meta = True

                skip = False
                while self.playlist.data[u'running'] and transcode:
                    bytes_until_meta = (metadata_interval - self.byte_count)
                    if bytes_until_meta == 0:
                        if icy_client:
                            metadata = self.get_meta(song)
                            self.request.send(
                                metadata.encode(u'ascii', u'ignore'))
                        self.byte_count = 0
                    else:
                        if bytes_until_meta < buffer_size:
                            chunk_bytes = bytes_until_meta
                        else:
                            chunk_bytes = buffer_size
                        buffer = transcode.stdout.read(chunk_bytes)

                        self.request.send(buffer)
                        buflen = len(buffer)
                        self.byte_count += buflen
                        self.playlist.data[u"sum_bytes"] += buflen
                        elapsed = time.time() - song_start_time
                        self.playlist.data[u'elapsed'] = elapsed
                        # set percentage elapsed
                        try:
                            self.playlist.data[u"progress"] = float(
                                elapsed * 100) / song.length
                        except ZeroDivisionError:
                            self.playlist.data[u"progress"] = 0

                        if len(buffer) == 0: break

                    if self.playlist.data[u'skip']:
                        log.info(u">>")
                        skip = True
                        song = None  # don't scrobble
                        self.playlist.data[u"elapsed"] = 0
                        self.playlist.data[u"progress"] = 0
                        break

                    if self.playlist.data[u'status'] == u'stopped':
                        log.info(u".")
                        skip = True
                        song = None  # don't scrobble
                        self.playlist.data[u"elapsed"] = 0
                        break

                if not skip:
                    # increment the counter if we're not ffwding
                    self.playlist.next()
                else:
                    self.playlist.data[u'skip'] = False
                self.dirty_meta = True
            except error, e:
                if isinstance(e.args, tuple):
                    print "errno is %d" % e[0]
                    if e[0] == errno.EPIPE:
                        # remote peer disconnected
                        print "Detected remote disconnect"

                    elif e.errno == errno.ECONNRESET:
                        self.empty_scrobble_queue()
                        log.info(u"Client disconnected")
                    else:
                        log.info(u"Unknown socket error")
                        self.empty_scrobble_queue()
                        log.exception(errno.errorcode[e.errno])
                else:
                    print "socket error ", e
                self.request.close()
                self.playlist.data[u'status'] = 'stopped'
                break  # while
            except IOError, e:
                log.info("IO ERROR")
            except KeyboardInterrupt:
                self.playlist.data[u'running'] = False