예제 #1
0
    def __init__(self, extensionsloader):
        self.extensions = extensionsloader
        self.module = {'name': 'Explorer'}

        self.functions = Functions()
        self.userconf = ConfigLoader()

        self.songs_tree = {}
        self.albums = {}

        # Create the Albums view
        def launch_explorer(wdg):
            self.widgets = wdg

            self.aview = AlbumsView(self.widgets, self.extensions)
            self.search = Search(self.widgets, self.aview)
            self.filter = Filter(self.widgets, self.aview)

            # Populate the view
            self.populate()

            # Connect to signals
            def repopulate(wdg):
                self.extensions.load_event('OnAbortPlayback')
                self.populate(True)

            self.widgets[0][3].connect('clicked', repopulate)

        self.extensions.connect('OnBluemindoStarted', launch_explorer)
        self.extensions.connect('AskShuffleSong', self.shuffle_song_asked)
예제 #2
0
 def __init__(self,method,url,data=None,cookies=None,headers=None):
     config = ConfigLoader()
     url_pre = config.get('api','url_pre')
     try:
         if method == 'get':
             self.resp = requests.get(url=url_pre+url, params=data, cookies=cookies, headers=headers)
         elif method == 'post':
             self.resp = requests.post(url=url_pre+url, data=data, cookies=cookies, headers=headers)
         elif method == 'delete':
             self.resp = requests.delete(url=url_pre+url, data=data, cookies=cookies, headers=headers)
     except Exception as e:
         raise e
예제 #3
0
    def __init__(self):
        if Functions.ref2 is None:
            Functions.ref2 = 42

            self.userconf = ConfigLoader()

            # Just set the data and the locale dir
            if isdir('../data') and isfile('../locale/bluemindo.pot'):
                self.datadir = '../data'
                self.localedir = '../locale'
            else:
                self.datadir = '/usr/share/bluemindo'
                self.localedir = '/usr/share/locale'
예제 #4
0
class Context:
    config = ConfigLoader()
    # 投资人测试数据
    normal_user = config.get('basic', 'normal_user')
    normal_pwd = config.get('basic', 'normal_pwd')
    normal_member_id = config.get('basic', 'normal_member_id')
    # 管理员测试数据
    admin_user = config.get('basic', 'admin_user')
    admin_pwd = config.get('basic', 'admin_pwd')
    # 借款人测试数据
    loan_member_id = config.get('basic', 'loan_member_id')
예제 #5
0
class Context:
    config = ConfigLoader()
    normal_user = config.get('basic','normal_user')
    normal_pwd = config.get('basic','normal_pwd')
    normal_member_id = config.get('basic','normal_member_id')

    admin_user = config.get('basic','admin_user')
    admin_pwd = config.get('basic','admin_pwd')

    loan_member_id = config.get('basic','loan_member_id')
    unnormal_member_id = config.get('basic','unnormal_member_id')
예제 #6
0
 def __init__(self, method, url, data=None, cookies=None, headers=None):
     config1 = ConfigLoader()
     url_pre = config1.get_conf_str("api", "url_pre")
     url = url_pre + url
     try:
         if method == "get":
             self.resp = requests.get(url=url,
                                      params=data,
                                      cookies=cookies,
                                      headers=headers)
         elif method == "pose":
             self.resp = requests.post(url=url,
                                       data=data,
                                       cookies=cookies,
                                       headers=headers)
         elif method == "delete":
             self.resp = requests.delete(url=url,
                                         data=data,
                                         cookies=cookies,
                                         headers=headers)
     except Exception as e:
         raise e
예제 #7
0
 def __init__(self):
     config = ConfigLoader()
     host = config.get('mysql', 'host')
     port = config.getint('mysql', 'port')  # port 是一个数值
     user = config.get('mysql', 'usr')
     password = config.get('mysql', 'pwd')
     # 异常处理
     self.mysql = pymysql.connect(host=host,
                                  user=user,
                                  password=password,
                                  port=port,
                                  cursorclass=pymysql.cursors.DictCursor)
예제 #8
0
class WebServices(object):
    """A class to handles many WebServices."""

    config = ConfigLoader()
    functions = Functions()
    lock = Lock()

    def get_xml(self, url):
        """This function downloads a file and returns an ElementTree object."""
        req = urlopen(url)
        content = req.read()

        return ElementTree.fromstring(content)

    def get_html(self, url):
        """This function downloads a file and returns its content."""
        req = urlopen(url)
        content = req.read()

        return content
예제 #9
0
 def __init__(self):
     config = ConfigLoader()
     host = config.get_conf_str("mysql", "host")
     port = config.get_conf_int("mysql", "port")
     user = config.get_conf_str("mysql", "user")
     pwd = config.get_conf_str("mysql", "pwd")
     charset = str(config.get_conf_str("mysql", "charset"))
     # 异常处理
     try:
         self.mysql = pymysql.connect(
             host=host,
             user=user,
             password=pwd,
             database=None,
             port=port,
             cursorclass=pymysql.cursors.DictCursor,
             charset='utf8')  # 返回字典对象
     except Exception as e:
         print("Mysql connect failed!")
예제 #10
0
    def __init__(self, widgets, aview):
        self.widgets = widgets

        self.functions = Functions()
        self.userconf = ConfigLoader()

        # GUI
        self.filter_button = self.widgets[1].get_object('tool-filter')
        self.filter_button.connect('clicked', self.on_button_clicked)

        gladefile = join(self.functions.datadir, 'glade', 'filterbar.ui')
        self.fbox = gtk_builder()
        self.fbox.set_translation_domain('bluemindo')
        self.fbox.add_from_file(gladefile)
        self.filter_box = self.fbox.get_object('infobar')

        wdg_place = self.widgets[1].get_object('filter-emplacement')
        wdg_place.add(self.filter_box)

        self.fbox.get_object('label_filter').set_text(_('Filter the results:'))

        # Create ComboBoxes
        self.genre_fstore = ListStore(int, str)
        self.genre_fcombo = self.fbox.get_object('combobox-genre')
        self.genre_fcombo.set_model(self.genre_fstore)
        renderer_text = CellRendererText()
        self.genre_fcombo.pack_start(renderer_text, True)
        self.genre_fcombo.set_entry_text_column(1)
        self.genre_fcombo.add_attribute(renderer_text, 'text', 1)

        self.year_fstore = ListStore(int, str)
        self.year_fcombo = self.fbox.get_object('combobox-year')
        self.year_fcombo.set_model(self.year_fstore)
        renderer_text = CellRendererText()
        self.year_fcombo.pack_start(renderer_text, True)
        self.year_fcombo.set_entry_text_column(1)
        self.year_fcombo.add_attribute(renderer_text, 'text', 1)
예제 #11
0
 def __init__(self):
     config = ConfigLoader()
     host = config.get('mysql', 'host')
     port = config.getint('mysql', 'port')
     user = config.get('mysql', 'usr')
     password = config.get('mysql', 'pwd')
     #自行添加异常处理
     try:
         self.mysql = pymysql.connect(
             host=host,
             user=user,
             password=password,
             port=port,
             cursorclass=pymysql.cursors.DictCursor)  #建立连接
         print('数据库连接成功!')
     except AssertionError as e:
         print('数据库连接失败!', e)
         raise e
