def __init__(self):
        self.view = PlayerWindow()
        self.playlist = QtMultimedia.QMediaPlaylist()
        self.player = QtMultimedia.QMediaPlayer()
        self.player.setPlaylist(self.playlist)

        self.progress_bar_pressed = False
        self.last_volume = None

        self.connect()
Exemple #2
0
 def add_playlist(self,name):
     print('adding playlist',name);
     if name in self._playlists :
         print("can't add that playlist")
         return False
     self._playlists_mdata[name] = [];
     new_playlist = QtMultimedia.QMediaPlaylist()
     self._playlists[name] = new_playlist;
     new_playlist.dbase_id = self.add_playlist_to_database(name);
     print('added playlsit' , name);
     self.playlistAdded.emit(name);
Exemple #3
0
 def set_file(self, url):
     if url.scheme() == '':
         url.setScheme('file')
     self.label.setText(url.fileName())
     content = qtmm.QMediaContent(url)
     # self.player.setMedia(content)
     self.playlist = qtmm.QMediaPlaylist()
     self.playlist.addMedia(content)
     self.playlist.setCurrentIndex(1)
     self.player.setPlaylist(self.playlist)
     self.loop_cb.setChecked(False)
Exemple #4
0
    def init(self):
        self.database_con , self.database_cur = setup_database();
        self._playback_rate = 1.0
        self._repeating = False
        self._shuffled = False
        
        self._playlists_mdata = {} # mdata = meta data
        self._playlists = {}
        self._current_playlist = None;
        self._current_playlist_mdata = None;
        self._current_playlist_name = None;
        self._library = QtMultimedia.QMediaPlaylist();
        self._library_set = set()

        self._playlists["Library"] = self._library
        self._playlists_mdata["Library"] = []
        self._playlists["Now Playing"] = QtMultimedia.QMediaPlaylist()
        self._playlists_mdata["Now Playing"] = []
        #it's first signal will be emitted later in read_from_database
        
        self.player = QtMultimedia.QMediaPlayer(self)
        self.player.setVolume(50);
Exemple #5
0
 def __init__(self) -> None:
     super().__init__()
     self.player = QtMultimedia.QMediaPlayer()
     self.playlist = QtMultimedia.QMediaPlaylist()
     self.musics: List[MusicEntry] = list()
     self.currentIndex = -1
     self.playbackMode = MyPlaylist.PlaybackMode.LOOP
     self.playing = False
     self.player.positionChanged.connect(self.positionChanged.emit)
     self.player.durationChanged.connect(self.durationChanged.emit)
     self.player.stateChanged.connect(self.onPlayerStateChanged)
     self.history: Dict[int, int] = dict()
     self.historyIndex = -1
Exemple #6
0
 def add_playlist(self, name):
     print('adding playlist', name)
     if name in self._playlists:
         print("The playlist already exists!")
         error = QtWidgets.QMessageBox()
         error.critical(None, "Error", "The playlist already exists!",
                        QMessageBox.Ok, QMessageBox.NoButton)
         error.setFixedSize(500, 200)
         return False
     self._playlists_mdata[name] = []
     new_playlist = QtMultimedia.QMediaPlaylist()
     self._playlists[name] = new_playlist
     new_playlist.dbase_id = self.add_playlist_to_database(name)
     print('added playlsit', name)
     self.playlistAdded.emit(name)
     return True
Exemple #7
0
    def __init__(self, inputStream: StreamConfiguration, parentWidget):
        super(StreamPlayer, self).__init__()
        self.inputStream = inputStream
        self.parentWidget = parentWidget
        self.lcDispatcher.setInputStream(self.inputStream)

        self.mediaPlaylist = QtMultimedia.QMediaPlaylist()
        self.mediaPlaylist.addMedia(QUrl(self.inputStream.sURI))
        self.setMedia(self.mediaPlaylist)
        self.setMuted(True)

        self.stateChanged.connect(self.parentWidget.onPlayingStateChanged)
        self.mediaStatusChanged.connect(self.parentWidget.onErrorOccured)
        # self.error.connect(self.parentWidget.onErrorOccured)

        if self.lcDispatcher.dispatcher():
            self.play()
        else:
            self.stop()
Exemple #8
0
def show_pronunciation_to_writing_dialog(pronunciation, audio_file, callback):
    dialog = EphemeralDialog()
    possible_fonts = qg.QFontDatabase().families(qg.QFontDatabase.Japanese)
    japanese_fonts = [font for font in possible_fonts if 'jp' in font.lower()]
    font = qg.QFont(japanese_fonts[0])
    dialog.setFont(font)
    big_font = qg.QFont(font)
    big_font.setPointSize(font.pointSize() * 1.5)
    dialog.pronunciation = qw.QLabel(pronunciation.replace('\t', ''))
    dialog.pronunciation.setFont(big_font)
    dialog.pronunciation.setTextInteractionFlags(qc.Qt.TextSelectableByMouse)
    dialog.writing_button = qw.QPushButton('Check writing')
    dialog.writing_button.setDefault(True)

    def check():
        dialog.media_player.stop()
        dialog.accept()
        callback()

    dialog.writing_button.clicked.connect(check)

    vlayout = qw.QVBoxLayout()
    vlayout.addWidget(dialog.pronunciation)
    vlayout.addWidget(dialog.writing_button)
    dialog.setLayout(vlayout)

    dialog.playlist = qm.QMediaPlaylist()
    dialog.playlist.addMedia(qc.QUrl.fromLocalFile(
        os.path.abspath(audio_file)))
    dialog.playlist.setPlaybackMode(qm.QMediaPlaylist.Loop)
    dialog.media_player = qm.QMediaPlayer()
    dialog.media_player.setPlaylist(dialog.playlist)
    dialog.media_player.play()

    dialog.show()

    return dialog