예제 #12
0
    def __init__(self, widgets, extensions):
        self.widgets = widgets
        self.extensions = extensions

        self.functions = Functions()
        self.userconf = ConfigLoader()
        self.dblclick = None

        # Create the IconView
        self.albumview = self.widgets[1].get_object('albumview')
        self.albummodel = ListStore(Pixbuf, str, str, str, int, str, str)

        self.albumview.set_pixbuf_column(0)
        self.albumview.set_markup_column(1)

        self.albumview.set_column_spacing(0)
        self.albumview.set_spacing(0)
        self.albumview.set_item_width(100)
        self.albumview.set_property('activate-on-single-click', False)

        # Add a filter to the ListStore model
        self.albumfilter = self.albummodel.filter_new(None)
        self.remove_filter_data()
        self.matched = False

        def filter_visible(model, iter, data):
            usrf = self.widgets[1].get_object('searchentry').get_text()
            search_a = model.get_value(iter, 3)
            search_b = model.get_value(iter, 2)
            pre_result = False

            if self.matched:
                usrf_a = self.matched[0]
                usrf_b = self.matched[1]

                if usrf_b == 'blm.!ARTIST!':
                    if usrf_a.lower() == search_b.lower():
                        # Matched an artist
                        pre_result = True
                else:   
                    if (usrf_a.lower() == search_a.lower() and
                        usrf_b.lower() == search_b.lower()):
                        # Matched an album
                        pre_result = True
            else:
                if len(model) > 0:
                    if (usrf.lower() in search_a.lower() or
                        usrf.lower() in search_b.lower()):
                        # Found an element (artist or album name is close)
                        pre_result = True
                    else:
                        # No element founded at all, return False anyway
                        return False

            # Apply filters
            fdg = self.filter_data['genre']
            fdy = self.filter_data['year']

            # Filter results by genres
            if fdg is not None and fdg != model.get_value(iter, 5):
                pre_result = False

            # Filter results by years
            if fdy is not None and fdy != model.get_value(iter, 6):
                pre_result = False

            # Return the final result
            return pre_result


        self.albumfilter.set_visible_func(filter_visible)
        self.albumview.set_model(self.albumfilter)

        # Connect to signals
        def grab_entry_focus(widget, event):
            key = event.string
            if (key.lower() in 'a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,'
                               'x,y,z,0,1,2,3,4,5,6,7,8,9'.split(',')):
                self.widgets[1].get_object('searchentry').grab_focus()
                self.widgets[1].get_object('searchentry').set_text(key)
                self.widgets[1].get_object('searchentry').set_position(-1)

        self.albumview.connect('key-press-event', grab_entry_focus)
        self.albumview.connect('selection_changed', self.on_selection_changed)
예제 #13
0
class Explorer:
    def __init__(self, extensionsloader):
        self.extensions = extensionsloader
        self.module = {'name': 'Explorer'}

        self.functions = Functions()
        self.userconf = ConfigLoader()

        self.songs_tree = {}
        self.albums = {}

        # Create the Albums view
        def launch_explorer(wdg):
            self.widgets = wdg

            self.aview = AlbumsView(self.widgets, self.extensions)
            self.search = Search(self.widgets, self.aview)
            self.filter = Filter(self.widgets, self.aview)

            # Populate the view
            self.populate()

            # Connect to signals
            def repopulate(wdg):
                self.extensions.load_event('OnAbortPlayback')
                self.populate(True)

            self.widgets[0][3].connect('clicked', repopulate)

        self.extensions.connect('OnBluemindoStarted', launch_explorer)
        self.extensions.connect('AskShuffleSong', self.shuffle_song_asked)

    def populate(self, force_scan=False):
        threads_enter()

        # Do we have a working directory or not?
        if self.userconf.config['Explorer']['folder'] == '':
            fcdialog = FileChooserDialog(
                title=_('Open your music directory'),
                action=FileChooserAction.SELECT_FOLDER,
                buttons=(_('Select'), ResponseType.OK))

            fcdialog.set_transient_for(self.widgets[0][11])
            response = fcdialog.run()
            if response == ResponseType.OK:
                foldername = fcdialog.get_filename()
                self.userconf.update_key('Explorer', 'folder', foldername)
                force_scan = True
            else:
                print("Bluemindo can't work without opening a music " +
                      "directory. Exiting…")
                exit(0)

            fcdialog.destroy()

        # Call database
        musicdb = MusicDatabase(self.userconf.config['Explorer']['folder'])

        # Do we scan for new files?
        if (bool(int(self.userconf.config['Explorer']['scan_at_startup']))
                or force_scan):

            def do_scan():
                # Freeze user interface
                gldfile = join(self.functions.datadir, 'glade', 'loading.ui')
                win = gtk_builder()
                win.set_translation_domain('bluemindo')
                win.add_from_file(gldfile)
                box_content = win.get_object('box1')

                # Create an interface to help the user waiting for the job
                bluemindo = join(self.functions.datadir, 'image',
                                 'bluemindo.png')
                img = win.get_object('image')
                cover_px = Pixbuf.new_from_file(bluemindo)
                idle_add(img.set_from_pixbuf, cover_px)

                idle_add(
                    win.get_object('label').set_markup,
                    '<span size="x-large"><b>' +
                    _('Reloading music database.') + '</b></span>')

                idle_add(self.widgets[0][2].set_sensitive, False)
                idle_add(self.widgets[0][3].set_sensitive, False)
                idle_add(self.widgets[0][5].set_sensitive, False)
                idle_add(self.widgets[0][6].set_sensitive, False)
                idle_add(self.widgets[0][7].set_sensitive, False)
                idle_add(self.widgets[0][8].set_sensitive, False)

                idle_add(self.widgets[1].get_object('box1').add, box_content)

                lbl = win.get_object('label_info')
                idle_add(lbl.set_text,
                         _('Starting… Prepares to search for new files.'))

                # Update GUI
                box_content.show_all()
                self.widgets[1].get_object('box2').hide()

                # Do the scanning
                pb = win.get_object('progressbar')
                musicdb.scan(lbl, pb)

                # Show original GUI
                idle_add(self.widgets[0][2].set_sensitive, True)
                idle_add(self.widgets[0][3].set_sensitive, True)
                idle_add(box_content.hide)
                idle_add(self.widgets[1].get_object('box2').show_all)
                idle_add(self.create_view)

            thread = Thread(group=None,
                            target=do_scan,
                            name='scanning',
                            args=())
            thread.start()
        else:
            self.create_view()

        threads_leave()

    def create_view(self):
        # Call database
        musicdb = MusicDatabase(self.userconf.config['Explorer']['folder'])
        self.database = musicdb.load()

        self.albums_tree = []
        album_names = []
        album_iter = {}

        # Activate player buttons
        self.widgets[0][5].set_sensitive(True)
        self.widgets[0][6].set_sensitive(True)
        self.widgets[0][7].set_sensitive(True)
        self.widgets[0][8].set_sensitive(True)

        # Create the tree artists→albums→songs
        def unique(seq, keepstr=True):
            """This function ensures there are only unique values."""
            t = type(seq)
            if t in (str, str):
                t = (list, ''.join)[bool(keepstr)]
            seen = []
            return t(c for c in seq if not (c in seen or seen.append(c)))

        # Create the songs tree
        songs_tree = {}
        artists = []
        albums = []
        albums_dl = []

        for result in self.database:
            artists.append(result[1])
            albums.append((result[1], result[2]))

        artists = unique(artists)
        albums = unique(albums)

        for a in artists:
            songs_tree[a] = {}

        for a in albums:
            songs_tree[a[0]][a[1]] = []

        # Add songs
        for result in self.database:
            songs_tree[result[1]][result[2]].append(result)

        # Sort songs
        for artist in songs_tree.values():
            for album in artist.values():
                album.sort(key=lambda student: student[3])

        self.songs_tree = songs_tree

        i = 0
        for art in self.songs_tree:
            for alb in self.songs_tree[art]:
                album_names.append(alb)
                self.albums_tree.append({'album': alb, 'artist': art})
                i = i + 1

        # Sort everything
        self.albums_tree.sort(key=lambda item: item['album'].lower())
        self.albums_tree.sort(key=lambda item: item['artist'].lower())

        # Send the music tree to all extensions
        self.extensions.load_event('OnSongsTreeCreated', self.songs_tree)

        # Launch explorer GUI
        self.search.generate_autocompletion(artists, albums, self.songs_tree)
        self.aview.populate_albums(self.albums_tree, self.albums,
                                   self.songs_tree, self.search)
        self.filter.launch(self.albums_tree, self.songs_tree, self.aview)

    def shuffle_song_asked(self):
        if len(self.database) > 1:
            index = randrange(len(self.database))
            song_inf = self.database[index]

            song = Song(filename=song_inf[8])
            self.extensions.load_event('OnPlayNewSong', song)