Exemple #9
0
def show_sentence_detail_dialog(text, pronunciation, translation, source_url,
                                creator, license_url, lemmas, grammars,
                                graphemes, forward_pronunciations,
                                backward_pronunciations, sounds, audio_file,
                                callback):
    def position_in(text):
        def position_in_text(detail):
            if isinstance(text, tuple):
                return tuple(
                    position_in(t)(d) for t, d in zip(text, detail[1:]))
            try:
                return text.index(detail)
            except ValueError:
                return len(text)

        return position_in_text

    lemmas = sorted(lemmas, key=position_in((text, )))
    graphemes = sorted(graphemes, key=position_in((text, )))
    forward_pronunciations = sorted(forward_pronunciations,
                                    key=position_in((text, pronunciation)))
    backward_pronunciations = sorted(backward_pronunciations,
                                     key=position_in((text, pronunciation)))
    sounds = sorted(sounds, key=position_in((pronunciation, )))
    dialog = EphemeralDialog()
    possible_fonts = qg.QFontDatabase().families(qg.QFontDatabase.Japanese)
    japanese_fonts = [font for font in possible_fonts if 'jp' in font.lower()]
    font = qg.QFont(japanese_fonts[0])
    dialog.setFont(font)
    big_font = qg.QFont(font)
    big_font.setPointSize(font.pointSize() * 1.5)
    rows = (row.split('\t') for row in (text, pronunciation))
    dialog.text_pronunciation_table = qw.QLabel(f'''<table><tr>{
            '</tr/><tr>'.join(
                ''.join(f'<td>{part}</td>' for part in row)
                for row in rows)
                }</tr></table>''')
    dialog.text_pronunciation_table.setFont(big_font)
    dialog.text_pronunciation_table.setTextInteractionFlags(
        qc.Qt.TextSelectableByMouse)
    dialog.translation = qw.QLabel(translation)
    dialog.translation.setFont(big_font)
    dialog.translation.setTextInteractionFlags(qc.Qt.TextSelectableByMouse)
    dialog.attribution = qw.QLabel(
        f'Example from <a href="{source_url}">{urllib.parse.unquote(source_url)}</a> '
        f'by {creator}, '
        f'licensed under <a href="{license_url}">{urllib.parse.unquote(license_url)}</a>'
    )
    dialog.attribution.setOpenExternalLinks(True)
    dialog.learn_button = qw.QPushButton('Learn')
    dialog.learn_button.setDefault(True)

    hlayout = qw.QHBoxLayout()
    lemma_checkboxes = []
    grammar_checkboxes = []
    grapheme_checkboxes = []
    forward_pronunciation_checkboxes = []
    backward_pronunciation_checkboxes = []
    sound_checkboxes = []

    def lemma_template(lemma, disambiguator, gloss):
        text = 'the meaning of %s (%s)' % (lemma, disambiguator)
        movie = None
        tooltip = gloss
        return text, movie, tooltip

    def writing_template(grapheme):
        relative_path = f'data/kanjivg/kanji/{ord(grapheme):05x}.gif'
        gif_path = os.path.join(os.path.dirname(__file__), relative_path)
        text = 'writing '
        movie = os.path.abspath(gif_path)
        tooltip = grapheme
        return text, movie, tooltip

    def format_template(template):
        return lambda *args: (template.format(*args), None, None)

    for memory_items, checkboxes, template in (
        (lemmas, lemma_checkboxes,
         lemma_template), (grammars, grammar_checkboxes,
                           format_template('the form {}')),
        (graphemes, grapheme_checkboxes, writing_template),
        (forward_pronunciations, forward_pronunciation_checkboxes,
         format_template('{} pronounced as {}')),
        (backward_pronunciations, backward_pronunciation_checkboxes,
         format_template('{1} written as {0}')),
        (sounds, sound_checkboxes, format_template('pronouncing {}'))):
        if not memory_items:
            continue
        vlayout = qw.QVBoxLayout()
        for item in memory_items:
            boxlabel, movie, tooltip = template(*item[1:])
            checkbox = qw.QCheckBox(boxlabel)
            checkbox.setCheckState(qc.Qt.CheckState.Checked)
            if tooltip:
                checkbox.setToolTip(tooltip)
            checkboxes.append(checkbox)
            if movie:
                boxlayout = qw.QHBoxLayout()
                label = MovieLabel(movie,
                                   size=qc.QSize(font.pointSize() * 2,
                                                 font.pointSize() * 2),
                                   hover_size=qc.QSize(-1, -1))
                boxlayout.addWidget(checkbox)
                boxlayout.addWidget(label)
                vlayout.addLayout(boxlayout)
            else:
                vlayout.addWidget(checkbox)
        scrollframe = VerticalScrollFrame()
        scrollframe.setLayout(vlayout)
        hlayout.addWidget(scrollframe.scrollarea)

    def learn():
        dialog.media_player.stop()
        dialog.accept()
        callback(
            **{
                table + '_selection': [(item[0], checkbox.isChecked())
                                       for item, checkbox in zip(
                                           memory_items, checkboxes)]
                for table, memory_items, checkboxes in (
                    ('lemma', lemmas, lemma_checkboxes), ('grammar', grammars,
                                                          grammar_checkboxes),
                    ('grapheme', graphemes, grapheme_checkboxes),
                    ('forward_pronunciation', forward_pronunciations,
                     forward_pronunciation_checkboxes),
                    ('backward_pronunciation', backward_pronunciations,
                     backward_pronunciation_checkboxes), ('sound', sounds,
                                                          sound_checkboxes))
            })

    dialog.learn_button.clicked.connect(learn)

    vlayout = qw.QVBoxLayout()
    vlayout.addWidget(dialog.text_pronunciation_table)
    vlayout.addWidget(dialog.translation)
    vlayout.addLayout(hlayout)
    vlayout.addWidget(dialog.attribution)
    vlayout.addWidget(dialog.learn_button)
    dialog.setLayout(vlayout)

    dialog.playlist = qm.QMediaPlaylist()
    dialog.playlist.addMedia(qc.QUrl.fromLocalFile(
        os.path.abspath(audio_file)))
    dialog.playlist.setPlaybackMode(qm.QMediaPlaylist.Loop)
    dialog.media_player = qm.QMediaPlayer()
    dialog.media_player.setPlaylist(dialog.playlist)
    dialog.media_player.play()

    dialog.show()

    return dialog