예제 #14
0
    def __init__(self, widgets, aview):
        self.widgets = widgets

        self.aview = aview
        self.albumview = aview.albumview
        self.albumfilter = aview.albumfilter
        self.matched = aview.matched

        self.functions = Functions()
        self.userconf = ConfigLoader()

        # Create the autocompletion columns
        self.completion_model = ListStore(Pixbuf, str, str, str, str, str, str,
                                          str)
        ecomplet = EntryCompletion()
        ecomplet.set_model(self.completion_model)

        pixbufcell = CellRendererPixbuf()
        ecomplet.pack_start(pixbufcell, False)
        ecomplet.add_attribute(pixbufcell, 'pixbuf', 0)

        markupcell = CellRendererText()
        markupcell.props.xpad = 10
        ecomplet.pack_start(markupcell, True)
        ecomplet.add_attribute(markupcell, 'markup', 1)

        markupcell = CellRendererText()
        markupcell.props.xpad = 5
        ecomplet.pack_start(markupcell, False)
        ecomplet.add_attribute(markupcell, 'markup', 2)

        pixbufcell = CellRendererPixbuf()
        ecomplet.pack_start(pixbufcell, False)
        ecomplet.add_attribute(pixbufcell, 'icon_name', 3)

        ecomplet.props.text_column = 4

        def matched(widget, model, iter):
            item = model[iter]
            data_a = item[4]
            data_b = item[5]

            self.aview.matched = [data_a, data_b]
            self.albumfilter.refilter()

            if data_b == 'blm.!ARTIST!':
                # Matched an artist: show albums
                return False
            elif exists(data_b):
                # Matched a song: queue to playlist
                sng = Song(filename=item[5])
                self.aview.queue(sng)

                # Go back to empty search
                self.aview.matched = False
                searchentry = widget.get_entry()
                searchentry.set_text('')
                return True
            #elif len(self.albumfilter) == 1:
            else:
                # Matched an album: load it in a panel
                album = Album(data_b, data_a, self.songs_tree)
                if hasattr(album, 'name'):
                    self.aview.on_album_matched(album)

                    # Go back to empty search
                    self.aview.matched = False
                    searchentry = widget.get_entry()
                    searchentry.set_text('')
                    return True

        ecomplet.connect('match-selected', matched)

        searchentry = self.widgets[1].get_object('searchentry')
        searchentry.set_completion(ecomplet)
        searchentry.grab_focus()

        def do_filter(widget):
            self.albumfilter.refilter()
            self.aview.matched = False

        searchentry.connect('changed', do_filter)
        self.searchentry = searchentry
예제 #15
0
    do_excel = DoExcel(contants.case_file)  # 实例化一个DoExcel对象
    sheet_names = do_excel.get_sheet_names()  # 获取Excel文件中全部sheet名称,返回为一个列表
    print("sheet名称列表:",sheet_names)
    cases_list = ['login', 'register'] # 定义一个执行测试用例的列表

    #  根据sheet_names 分别取到全部用例来执行
    for sheet_name in sheet_names:
        # 获取login的所有测试用例,返回的是一个cases列表,列表里面是多个Case类实例,每个实例的属性对应Excel表中每列的值
        if sheet_name in cases_list: #如果当前的这个sheet_name不在可执行的case_list里面,就不执行
            cases = do_excel.get_cases(sheet_name)
            print(sheet_name+' 测试用例个数:', len(cases))
            for case in cases:  # 遍历测试用例列表,每进for一次,就取一个case实例
                print("case信息:", case.__dict__)  # 打印case信息  对象的内置的私有方法
                # data = eval(case.data)  # Excel里面取到data是一个字符串,使用eval函数将字符串转换成字典
                data = json.loads(case.data)
                config = ConfigLoader()
                url_pre = config.get('api','url_pre')
                url = url_pre + case.url
                resp = Request(method=case.method, url=url, data=data)  # 通过封装的Request类来完成接口的调用
                print('status_code:', resp.get_status_code())  # 打印响应码
                resp_dict = resp.get_json()  # 获取请求响应,字典
                # 通过json.dumps函数将字典转换成格式化后的字符串
                resp_text = json.dumps(resp_dict, ensure_ascii=False, indent=4)
                print('response: ', resp_text)  # 打印响应

                if case.expected == resp.get_text():
                    print("result : PASS")
                    do_excel.write_result_by_case_id(sheet_name=sheet_name,case_id=case.case_id,
                                                     actual=resp.get_text(),result='PASS')
                else:
                    print("result : FAIL")
예제 #16
0
class Functions(object):
    ref = None
    ref2 = None

    def __new__(cls, *args, **kws):
        # Singleton
        if cls.ref is None:
            cls.ref = object.__new__(cls)
        return cls.ref

    def __init__(self):
        if Functions.ref2 is None:
            Functions.ref2 = 42

            self.userconf = ConfigLoader()

            # Just set the data and the locale dir
            if isdir('../data') and isfile('../locale/bluemindo.pot'):
                self.datadir = '../data'
                self.localedir = '../locale'
            else:
                self.datadir = '/usr/share/bluemindo'
                self.localedir = '/usr/share/locale'

    def get_hash(self, str1, str2):
        """Just return the hash for given strings"""
        md5 = md5_new()
        md5.update(str1.encode('utf-8'))
        md5.update(str2.encode('utf-8'))

        return str(md5.hexdigest())

    def view_encode(self, string, limit=25):
        if (len(string)) > limit:
            string = string[:limit] + '…'

        string = markup_escape_text(string)
        return string

    def unescape(string):
        """Unescape an escaped string with markup_escape_text."""
        _str = xml_unescape(string, {'&apos;': "'", '&quot;': '"'})

        return _str

    def human_length(self, length):
        """Return the length in a human-readable way"""
        lg0 = int(length / 60)
        lg1 = int(length % 60)

        if lg0 >= 0 and lg0 < 10:
            lg0 = '0' + str(lg0)

        if lg1 >= 0 and lg1 < 10:
            lg1 = '0' + str(lg1)

        lg = str(lg0) + ':' + str(lg1)
        return lg

    def clear_html(self, text, only_bold=False):
        """Return the text without html"""
        if text.startswith('<b>') and text.endswith('</b>'):
            text = text[3:-4]

        if not only_bold:
            if text.startswith('<span size="small">'):
                text = text[19:-7]

        return text

    def open_bluemindo(self, window):
        """Handle the Bluemindo's window open and change width,
        height and position on the screen."""
        width = int(self.userconf.config['Window']['width'])
        height = int(self.userconf.config['Window']['height'])
        window.resize(width, height)

        x = int(self.userconf.config['Window']['x'])
        y = int(self.userconf.config['Window']['y'])
        window.move(x, y)

    def close_bluemindo(self, window, quit=True):
        """This function is called when the Bluemindo's main window is
        closed."""
        # Backup window width, height and position
        if window is not None and window.get_properties('visible')[0]:
            width = window.get_size()[0]
            height = window.get_size()[1]
            x = window.get_position()[0]
            y = window.get_position()[1]

            self.userconf.update_key('Window', 'width', str(width))
            self.userconf.update_key('Window', 'height', str(height))
            self.userconf.update_key('Window', 'x', str(x))
            self.userconf.update_key('Window', 'y', str(y))

        # Delete the socket file and quit GTK
        if quit:
            SOCKET_NAME = '/tmp/bluemindo'
            if exists(SOCKET_NAME):
                remove(SOCKET_NAME)

            pid_filename = join(self.datadir, 'pid')
            if isfile(pid_filename):
                remove(pid_filename)

            current_playing = join(self.datadir, 'current-playing')
            if isfile(current_playing):
                remove(current_playing)

            print('The dolphin has plunge!')
            idle_add(gtk_main_quit)
        # Hide window
        else:
            if window.get_properties('visible')[0]:
                window.hide()
예제 #17
0
 def __init__(self):
     self.config = ConfigLoader()
예제 #18
0
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation version 3 of the License.

# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.

# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

from os.path import join, exists
import sqlite3 as sqlite

from common.config import ConfigLoader
config = ConfigLoader()


class SQLite(object):
    def __init__(self):
        sqlfile = join(config.datadir, 'songs.db')
        if not exists(sqlfile):
            database_exist = False
        else:
            database_exist = True

        self.cx = sqlite.connect(sqlfile)
        self.cur = self.cx.cursor()
        self.cx.text_factory = str

        if not database_exist:
예제 #19
0
class Playlist:
    def __init__(self, extensionsloader):
        self.extensions = extensionsloader
        self.module = {'name': 'Playlist'}

        self.functions = Functions()
        self.userconf = ConfigLoader()

        self.config = {}
        rpt = self.userconf.config['Playlist']['repeat']
        self.config['repeat'] = bool(int(rpt))
        shf = self.userconf.config['Playlist']['shuffle']
        self.config['shuffle'] = bool(int(shf))
        shm = self.userconf.config['Playlist']['shuffle_mode']
        self.config['shuffle_mode'] = shm

        self.lastfm = LastFm()
        self.playlists_mgmnt = Playlists()

        self.playlist_content = {}
        self.playlist_identifier = 0
        self.playlist_current = None
        self.current_playlist_id = 0
        self.user_playlists = {}
        self.last_user_playlist = None

        self.similar_artists = []
        self.is_in_similar_thread = False

        # Create the Playlist view
        def launch_playlist(wdg):
            self.widgets = wdg[1]

            self.playlist_label = self.widgets.get_object('label_playlist')
            self.playlist_repeat = self.widgets.get_object('tool-repeat')
            self.playlist_shuffle = self.widgets.get_object('tool-shuffle')
            self.playlist_clean = self.widgets.get_object('tool-clean')
            self.playlist_combo = self.widgets.get_object('combo-playlist')
            self.playlist_save = self.widgets.get_object('tool-saveplaylist')
            self.playlist_lyrics = self.widgets.get_object('tool-lyrics')

            self.playlist_tree = self.widgets.get_object('treeview_playlist')
            self.playlist_tree.set_headers_visible(False)
            self.playlist_tree.props.reorderable = True
            self.playlist_tree.connect('key_press_event', self.key_pressed)
            self.playlist_tree.connect('row_activated', self.row_activated)

            self.liststore = ListStore(str, str, str, str, int)
            self.playlist_tree.set_model(self.liststore)

            renderer_pix = CellRendererPixbuf()
            column_pixbuf = TreeViewColumn('1', renderer_pix, icon_name=0)
            column_pixbuf.set_fixed_width(18)
            self.playlist_tree.append_column(column_pixbuf)

            renderer_text = CellRendererText()
            column_text = TreeViewColumn('2', renderer_text, markup=1)
            column_text.props.expand = True
            column_text.props.max_width = 192
            self.playlist_tree.append_column(column_text)

            column_text = TreeViewColumn('3', renderer_text, markup=2)
            column_text.set_fixed_width(40)
            self.playlist_tree.append_column(column_text)

            self.repeat_btn = self.widgets.get_object('tool-repeat')
            if self.config['repeat']:
                self.repeat_btn.set_active(True)
            self.repeat_btn.connect('clicked', self.toggle, 'repeat')

            self.shuffle_btn = self.widgets.get_object('tool-shuffle')
            if self.config['shuffle']:
                self.shuffle_btn.set_active(True)
            self.shuffle_btn.connect('clicked', self.toggle, 'shuffle')

            def clean_wdg(widget):
                # Clean playlist
                self.clean()

                # Show popover
                if self.current_playlist_id > 3:
                    self.clean_btn.set_sensitive(True)
                    self.clean_pop.show_all()

            self.clean_btn = self.widgets.get_object('tool-clean')
            self.clean_btn.connect('clicked', clean_wdg)
            self.clean_pop = Popover.new(self.clean_btn)
            self.clean_pop.set_size_request(100, 30)

            gtkpla = join(self.functions.datadir, 'glade', 'plist-del-pop.ui')
            win = gtk_builder()
            win.set_translation_domain('bluemindo')
            win.add_from_file(gtkpla)
            hbox = win.get_object('box-playlist')
            lbl = win.get_object('label')
            lbl.set_text(_('Do you also want to remove the playlist?'))
            btn = win.get_object('del-btn')
            btn.set_label(_('Delete'))
            btn.connect('clicked', self.delete_playlist)
            self.clean_pop.add(hbox)

            # Populate combobox
            self.combolist = ListStore(int, str)

            self.combobox = self.widgets.get_object('combobox')
            self.combobox.set_model(self.combolist)
            self.combobox.set_popup_fixed_width(False)
            self.combobox.props.expand = False

            renderer_text = CellRendererText()
            renderer_text.props.ellipsize = EllipsizeMode.END
            self.combobox.pack_start(renderer_text, True)
            self.combobox.set_entry_text_column(1)
            self.combobox.add_attribute(renderer_text, 'text', 1)

            self.combolist.append([0, _('Current')])
            self.combolist.append([1, _('Top 50 songs')])
            self.combolist.append([2, _('Top 10 albums')])

            playlists = self.playlists_mgmnt.get_playlists()

            if len(playlists) > 0:
                self.combolist.append([3, ''])
                item_id = 3

                playlists.sort(key=lambda it: it[1])
                for item in playlists:
                    item_id += 1
                    self.combolist.append([item_id, item])
                    self.user_playlists[item_id] = item
                    self.last_user_playlist = item_id

            def combo_sep(model, iter):
                if model[iter][0] == 3:
                    return True
            self.combobox.set_row_separator_func(combo_sep)

            def on_combo_changed(widget):
                path = widget.get_active()
                item_id = self.combolist[path][0]

                # First, clean the playlist
                self.clean(None)

                # Second, populate the playlist
                if item_id > 0:
                    self.populate(item_id)

                # Then, update playlist identifier
                self.current_playlist_id = item_id

                # Show delete/remove button if the playlist is from the user
                if item_id > 3:
                    self.clean_btn.set_sensitive(True)

            self.combobox.set_active(0)
            self.combobox.connect('changed', on_combo_changed)
            
            self.tool_save = self.widgets.get_object('tool-saveplaylist')
            self.tool_save.connect('clicked', self.save_playlist)
            self.save_pop = Popover.new(self.tool_save)
            self.save_pop.set_size_request(100, 30)

            gtkpla = join(self.functions.datadir, 'glade', 'plist-add-pop.ui')
            win = gtk_builder()
            win.set_translation_domain('bluemindo')
            win.add_from_file(gtkpla)
            hbox = win.get_object('box-playlist')
            self.save_pop.add(hbox)

            self.save_entry = win.get_object('save-entry')
            self.save_entry.connect('key_press_event', self.save_playlist_key)
            self.save_btn = win.get_object('save-btn')
            self.save_btn.connect('clicked', self.save_playlist_button)
            self.save_btn.set_label(_('Save'))

            self.clean_btn.set_sensitive(False)
            self.tool_save.set_sensitive(False)

        # Acquire the songs tree
        def acquire_tree(st):
            self.songs_tree = st

        self.extensions.connect('OnBluemindoStarted', launch_playlist)
        self.extensions.connect('OnSongsTreeCreated', acquire_tree)
        self.extensions.connect('OnSongQueued', self.on_new_song_queued)
        self.extensions.connect('OnAlbumQueued', self.on_new_album_queued)
        self.extensions.connect('AskPreviousSong', self.ask_previous_song)
        self.extensions.connect('AskNextSong', self.ask_next_song)
        self.extensions.connect('HasStartedSong', self.song_started)


    def toggle(self, widget, action):
        if action == 'repeat' and self.config['repeat']:
            self.config['repeat'] = False
            self.repeat_btn.set_active(False)
            self.userconf.update_key('Playlist', 'repeat', str(int(False)))
        elif action == 'repeat' and not self.config['repeat']:
            self.config['repeat'] = True
            self.repeat_btn.set_active(True)
            self.userconf.update_key('Playlist', 'repeat', str(int(True)))
        elif action == 'shuffle' and self.config['shuffle']:
            self.config['shuffle'] = False
            self.shuffle_btn.set_active(False)
            self.userconf.update_key('Playlist', 'shuffle', str(int(False)))
        elif action == 'shuffle' and not self.config['shuffle']:
            self.config['shuffle'] = True
            self.shuffle_btn.set_active(True)
            self.userconf.update_key('Playlist', 'shuffle', str(int(True)))

    def row_activated(self, widget, path, column):
        item_iter = self.liststore.get_iter(path)

        # Get the founded element.
        item_identifier = self.liststore.get_value(item_iter, 4)
        current_item = self.playlist_content[item_identifier]

        # The element is a song.
        if self.playlist_content[item_identifier].kind == 'song':
            self.playlist_current = [item_iter, item_identifier, None]
            self.extensions.load_event('OnPlayNewSong', current_item)
        # The element is an album.
        else:
            self.extensions.load_event('OnAbortPlayback')
            sng = self.playlist_content[item_identifier].tracks[0]
            self.playlist_current = [item_iter, item_identifier, 0]
            self.extensions.load_event('OnPlayNewSong', sng)

    def key_pressed(self, widget, eventkey):
        if eventkey.get_keyval()[1] == KEY_Delete:
            # Delete an item from the playlist
            selection = self.playlist_tree.get_selection()
            selected = selection.get_selected_rows()
            liststore = selected[0]
            listpath = selected[1]

            if len(listpath) > 0:
                selpath = listpath[0]
                playlist_identifier = liststore[selpath][4]

                # Are we removing the currently playing item?
                if self.playlist_current is not None:
                    item_iter, item_path, item_in_album = self.playlist_current
                    if selpath == TreePath.new_from_string(str(item_path)):
                        self.playlist_current = None

                # Removal
                del self.playlist_content[playlist_identifier]
                del liststore[selpath]

    def clean(self, data=None):
        self.playlist_content = {}
        self.playlist_identifier = 0
        self.playlist_current = None
        self.liststore.clear()

        # Update GUI
        self.clean_btn.set_sensitive(False)
        self.tool_save.set_sensitive(False)

    def populate(self, playlist_id):
        if playlist_id in (1, 2):
            # Automatic playlists based on listening stats
            if playlist_id == 1:
                tb = 'stats_songs'
                lm = 50
            elif playlist_id == 2:
                tb = 'stats_albums'
                lm = 10

            result = []
            txt = ('select * from %s order by tracks desc limit %u' % (tb, lm))

            sql = SQLite()
            cur = sql.execute(txt)
            for sg in cur:
                result.append(sg)
            sql.close()

            for item in result:
                if playlist_id == 1:
                    sng = Song(filename=item[0])
                    if hasattr(sng, 'title'):
                        self.on_new_song_queued(sng)
                elif playlist_id == 2:
                    album_name = item[0]
                    for it in self.songs_tree:
                        if album_name in self.songs_tree[it]:
                            self.on_new_album_queued(Album(it, album_name,
                                                           self.songs_tree))
                            break
        elif playlist_id > 3:
            # User-created playlists
            user_plist = self.user_playlists[playlist_id]
            plist = self.playlists_mgmnt.load_playlist(user_plist)

            for item in plist:
                sng = Song(filename=item)
                if hasattr(sng, 'title'):
                    self.on_new_song_queued(sng)

    def delete_playlist(self, widget):
        if self.current_playlist_id > 3:
            user_plist = self.user_playlists[self.current_playlist_id]
            self.playlists_mgmnt.delete_playlist(user_plist)

            # Delete the playlist from the list
            del self.user_playlists[self.current_playlist_id]

            cblid = 0
            for item in self.combolist:
                if item[0] == self.current_playlist_id:
                    del self.combolist[cblid]
                    break
                cblid += 1

            # Move back to "Current" playlist
            self.combobox.set_active(0)

    def save_playlist_key(self, widget, eventkey):
        if eventkey.get_keyval()[1] == KEY_Return:
            self.save_playlist_button(None)

    def save_playlist_button(self, widget):
        user_entry = self.save_entry.get_text()
        user_entry = user_entry.replace('\\', '-')
        user_entry = user_entry.replace('/', '-')
        user_entry = user_entry.replace('*', '-')
        user_entry = user_entry.replace('|', '-')

        if len(user_entry) > 0:
            rtn_value = self.playlists_mgmnt.create_new_playlist(user_entry)

            if rtn_value:
                self.save_pop.hide()

                # Add playlist to GUI
                if self.last_user_playlist is None:
                    self.combolist.append([3, ''])
                    self.last_user_playlist = 3

                self.last_user_playlist += 1
                self.combolist.append([self.last_user_playlist, user_entry])
                self.user_playlists[self.last_user_playlist] = user_entry

                # Write the playlist
                self.write_playlist(user_entry)

                # Select the new playlist
                self.combobox.set_active(self.last_user_playlist)

    def save_playlist(self, widget):
        if self.current_playlist_id < 3:
            # Create a new playlist
            self.save_entry.set_text('')
            self.save_pop.show_all()
        elif self.current_playlist_id > 3:
            # Update an existing playlist
            user_plist = self.user_playlists[self.current_playlist_id]
            self.write_playlist(user_plist)

    def write_playlist(self, user_plist):
        plist_content = []
        for item in self.liststore:
            item_id = item[4]
            plist_content.append(self.playlist_content[item_id])

        self.playlists_mgmnt.write_playlist(user_plist, plist_content)

    def on_new_song_queued(self, song_info):
        title = song_info.title
        artist = song_info.artist
        album = song_info.album
        filename = song_info.filename
        length = self.functions.human_length(song_info.length)

        self.liststore.append(('audio-x-generic-symbolic', '<b>' +
                               self.functions.view_encode(title, 99) +
                               '</b>\n' + self.functions.view_encode(artist),
                               '<span foreground="grey">' +
                               length + '</span>',
                               filename, self.playlist_identifier))

        self.playlist_content[self.playlist_identifier] = song_info
        self.playlist_identifier += 1

        # Update GUI
        self.clean_btn.set_sensitive(True)
        self.tool_save.set_sensitive(True)

    def on_new_album_queued(self, album_info):
        artist = album_info.artist
        album = album_info.name
        songs_count = str(len(album_info.tracks)) + ' ♫'

        self.liststore.append(('media-optical-symbolic', '<b>' +
                               self.functions.view_encode(album, 99) +
                               '</b>\n' + self.functions.view_encode(artist),
                               '<span foreground="grey">' +
                               songs_count + '</span>', '[album]',
                               self.playlist_identifier))

        self.playlist_content[self.playlist_identifier] = album_info
        self.playlist_identifier += 1

        # Update GUI
        self.clean_btn.set_sensitive(True)
        self.tool_save.set_sensitive(True)

    def ask_next_song(self, current_song):
        self.ask_for_a_song(True, current_song)

    def ask_previous_song(self, current_song):
        self.ask_for_a_song(False, current_song)

    def ask_for_a_song(self, next=True, current_song=None):
        def walk_in_playlist(item_iter, next=True):
            base_item_iter = item_iter
            if item_iter is None:
                # Find first song.
                item_iter = self.liststore.get_iter_first()
            elif next:
                # Find next song.
                path = self.liststore.get_path(self.playlist_current[0])
                path_int = int(path.to_string())
                max_id = len(self.playlist_content) - 1

                if (path_int + 1 <= max_id): # There is a song to launch!
                    item_iter = self.liststore.get_iter(path_int + 1)
                else: # There is no song to launch!
                    if not self.config['repeat']:
                        self.extensions.load_event('OnAbortPlayback')
                        return
                    else:
                        item_iter = self.liststore.get_iter_first()
            elif not next:
                # Find previous song.
                path = self.liststore.get_path(self.playlist_current[0])
                path_int = int(path.to_string())
                max_id = len(self.playlist_content) - 1

                if (path_int -1 >= 0): # There is a song to launch.
                    item_iter = self.liststore.get_iter(path_int - 1)
                else: # There is no song to launch!
                    if not self.config['repeat']:
                        self.extensions.load_event('OnAbortPlayback')
                        return
                    else:
                        item_iter = self.liststore.get_iter_from_string(str(max_id))

            # Get the founded element.
            item_identifier = self.liststore.get_value(item_iter, 4)
            current_item = self.playlist_content[item_identifier]

            def launch_founded_item(item_identifier, item_iter, current_item):
                # The element is a song.
                if self.playlist_content[item_identifier].kind == 'song':
                    self.playlist_current = [item_iter, item_identifier, None]
                    self.extensions.load_event('OnPlayNewSong', current_item)
                # The element is an album.
                else:
                    self.extensions.load_event('OnAbortPlayback')
                    sng = self.playlist_content[item_identifier].tracks[0]
                    sng.rg_mode_guess = 'album'
                    self.playlist_current = [item_iter, item_identifier, 0]
                    self.extensions.load_event('OnPlayNewSong', sng)

            # Are we currently listening from an album?
            if base_item_iter is not None:
                kind = self.playlist_content[self.playlist_current[1]].kind

                if kind == 'album':
                    base_item_identifier = self.liststore.get_value(base_item_iter, 4)
                    tracks = self.playlist_content[self.playlist_current[1]].tracks
                    max_sng = len(tracks) - 1

                    if next:
                        if self.playlist_current[2] < max_sng:
                            item_in_album = self.playlist_current[2] + 1
                        else:
                            return launch_founded_item(item_identifier, item_iter, current_item)
                    elif not next:
                        if self.playlist_current[2] - 1 > -1:
                            item_in_album = self.playlist_current[2] - 1
                        else:
                            return launch_founded_item(item_identifier, item_iter, current_item)

                    sng = self.playlist_content[base_item_identifier].tracks[item_in_album]
                    sng.rg_mode_guess = 'album'
                    self.playlist_current = [base_item_iter, base_item_identifier, item_in_album]
                    self.extensions.load_event('OnPlayNewSong', sng)
                    return

            launch_founded_item(item_identifier, item_iter, current_item)

        if len(self.playlist_content) == 0:
            # Playlist is empty.
            if not self.config['shuffle']:
                # Shuffle disabled: abort playback.
                self.extensions.load_event('OnAbortPlayback')
            else:
                # Shuffle enabled.
                if self.config['shuffle_mode'] == 'random':
                    # Random mode: seek for shuffle song.
                    self.extensions.load_event('AskShuffleSong')
                elif self.config['shuffle_mode'] == 'similar':
                    # Similar mode: seek for a similar song.
                    if len(self.similar_artists) == 0:
                        # No similar song founded: seek for any one.
                        self.extensions.load_event('AskShuffleSong')
                        return

                    # Choose one song in the list of similar artists
                    index = randrange(len(self.similar_artists))
                    artist = self.similar_artists[index]

                    mdb = MusicDatabase(None)
                    songs_list = mdb.load_from_artist(artist)
                    if len(songs_list) > 1:
                        index = randrange(len(songs_list))
                        song = songs_list[index]

                        sng = Song(filename=song[8])
                        print ('[SIMILAR] Playing a song from ' + sng.artist)
                        self.extensions.load_event('OnPlayNewSong', sng)
                    else:
                        self.extensions.load_event('AskShuffleSong')
        else:
            # Playlist is not empty, walk in it!
            if self.playlist_current is None:
                # Currently no current item in playlist, choose the first one!
                walk_in_playlist(None)
            else:
                # The current playling song is in the playlist!
                if next:
                    walk_in_playlist(self.playlist_current[0])
                else:
                    walk_in_playlist(self.playlist_current[0], False)


    def song_started(self, song):
        # First, try to download a few similar artists names
        if self.config['shuffle_mode'] == 'similar':
            def download_similars():
                threads_enter()
                art = self.lastfm.get_similar_artists(song.artist)

                self.similar_artists = []
                mdb = MusicDatabase(None)

                for artist in art:
                    if mdb.artist_exists(artist):
                        self.similar_artists.append(artist)

                self.is_in_similar_thread = False
                threads_leave()

            if not self.is_in_similar_thread:
                self.is_in_similar_thread = True
                thread = Thread(group=None, target=download_similars,
                                name='similars', args=())
                thread.start()

        # Second, update statistics for this song
        song.increment_statistics()
        alb = Album(song.artist, song.album, self.songs_tree)
        alb.increment_statistics()

        # Then, highlight currently playing song/album if it's in playlist
        if self.playlist_current is not None:
            # Currently playing item is in the playlist
            item_iter, item_path, item_in_album = self.playlist_current

            # Remove marker of all items
            for item in self.liststore:
                current_label = item[1]
                if current_label[:2] == '◎ ':
                    item[1] = current_label[2:]

            # Add marker on one item
            current_label = self.liststore[item_iter][1]
            if current_label[:2] != '◎ ':
                self.liststore[item_iter][1] = '◎ ' + current_label