Exemple #10
0
    def __init__(self):
        super(myplayer, self).__init__()
        self.ui = Ui_musicplayer()
        self.ui.setupUi(self)
        self.setFixedSize(440, 460)
        self.ui.config.clicked.connect(self.menu_config)
        #******************#
        # play/pause
        #******************#
        self.ui.play_button.clicked.connect(self.play)
        self.onplay = 0
        self.iconpausa = QtGui.QIcon()
        self.iconpausa.addPixmap(QtGui.QPixmap(":/neuron_music/img/pausa.png"),
                                 QtGui.QIcon.Normal, QtGui.QIcon.On)
        self.iconplay = QtGui.QIcon()
        self.iconplay.addPixmap(QtGui.QPixmap(":/neuron_music/img/play.png"),
                                QtGui.QIcon.Normal, QtGui.QIcon.On)

        #******************#
        # playlist
        #******************#
        self.player = QtMultimedia.QMediaPlayer()
        self.path = list()
        try:
            if system == "Windows":
                self.musicpath = os.listdir(CURRENT_DIR + r'\records')
                for i in self.musicpath:
                    self.path.append(CURRENT_DIR + r'\records' + "\\" + i)
            elif system == "Linux":
                self.musicpath = os.listdir(CURRENT_DIR + '/records')
                for i in self.musicpath:
                    self.path.append(CURRENT_DIR + '/records/' + i)
        except:
            pass
        self.playlist = QtMultimedia.QMediaPlaylist()
        self.player.setPlaylist(self.playlist)
        for i in self.path:
            self.playlist.addMedia(
                QtMultimedia.QMediaContent(QtCore.QUrl.fromLocalFile(i)))
        self.ui.next_button.clicked.connect(self.playlist.next)
        self.ui.back_button.clicked.connect(self.playlist.previous)
        #******************#
        # playlist elementos texto/imagen
        #******************#
        self.playlist.currentMediaChanged.connect(self.songChanged)
        #******************#
        # volumen
        #******************#
        self.player.setVolume(80)
        self.ui.control_volumen.setMinimum(0)
        self.ui.control_volumen.setMaximum(100)
        self.ui.control_volumen.setValue(80)
        self.ui.control_volumen.valueChanged.connect(self.player.setVolume)
        #******************#
        # volume hiden
        #******************#
        self.volumen_r_l = self.ui.control_volumen
        self.volumen_r_l.lower()
        self.vol_buttom = 0
        self.ui.img_volumen.mousePressEvent = self.hide_volumen
        #******************#
        # time
        #******************#
        self.ui.time_inicio.setStyleSheet('color:#ffffff;font-size:15px;')
        self.ui.time_final.setStyleSheet('color:#ffffff;font-size:15px;')
        self.ui.time_final.setFixedWidth(80)
        self.ui.slider_2.setValue(0)
        self.player.durationChanged.connect(self.cargar_duracion)
        self.player.positionChanged.connect(self.cargar_posicion)
        self.ui.slider_2.valueChanged.connect(self.player.setPosition)
    def __init__(self, config, root, app):
        # mainwindow 初始化 ======================================================================
        super().__init__()
        self.app = app
        # 保存传入的初始化数据
        Add('config')
        Space["config"] = config
        Add('root')
        Space["root"] = root

        TrayIcon_img = dir_mix(Space["root"],
                               Space["config"]['cover'])  # 用人物预览图作为托盘图标 和 显示图标

        with open(dir_mix(Space["root"], Space["config"]['Script']),
                  'r',
                  encoding='utf-8') as f:
            Add('Script')
            Space["Script"] = json.loads(f.read())  # 获取Script的参数
        Setting = Space["Script"]["Setting"]  # 获取Setting的数据集合

        self.ImageSize = Setting["ImageSize"]
        Add('Change')
        Space['Change'] = Setting["Change"]

        try:
            self.sound_Actions = Space["Script"]["sound"]
        except:
            pass

        Add('Info')
        Space['Info'] = {}
        Space['Info']["Play_complete"] = {}  # 播放组件是否播放完毕设置
        Space['Info']["Move"] = {}
        Space['Info']["Move"]["Window"] = {}

        Add('Control_Api')
        Space['Control_Api'] = {}

        # 核心控制器类
        Add("CoreControl")
        Space["CoreControl"] = Special_Control.CoreControl()

        self.setupUi(self)  # 创建标准窗口
        self.setAttribute(QtCore.Qt.WA_TranslucentBackground)  # 设置窗口背景透明
        self.setWindowTitle(
            Space["config"]['Name'])  # 把窗口名称设置成config.json中的Name键的值
        self.setWindowIcon(QtGui.QIcon(TrayIcon_img))  # 设置Icon

        self.Cache = {}  # 图片缓存字典

        # 组件创建
        self.label = Special_Label(self)  # 创建特殊的Label
        self.PlayBoard = PlayBoard()  # 创建播放器
        self.PlayBoard.play.connect(self.graph)
        self.Find = Find()  # 实例化指令查询插件
        self.sound = QtMultimedia.QMediaPlayer()  # 创立音频播放组件

        Space['BGMPlayer'] = QtMultimedia.QMediaPlayer()
        Space['BGMPlaylist'] = QtMultimedia.QMediaPlaylist()

        self.User = User()  # User组件 (会创建CommonSet,在Setbox前加载)

        self.Setbox = Setbox(self)

        self.ChangeWindowFlags(True)

        # 核心控制器绑定组件 ============================================
        Space["CoreControl"].play.connect(self.PlayNew)
        Space["CoreControl"].sound.connect(self.soundPlay)
        Space["CoreControl"].ChangeSize.connect(self.ChangeSize)
        Space["CoreControl"].Move.connect(self.MovePeson)

        Space["CoreControl"].clean.connect(self.PlayBoard.terminate)
        Space["CoreControl"].clean.connect(self.Setbox.close)
        Space["CoreControl"].clean.connect(self.close)
        Space["CoreControl"].clean.connect(self.app.exit)

        # Special_Label组件事件绑定 ============================================
        self.label.LeftButton_release.connect(
            self.LeftButton_release)  # 绑定鼠标左键点击事件[松开左键]
        self.label.LeftButton_click.connect(
            self.LeftButton_click)  # 绑定鼠标左键点击事件[松开左键]

        self.label.RightButton_release.connect(
            self.RightButton_release)  # 绑定鼠标右键点击事件[松开右键]
        self.label.RightButton_Move.connect(self.RightButton_Move)

        # 设置事件绑定 ===========================
        self.Setbox.MovePeson.connect(self.MovePeson)
        self.Setbox.ResetWindowFlag.connect(self.ChangeWindowFlags)
        # TrayIcon 组件 =====================================
        self.TrayIcon = TrayIcon(self)
        self.TrayIcon.setIcon(QtGui.QIcon(TrayIcon_img))
        self.TrayIcon.show()
        self.TrayIcon.AddActions("退出", self.close_)
        self.TrayIcon.AddActions("设置", self.Setbox.show)

        # 线程启动
        self.PlayBoard.start()

        if Space['CommonSet']["Change"] != None:
            Space['Change'] = Space['CommonSet']["Change"]
        self.ChangeSize()  # 设置窗口初始大小

        # Importer
        plugin.Importer()
    def __init__(self):
        super(MainWindow, self).__init__()

        self.setWindowTitle('Video Splitter')

        self.playlist = QtMultimedia.QMediaPlaylist()
        self.player = QtMultimedia.QMediaPlayer()

        # Setting QToolBar
        tool_bar = QtWidgets.QToolBar()
        tool_bar.setWindowTitle('Toolbar')
        self.addToolBar(tool_bar)

        file_menu = self.menuBar().addMenu("&File")

        # Define actions for in the file menu
        open_action = QtWidgets.QAction("Open",
                                        self,
                                        shortcut="Ctrl+O",
                                        triggered=self.open)
        exit_action = QtWidgets.QAction(
            "E&xit",
            self,
            shortcut="Ctrl+Q",
            triggered=QtWidgets.QApplication.instance().quit)

        file_menu.addAction(open_action)
        file_menu.addAction(exit_action)

        play_menu = self.menuBar().addMenu("&Play")

        # add icons and actions
        # Play
        play_icon = self.style().standardIcon(QtWidgets.QStyle.SP_MediaPlay)
        self.play_action = tool_bar.addAction(play_icon, "Play")
        self.play_action.triggered.connect(self.player.play)
        play_menu.addAction(self.play_action)

        # Pause
        pause_icon = self.style().standardIcon(QtWidgets.QStyle.SP_MediaPause)
        self.pause_action = tool_bar.addAction(pause_icon, "Pause")
        self.pause_action.triggered.connect(self.player.pause)
        play_menu.addAction(self.pause_action)

        # Stop
        stop_icon = self.style().standardIcon(QtWidgets.QStyle.SP_MediaStop)
        self.stop_action = tool_bar.addAction(stop_icon, "Stop")
        self.stop_action.triggered.connect(self.player.stop)
        play_menu.addAction(self.stop_action)

        # Previous
        previous_icon = self.style().standardIcon(
            QtWidgets.QStyle.SP_MediaSkipBackward)
        self.previous_action = tool_bar.addAction(previous_icon, "Previous")
        self.previous_action.triggered.connect(self.previous_clicked)
        play_menu.addAction(self.previous_action)

        # Next
        next_icon = self.style().standardIcon(
            QtWidgets.QStyle.SP_MediaSkipForward)
        self.next_action = tool_bar.addAction(next_icon, "Next")
        self.next_action.triggered.connect(self.playlist.next)
        play_menu.addAction(self.next_action)

        # About menu
        about_menu = self.menuBar().addMenu("&About")
        about_qt_action = QtWidgets.QAction("About &Qt", self)
        about_menu.addAction(about_qt_action)

        # Create video widget
        self.video_widget = QtMultimediaWidgets.QVideoWidget()

        # Create widget that will contain all of the UI elements
        self.window_widget = QtWidgets.QWidget()
        self.setCentralWidget(self.window_widget)

        # add slider to control volume
        self.vol_slider = QtWidgets.QSlider()
        self.vol_slider.setOrientation(QtGui.Qt.Horizontal)
        self.vol_slider.setMinimum(0)
        self.vol_slider.setMaximum(100)
        self.vol_slider.setFixedWidth(120)
        self.vol_slider.setValue(self.player.volume())
        self.vol_slider.setTickInterval(10)
        self.vol_slider.setTickPosition(QtWidgets.QSlider.TicksBelow)
        self.vol_slider.setToolTip("Volume")
        self.vol_slider.valueChanged.connect(self.player.setVolume)

        tool_bar.addSeparator()
        tool_bar.addWidget(self.vol_slider)
        tool_bar.addSeparator()

        # Split
        split_icon = self.style().standardIcon(QtWidgets.QStyle.SP_ArrowDown)
        self.split_action = tool_bar.addAction(split_icon, 'Split')
        self.split_action.triggered.connect(self.split)

        tool_bar.addSeparator()

        self.speed_slider = QtWidgets.QSlider()
        self.speed_slider.setOrientation(QtGui.Qt.Horizontal)
        self.speed_slider.setMinimum(0)
        self.speed_slider.setMaximum(200)
        self.speed_slider.setValue(100)
        self.speed_slider.setFixedWidth(120)
        self.speed_slider.setToolTip("Speed")
        self.speed_slider.valueChanged.connect(self.set_speed)

        self.speed_label = QtWidgets.QLabel('  ' +
                                            str(self.speed_slider.value() /
                                                100) + 'x')

        tool_bar.addWidget(self.speed_slider)
        tool_bar.addWidget(self.speed_label)

        # BOTTOM STUFF

        # Time slider
        self.time_slider = QtWidgets.QSlider()
        self.time_slider.setOrientation(QtGui.Qt.Horizontal)
        self.time_slider.setRange(0, 0)

        # Empty layout to store all cuts
        self.cuts_layout = QtWidgets.QVBoxLayout()

        # Details under the slider
        self.time_details = QtWidgets.QHBoxLayout()
        self.current_label = QtWidgets.QLabel('')
        self.duration_label = QtWidgets.QLabel('')

        self.current_label.setFixedHeight(9)
        self.duration_label.setFixedHeight(9)

        self.time_details.addWidget(self.current_label)
        self.time_details.addStretch(1)
        self.time_details.addWidget(self.duration_label)

        # MAIN UI WINDOW LAYOUT
        self.main_layout = QtWidgets.QVBoxLayout()
        self.main_layout.addWidget(self.video_widget)
        self.main_layout.addWidget(self.time_slider)
        self.main_layout.addLayout(self.time_details)
        self.main_layout.addLayout(self.cuts_layout)

        self.window_widget.setLayout(self.main_layout)

        self.player.setPlaylist(self.playlist)
        self.player.stateChanged.connect(self.update_buttons)
        self.player.setVideoOutput(self.video_widget)

        self.update_buttons(self.player.state())

        # Initialize duration and current (both represented in milliseconds)
        self.duration = 0
        self.current = 0
        self.cuts = []

        self.player.positionChanged.connect(self.position_changed)
        self.time_slider.valueChanged.connect(self.set_position)
    def __init__(self, song_dir):
        super(BasicPlayer, self).__init__()

        self.playlist = QtMultimedia.QMediaPlaylist()
        self.playlist.currentIndexChanged.connect(self.on_index_changed)

        self.player = QtMultimedia.QMediaPlayer()
        self.player.error.connect(self.on_media_error)
        self.player.setPlaylist(self.playlist)

        self.load_directory(song_dir)

        self.body = QtWidgets.QVBoxLayout()

        def fetch_title(record):
            return record.title

        def fetch_dur(record):
            return record.duration_str

        self.play2table = Playlist2Table(self.playlist, {
            "Title": fetch_title,
            "Duration": fetch_dur
        })

        self.playtable = QtWidgets.QTableView()
        self.playtable.horizontalHeader().setSectionResizeMode(
            QtWidgets.QHeaderView.ResizeToContents)
        self.playtable.verticalHeader().hide()
        self.playtable.horizontalHeader().hide()
        self.playtable.horizontalHeader().setSectionResizeMode(
            QtWidgets.QHeaderView.Stretch)
        self.playtable.setSelectionBehavior(
            QtWidgets.QAbstractItemView.SelectRows)
        self.playtable.setSizePolicy(QtWidgets.QSizePolicy.Expanding,
                                     QtWidgets.QSizePolicy.Expanding)
        self.playtable.resizeColumnsToContents()
        self.playtable.resizeRowsToContents()

        self.playtable.setModel(self.play2table)

        self.body.addWidget(self.playtable, 1)
        self.body.setStretch(0, 1)

        # basic player controls
        self.controls = QtWidgets.QHBoxLayout()

        self.playBtn = QtWidgets.QPushButton("Play")
        self.playBtn.clicked.connect(self.on_play_click)

        self.stopBtn = QtWidgets.QPushButton("Stop")
        self.stopBtn.clicked.connect(self.on_stop_click)

        self.controls.addWidget(self.playBtn)
        self.controls.addWidget(self.stopBtn)

        self.body.addLayout(self.controls)

        self.setLayout(self.body)

        self.playtable.doubleClicked.connect(self.on_doubleclick)