예제 #20
0
    def __init__(self, extensionsloader):
        self.extensions = extensionsloader
        self.module = {'name': 'Player'}
        self.config = {}

        self.functions = Functions()
        self.userconf = ConfigLoader()

        self.lyrics_downloader = LyricsDownloader()

        def start_playback(wdg):
            # Create GStreamer instance
            self.gst = GStreamer()
            self.gst.set_playback('gapless')
            self.gst.player.connect('about-to-finish', self.song_nearly_ended)
            self.gst.stop()

            self.current_song = False
            self.current_album = False

            # Prepare buttons
            self.btn_playpause = wdg[0][7]
            self.btn_previous = wdg[0][5]
            self.btn_next = wdg[0][8]
            self.btn_stop = wdg[0][6]

            self.btn_previous.connect('clicked', self.previous_pressed)
            self.btn_stop.connect('clicked', self.stop_pressed)
            self.btn_playpause.connect('clicked', self.play_pressed)
            self.btn_next.connect('clicked', self.next_pressed)

            self.btn_player = wdg[0][9]
            self.headerbar = wdg[0][0]

            # Create the player box and popover
            gtkpla = join(self.functions.datadir, 'glade', 'playerbar.ui')
            win = gtk_builder()
            win.set_translation_domain('bluemindo')
            win.add_from_file(gtkpla)
            basebox = win.get_object('playerbox')
            wdg[0][0].add(basebox)

            self.player_event = win.get_object('player_event')
            self.player_event.set_size_request(32, 32)
            self.player_button_img = win.get_object('image_cover')
            self.player_event.connect('button-press-event', self.show_player)
            default = join(self.functions.datadir, 'image', 'logo_head_big.png')
            cover_px = Pixbuf.new_from_file_at_scale(default, 20, 20, True)
            self.player_button_img.set_from_pixbuf(cover_px)
            self.player_event.set_sensitive(False)

            self.player_scalab = win.get_object('label_scale')
            self.player_scalab.set_markup('<span size="small">00:00</span>')
            self.player_sca = win.get_object('scale')
            self.player_sca.connect('change-value', self.on_change_value)
            self.player_sca.set_sensitive(False)

            # Create the player popover
            gtkpla = join(self.functions.datadir, 'glade', 'playerpopover.ui')
            win = gtk_builder()
            win.add_from_file(gtkpla)
            hbox = win.get_object('box-player')

            self.player_img = win.get_object('image')
            self.player_pop = Popover.new(self.player_event)
            self.player_pop.set_size_request(200, 200)
            self.player_pop.add(hbox)

            self.lyrics_button = wdg[1].get_object('tool-lyrics')
            self.lyrics_pop = Popover.new(self.lyrics_button)
            self.lyrics_pop.set_size_request(400, 600)
            box = Box(1, 0)
            self.lyrics_swin = ScrolledWindow()
            lyrics_tview = TextView()
            lyrics_tview.set_editable(False)
            self.lyrics_buffer = TextBuffer()
            lyrics_tview.set_buffer(self.lyrics_buffer)
            self.lyrics_swin.add(lyrics_tview)
            box.add(self.lyrics_swin)
            self.lyrics_wait = Spinner()
            self.lyrics_wait.props.active = True
            box.add(self.lyrics_wait)
            self.lyrics_pop.add(box)

            def show_lyrics(widget):
                if self.current_song:
                    title = self.current_song.title
                    artist = self.current_song.artist
                    album = self.current_song.album
                    filename = self.current_song.filename

                    sn = self.functions.get_hash(title, artist)
                    lyrics_file = join(self.userconf.datadir, '%s.lyrics' % sn)

                    lyrics = self.lyrics_downloader.get_lyrics(title,
                                                               artist,
                                                               True)

                    self.lyrics_pop.show_all()

                    if lyrics is not None:
                        self.lyrics_wait.hide()
                        self.lyrics_swin.show()
                        self.lyrics_buffer.set_text(lyrics)
                    else:
                        self.lyrics_swin.hide()
                        self.lyrics_wait.show()
                        self.lyrics_buffer.set_text('')

            self.lyrics_button.connect('clicked', show_lyrics)
            self.lyrics_button.set_sensitive(False)

        # Acquire the songs tree
        def acquire_tree(st):
            self.songs_tree = st

        self.extensions.connect('OnSongsTreeCreated', acquire_tree)
        self.extensions.connect('OnBluemindoStarted', start_playback)
        self.extensions.connect('OnPlayNewSong', self.on_play_new_song)
        self.extensions.connect('OnPlayNewAlbum', self.on_play_new_album)
        self.extensions.connect('OnAbortPlayback', self.on_abort_playback)

        self.extensions.connect('OnPlayPressed', self.play_pressed)
        self.extensions.connect('OnStopPressed', self.stop_pressed)
        self.extensions.connect('OnNextPressed', self.next_pressed)
        self.extensions.connect('OnPreviousPressed', self.previous_pressed)
예제 #21
0
    def __init__(self, extensionsloader):
        self.extensions = extensionsloader
        self.module = {'name': 'Playlist'}

        self.functions = Functions()
        self.userconf = ConfigLoader()

        self.config = {}
        rpt = self.userconf.config['Playlist']['repeat']
        self.config['repeat'] = bool(int(rpt))
        shf = self.userconf.config['Playlist']['shuffle']
        self.config['shuffle'] = bool(int(shf))
        shm = self.userconf.config['Playlist']['shuffle_mode']
        self.config['shuffle_mode'] = shm

        self.lastfm = LastFm()
        self.playlists_mgmnt = Playlists()

        self.playlist_content = {}
        self.playlist_identifier = 0
        self.playlist_current = None
        self.current_playlist_id = 0
        self.user_playlists = {}
        self.last_user_playlist = None

        self.similar_artists = []
        self.is_in_similar_thread = False

        # Create the Playlist view
        def launch_playlist(wdg):
            self.widgets = wdg[1]

            self.playlist_label = self.widgets.get_object('label_playlist')
            self.playlist_repeat = self.widgets.get_object('tool-repeat')
            self.playlist_shuffle = self.widgets.get_object('tool-shuffle')
            self.playlist_clean = self.widgets.get_object('tool-clean')
            self.playlist_combo = self.widgets.get_object('combo-playlist')
            self.playlist_save = self.widgets.get_object('tool-saveplaylist')
            self.playlist_lyrics = self.widgets.get_object('tool-lyrics')

            self.playlist_tree = self.widgets.get_object('treeview_playlist')
            self.playlist_tree.set_headers_visible(False)
            self.playlist_tree.props.reorderable = True
            self.playlist_tree.connect('key_press_event', self.key_pressed)
            self.playlist_tree.connect('row_activated', self.row_activated)

            self.liststore = ListStore(str, str, str, str, int)
            self.playlist_tree.set_model(self.liststore)

            renderer_pix = CellRendererPixbuf()
            column_pixbuf = TreeViewColumn('1', renderer_pix, icon_name=0)
            column_pixbuf.set_fixed_width(18)
            self.playlist_tree.append_column(column_pixbuf)

            renderer_text = CellRendererText()
            column_text = TreeViewColumn('2', renderer_text, markup=1)
            column_text.props.expand = True
            column_text.props.max_width = 192
            self.playlist_tree.append_column(column_text)

            column_text = TreeViewColumn('3', renderer_text, markup=2)
            column_text.set_fixed_width(40)
            self.playlist_tree.append_column(column_text)

            self.repeat_btn = self.widgets.get_object('tool-repeat')
            if self.config['repeat']:
                self.repeat_btn.set_active(True)
            self.repeat_btn.connect('clicked', self.toggle, 'repeat')

            self.shuffle_btn = self.widgets.get_object('tool-shuffle')
            if self.config['shuffle']:
                self.shuffle_btn.set_active(True)
            self.shuffle_btn.connect('clicked', self.toggle, 'shuffle')

            def clean_wdg(widget):
                # Clean playlist
                self.clean()

                # Show popover
                if self.current_playlist_id > 3:
                    self.clean_btn.set_sensitive(True)
                    self.clean_pop.show_all()

            self.clean_btn = self.widgets.get_object('tool-clean')
            self.clean_btn.connect('clicked', clean_wdg)
            self.clean_pop = Popover.new(self.clean_btn)
            self.clean_pop.set_size_request(100, 30)

            gtkpla = join(self.functions.datadir, 'glade', 'plist-del-pop.ui')
            win = gtk_builder()
            win.set_translation_domain('bluemindo')
            win.add_from_file(gtkpla)
            hbox = win.get_object('box-playlist')
            lbl = win.get_object('label')
            lbl.set_text(_('Do you also want to remove the playlist?'))
            btn = win.get_object('del-btn')
            btn.set_label(_('Delete'))
            btn.connect('clicked', self.delete_playlist)
            self.clean_pop.add(hbox)

            # Populate combobox
            self.combolist = ListStore(int, str)

            self.combobox = self.widgets.get_object('combobox')
            self.combobox.set_model(self.combolist)
            self.combobox.set_popup_fixed_width(False)
            self.combobox.props.expand = False

            renderer_text = CellRendererText()
            renderer_text.props.ellipsize = EllipsizeMode.END
            self.combobox.pack_start(renderer_text, True)
            self.combobox.set_entry_text_column(1)
            self.combobox.add_attribute(renderer_text, 'text', 1)

            self.combolist.append([0, _('Current')])
            self.combolist.append([1, _('Top 50 songs')])
            self.combolist.append([2, _('Top 10 albums')])

            playlists = self.playlists_mgmnt.get_playlists()

            if len(playlists) > 0:
                self.combolist.append([3, ''])
                item_id = 3

                playlists.sort(key=lambda it: it[1])
                for item in playlists:
                    item_id += 1
                    self.combolist.append([item_id, item])
                    self.user_playlists[item_id] = item
                    self.last_user_playlist = item_id

            def combo_sep(model, iter):
                if model[iter][0] == 3:
                    return True
            self.combobox.set_row_separator_func(combo_sep)

            def on_combo_changed(widget):
                path = widget.get_active()
                item_id = self.combolist[path][0]

                # First, clean the playlist
                self.clean(None)

                # Second, populate the playlist
                if item_id > 0:
                    self.populate(item_id)

                # Then, update playlist identifier
                self.current_playlist_id = item_id

                # Show delete/remove button if the playlist is from the user
                if item_id > 3:
                    self.clean_btn.set_sensitive(True)

            self.combobox.set_active(0)
            self.combobox.connect('changed', on_combo_changed)
            
            self.tool_save = self.widgets.get_object('tool-saveplaylist')
            self.tool_save.connect('clicked', self.save_playlist)
            self.save_pop = Popover.new(self.tool_save)
            self.save_pop.set_size_request(100, 30)

            gtkpla = join(self.functions.datadir, 'glade', 'plist-add-pop.ui')
            win = gtk_builder()
            win.set_translation_domain('bluemindo')
            win.add_from_file(gtkpla)
            hbox = win.get_object('box-playlist')
            self.save_pop.add(hbox)

            self.save_entry = win.get_object('save-entry')
            self.save_entry.connect('key_press_event', self.save_playlist_key)
            self.save_btn = win.get_object('save-btn')
            self.save_btn.connect('clicked', self.save_playlist_button)
            self.save_btn.set_label(_('Save'))

            self.clean_btn.set_sensitive(False)
            self.tool_save.set_sensitive(False)

        # Acquire the songs tree
        def acquire_tree(st):
            self.songs_tree = st

        self.extensions.connect('OnBluemindoStarted', launch_playlist)
        self.extensions.connect('OnSongsTreeCreated', acquire_tree)
        self.extensions.connect('OnSongQueued', self.on_new_song_queued)
        self.extensions.connect('OnAlbumQueued', self.on_new_album_queued)
        self.extensions.connect('AskPreviousSong', self.ask_previous_song)
        self.extensions.connect('AskNextSong', self.ask_next_song)
        self.extensions.connect('HasStartedSong', self.song_started)