Ejemplo n.º 1
0
class Player(QDialog):
    def __init__(self):
        super().__init__()
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        # self.show()
        self.ui.btn_play.clicked.connect(self.playvideo) #включить видео
        self.ui.btn_stop.clicked.connect(self.stopvideo) #остановить видео
        self.ui.btn_pause.clicked.connect(self.pausevideo) #пауза
        self.ui.btn_back.clicked.connect(self.hidewindow) #скрыть окно плеера
        self.ui.verticalSlider.valueChanged.connect(self.setvolume) #громкость
        # self.ui.horizontalSlider.valueChanged.connect(self.settimevideo) #перемотка - починить функцию
        self.ui.listWidget.addItems(listdir("records")) #генерация списка файлов в папке records
        self.ui.listWidget.itemClicked.connect(self.playthis) #выбор видео


        self.player = QMediaPlayer()
        self.player.positionChanged.connect(self.setvideoonslider)#автодвижение ползунка
        self.video = QVideoWidget(self.ui.label)
        self.video.resize(621, 451)
        self.video.move(0, 0)
        self.player.setVideoOutput(self.video)
        self.video.show()

        self.ui.label.customContextMenuRequested.connect(self.testfun) #ПРАВАЯ КНОПКА МЫШИ

    def testfun(self):
        print("Тест успешен")

    def playvideo(self):
        self.player.play()
        self.ui.horizontalSlider.setMaximum(self.player.duration())
        self.ui.horizontalSlider.setPageStep(self.player.duration() / 10)

    def stopvideo(self):
        self.player.stop()

    def pausevideo(self):
        self.player.pause()

    def hidewindow(self):
        self.hide()

    def setvolume(self):
        self.player.setVolume(self.ui.verticalSlider.value())

    def settimevideo(self):
        self.player.setPosition(self.ui.horizontalSlider.value())

    def playthis(self):
        self.player.setMedia(QMediaContent(QUrl.fromLocalFile("records/" + str(self.ui.listWidget.currentItem().text()))))

    def setvideoonslider(self):
        self.ui.horizontalSlider.setValue(self.player.position())
        self.ui.lbl_time.setText(str(int(self.player.position() / 1000)) + "/" + str(int(self.player.duration() / 1000)))

    def test(self):
        print("Тест пройден")
Ejemplo n.º 2
0
class MyWin(QMainWindow):
    def __init__(self, parent=None):
        QMainWindow.__init__(self, parent)
        self.ui = Ui_VideoPlayer()
        self.ui.setupUi(self)

        self.media_player = QMediaPlayer(None, QMediaPlayer.VideoSurface)
        self.media_player_widget = QVideoWidget(self.ui.mid_frame)
        self.ui.mid_frame_layout.addWidget(self.media_player_widget)

        self.media_player.setVideoOutput(self.media_player_widget)
        self.media_player.error.connect(self.handleError)

        # fileName="E:/Dropbox/Hobby/PRG/PyWork/FGet/view/qt_ui/files/1.mp4"
        # self.media_player.setMedia(QMediaContent(QUrl.fromLocalFile(fileName)))

        # fileName="E:/exchange/DiskD/kl/1/road_to_abbi_big-1080.mp4.Epidemz.net_Triksa.com.mp4"
        # self.media_player.setMedia(QMediaContent(QUrl.fromLocalFile(fileName)))



        self.ui.bn_go.clicked.connect(self.go)

        self.media_player.bufferStatusChanged.connect(self.buf)
        self.media_player.mediaStatusChanged.connect(self.med)

        # url='http://tubedupe.com/get_file/1/693b07616d5019e3e266e772676e3048/56000/56102/56102.mp4'
        url = 'http://tubedupe.com/get_file/1/4b274e3f4027b13bf6d6ae5601dd7a09/50000/50768/50768.mp4'
        url = 'http://www.mypornovideo.net/video_file/2015/2/830/grudastaja_blondinka_ebetsja_s_kuchejj_muzhikov.flv'
        url = "http://im.50f9bc00.493dea4.cdn2b.movies.mxn.com/0/399/399060/NOWATERMARK_IPOD.mp4?s=1423689551&e=1423696751&ri=1227&rs=44&h=d0a58a04acc858983a202b5e8dea575a"

        self.media_player.setMedia(QMediaContent(QUrl(url)))

        self.media_player.play()
        self.media_player.setMuted(True)
        print(self.media_player.duration())

        print('Done')

    def handleError(self):
        print('Error: ' + self.media_player.errorString())

    def buf(self, percent):
        print(percent, '%')

    def med(self, media):
        print(media)

    def go(self):
        dur = self.media_player.duration()
        pos = self.media_player.position()

        print(dur // 1000, pos // 1000)
        print(self.media_player.bufferStatus())

        # self.hide()
        self.media_player.stop()
class VideoPlayerWithControls( QWidget ):
	def __init__( self ):
		super().__init__()

		self.video_w = QVideoWidget()
		self.v_player = QMediaPlayer( None, QMediaPlayer.VideoSurface )
		self.v_player.setVideoOutput( self.video_w )
		self.v_player.setNotifyInterval( 50 )
		self.v_player.stateChanged.connect( self.video_ended )

		self.controls = VideoControls( self.v_player )

		self._layout = QVBoxLayout()

		self._layout.addWidget( self.video_w )
		self._layout.addWidget( self.controls )

		self._layout.setSpacing( 0 )
		self._layout.setContentsMargins( 0, 0, 0, 0 )

		self.setLayout( self._layout )

	def video_ended( self, state ):
		if state == QMediaPlayer.StoppedState:
			self.v_player.setPosition( self.v_player.duration() - 10 )
			self.v_player.play()
			self.v_player.pause()
Ejemplo n.º 4
0
class QMediaPlayerAdapter(Player):
    def __init__(self, interval=1):
        self.__callback = None
        self.__player = QMediaPlayer()
        self.setNotifyInterval(interval)

    def setNotifyInterval(self, interval):
        self.__player.setNotifyInterval(interval)

    def setMusicPath(self, filePath):
        qUrl = QUrl(filePath)
        self.__player.setMedia(QMediaContent(qUrl))

    def getState(self):
        return self.__player.state()

    def getStatus(self):
        return self.__player.mediaStatus()

    def getPosition(self):
        return self.__player.position()

    def getDuration(self):
        return self.__player.duration()

    def start(self):
        if self.__player.state() != QMediaPlayer.NoMedia:
            self.__player.play()
            # self.__player.setPosition(self.__player.duration() - 2000)
        else:
            raise ValueError(
                "The media of the player should be set before the player get started."
            )

    def pause(self):
        self.__player.pause()

    def stop(self):
        self.__player.stop()

    def setCallback(self, callback):
        '''if not isinstance(callback, PlayerCallback):
            raise TypeError("The callback should be instance of PlayerCallback.")'''

        self.__callback = callback
        self.__player.mediaStatusChanged.connect(
            self.__callback.onMediaStatusChanged)
        self.__player.stateChanged.connect(self.__callback.onStateChanged)
        self.__player.positionChanged.connect(
            self.__callback.onPlayerPositionChanged)
Ejemplo n.º 5
0
class videoPlayer(QWidget):  # 视频播放类
    def __init__(self, parent=None):  # 构造函数
        super(videoPlayer, self).__init__(parent=parent)  # 类的继承
        self.mainwindow = parent

        self.length = 0  # 视频总时长
        self.position = 0  # 视频当前时长
        self.count = 0
        self.player_status = -1

        # 设置窗口
        self.setGeometry(300, 50, 800, 600)  #大小,与桌面放置位置
        # self.setWindowIcon(QIcon(':/images/video_player_icon.png'))  # 程序图标
        # self.setWindowTitle(titleName)  # 窗口名称
        # self.setWindowFlags(Qt.WindowCloseButtonHint | Qt.WindowMinimizeButtonHint)

        # 设置窗口背景
        self.palette = QPalette()
        self.palette.setColor(QPalette.Background, Qt.black)
        self.setPalette(self.palette)

        self.now_position = QLabel("/  00:00")  # 目前时间进度
        self.all_duration = QLabel('00:00')  # 总的时间进度
        self.all_duration.setStyleSheet('''QLabel{color:#000000}''')
        self.now_position.setStyleSheet('''QLabel{color:#000000}''')

        #视频插件
        self.video_widget = QVideoWidget(self)
        self.video_widget.setGeometry(QRect(0, 0, 1200, 700))  #大小,与桌面放置位置
        #self.video_widget.resize(1200, 700)  # 设置插件宽度与高度
        #self.video_widget.move(0, 30)   # 设置插件放置位置
        self.video_palette = QPalette()
        self.video_palette.setColor(QPalette.Background, Qt.black)  # 设置播放器背景
        self.video_widget.setPalette(self.video_palette)
        video_widget_color = "background-color:#000000"
        self.video_widget.setStyleSheet(video_widget_color)

        #布局容器
        self.verticalLayout = QVBoxLayout()
        self.verticalLayout.setSpacing(0)
        #self.verticalLayout.setContentsMargins(0, 5, 0, 10)
        self.layout = QHBoxLayout()
        self.layout.setSpacing(15)  # 各个插件的间距

        # 设置播放器
        self.player = QMediaPlayer(self)
        self.player.setVideoOutput(self.video_widget)
        #设置播放按钮事件
        self.player.durationChanged.connect(self.get_duration_func)
        # self.player.positionChanged.connect(self.progress)  # 媒体播放时发出信号
        self.player.mediaStatusChanged.connect(self.playerStatusChanged)
        self.player.error.connect(self.player_error)

        # 播放按钮
        self.play_btn = QPushButton(self)
        self.play_btn.setIcon(QIcon(':/images/play_btn_icon.png'))  # 设置按钮图标,下同
        self.play_btn.setIconSize(QSize(35, 35))
        self.play_btn.setStyleSheet(
            '''QPushButton{border:none;}QPushButton:hover{border:none;border-radius:35px;}'''
        )
        self.play_btn.setCursor(QCursor(Qt.PointingHandCursor))
        self.play_btn.setToolTip("播放")
        self.play_btn.setFlat(True)
        #self.play_btn.hide()
        #isHidden()      #判定控件是否隐藏

        #isVisible()     判定控件是否显示
        self.play_btn.clicked.connect(self.start_button)

        #音量条
        self.volume_slider = QSlider(Qt.Horizontal)  # 声音设置
        self.volume_slider.setMinimum(0)  # 音量0到100
        self.volume_slider.setMaximum(100)

        self.volume_slider.valueChanged.connect(self.volumes_change)

        self.volume_slider.setStyleSheet('''QSlider{}
QSlider::sub-page:horizontal:disabled{background: #00009C;  border-color: #999;  }
QSlider::add-page:horizontal:disabled{background: #eee;  border-color: #999; }
QSlider::handle:horizontal:disabled{background: #eee;  border: 1px solid #aaa;  border-radius: 4px;  }
QSlider::add-page:horizontal{background: #575757;  border: 0px solid #777;  height: 10px;border-radius: 2px; }
QSlider::handle:horizontal:hover{background:qradialgradient(spread:pad, cx:0.5, cy:0.5, radius:0.5, fx:0.5, fy:0.5, stop:0.6 #2A8BDA,   stop:0.778409 rgba(255, 255, 255, 255));  width: 11px;  margin-top: -3px;  margin-bottom: -3px;  border-radius: 5px; }
QSlider::sub-page:horizontal{background: qlineargradient(x1:0, y1:0, x2:0, y2:1,   stop:0 #B1B1B1, stop:1 #c4c4c4);  background: qlineargradient(x1: 0, y1: 0.2, x2: 1, y2: 1,stop: 0 #5DCCFF, stop: 1 #1874CD);  border: 1px solid #4A708B;  height: 10px;  border-radius: 2px;  }
QSlider::groove:horizontal{border: 1px solid #4A708B;  background: #C0C0C0;  height: 5px;  border-radius: 1px;  padding-left:-1px;  padding-right:-1px;}
QSlider::handle:horizontal{background: qradialgradient(spread:pad, cx:0.5, cy:0.5, radius:0.5, fx:0.5, fy:0.5,   stop:0.6 #45ADED, stop:0.778409 rgba(255, 255, 255, 255));  width: 11px;  margin-top: -3px;  margin-bottom: -3px;  border-radius: 5px; }'''
                                         )

        #视频播放进度条
        self.video_slider = QSlider(Qt.Horizontal, self)  # 视频进度拖拖动
        self.video_slider.setMinimum(0)  # 视频进度0到100%
        #self.video_slider.setMaximum(100)
        self.video_slider.setSingleStep(1)
        self.video_slider.setGeometry(QRect(0, 0, 200, 10))
        self.video_slider.sliderReleased.connect(self.video_silder_released)
        self.video_slider.sliderPressed.connect(self.video_silder_pressed)

        self.video_slider.setStyleSheet('''QSlider{}
QSlider::sub-page:horizontal:disabled{background: #00009C;  border-color: #999;  }
QSlider::add-page:horizontal:disabled{background: #eee;  border-color: #999; }
QSlider::handle:horizontal:disabled{background: #eee;  border: 1px solid #aaa;  border-radius: 4px;  }
QSlider::add-page:horizontal{background: #575757;  border: 0px solid #777;  height: 10px;border-radius: 2px; }
QSlider::handle:horizontal:hover{background:qradialgradient(spread:pad, cx:0.5, cy:0.5, radius:0.5, fx:0.5, fy:0.5, stop:0.6 #2A8BDA,   stop:0.778409 rgba(255, 255, 255, 255));  width: 11px;  margin-top: -3px;  margin-bottom: -3px;  border-radius: 5px; }
QSlider::sub-page:horizontal{background: qlineargradient(x1:0, y1:0, x2:0, y2:1,   stop:0 #B1B1B1, stop:1 #c4c4c4);  background: qlineargradient(x1: 0, y1: 0.2, x2: 1, y2: 1,stop: 0 #5DCCFF, stop: 1 #1874CD);  border: 1px solid #4A708B;  height: 10px;  border-radius: 2px;  }
QSlider::groove:horizontal{border: 1px solid #4A708B;  background: #C0C0C0;  height: 5px;  border-radius: 1px;  padding-left:-1px;  padding-right:-1px;}
QSlider::handle:horizontal{background: qradialgradient(spread:pad, cx:0.5, cy:0.5, radius:0.5, fx:0.5, fy:0.5,   stop:0.6 #45ADED, stop:0.778409 rgba(255, 255, 255, 255));  width: 11px;  margin-top: -3px;  margin-bottom: -3px;  border-radius: 5px; }'''
                                        )

        #静音按钮
        self.mute_button = QPushButton('')
        self.mute_button.clicked.connect(self.mute)
        self.mute_button.setIconSize(QSize(30, 30))
        self.mute_button.setStyleSheet(
            '''QPushButton{border:none;}QPushButton:hover{border:none;}''')
        self.mute_button.setCursor(QCursor(Qt.PointingHandCursor))
        self.mute_button.setToolTip("播放")
        self.mute_button.setFlat(True)
        self.mute_button.setIcon(QIcon(':/images/sound_btn_icon.png'))

        #暂停按钮
        self.pause_btn = QPushButton('')
        self.pause_btn.setIcon(QIcon(':/images/stop_btn_icon.png'))
        self.pause_btn.clicked.connect(self.stop_button)
        self.pause_btn.setIconSize(QSize(35, 35))
        self.pause_btn.setStyleSheet(
            '''QPushButton{border:none;}QPushButton:hover{border:none;}''')
        self.pause_btn.setCursor(QCursor(Qt.PointingHandCursor))
        self.pause_btn.setToolTip("播放")
        self.pause_btn.setFlat(True)
        self.pause_btn.hide()

        #音量值和音量显示标签
        self.volume_value = QLabel()
        self.volume_value.setText(' ' * 5)
        self.volume_value.setStyleSheet('''QLabel{color:#000000;}''')

        self.volume_t = QLabel()

        self.volume_t.setStyleSheet('''QLabel{color:#000000;}''')

        #视频文件打开按钮
        self.open_btn = QPushButton('Open')
        self.open_btn.clicked.connect(self.getfile)

        #全屏按钮
        self.screen_btn = QPushButton('')
        self.screen_btn.setIcon(
            QIcon(QPixmap(':/images/fullsrceen_btn_icon.png')))
        self.screen_btn.setIconSize(QSize(38, 38))
        self.screen_btn.setStyleSheet(
            '''QPushButton{border:none;}QPushButton:hover{border:1px solid #F3F3F5;border-radius:35px;}'''
        )
        self.screen_btn.setCursor(QCursor(Qt.PointingHandCursor))
        self.screen_btn.setToolTip("播放")
        self.screen_btn.setFlat(True)
        self.screen_btn.clicked.connect(self.fullscreen)

        #添加按钮组件
        self.verticalLayout.addStretch()
        self.layout.addWidget(self.play_btn, 0,
                              Qt.AlignCenter | Qt.AlignVCenter)
        self.layout.addWidget(self.pause_btn, 0, Qt.AlignCenter
                              | Qt.AlignVCenter)  # 插件,与前一个模块的距离,位置

        self.layout.addWidget(self.all_duration, 0,
                              Qt.AlignCenter | Qt.AlignVCenter)
        self.layout.addWidget(self.now_position, 0,
                              Qt.AlignCenter | Qt.AlignVCenter)
        self.layout.addWidget(self.video_slider, 15,
                              Qt.AlignVCenter | Qt.AlignVCenter)
        self.layout.addWidget(self.mute_button, 0,
                              Qt.AlignCenter | Qt.AlignVCenter)
        self.layout.addWidget(self.volume_slider, 0,
                              Qt.AlignCenter | Qt.AlignVCenter)

        self.layout.addWidget(self.volume_value, 0,
                              Qt.AlignCenter | Qt.AlignVCenter)

        #self.layout.addWidget(self.screen_btn)
        #self.layout.addWidget(self.open_btn)
        self.verticalLayout.addLayout(self.layout)

        #self.verticalLayout.addLayout(self.layout)
        self.setLayout(self.verticalLayout)

    def player_error(self, errorCode):
        print('error = ' + str(errorCode))
        try:
            if errorCode == 0:
                pass
            elif errorCode == 1:
                self.showAlertWindow('errorCode:1 \n\n无效视频源。')
            elif errorCode == 2:
                self.showAlertWindow('errorCode:2 \n\n不支持的媒体格式')
            elif errorCode == 3:
                self.showAlertWindow('errorCode:3 \n\n网络错误')
            elif errorCode == 4:
                self.showAlertWindow('errorCode:4 \n\n没有权限播放该视频')
            elif errorCode == 5:
                self.showAlertWindow('errorCode:5 \n\n视频服务不存在,无法继续播放。')
            else:
                self.showAlertWindow('未知错误')
        except:
            self.showAlertWindow('视频加载异常')

    def video_silder_pressed(self):
        if self.player.state != 0:
            self.player.pause()

    def playerStatusChanged(self, status):
        self.player_status = status
        if status == 7:
            self.play_btn.show()
            self.pause_btn.hide()

        #print('playerStatusChanged =' + str(status) + '...............')

    def resizeEvent(self, e):
        #print(e.size().width(), e.size().height())
        newSize = e.size()
        self.video_widget.setGeometry(0, 0, newSize.width(),
                                      newSize.height() - 50)
        #self.video_widget.setGeometry(0, 0, 0, 0)

    def closeEvent(self, e):
        self.player.stop()

    def get_duration_func(self, d):
        try:
            end_number = int(d / 1000 / 10) + 1
            #print('end_number = ' + str(end_number))
            sum = 0
            for n in range(1, end_number):
                sum = sum + n

            vv = int((100 / (d / 1000)) * (d / 1000))
            self.video_slider.setMaximum(d)
            #self.video_slider.setMaximum(vv + sum)
            #print(100 + sum)

            all_second = int(d / 1000 % 60)  # 视频播放时间
            all_minute = int(d / 1000 / 60)

            if all_minute < 10:

                if all_second < 10:

                    self.all_duration.setText('0' + str(all_minute) + ':0' +
                                              str(all_second))
                else:

                    self.all_duration.setText('0' + str(all_minute) + ':' +
                                              str(all_second))
            else:

                if all_second < 10:

                    self.all_duration.setText(
                        str(all_minute) + ':0' + str(all_second))
                else:

                    self.all_duration.setText(
                        str(all_minute) + ':' + str(all_second))
        except Exception as e:
            pass

    def mouseDoubleClickEvent(self, e):
        try:

            #print('mouseDoubleClickEvent................... = ' + str(self.player.state()))
            if self.player.state() == 2:
                #视频暂停
                self.player.play()
                self.play_btn.hide()
                self.pause_btn.show()

            elif self.player.state() == 1:
                # 正在播放
                self.player.pause()
                self.play_btn.show()
                self.pause_btn.hide()
            else:
                #视频停止
                self.play_btn.hide()
                self.pause_btn.show()
                self.player.setPosition(0)
                self.video_slider.setValue(0)
                self.player.play()
        except Exception as e:
            pass

    def start_button(self):  # 视频播放按钮
        try:

            self.play_btn.hide()
            self.pause_btn.show()

            if self.player_status == 7:
                self.video_slider.setValue(0)
                self.player.setPosition(0)

            self.player.play()
        except Exception as e:
            pass

    def stop_button(self):  # 视频暂停按钮
        self.play_btn.show()
        self.pause_btn.hide()
        self.player.pause()

    def getfile(self, filepath):  # 打开视频文件
        try:

            #print(str(filepath))
            url = QUrl.fromLocalFile(filepath)
            if url.isValid():
                self.player.setMedia(QMediaContent(url))  # 返回该文件地址,并把地址放入播放内容中
                self.player.setVolume(50)  # 设置默认打开音量即为音量条大小
                self.volume_value.setText(str(50))
                self.volume_slider.setValue(50)
            else:
                self.showAlertWindow('视频地址无效')

        except Exception as e:
            self.showAlertWindow()

    def clearVolumeValue():
        self.volume_value.setText(' ' * 5)

    def volumes_change(self):  # 拖动进度条设置声音
        try:
            size = self.volume_slider.value()
            if size:
                # 但进度条的值不为0时,此时音量不为静音,音量值即为进度条值
                self.player.setMuted(False)
                self.player.setVolume(size)
                volume_value = str(size) + ' ' * 4
                self.volume_value.setText(volume_value)
                #print(size)
                self.mute_button.setIcon(QIcon(':/images/sound_btn_icon.png'))
            else:
                self.player.setMuted(True)
                self.mute_button.setIcon(QIcon(':/images/mute_btn_icon.png'))
                self.player.setVolume(0)
                volume_value = '0' + ' ' * 4
                self.volume_value.setText(volume_value)

            if len(str(size)) == 1:
                volume_value = str(size) + ' ' * 4
            elif len(str(size)) == 2:
                volume_value = str(size) + ' ' * 3
            else:
                volume_value = str(size) + ' ' * 2

            self.volume_value.setText(volume_value)
        except Exception as e:
            pass

    def mute(self):
        try:
            if self.player.isMuted():
                self.mute_button.setIcon(QIcon(':/images/sound_btn_icon.png'))
                self.player.setMuted(False)
                self.volume_slider.setValue(50)
                volume_value = '50' + ' ' * 4
                self.volume_value.setText(volume_value)
            else:
                self.mute_button.setIcon(QIcon(':/images/mute_btn_icon.png'))
                self.player.setMuted(True)  # 若不为静音,则设置为静音,音量置为0
                self.volume_slider.setValue(0)
                volume_value = '0' + ' ' * 4
                self.volume_value.setText(volume_value)
        except Exception as e:
            pass

    def progress(self):  # 视频进度条自动释放与播放时间

        try:

            self.length = self.player.duration() + 1
            self.position = self.player.position()
            #print(str(self.length) + ':' + str(self.position))
            self.count += 1

            video_silder_maximum = self.video_slider.maximum()

            #video_silder_value = int(((video_silder_maximum / (self.length / 1000)) * (self.position / 1000)))

            #self.video_slider.setValue(video_silder_value + self.count)

            self.video_slider.setValue(self.position)

            #print('video_slider_value = ' + str(video_silder_value + self.count))

            now_second = int(self.position / 1000 % 60)
            now_minute = int(self.position / 1000 / 60)
            self.mainwindow.resultlist2.addItem("{0:02d} : {1:02d}".format(
                now_minute, now_second))
            #print(str(now_minute) + ':' + str(now_second))
            if now_minute < 10:
                if now_second < 10:

                    self.now_position.setText('/  0' + str(now_minute) + ':0' +
                                              str(now_second))
                else:

                    self.now_position.setText('/  0' + str(now_minute) + ':' +
                                              str(now_second))
            else:

                #print('now_minute < 10' + str(now_minute) + ':' + str(now_second))

                if now_second < 10:
                    #print('now_second < 10' + str(now_minute) + ':' + str(now_second))
                    #self.now_position.setText(str(now_minute) + ':0' + str(now_second))
                    self.now_position.setText('/  ' + str(now_minute) + ':0' +
                                              str(now_second))
                else:
                    #print('now_second > 10' + str(now_minute) + ':' + str(now_second))
                    self.now_position.setText('/  ' + str(now_minute) + ':' +
                                              str(now_second))
        except Exception as e:
            pass

    def video_silder_released(self):  # 释放滑条时,改变视频播放进度
        try:

            #print('video_silder_released......')
            if self.player.state() != 0:
                self.player.setPosition(self.video_slider.value())
                self.player.play()
            else:  #如果视频是停止状态,则拖动进度条无效
                self.video_slider.setValue(0)
        except Exception as e:
            pass

    def fullscreen(self):
        self.showFullScreen()

    def keyPressEvent(self, event):  # 重新改写按键
        if event.key() == Qt.Key_Escape:
            self.winquit()

    def winquit(self):  # 退出窗口
        self.showNormal()

    def showAlertWindow(self, msg='视频加载出错!'):
        reply = QMessageBox.information(self, "消息框标题", msg, QMessageBox.Yes)

    def setWindowTitleName(self, titleName):
        self.setWindowTitle(titleName)  # 窗口名称
Ejemplo n.º 6
0
class Player(QWidget):

    fullScreenChanged = pyqtSignal(bool)

    def __init__(self, playlist, parent=None):
        super(Player, self).__init__(parent)

        self.colorDialog = None
        self.trackInfo = ""
        self.statusInfo = ""
        self.duration = 0

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

        self.player.durationChanged.connect(self.durationChanged)
        self.player.positionChanged.connect(self.positionChanged)
        self.player.metaDataChanged.connect(self.metaDataChanged)
        self.playlist.currentIndexChanged.connect(self.playlistPositionChanged)
        self.player.mediaStatusChanged.connect(self.statusChanged)
        self.player.bufferStatusChanged.connect(self.bufferingProgress)
        self.player.videoAvailableChanged.connect(self.videoAvailableChanged)
        self.player.error.connect(self.displayErrorMessage)

        self.videoWidget = VideoWidget()
        self.player.setVideoOutput(self.videoWidget)

        self.playlistModel = PlaylistModel()
        self.playlistModel.setPlaylist(self.playlist)

        self.playlistView = QListView()
        self.playlistView.setModel(self.playlistModel)
        self.playlistView.setCurrentIndex(
            self.playlistModel.index(self.playlist.currentIndex(), 0))

        self.playlistView.activated.connect(self.jump)

        self.slider = QSlider(Qt.Horizontal)
        self.slider.setRange(0, self.player.duration() / 1000)

        self.labelDuration = QLabel()
        self.slider.sliderMoved.connect(self.seek)

        #        self.labelHistogram = QLabel()
        #        self.labelHistogram.setText("Histogram:")
        #        self.histogram = HistogramWidget()
        #        histogramLayout = QHBoxLayout()
        #        histogramLayout.addWidget(self.labelHistogram)
        #        histogramLayout.addWidget(self.histogram, 1)

        self.probe = QVideoProbe()
        #        self.probe.videoFrameProbed.connect(self.histogram.processFrame)
        self.probe.setSource(self.player)

        openButton = QPushButton("打开", clicked=self.open)

        controls = PlayerControls()
        controls.setState(self.player.state())
        controls.setVolume(self.player.volume())
        controls.setMuted(controls.isMuted())

        controls.play.connect(self.player.play)
        controls.pause.connect(self.player.pause)
        controls.stop.connect(self.player.stop)
        controls.next.connect(self.playlist.next)
        controls.previous.connect(self.previousClicked)
        controls.changeVolume.connect(self.player.setVolume)
        controls.changeMuting.connect(self.player.setMuted)
        controls.changeRate.connect(self.player.setPlaybackRate)
        controls.stop.connect(self.videoWidget.update)

        self.player.stateChanged.connect(controls.setState)
        self.player.volumeChanged.connect(controls.setVolume)
        self.player.mutedChanged.connect(controls.setMuted)

        self.fullScreenButton = QPushButton("全屏")
        self.fullScreenButton.setCheckable(True)

        self.colorButton = QPushButton("颜色选项")
        self.colorButton.setEnabled(False)
        self.colorButton.clicked.connect(self.showColorDialog)

        displayLayout = QHBoxLayout()
        displayLayout.addWidget(self.videoWidget, 2)
        displayLayout.addWidget(self.playlistView)

        controlLayout = QHBoxLayout()
        controlLayout.setContentsMargins(0, 0, 0, 0)
        controlLayout.addWidget(openButton)
        controlLayout.addStretch(1)
        controlLayout.addWidget(controls)
        controlLayout.addStretch(1)
        controlLayout.addWidget(self.fullScreenButton)
        controlLayout.addWidget(self.colorButton)

        layout = QVBoxLayout()
        layout.addLayout(displayLayout)
        hLayout = QHBoxLayout()
        hLayout.addWidget(self.slider)
        hLayout.addWidget(self.labelDuration)
        layout.addLayout(hLayout)
        layout.addLayout(controlLayout)
        #        layout.addLayout(histogramLayout)

        self.setLayout(layout)

        if not self.player.isAvailable():
            QMessageBox.warning(
                self, "Service not available",
                "The QMediaPlayer object does not have a valid service.\n"
                "Please check the media service plugins are installed.")

            controls.setEnabled(False)
            self.playlistView.setEnabled(False)
            openButton.setEnabled(False)
            self.colorButton.setEnabled(False)
            self.fullScreenButton.setEnabled(False)

        self.metaDataChanged()

        self.addToPlaylist(playlist)

    def open(self):
        fileNames, _ = QFileDialog.getOpenFileNames(self, "Open Files")
        self.addToPlaylist(fileNames)

    def addToPlaylist(self, fileNames):
        for name in fileNames:
            fileInfo = QFileInfo(name)
            if fileInfo.exists():
                url = QUrl.fromLocalFile(fileInfo.absoluteFilePath())
                if fileInfo.suffix().lower() == 'm3u':
                    self.playlist.load(url)
                else:
                    self.playlist.addMedia(QMediaContent(url))
            else:
                url = QUrl(name)
                if url.isValid():
                    self.playlist.addMedia(QMediaContent(url))

    def durationChanged(self, duration):
        duration /= 1000

        self.duration = duration
        self.slider.setMaximum(duration)

    def positionChanged(self, progress):
        progress /= 1000

        if not self.slider.isSliderDown():
            self.slider.setValue(progress)

        self.updateDurationInfo(progress)

    def metaDataChanged(self):
        if self.player.isMetaDataAvailable():
            self.setTrackInfo(
                "%s - %s" % (self.player.metaData(QMediaMetaData.AlbumArtist),
                             self.player.metaData(QMediaMetaData.Title)))

    def previousClicked(self):
        # Go to the previous track if we are within the first 5 seconds of
        # playback.  Otherwise, seek to the beginning.
        if self.player.position() <= 5000:
            self.playlist.previous()
        else:
            self.player.setPosition(0)

    def jump(self, index):
        if index.isValid():
            self.playlist.setCurrentIndex(index.row())
            self.player.play()

    def playlistPositionChanged(self, position):
        self.playlistView.setCurrentIndex(self.playlistModel.index(
            position, 0))

    def seek(self, seconds):
        self.player.setPosition(seconds * 1000)

    def statusChanged(self, status):
        self.handleCursor(status)

        if status == QMediaPlayer.LoadingMedia:
            self.setStatusInfo("Loading...")
        elif status == QMediaPlayer.StalledMedia:
            self.setStatusInfo("Media Stalled")
        elif status == QMediaPlayer.EndOfMedia:
            QApplication.alert(self)
        elif status == QMediaPlayer.InvalidMedia:
            self.displayErrorMessage()
        else:
            self.setStatusInfo("")

    def handleCursor(self, status):
        if status in (QMediaPlayer.LoadingMedia, QMediaPlayer.BufferingMedia,
                      QMediaPlayer.StalledMedia):
            self.setCursor(Qt.BusyCursor)
        else:
            self.unsetCursor()

    def bufferingProgress(self, progress):
        self.setStatusInfo("Buffering %d%" % progress)

    def videoAvailableChanged(self, available):
        if available:
            self.fullScreenButton.clicked.connect(
                self.videoWidget.setFullScreen)
            self.videoWidget.fullScreenChanged.connect(
                self.fullScreenButton.setChecked)

            if self.fullScreenButton.isChecked():
                self.videoWidget.setFullScreen(True)
        else:
            self.fullScreenButton.clicked.disconnect(
                self.videoWidget.setFullScreen)
            self.videoWidget.fullScreenChanged.disconnect(
                self.fullScreenButton.setChecked)

            self.videoWidget.setFullScreen(False)

        self.colorButton.setEnabled(available)

    def setTrackInfo(self, info):
        self.trackInfo = info

        if self.statusInfo != "":
            self.setWindowTitle("%s | %s" % (self.trackInfo, self.statusInfo))
        else:
            self.setWindowTitle(self.trackInfo)

    def setStatusInfo(self, info):
        self.statusInfo = info

        if self.statusInfo != "":
            self.setWindowTitle("%s | %s" % (self.trackInfo, self.statusInfo))
        else:
            self.setWindowTitle(self.trackInfo)

    def displayErrorMessage(self):
        self.setStatusInfo(self.player.errorString())

    def updateDurationInfo(self, currentInfo):
        duration = self.duration
        if currentInfo or duration:
            currentTime = QTime((currentInfo / 3600) % 60,
                                (currentInfo / 60) % 60, currentInfo % 60,
                                (currentInfo * 1000) % 1000)
            totalTime = QTime((duration / 3600) % 60, (duration / 60) % 60,
                              duration % 60, (duration * 1000) % 1000)

            format = 'hh:mm:ss' if duration > 3600 else 'mm:ss'
            tStr = currentTime.toString(format) + " / " + totalTime.toString(
                format)
        else:
            tStr = ""

        self.labelDuration.setText(tStr)

    def showColorDialog(self):
        if self.colorDialog is None:
            brightnessSlider = QSlider(Qt.Horizontal)
            brightnessSlider.setRange(-100, 100)
            brightnessSlider.setValue(self.videoWidget.brightness())
            brightnessSlider.sliderMoved.connect(
                self.videoWidget.setBrightness)
            self.videoWidget.brightnessChanged.connect(
                brightnessSlider.setValue)

            contrastSlider = QSlider(Qt.Horizontal)
            contrastSlider.setRange(-100, 100)
            contrastSlider.setValue(self.videoWidget.contrast())
            contrastSlider.sliderMoved.connect(self.videoWidget.setContrast)
            self.videoWidget.contrastChanged.connect(contrastSlider.setValue)

            hueSlider = QSlider(Qt.Horizontal)
            hueSlider.setRange(-100, 100)
            hueSlider.setValue(self.videoWidget.hue())
            hueSlider.sliderMoved.connect(self.videoWidget.setHue)
            self.videoWidget.hueChanged.connect(hueSlider.setValue)

            saturationSlider = QSlider(Qt.Horizontal)
            saturationSlider.setRange(-100, 100)
            saturationSlider.setValue(self.videoWidget.saturation())
            saturationSlider.sliderMoved.connect(
                self.videoWidget.setSaturation)
            self.videoWidget.saturationChanged.connect(
                saturationSlider.setValue)

            layout = QFormLayout()
            layout.addRow("亮度", brightnessSlider)
            layout.addRow("对比度", contrastSlider)
            layout.addRow("色调", hueSlider)
            layout.addRow("饱和度", saturationSlider)

            button = QPushButton("关闭")
            layout.addRow(button)

            self.colorDialog = QDialog(self)
            self.colorDialog.setWindowTitle("颜色选项")
            self.colorDialog.setLayout(layout)

            button.clicked.connect(self.colorDialog.close)

        self.colorDialog.show()
Ejemplo n.º 7
0
class VideoPlayer(QWidget):

    def __init__(self, aPath, parent=None):
        super(VideoPlayer, self).__init__(parent)

        self.setAttribute(Qt.WA_NoSystemBackground, True)
        self.setAcceptDrops(True)
        
        self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.StreamPlayback)
        self.mediaPlayer.setVolume(80)
        
        self.videoWidget = QVideoWidget(self)
        self.videoWidget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.videoWidget.setMinimumSize(QSize(640, 360))
        
        self.lbl = QLineEdit('00:00:00')
        self.lbl.setReadOnly(True)
        self.lbl.setFixedWidth(70)
        self.lbl.setUpdatesEnabled(True)
        self.lbl.setStyleSheet(stylesheet(self))

        self.elbl = QLineEdit('00:00:00')
        self.elbl.setReadOnly(True)
        self.elbl.setFixedWidth(70)
        self.elbl.setUpdatesEnabled(True)
        self.elbl.setStyleSheet(stylesheet(self))

        self.playButton = QPushButton()
        self.playButton.setEnabled(False)
        self.playButton.setFixedWidth(32)
        self.playButton.setStyleSheet("background-color: black")
        self.playButton.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay))
        self.playButton.clicked.connect(self.play)

        self.positionSlider = QSlider(Qt.Horizontal, self)
        self.positionSlider.setStyleSheet(stylesheet(self))
        self.positionSlider.setRange(0, 100)
        self.positionSlider.sliderMoved.connect(self.setPosition)
        self.positionSlider.sliderMoved.connect(self.handleLabel)
        self.positionSlider.setSingleStep(2)
        self.positionSlider.setPageStep(20)
        self.positionSlider.setAttribute(Qt.WA_TranslucentBackground, True)

        self.clip = QApplication.clipboard()
        self.process = QProcess(self)
        self.process.readyRead.connect(self.dataReady)
        self.process.finished.connect(self.playFromURL)

        self.myurl = ""

        # channel list
        self.channelList = QListView(self)
        self.channelList.setMinimumSize(QSize(150, 0))
        self.channelList.setMaximumSize(QSize(150, 4000))
        self.channelList.setFrameShape(QFrame.Box)
        self.channelList.setObjectName("channelList")
        self.channelList.setStyleSheet("background-color: black; color: #585858;")
        self.channelList.setFocus()
        # for adding items to list must create a model
        self.model = QStandardItemModel()
        self.channelList.setModel(self.model)

        self.controlLayout = QHBoxLayout()
        self.controlLayout.setContentsMargins(5, 0, 5, 0)
        self.controlLayout.addWidget(self.playButton)
        self.controlLayout.addWidget(self.lbl)
        self.controlLayout.addWidget(self.positionSlider)
        self.controlLayout.addWidget(self.elbl)

        self.mainLayout = QHBoxLayout()

        # contains video and cotrol widgets to the left side
        self.layout = QVBoxLayout()
        self.layout.setContentsMargins(0, 0, 0, 0)
        self.layout.addWidget(self.videoWidget)
        self.layout.addLayout(self.controlLayout)
        
        # adds channels list to the right
        self.mainLayout.addLayout(self.layout)
        self.mainLayout.addWidget(self.channelList)

        self.setLayout(self.mainLayout)

        self.myinfo = "©2020\nTIVOpy v1.0"

        self.widescreen = True

        #### shortcuts ####
        self.shortcut = QShortcut(QKeySequence("q"), self)
        self.shortcut.activated.connect(self.handleQuit)
        self.shortcut = QShortcut(QKeySequence("u"), self)
        self.shortcut.activated.connect(self.playFromURL)
        self.shortcut = QShortcut(QKeySequence(Qt.Key_Space), self)
        self.shortcut.activated.connect(self.play)
        self.shortcut = QShortcut(QKeySequence(Qt.Key_F), self)
        self.shortcut.activated.connect(self.handleFullscreen)
        self.shortcut = QShortcut(QKeySequence(Qt.Key_Escape), self)
        self.shortcut.activated.connect(self.exitFullscreen)
        self.shortcut.activated.connect(self.handleFullscreen)
        self.shortcut = QShortcut(QKeySequence("i"), self)
        self.shortcut.activated.connect(self.handleInfo)
        self.shortcut = QShortcut(QKeySequence("s"), self)
        self.shortcut.activated.connect(self.toggleSlider)
        self.shortcut = QShortcut(QKeySequence(Qt.Key_Right), self)
        self.shortcut.activated.connect(self.forwardSlider)
        self.shortcut = QShortcut(QKeySequence(Qt.Key_Left), self)
        self.shortcut.activated.connect(self.backSlider)

        self.mediaPlayer.setVideoOutput(self.videoWidget)
        self.mediaPlayer.stateChanged.connect(self.mediaStateChanged)
        self.mediaPlayer.positionChanged.connect(self.positionChanged)
        self.mediaPlayer.positionChanged.connect(self.handleLabel)
        self.mediaPlayer.durationChanged.connect(self.durationChanged)
        self.mediaPlayer.error.connect(self.handleError)

        self.populateChannelList()
        self.selectChannel()
        self.initialPlay()

    def playFromURL(self):
        self.mediaPlayer.pause()
        self.myurl = self.clip.text()
        self.mediaPlayer.setMedia(QMediaContent(QUrl(self.myurl)))
        self.playButton.setEnabled(True)
        self.mediaPlayer.play()
        self.hideSlider()
        print(self.myurl)

    def dataReady(self):
        self.myurl = str(self.process.readAll(), encoding='utf8').rstrip()  ###
        self.myurl = self.myurl.partition("\n")[0]
        print(self.myurl)
        self.clip.setText(self.myurl)
        self.playFromURL()

    def play(self):
        if self.mediaPlayer.state() == QMediaPlayer.PlayingState:
            self.mediaPlayer.pause()
        else:
            self.mediaPlayer.play()

    def mediaStateChanged(self, state):
        if self.mediaPlayer.state() == QMediaPlayer.PlayingState:
            self.playButton.setIcon(
                self.style().standardIcon(QStyle.SP_MediaPause))
        else:
            self.playButton.setIcon(
                self.style().standardIcon(QStyle.SP_MediaPlay))

    def positionChanged(self, position):
        self.positionSlider.setValue(position)

    def durationChanged(self, duration):
        self.positionSlider.setRange(0, duration)
        mtime = QTime(0, 0, 0, 0)
        mtime = mtime.addMSecs(self.mediaPlayer.duration())
        self.elbl.setText(mtime.toString())

    def setPosition(self, position):
        self.mediaPlayer.setPosition(position)

    def handleError(self):
        self.playButton.setEnabled(False)
        print("Error: ", self.mediaPlayer.errorString())

    def handleQuit(self):
        self.mediaPlayer.stop()
        print("Goodbye ...")
        app.quit()

    def contextMenuRequested(self, point):
        menu = QMenu()
        actionURL = menu.addAction(QIcon.fromTheme("browser"), "URL from Clipboard (u)")
        menu.addSeparator()
        actionToggle = menu.addAction(QIcon.fromTheme("next"), "Show / Hide Channels (s)")
        actionFull = menu.addAction(QIcon.fromTheme("view-fullscreen"), "Fullscreen (f)")
        menu.addSeparator()
        actionInfo = menu.addAction(QIcon.fromTheme("help-about"), "About (i)")
        menu.addSeparator()
        actionQuit = menu.addAction(QIcon.fromTheme("application-exit"), "Exit (q)")

        actionQuit.triggered.connect(self.handleQuit)
        actionFull.triggered.connect(self.handleFullscreen)
        actionInfo.triggered.connect(self.handleInfo)
        actionToggle.triggered.connect(self.toggleSlider)
        actionURL.triggered.connect(self.playFromURL)
        menu.exec_(self.mapToGlobal(point))

    def wheelEvent(self, event):
        mscale = event.angleDelta().y() / 13
        self.mediaPlayer.setVolume(self.mediaPlayer.volume() + mscale)
        print("Volume: " + str(self.mediaPlayer.volume()))

    def mouseDoubleClickEvent(self, event):
        if event.buttons() == Qt.LeftButton:
            self.handleFullscreen()

    def handleFullscreen(self):
        if self.windowState() and Qt.WindowFullScreen:
            self.showNormal()
        else:
            self.showFullScreen()

    def exitFullscreen(self):
        self.showNormal()

    def handleInfo(self):
        QMessageBox.about(self, "About", self.myinfo)

    def toggleSlider(self):
        if self.positionSlider.isVisible():
            self.hideSlider()
        else:
            self.showSlider()

    def hideSlider(self):
        self.channelList.hide()
        self.playButton.hide()
        self.lbl.hide()
        self.positionSlider.hide()
        self.elbl.hide()

    def showSlider(self):
        self.channelList.show()
        self.playButton.show()
        self.lbl.show()
        self.positionSlider.show()
        self.elbl.show()
        self.channelList.setFocus()

    def forwardSlider(self):
        self.mediaPlayer.setPosition(self.mediaPlayer.position() + 1000 * 60)

    def backSlider(self):
        self.mediaPlayer.setPosition(self.mediaPlayer.position() - 1000 * 60)

    def volumeUp(self):
        self.mediaPlayer.setVolume(self.mediaPlayer.volume() + 10)
        print("Volume: " + str(self.mediaPlayer.volume()))

    def volumeDown(self):
        self.mediaPlayer.setVolume(self.mediaPlayer.volume() - 10)
        print("Volume: " + str(self.mediaPlayer.volume()))

    def dragEnterEvent(self, event):
        if event.mimeData().hasUrls():
            event.accept()
        elif event.mimeData().hasText():
            event.accept()
        else:
            event.ignore()

    def dropEvent(self, event):
        print("drop")
        if event.mimeData().hasUrls():
            url = event.mimeData().urls()[0].toString()
            print("url = ", url)
            self.mediaPlayer.stop()
            self.mediaPlayer.setMedia(QMediaContent(QUrl(url)))
            self.playButton.setEnabled(True)
            self.mediaPlayer.play()
        elif event.mimeData().hasText():
            mydrop = event.mimeData().text()
            print("generic url = ", mydrop)
            self.mediaPlayer.setMedia(QMediaContent(QUrl(mydrop)))
            self.playButton.setEnabled(True)
            self.mediaPlayer.play()
            self.hideSlider()

    def loadFilm(self, f):
        self.mediaPlayer.setMedia(QMediaContent(QUrl.fromLocalFile(f)))
        self.playButton.setEnabled(True)
        self.mediaPlayer.play()

    def populateChannelList(self):
        # file must be in same directory as the script
        FILEPATH = os.path.join(os.path.dirname(os.path.realpath(__file__)), "canaletv.txt")
        # lines from file with "channel name" -- "link"
        channelArray = []
        # split file by line and adding it to the array
        with open(FILEPATH) as f:
            for line in f:
                channelArray.append(line.rstrip())
        # dictionary with key = channel name and value = link
        self.channelDict = dict(ch.split(" -- ") for ch in channelArray)
        for channel in self.channelDict.keys():
            item = QStandardItem(channel)
            self.model.appendRow(item)

    def selectedItemBehavior(self, index):
    # gets the link for the selected channel and plays it
        itms = self.channelList.selectedIndexes()
        for it in itms:
            channel = it.data()
            link = self.channelDict[channel]
            self.mediaPlayer.setMedia(QMediaContent(QUrl(link)))
            self.play()

    def selectChannel(self):
    # selecting channel from sidebar calls selectedItemBehavior
        self.selModel = self.channelList.selectionModel()
        self.selModel.selectionChanged.connect(self.selectedItemBehavior)

    def initialPlay(self):
    # play somenting when app opens
        self.mediaPlayer.setMedia(QMediaContent(QUrl("https://vid.hls.protv.ro/proxhdn/proxhd_3_34/index.m3u8?1")))
        self.play()

    def handleLabel(self):
        self.lbl.clear()
        mtime = QTime(0, 0, 0, 0)
        self.time = mtime.addMSecs(self.mediaPlayer.position())
        self.lbl.setText(self.time.toString())
Ejemplo n.º 8
0
class VideoPlayer(QWidget):
    def __init__(self, parent=None):
        super(VideoPlayer, self).__init__(parent)
        self._source = None
        self._total_duration = 0
        self.widget_layout = QVBoxLayout()
        self.media_player = QMediaPlayer(None, QMediaPlayer.VideoSurface)
        self.video_player = QVideoWidget()
        self.widget_layout.addWidget(self.video_player)
        self.media_player.setVideoOutput(self.video_player)
        # self.media_player.stateChanged.connect(self.mediaStateChanged)
        self.media_player.positionChanged.connect(self.on_positionChanged)
        self.signals = VideoPlayerWidgetSignals()
        self.media_player.durationChanged.connect(self.on_durationChanged)
        self.setLayout(self.widget_layout)
        print(self.media_player.duration())

    @property
    def total_duration(self):
        return self._total_duration

    @total_duration.setter
    def total_duration(self, val):
        self._total_duration = val

    @property
    def source(self):
        return self._source

    @source.setter
    def source(self, value):
        self._source = value
        self._total_duration = math.floor(VideoUtilities.duration(self.source))

    def play(self):
        if self._source:
            self.media_player.setMedia(
                QMediaContent(QUrl.fromLocalFile(self._source)))
            self.media_player.play()

    def resume(self):
        if self.media_player.state() == QMediaPlayer.PlayingState:
            self.media_player.pause()
        else:
            self.media_player.play()

    def stop(self):
        if self.media_player.state() == QMediaPlayer.PlayingState:
            self.media_player.stop()

    def go_to(self, second: int):
        if self.media_player:
            self.media_player.setPosition(second * 1000)

    @QtCore.pyqtSlot('qint64')
    def on_positionChanged(self, position):
        self.signals.video_position_changed_signal.emit(
            math.floor(position / 1000), self.total_duration)
        if self.media_player.state() == QMediaPlayer.StoppedState:
            if 0 <= position <= self.total_duration * 1000:
                self.media_player.play()

    @QtCore.pyqtSlot('qint64')
    def on_durationChanged(self, duration):
        self.signals.video_duration_changed_signal.emit(
            math.floor(duration / 1000))
Ejemplo n.º 9
0
class EventAction():
    def __init__(self):
        #self.parent = parent
        self.isLoop = 0         #0循环列表,1单曲循环
        self.isRandom = 0       #0不随机,1随机
        self.fileList = []      #曲目名称列表
        self.randomList =[]     #播放列表
        self.soundID = 0        #当前歌曲ID
        self.playStat = False  #当前播放状态 (0未播放,1播放)
        self.openPath = "F:/mp3/" #歌曲目录
        self.isPreview = 0       #试用开关,0正常播放,1列表中的歌曲每首歌曲放10秒
        self.currentVolume = 0.1#默认的起始音量
        self.isInitPlay = 1     #是否是初始播放
        #==>>打开目录
        self.config=configparser.ConfigParser()
        self.config.read('config.ini')
        self.openDir()
        #打开目录<<==
        self.playObj = QMediaPlayer()

        self.currentImg = ""    #当前图片
        self.songText = {}      #歌词
        self.songTextKey=[]     #歌词KEY



    #打开歌曲目录
    def openDir(self):
        self.openPath = self.config.get('Save','musicPath')
        isMusicDir = os.path.isdir(self.openPath)#检查是否为目录
        if isMusicDir:
            dirFile = os.listdir(self.openPath)#目录中的所有文件
            #遍历有效音乐文件
            i=0;
            for file in dirFile:
                fileName,fileType=os.path.splitext(file)
                if fileType==".mp3" or fileType==".wav":
                    self.fileList.append(file)
                    self.randomList.append(i)
                    i+=1
        if self.isRandom==1:
            self.shuffleMusic(1)

    #随机(打乱播放顺序)
    def shuffleMusic(self,isshuffle):
        if isshuffle:
            random.shuffle(self.randomList)#乱序
        else:
            self.randomList.sort()#排序

    #初始化播放
    def initPlay(self):
        self.soundID = int(self.config.get('Save','soundID'))
        self.playStat = self.config.get('Save','playStat')
        self.pastTime = self.config.getint('Save','pastTime')
        self.currentVolume = self.config.getint('Save','volume')
        self.isRandom = self.config.getint('Save','isRandom')
        self.isLoop = self.config.getint('Save','isLoop')

        if self.soundID!="":
            self.play(self.soundID)
        if self.isRandom:#打乱列表
            self.shuffleMusic(1)
        self.playObj.setVolume(self.currentVolume)


    #播放
    def play(self,i):
        source = self.openPath + self.fileList[i]
        self.playObj.setMedia(QMediaContent(QUrl.fromLocalFile(source)))
        #解析文件中的ID3V2
        self.currentImg = ""
        f = QFile(source)
        if f.open(QIODevice.ReadOnly):
            #读取标签
            headData = f.read(10)
            data = headData[:0]
            if self.id3v2(headData):#检测是否有ID3
                #标签的大小计算
                tag = headData[6:10]
                tagSize = (tag[0]&0x7f)*0x200000+(tag[1]&0x7f)*0x4000+(tag[2]&0x7f)*0x80+(tag[3]&0x7f)
                data =f.read(tagSize)
                while len(data)>10:
                    data = self.resolve(data)
        f.close()
        self.playObj.play()

    def testPlay(self):
        #ps =QMediaMetaData()
        #print("QMediaMetaData",ps)
        #print("metaData",self.playObj.metaData(QMediaMetaData.Title))
        #print("position",self.playObj.position())
        #print("playlist",self.playObj.playlist)
        #print("availability",self.playObj.availability())
        #print("bufferStatus",self.playObj.bufferStatus())
        #print("currentMedia",self.playObj.currentMedia())
        #print("currentNetworkConfiguration",self.playObj.currentNetworkConfiguration())
        #print("duration",self.playObj.duration())
        #print("error",self.playObj.error())
        #print("errorString",self.playObj.errorString())
        #print("isAudioAvailable",self.playObj.isAudioAvailable())
        #print("isMuted",self.playObj.isMuted())
        #print("isSeekable",self.playObj.isSeekable())
        #print("media",self.playObj.media())
        #print("media:::::::A",self.playObj.media().canonicalResource().audioBitRate())
        #print("media:::::::B",self.playObj.media().canonicalResource().audioCodec())
        #print("media:::::::C",self.playObj.media().canonicalResource().channelCount())
        #print("media:::::::D",self.playObj.media().canonicalResource().dataSize())
        #print("media:::::::e",self.playObj.media().canonicalResource().isNull())
        #print("media:::::::f",self.playObj.media().canonicalResource().language())
        #print("media:::::::g",self.playObj.media().canonicalResource().mimeType())
        #print("media:::::::h",self.playObj.media().canonicalResource().request())
        #print("isVideoAvailable",self.playObj.isVideoAvailable())
        #print("mediaStatus",self.playObj.mediaStatus())
        #print("mediaStream",self.playObj.mediaStream())
        #print("playbackRate",self.playObj.playbackRate())
        #print("state",self.playObj.state())
        #print("volume",self.playObj.volume())
        # print("volume",self.playObj.filename)
        pass



    #换歌之前先停止,释放内存
    def stopPlay(self):
        self.playObj.pause()

    #上一首
    def prevPlay(self):
        self.stopPlay()
        if self.isRandom:
            key = self.searchID(self.soundID)-1
            if key<0:
                key=0
            self.soundID = self.randomList[key]
        else:
            self.soundID-=1
            if self.soundID< 0:
                self.soundID = len(self.randomList)-1
        self.play(self.soundID)

    #下一首
    def nextPlay(self):
        self.stopPlay()
        if self.isRandom:
            key = self.searchID(self.soundID)+1
            if key>(len(self.randomList)-1):
                key=len(self.randomList)-1
            self.soundID = self.randomList[key]
        else:
            self.soundID+=1
            if self.soundID > (len(self.randomList)-1):
                self.soundID = 0
        #print("next:::",self.soundID)
        self.play(self.soundID)

    #快退
    def rewindPlay(self):
        #print("<<")
        rewindTime = int(self.playObj.position()) - 10*1000
        if rewindTime < 0:
            rewindTime = 0
        self.playObj.setPosition(rewindTime)

    #快进
    def forwardPlay(self):
        #print(">>")
        forwardTime = int(self.playObj.position()) + 10*1000
        if forwardTime > int(self.playObj.duration()):
            forwardTime = int(self.playObj.duration())
        self.playObj.setPosition(forwardTime)

    #播放/暂停
    def playORpause(self):
        if self.playObj.state()==1:
            self.playObj.pause()
        else:
            self.playObj.play()

    #音量加
    def raisevolPlay(self):
        self.playObj.setVolume(self.playObj.volume()+10)
        self.currentVolume = self.playObj.volume()
    #音量减
    def lowervolPlay(self):
        self.playObj.setVolume(self.playObj.volume()-10)
        self.currentVolume = self.playObj.volume()

    #静音
    def mutePlay(self):
        if self.playObj.isMuted():
            self.playObj.setMuted(False)
        else:
            self.playObj.setMuted(True)
    #volume

    #跟据v找K
    def searchID(self,v):
        for index, item in enumerate(self.randomList):
            if item ==v:
                return index
        return 0

    #解析文件中是否有id3v2
    def id3v2(self,headData):
        if str(headData[:3],encoding=("utf-8")) != "ID3":
            return False
        return True

    #解析文件中的歌词与图片
    def resolve(self,data):
        tagName =  str(data[:4],encoding=("utf-8"))
        size = data[4:8]
        #sizeS = size[0]*0x1000000 + size[1]*0x10000 + size[2]*0x100 + size[3]
        sizeS=int.from_bytes(size, byteorder='big')
        flags = data[8:10]
        tagContent = data[10:sizeS+10]

        if tagName=="TEXT":#歌词
            #print("歌词")
            condingType=int.from_bytes(tagContent[:1], byteorder='big')
            if condingType == 0:#0代表字符使用ISO-8859-1编码方式;
                try:
                    content = str(tagContent[1:],encoding="gbk")
                except:
                    content =""
            elif condingType == 1:#1代表字符使用UTF-16编码方式;
                try:
                    content = str(tagContent[1:],encoding="UTF-16")
                except:
                    content =""
            elif condingType == 2:#2代表字符使用 UTF-16BE编码方式;
                content =""
            elif condingType == 3:#3代表字符使用UTF-8编码方式。
                try:
                    content = str(tagContent[1:],encoding="UTF-8")
                except:
                    content =""
            if content!="":
                temp={}
                self.songTextKey=[]
                contentSplit = content.splitlines()
                for k in range(len(contentSplit)):
                    if contentSplit[k][1].isdigit():
                        xxx = contentSplit[k].split("]")
                        tempKey = "%d" %(int(xxx[0][1:3])*60 +int(xxx[0][4:6]) )
                        temp[str(tempKey)] = xxx[1]
                        self.songTextKey.append(tempKey)
                    else:
                        endKey = contentSplit[k].find("]",0)
                        self.songTextKey.append(k)
                        temp[str(k)] = contentSplit[k][1:endKey]
                self.songText = temp
            else:
                self.songText = {}
        elif tagName=="APIC":#图片
            #print("图片")
            self.currentImg = tagContent[17:]
        return data[10+sizeS:]
class videoViewer(QDialog):
    def __init__(self):
        super(videoViewer,self).__init__()

        loadUi('..\gui\viewer.ui',self)
        self.setWindowTitle('Recorded Videos')
        self.setWindowIcon(QIcon('..\resources\icon.png'))
        self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.VideoSurface)
        videoWidget = QVideoWidget(self)
        layout = QVBoxLayout()
        layout.addWidget(videoWidget)
        self.mediaPlayer.setVideoOutput(videoWidget)
        self.videoWidget.setLayout(layout)

        self.userPath = os.path.join(os.getcwd(),'..\data')
        userList = [o for o in os.listdir(self.userPath) if os.path.isdir(os.path.join(self.userPath,o))]
        self.list1.addItems(userList)
        self.list1.itemClicked.connect(self.loadFile)
        self.playButton.clicked.connect(self.play)
        self.pauseButton.clicked.connect(self.pause)
        self.stopButton.clicked.connect(self.stop)
        self.exitButton.clicked.connect(self.exit)
        self.playButton.setEnabled(False)
        self.pauseButton.setEnabled(False)
        self.stopButton.setEnabled(False)
        self.timer = QTimer(self)
        self.timer.timeout.connect(self.updateFrame)
        self.understanding1.setText('-')
        self.understanding2.setText('-')
        self.data = pickle.load(open('..\data\data.pkl','rb'))
        self.mediaPlayer.mediaStatusChanged.connect(self.mediaStatusfn)

    def mediaStatusfn(self):
        if self.mediaPlayer.position()==self.mediaPlayer.duration():
            self.mediaPlayer.stop()




    def updateFrame(self):

        currentFrame = round(self.mediaPlayer.position()*30/1000)
        totalFrame = round(self.mediaPlayer.duration()*30/1000)
        if currentFrame>totalFrame:
            self.timer.stop()
            self.mediaPlayer.stop()
        else:
            if self.understandingData[self.i][0]<currentFrame and self.i<len(self.understandingData)-1:
                self.i += 1
                self.understanding1.setText(str(self.understandingData[self.i][1]))
                self.understanding2.setText(str(self.understandingData[self.i][1]))


    def play(self):
        self.mediaPlayer.play()
        self.pauseButton.setEnabled(True)
        self.playButton.setEnabled(False)
        self.stopButton.setEnabled(True)
        self.timer.start(30)


    def pause(self):
        self.mediaPlayer.pause()
        self.playButton.setEnabled(True)
        self.pauseButton.setEnabled(False)
        self.timer.stop()

    def stop(self):
        self.mediaPlayer.stop()
        self.playButton.setEnabled(True)
        self.pauseButton.setEnabled(False)
        self.stopButton.setEnabled(False)
        self.timer.stop()

    def exit(self):
        self.close()

    def loadFile(self, item):
        self.filePath = os.path.join(self.userPath,item.text())
        fileList = [o for o in os.listdir(self.filePath) if not os.path.isdir(os.path.join(self.filePath,o))]
        self.list2.clear()
        self.list2.addItems(fileList)
        self.list2.itemClicked.connect(self.playFile)

    def playFile(self, item):
        if (os.path.splitext(item.text())[-1].lower()=='.avi'):
            self.fileLabel.setText(item.text())
            self.mediaPlayer.setMedia(QMediaContent(QUrl.fromLocalFile(os.path.join(self.filePath,item.text()))))
            for file, understanding in self.data.items():
                if os.path.basename(file)==item.text():
                    self.understandingData = understanding
                    break
            self.playButton.setEnabled(True)
            self.pauseButton.setEnabled(False)
            self.stopButton.setEnabled(False)
            self.i = 0
Ejemplo n.º 11
0
class jaabaGUI(QMainWindow):
    """ controller for the blob labeling GUI"""
    def __init__(self,parent=None):
        QMainWindow.__init__(self,parent)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        #add new slider
        # self.positionSlider=QSlider(Qt.Horizontal)
        # self.positionSlider.setGeometry (800,800,100,30)
        # self.positionSlider.setRange(0, 0)
        # self.positionSlider.sliderMoved.connect(self.setPosition)

        #setup Video
        #video player
        self.mediaPlayer1 = QMediaPlayer(None, QMediaPlayer.VideoSurface)
        self.mediaPlayer2 = QMediaPlayer(None, QMediaPlayer.VideoSurface)
        #self.mediaPlayer.metaDataChanged.connect(self.metaDataChanged)
        self.mediaPlayer1.durationChanged.connect(self.durationChanged)
        self.mediaPlayer1.positionChanged.connect(self.positionChanged)
        self.mediaPlayer2.positionChanged.connect(self.positionChanged)
        

        #visualizetion
        self.scene = QGraphicsScene()
        self.ui.graphicsView.setScene(self.scene)
        #self.scene.setBackgroundBrush(Qt.black)
        self.videoItem1 = QGraphicsVideoItem()
        self.videoItem2 = QGraphicsVideoItem()
        self.scene.addItem(self.videoItem1)
        self.scene.addItem(self.videoItem2)
        self.mediaPlayer1.setVideoOutput(self.videoItem1)
        self.mediaPlayer2.setVideoOutput(self.videoItem2)

        #slide bar
        print self.ui.horizontalSlider
        self.ui.horizontalSlider.setRange(0, 0)
        self.ui.horizontalSlider.sliderMoved.connect(self.setPosition)
        # self.ui.horizontalSlider.sliderPressed.connect(self.sliderPressed)



        #print self.ui.graphicsView.width()/2,self.ui.graphicsView.height()
        #self.videoItem1.setSize(QSizeF(self.ui.graphicsView.width()/2,self.ui.graphicsView.height()))
        #self.videoItem2.setSize(QSizeF(self.ui.graphicsView.width()*10,self.ui.graphicsView.height()*10))
       # self.videoItem2.setSize(graphicsView.size())
        #self.videoItem2.setOffset(QPointF(500,500))
        #self.videoItem2.setOffset(QPointF(self.ui.graphicsView.width()/2,0))   
        #self.videoItem2.setPos(QPointF(0,0))
        # print self.ui.graphicsView.width(), self.ui.graphicsView.height()
        # print self.ui.graphicsView.size()
        # print self.videoItem2.boundingRect().width(), self.videoItem2.boundingRect().height()
        # print self.ui.graphicsView.sceneRect()
        #self.mediaPlayer.stateChanged.connect(self.mediaStateChanged)

        #callbacks
        self.ui.actionQuit.triggered.connect(self.quit)
        self.ui.actionLoad_Project.triggered.connect(self.loadVideo)
        #self.ui.buttonPlay.clicked[bool].connect(self.setToggleText)
        self.ui.buttonPlay.clicked.connect(self.play)
        #print self.ui.graphicsView.sizeHint()


        #initialization
        self.loaded = False
        self.videoFilename = None
        self.frame_count=None
        self.width=None
        self.height=None
        self.frame_trans=None



        
    # ###actions starts from here###
    def quit(self):
        QApplication.quit()

    def loadVideo(self):
        self.writeLog("Loading video...")

        self.videoFilename = QFileDialog.getOpenFileName(self, 'Open File', '.')[0]
        if not self.videoFilename:
            self.writeLog("User cancelled - no video loaded")
            return
        else:
       		cap=cv2.VideoCapture(self.videoFilename)
	    	self.frame_count=cap.get(cv2.CAP_PROP_FRAME_COUNT)
	    	self.width=cap.get(3)
	    	self.height=cap.get(4)
	        self.mediaPlayer2.setMedia(QMediaContent(QUrl.fromLocalFile(self.videoFilename )))
	        self.mediaPlayer1.setMedia(QMediaContent(QUrl.fromLocalFile(self.videoFilename )))
	        self.ui.buttonPlay.setEnabled(True)
            # self.mediaPlayer2.setVideoOutput(self.videoItem2)
            # self.mediaPlayer1.setVideoOutput(self.videoItem1)
            # size= self.videoItem2.nativeSize()
            # print size
            #print self.mediaPlayer.duration()
          
            #print self.mediaPlayer.metaData()
        self.writeLog("Video loaded!")

    def play(self):
    	
        self.videoItem1.setAspectRatioMode(0)
        self.videoItem2.setAspectRatioMode(0)
        self.scene.setSceneRect(0,0,self.ui.graphicsView.width(),self.ui.graphicsView.height())
        self.videoItem1.setSize(QSizeF(self.ui.graphicsView.width()/2,self.ui.graphicsView.height()))
        self.videoItem2.setSize(QSizeF(self.ui.graphicsView.width()/2,self.ui.graphicsView.height()))
        self.videoItem1.setPos(QPointF(0,0))
        self.videoItem2.setPos(QPointF(self.ui.graphicsView.width()/2,0))
        #self.ui.graphicsView.setGeometry(0,0, 600,800)
        #print 'graphicsView size', self.ui.graphicsView.size()
        #print 'graphicsScene size', self.scene.sceneRect()
        #self.videoItem2.setSize(QSizeF(1000,300))
        #print 'graphicsVideoItem size',self.videoItem2.size()
        # print 'item x',self.videoItem2.scenePos().x()
        # print 'item y', self.videoItem2.scenePos().y()
        # print 'item x',self.videoItem1.scenePos().x()
        # print 'item y', self.videoItem1.scenePos().y()

        if self.mediaPlayer1.state() == QMediaPlayer.PlayingState:
        	self.ui.buttonPlay.setIcon(self.ui.style().standardIcon(PyQt5.QtWidgets.QStyle.SP_MediaPlay))
        	self.ui.buttonPlay.setText("Play")
        	self.mediaPlayer1.pause()
        	self.writeLog("Video paused")
        else: 
        	self.ui.buttonPlay.setIcon(self.ui.style().standardIcon(PyQt5.QtWidgets.QStyle.SP_MediaPause))
	        self.ui.buttonPlay.setText("Stop")
	        self.mediaPlayer1.play()
	        self.writeLog("Playing video")

        if self.mediaPlayer2.state() == QMediaPlayer.PlayingState:
            self.mediaPlayer2.pause()
        else: 
            self.mediaPlayer2.play()


        
        #size= self.videoItem2.nativeSize()
        # print self.mediaPlayer.duration()
      
        #print self.mediaPlayer.metaData()
      

        # print self.ui.graphicsView.width(), self.ui.graphicsView.height()
        # print self.ui.graphicsView.size()
        # print self.videoItem2.boundingRect().width(), self.videoItem2.boundingRect().height()
        # print self.ui.graphicsView.sceneRect()
        # print self.scene.sceneRect()
        # print self.ui.graphicsView.sizeHint()

    

    def setPosition(self, position):
    	self.mediaPlayer1.setPosition(position) 
    	self.mediaPlayer2.setPosition(position)  

    # when position of media changed, set slider and text box accordingly.
    def positionChanged(self, position):
        self.ui.horizontalSlider.setValue(position)
        if isinstance(self.frame_trans,float):
	        # print type(position),position
	        # print type(self.frame_trans),self.frame_trans 
	        # print position/self.frame_trans
	     	self.ui.lineEdit.setText(str(int(round(position/self.frame_trans,0))))
	       
        self.writeLog(str(position))    
    
    def durationChanged(self, duration):
	    self.ui.horizontalSlider.setRange(0, duration) 
	    self.frame_trans=self.mediaPlayer1.duration()/self.frame_count
	    print self.frame_trans

    

    def writeLog(self,text):
        self.ui.log.setText(text)
Ejemplo n.º 12
0
class NewProject(QtWidgets.QWidget, Ui_NewProject):
    
    def __init__(self,projectfile,MainWidget):
        QtWidgets.QWidget.__init__(self)
        self.setupUi(self)
        self.setWindowFlags(Qt.WindowStaysOnTopHint)
        self.Main = MainWidget
        self.iface = self.Main.iface
        self.muteButton.setIcon(
                    self.style().standardIcon(QStyle.SP_MediaVolume))
        self.replayPlay_pushButton.setIcon(
                    self.style().standardIcon(QStyle.SP_MediaPlay))
        if projectfile.split('.')[-1] =="vgp":
            self.projectfile = projectfile
        else:
            self.projectfile = projectfile +'.vgp'   
        self.videofile = None
        self.GPXfile = None
        self.GPXList = None
        self.fps = None
        self.RealFps = None
        self.DB = None
        self.player = QMediaPlayer()
        self.player.setVideoOutput(self.video_frame_2)
        self.player.durationChanged.connect(self.durationChanged)
        self.player.positionChanged.connect(self.positionChanged)
        self.player.stateChanged.connect(self.mediaStateChanged)
        self.toolButton_3.clicked.connect(self.ManageDB)
        self.pushButton_2.clicked.connect(self.Synchronize)
        self.pushButton.clicked.connect(self.SelectVideoGPX)
        self.replayPlay_pushButton.clicked.connect(self.PlayPause)
        self.muteButton.clicked.connect(self.MuteUnmute)
        self.horizontalSlider.sliderMoved.connect(self.setPosition)
        self.toolButton.clicked.connect(self.SkipBackward)
        self.toolButton_2.clicked.connect(self.SkipForward)
        self.SkipBacktoolButton_7.clicked.connect(self.BackwardFrame)
        self.SkipFortoolButton_8.clicked.connect(self.ForwardFrame)
             
    def closeEvent(self, *args, **kwargs):
        self.player.stop()
        
        return QtWidgets.QWidget.closeEvent(self, *args, **kwargs)  
    
    def mediaStateChanged(self, state):
        if self.player.state() == QMediaPlayer.PlayingState:
            self.replayPlay_pushButton.setIcon(
                    self.style().standardIcon(QStyle.SP_MediaPause))
        else:
            self.replayPlay_pushButton.setIcon(
                    self.style().standardIcon(QStyle.SP_MediaPlay))
             
    def Synchronize(self):
        TimeItem = self.comboBox.currentIndex()
        duration = self.player.duration()
        position = self.player.position()
        VideoPartLen = round((duration-position) / 1000) 
        GpxPartition = self.GPXList[TimeItem:VideoPartLen+TimeItem]
        outputFile = open(self.projectfile ,'w')
        if self.DB == None:
            outputFile.write('VideoGis Project v0.1 DO NOT MODIFY'+
                             '\nVideo file location = ' +self.videofile+
                             '\nVideo start at msecond: '+
                              str(self.player.position())+
                              ' #fps = '+str(self.RealFps)+
                              '\nDB = None'+
                              '\n'+'Latitude # Longitude # Ele # Speed (m/s) # Course # Time  \n')
        else:
            outputFile.write('Video file location = ' +self.videofile+
                             '\nVideo start at msecond: '+
                              str(self.player.position())+
                              ' #fps = '+str(self.RealFps)+
                              '\nDB = '+str(self.DB.dataProvider().dataSourceUri().split('|')[0])+
                              '\n'+'Latitude # Longitude # Ele # Speed (m/s) # Course # Time  \n')    
        Counter = 0
        for x in GpxPartition:
            if Counter != 0:
                ActualLatitude = x[1][0]
                ActualLongitude = x[1][1]
                PreviousLatitude = GpxPartition[Counter-1][1][0]
                PreviousLongitude = GpxPartition[Counter-1][1][1]
                GeodesicCalcolus = Geodesic.WGS84.Inverse(PreviousLatitude, PreviousLongitude, ActualLatitude, ActualLongitude)
                Speed = GeodesicCalcolus['s12'] /1
                Course = GeodesicCalcolus['azi2']
                if Course < 0:
                    Course += 360
                Ele = x[1][2]
                Time = x[1][3]
                Counter = Counter + 1
            else:
                ActualLatitude = x[1][0]
                ActualLongitude = x[1][1]
                PreviousLatitude = GpxPartition[Counter+1][1][0]
                PreviousLongitude = GpxPartition[Counter+1][1][1]
                GeodesicCalcolus = Geodesic.WGS84.Inverse(ActualLatitude, ActualLongitude, PreviousLatitude, PreviousLongitude)
                Speed = GeodesicCalcolus['s12'] * 1
                Course = GeodesicCalcolus['azi2']
                if Course < 0:
                    Course += 360
                Ele = x[1][2]
                Time = x[1][3]
                Counter = Counter + 1  
            outputFile.write(str(ActualLatitude)+' '+str(ActualLongitude)+' '+str(Ele)+' '+str(Speed)+' '+str(Course)+' '+str(Time)+'\n')    
        outputFile.close() 
        self.Main.LoadProjFromNew(self.projectfile)
        if os.name == 'nt':
            os.remove (self.tmp)
        self.close()
         
    def SelectVideoGPX(self):
        if os.name == 'nt':
            ffmpeg = os.path.dirname(__file__)+'/FFMPEG/ffmpeg.exe'
            versione = 'ffmpeg.exe'
        else:
            ffmpeg = os.path.dirname(__file__)+'/FFMPEG/./ffmpeg'
            versione = 'ffmpeg'
        if os.path.exists(ffmpeg) == True:
            self.comboBox.clear()
            if self.player.state() == QMediaPlayer.PlayingState:
                self.player.pause()    
            self.videofile = None
            self.GPXfile = None
            options = QFileDialog.Options()
            options |= QFileDialog.DontUseNativeDialog
            self.videofile, _ = QFileDialog.getOpenFileName(self,"Select Video File", "","All Files (*);;Video File (*.mp4 *.avi *.ogv)", options=options)
            if self.videofile:        
                self.GPXfile, _ = QFileDialog.getOpenFileName(self,"Select GPX file", "","All Files (*);;Video File (*.gpx)", options=options)
                if self.GPXfile:
                    self.ParseGpx(self.GPXfile)
                    self.LoadVideo(self.videofile)
                    self.replayPosition_label.setText( "-:- / -:-")
        else:
            ret = QMessageBox.warning(self, "Warning", 'missing ffmpeg binaries, please download it from https://github.com/sagost/VideoUavTracker/blob/master/FFMPEG/'+versione+' and paste it in /.qgis3/python/plugins/Video_UAV_Tracker/FFMPEG/ ', QMessageBox.Ok)
            self.close()
            
    def ParseGpx(self,GPXfile):
        gpx = parse(GPXfile)
        track = gpx.getElementsByTagName("trkpt")
        GPXList = []
        Error = 0
        GpxProgressiveNumber = 0
        Timestamp = 'Segnaposto'
        for name in track:
            dict = {'Lat': 0, 'Lon': 0, 'Ele': 0, 'Time':0}

            a = (name.toprettyxml(indent = '') ).split()
            for x in a:
                if x.find('lat') == 0:
                    lat = float(x.split('"')[1])
                    dict['Lat'] = float(x.split('"')[1])    
                elif x.find('lon') == 0:
                    lon = float(x.split('"')[1])
                    dict['Lon'] = float(x.split('"')[1])    
                elif x.find('<ele>') == 0:
                    dict['Ele'] = float(x[5:-6])   
                elif x.find('<time>') == 0:
                    
                    try:
                        
                        gpxtime = time.strftime('%Y-%m-%dT%H:%M:%S.%fZ',time.strptime(x[6:-7], '%Y-%m-%dT%H:%M:%S.%fZ'))
                        dict['Time']= x[6:-7]
                        
                    except ValueError:
                        try:
                            gpxtime = time.strftime('%Y-%m-%dT%H:%M:%SZ',time.strptime(x[6:-7],'%Y-%m-%dT%H:%M:%SZ'))
                            dict['Time']= x[6:-7]
                            
                        except ValueError:
                            try:
                                gpxtime = time.strftime('%Y-%m-%dT%H:%M:%S',time.strptime(x[6:-7],'%Y-%m-%dT%H:%M:%S'))
                                dict['Time']= x[6:-7]
                            except ValueError:
                                try:
                                    gpxtime = time.strftime('%Y-%m-%dT%H.%M.%S',time.strptime(x[6:-7],'%Y-%m-%dT%H.%M.%S')) 
                                    dict['Time']= x[6:-7]
                                             
                                except ValueError:
                                    try:
                                        gpxtime = time.strftime('%Y-%m-%dT%H.%M.%S',time.strptime(x[6:-13],'%Y-%m-%dT%H.%M.%S'))
                                        dict['Time']= x[6:-13] 
                                 
                                    except ValueError:
                                        try:
                                            gpxtime = time.strftime('%Y-%m-%dT%H.%M.%S',time.strptime(x[6:-13],'%Y-%m-%dT%H:%M:%S'))
                                            dict['Time']= x[6:-13]
                                           
                                        except ValueError:
                                            Error = 1
                                            FormatoErrore = str(x)
            
            if dict['Time'] != Timestamp:               
                Point = [dict['Lat'],dict['Lon'],dict['Ele'],dict['Time']]
                self.comboBox.addItem(str(GpxProgressiveNumber) + '-'+gpxtime )    
                GPXList.append([GpxProgressiveNumber,Point])
                GpxProgressiveNumber = GpxProgressiveNumber + 1
                Timestamp = dict['Time'] 
            else:
                Timestamp = dict['Time']
                
        if Error == 0:
            self.GPXList = GPXList
        else:
            ret = QMessageBox.warning(self, "Warning", FormatoErrore +'  UNKOWN GPX TIME FORMAT - ABORTED', QMessageBox.Ok)  
            self.close
        
    def LoadVideo(self,videofile):
        fps = self.getVideoDetails(str(videofile))
        self.RealFps = float(fps)
        self.fps = (1 / self.RealFps )*1000
        url = QUrl.fromLocalFile(str(self.videofile))
        mc = QMediaContent(url)
        self.player.setMedia(mc)
        self.player.play()
          
    def setPosition(self, position):
        self.player.setPosition(position*1000)   
    
    def durationChanged(self, duration):
        duration /= 1000
        self.horizontalSlider.setMaximum(duration)

    def secTotime(self,seconds): 
            m, s = divmod(seconds, 60)
            h, m = divmod(m, 60)
            return "%d:%02d:%02d" % (h, m, s)
           
    def positionChanged(self, progress):
        duration = self.player.duration()
        totalTime = self.secTotime(duration/1000)
        actualTime = self.secTotime(progress/1000)
        self.replayPosition_label.setText(actualTime + ' / '+totalTime)
        progress /= 1000
        if not self.horizontalSlider.isSliderDown():
            self.horizontalSlider.setValue(progress) 
               
    def MuteUnmute(self):
        if self.player.mediaStatus() == 6 :
            if self.player.isMuted() == 1:
                self.player.setMuted(0)
                self.muteButton.setIcon(
                    self.style().standardIcon(QStyle.SP_MediaVolume))
            elif self.player.isMuted() == 0:
                self.player.setMuted(1)
                self.muteButton.setIcon(
                    self.style().standardIcon(QStyle.SP_MediaVolumeMuted))
                                 
    def PlayPause(self):
        if self.player.state() == QMediaPlayer.PlayingState:
            self.player.pause()
        else:
            self.player.play()
    
    def getVideoDetails(self,filepath):
        
        if os.name == 'nt':
            tmp = os.path.dirname(__file__)[0:-18]+'/Video_UAV_Tracker/tmp'
            tmp2 = '"'+tmp+'"'
            filepath2 = '"'+filepath+'"'
            a = open(tmp,'w')
            a.close()
            ffmpeg = '"'+os.path.dirname(__file__)[0:-18]+'/Video_UAV_Tracker/FFMPEG/ffmpeg.exe'+'"'
            a = os.popen(str(ffmpeg + ' -i '+filepath2+' 2> '+tmp2))
            while os.stat(tmp).st_size < 1500:
                pass
            a = open(tmp,'r')
            lines = a.readlines()
            a.close()
            for l in lines:
                l = l.strip()
                if str(l).startswith("Stream #0:0"):
                    linea = str(l).split(',')[-4]
                    dopo = linea.find('fps')
                    fps = float(linea[0:dopo])
                    self.tmp = tmp
                    return fps
        else:
            tmpf = tempfile.NamedTemporaryFile()
            ffmpeg = os.path.dirname(__file__)+'/FFMPEG/./ffmpeg'
            os.system(str(ffmpeg)+" -i \"%s\" 2> %s" % (filepath, tmpf.name))
            lines = tmpf.readlines()
            tmpf.close()
            for l in lines:
                l = l.strip()     
                if str(l).startswith("b'Stream #0:0"):
                    linea = str(l).split(',')[-4]
                    dopo = linea.find('fps')
                    fps = float(linea[0:dopo])
                    return fps
         
    def SkipForward(self): 
        position = self.player.position()
        self.player.setPosition(position+1000)
    
    def SkipBackward(self): 
        position = self.player.position()
        self.player.setPosition(position-1000)
    
    def ForwardFrame(self):  
        position = self.player.position()
        self.player.setPosition(position+int(self.fps))
    
    def BackwardFrame(self):
        position = self.player.position()
        self.player.setPosition(position-int(self.fps))

    def ManageDB(self):
        self.player.pause()
        shapeFileFirst,_ =  QFileDialog.getSaveFileName(caption = 'Save shape file', filter = "Esri shp (*.shp)")
        if shapeFileFirst:
            if shapeFileFirst.split('.')[-1] == 'shp':
                shapeFile = shapeFileFirst
            else:
                shapeFile = shapeFileFirst + '.shp'
            try:
                os.remove(shapeFile)
                os.remove(shapeFileFirst.split('.')[0]+'.qpg')
                os.remove(shapeFileFirst.split('.')[0]+'.prj')
                os.remove(shapeFileFirst.split('.')[0]+'.cpg')
                os.remove(shapeFileFirst.split('.')[0]+'.shx')
                os.remove(shapeFileFirst.split('.')[0]+'.dbf')
                
            except OSError:
                pass 
            crs = QgsCoordinateReferenceSystem(4326, QgsCoordinateReferenceSystem.EpsgCrsId)
            fields = QgsFields()
            QgsVectorFileWriter(shapeFile, "CP1250", fields, QgsWkbTypes.Point, crs, "ESRI Shapefile")
            EmptyLayer = QgsVectorLayer(shapeFile, shapeFile.split('.')[0].split('/')[-1], 'ogr')
            self.dialoga = TableManager(self.iface, EmptyLayer,self)
            self.dialoga.exec_()
    
    def AcceptNewDB(self,DB):
        self.DB = DB
Ejemplo n.º 13
0
class MainUi(QtWidgets.QMainWindow):
    def __init__(self):
        super().__init__()
        self.init_ui()
        self.player = QMediaPlayer(self)

    def init_ui(self):
        self.setFixedSize(550, 325)
        self.main_widget = QtWidgets.QWidget()  # 创建窗口主部件
        self.main_layout = QtWidgets.QGridLayout()  # 创建主部件的网格布局
        self.main_widget.setLayout(self.main_layout)  # 设置窗口主部件布局为网格布局

        self.left_widget = QtWidgets.QWidget()  # 创建左侧部件
        self.left_widget.setObjectName('left_widget')
        self.left_layout = QtWidgets.QGridLayout()  # 创建左侧部件的网格布局层
        self.left_widget.setLayout(self.left_layout)  # 设置左侧部件布局为网格
        self.left_widget.setStyleSheet('''
            QPushButton{border:none;color:white;}
            QPushButton#left_label{
                border:none;
                border-bottom:1px solid white;
                font-size:18px;
                font-weight:700;
                font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
            }
            QPushButton#left_button:hover{border-left:4px solid red;font-weight:700;}
        ''')

        self.right_widget = QtWidgets.QWidget()  # 创建右侧部件
        self.right_widget.setObjectName('right_widget')
        self.right_layout = QtWidgets.QGridLayout()
        self.right_widget.setLayout(self.right_layout)  # 设置右侧部件布局为网格
        self.right_bar_widget = QtWidgets.QWidget()  # 右侧顶部搜索框部件
        self.right_bar_layout = QtWidgets.QGridLayout()  # 右侧顶部搜索框网格布局

        self.right_bar_widget.setLayout(self.right_bar_layout)
        self.search_icon = QtWidgets.QLabel(chr(0xf002) + ' ' + '搜索  ')
        self.search_icon.setFont(qtawesome.font('fa', 16))
        self.right_bar_widget_search_input = QtWidgets.QLineEdit("")
        self.right_bar_widget_search_input.setPlaceholderText(
            "输入歌手、歌曲或用户,回车进行搜索")
        self.right_bar_layout.addWidget(self.search_icon, 0, 0, 1, 1)
        self.right_bar_layout.addWidget(self.right_bar_widget_search_input, 0,
                                        1, 1, 8)
        self.right_layout.addWidget(self.right_bar_widget, 0, 0, 1, 9)
        self.right_bar_widget_search_input.returnPressed.connect(
            self.Get_song_name)

        self.right_bar_widget_search_input.setStyleSheet('''QLineEdit{
                    border:1px solid gray;
                    width:300px;
                    border-radius:10px;
                    padding:2px 4px;
            }''')
        self.right_widget.setStyleSheet('''
            QWidget#right_widget{
                color:#232C51;
                background:white;
                border-top:1px solid darkGray;
                border-bottom:1px solid darkGray;
                border-right:1px solid darkGray;
                border-top-right-radius:10px;
                border-bottom-right-radius:10px;
            }
            QLabel#right_lable{
                border:none;
                font-size:16px;
                font-weight:700;
                font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
            }
        ''')

        # icon = QtGui.QIcon()
        # icon.addPixmap(QtGui.QPixmap("ico/瓜板.ico"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
        # self.setWindowIcon(icon)
        # self.setToolTip("")

        self.main_layout.addWidget(self.left_widget, 0, 0, 12,
                                   2)  # 左侧部件在第0行第0列,占8行3列
        self.main_layout.addWidget(self.right_widget, 0, 2, 12,
                                   10)  # 右侧部件在第0行第3列,占8行9列
        self.setCentralWidget(self.main_widget)  # 设置窗口主部件

        self.left_close = QtWidgets.QPushButton("")  # 关闭按钮
        self.left_visit = QtWidgets.QPushButton("")  # 空白按钮
        self.left_mini = QtWidgets.QPushButton("")  # 最小化按钮

        self.left_close.setFixedSize(15, 15)  # 设置关闭按钮的大小
        self.left_visit.setFixedSize(15, 15)  # 设置按钮大小
        self.left_mini.setFixedSize(15, 15)  # 设置最小化按钮大小

        self.left_layout.addWidget(self.left_mini, 0, 0, 1, 1)  # 放置最小化按钮
        self.left_layout.addWidget(self.left_close, 0, 2, 1, 1)  # 放置关闭按钮
        self.left_layout.addWidget(self.left_visit, 0, 1, 1, 1)  # 放置空白按钮

        self.left_close.setStyleSheet(
            '''QPushButton{background:#F76677;border-radius:5px;}QPushButton:hover{background:red;}'''
        )
        self.left_visit.setStyleSheet(
            '''QPushButton{background:#F7D674;border-radius:5px;}QPushButton:hover{background:yellow;}'''
        )
        self.left_mini.setStyleSheet(
            '''QPushButton{background:#6DDF6D;border-radius:5px;}QPushButton:hover{background:green;}'''
        )

        self.left_close.clicked.connect(self.left_close_event)  # 添加关闭功能

        self.setWindowFlag(QtCore.Qt.FramelessWindowHint)  # 隐藏边框
        self.setWindowOpacity(0.95)  # 设置窗口透明度
        # self.setAttribute(QtCore.Qt.WA_TranslucentBackground)  # 设置窗口背景透明
        self.main_layout.setSpacing(0)

    # 鼠标长按事件
    def mousePressEvent(self, event):
        if event.button() == QtCore.Qt.LeftButton:
            self.m_drag = True
            self.m_DragPosition = event.globalPos() - self.pos()
            event.accept()
            self.setCursor(QtGui.QCursor(QtCore.Qt.OpenHandCursor))

    # 鼠标移动事件
    def mouseMoveEvent(self, QMouseEvent):
        if QtCore.Qt.LeftButton and self.m_drag:
            self.move(QMouseEvent.globalPos() - self.m_DragPosition)
            QMouseEvent.accept()

    # 鼠标释放事件
    def mouseReleaseEvent(self, QMouseEvent):
        self.m_drag = False
        self.setCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor))

    def left_close_event(self):
        self.close()

    def Get_song_name(self):
        song_name = self.right_bar_widget_search_input.text()
        # 提取歌曲id
        a, song_id = Cloud_Music_API.single_search(song_name)
        #print(song_id)
        # 获取url
        song_url = Cloud_Music_API.song_url(song_id[1])
        # 播放音乐
        content = QMediaContent(QtCore.QUrl(song_url))
        self.player.setMedia(content)
        self.player.setVolume(30)
        self.player.play()
        self.duration = self.player.duration()  # 音乐的时长
class MainWindow(QMainWindow, Ui_MainWindow):
    def __init__(self, *args, **kwargs):
        super(MainWindow, self).__init__(*args, **kwargs)
        self.setupUi(self)
        self.threadpool = QThreadPool()
        print('Multithreading with maximum %d threads' %
              self.threadpool.maxThreadCount())

        self.player = QMediaPlayer()

        # Setup the playlist.
        self.playlist = QMediaPlaylist()
        self.player.setPlaylist(self.playlist)

        # Setup the player
        self.player.durationChanged.connect(self.update_duration)
        self.player.positionChanged.connect(self.update_position)
        self.playlist.currentIndexChanged.connect(
            self.playlist_position_changed)
        self.player.error.connect(self.erroralert)
        self.videoWidget = QVideoWidget()
        self.player.setVideoOutput(self.videoWidget)

        self.model = PlaylistModel(self.playlist)
        self.playListView.setModel(self.model)
        selection_model = self.playListView.selectionModel()
        selection_model.selectionChanged.connect(
            self.playlist_selection_changed)

        self.currentFrame = QVideoFrame()

        # Connect control buttons/slides for media player.
        self.playButton.pressed.connect(self.player.play)
        self.pauseButton.pressed.connect(self.player.pause)
        self.stopButton.pressed.connect(self.player.stop)

        layout = QVBoxLayout()
        layout.addWidget(self.videoWidget)
        self.viewWidget.setLayout(layout)

        self.probe = QVideoProbe()
        self.probe.videoFrameProbed.connect(self.on_videoFrameProbed)
        self.probe.setSource(self.player)

        self.timeSlider.valueChanged.connect(self.player.setPosition)

        self.open_file_action.triggered.connect(self.open_file)

        # button for save current frame
        self.saveButton.pressed.connect(self.save_frame)

        self.setAcceptDrops(True)

        self.show()

    def on_videoFrameProbed(self, frame):
        self.frame = frame

    def save_frame(self):
        worker = Worker(self.frame)
        self.threadpool.start(worker)

    def dragEnterEvent(self, e):
        if e.mimeData().hasUrls():
            e.acceptProposedAction()

    def dropEvent(self, e):
        for url in e.mimeData().urls():
            self.playlist.addMedia(QMediaContent(url))

        self.model.layoutChanged.emit()

        # If not playing, seeking to first of newly added + play.
        if self.player.state() != QMediaPlayer.PlayingState:
            i = self.playlist.mediaCount() - len(e.mimeData().urls())
            self.playlist.setCurrentIndex(i)
            self.player.play()

    def open_file(self):
        path, _ = QFileDialog.getOpenFileName(
            self, "Open file", "",
            "mp3 Audio (*.mp3);mp4 Video (*.mp4);Movie files (*.mov);All files (*.*)"
        )

        if path:
            self.playlist.addMedia(QMediaContent(QUrl.fromLocalFile(path)))

        self.model.layoutChanged.emit()

    def update_duration(self, duration):
        print("!", duration)
        print("?", self.player.duration())

        self.timeSlider.setMaximum(duration)

        if duration >= 0:
            self.totalTimeLabel.setText(hhmmss(duration))

    def update_position(self, position):
        if position >= 0:
            self.currentTimeLabel.setText(hhmmss(position))

        # Disable the events to prevent updating triggering a setPosition event (can cause stuttering).
        self.timeSlider.blockSignals(True)
        self.timeSlider.setValue(position)
        self.timeSlider.blockSignals(False)

    def playlist_selection_changed(self, ix):
        # We receive a QItemSelection from selectionChanged.
        i = ix.indexes()[0].row()
        self.playlist.setCurrentIndex(i)

    def playlist_position_changed(self, i):
        if i > -1:
            ix = self.model.index(i)
            self.playListView.setCurrentIndex(ix)
            # self.playlistView.setCurrentIndex(ix)

    def erroralert(self, *args):
        print(args)
Ejemplo n.º 15
0
class GameWindow(QWidget):
    def __init__(self, parent=None):
        super(GameWindow,self).__init__(parent)

        self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.VideoSurface)
        self.videoWidget = QVideoWidget()

        self.mediaPlayer.setVideoOutput(self.videoWidget)

        self.stringLabel = QLabel()
        self.stringLabel.setSizePolicy(QSizePolicy.Preferred,
                                      QSizePolicy.Maximum)
        self.stringLabel.setTextFormat(Qt.RichText)
        self.stringLabel.setAlignment(Qt.AlignHCenter)

        layout = QVBoxLayout()
        layout.addWidget(self.videoWidget)
        layout.addWidget(self.stringLabel)

        self.setLayout(layout)

        self.mediaPlayer.positionChanged.connect(self.positionChanged)

    def openFile(self, fileName):
        if fileName != '':
            self.mediaPlayer.setMedia(QMediaContent(QUrl.fromLocalFile(fileName)))

    def play(self):
        if self.mediaPlayer.state() == QMediaPlayer.PlayingState:
            self.mediaPlayer.pause()
        else:
            self.mediaPlayer.play()

    def playV(self, file, rate, visibility, labelString):
        self.position = 0
        self.startPos = 0
        self.duration = 0
        self.durChanged = False
        self.stopPos = False
        self.openFile(file)
        self.mediaPlayer.setPlaybackRate(rate)
        if visibility:
            self.videoWidget.show()
            self.stringLabel.show()
            self.stringLabel.setText(labelString)
        else:
            self.videoWidget.hide()
            self.stringLabel.show()
            self.stringLabel.setText(labelString)
        self.play()

    def closeEvent(self, event):
        event.ignore()
        self.mediaPlayer.stop()
        super(GameWindow, self).closeEvent(event)

    def positionChanged(self, pos):
        self.position = pos
        if not self.durChanged and self.position > 0:
            self.durationChanged(self.mediaPlayer.duration())
            self.durChanged = True
        if self.startPos > 0 and not self.stopPos and not self.videoWidget.isVisible():
            if self.position > self.startPos + 20000:
                self.play()
                self.stopPos = True

    def durationChanged(self, dur):
        self.duration = dur
        if self.duration > 40000 and not self.videoWidget.isVisible():
            self.startPos = random.randint(5000, self.duration - 25000)
            self.mediaPlayer.setPosition(self.startPos)

    def showPoints(self, pointsString):
        self.videoWidget.hide()
        self.stringLabel.show()
        self.stringLabel.setText(pointsString)
Ejemplo n.º 16
0
class MusicPlayer(QMainWindow):
    """MusicPlayer houses all of elements that directly interact with the main window."""

    def __init__(self, parent=None):
        """Initialize the QMainWindow widget.

        The window title, window icon, and window size are initialized here as well
        as the following widgets: QMediaPlayer, QMediaPlaylist, QMediaContent, QMenuBar,
        QToolBar, QLabel, QPixmap, QSlider, QDockWidget, QListWidget, QWidget, and
        QVBoxLayout. The connect signals for relavant widgets are also initialized.
        """
        super(MusicPlayer, self).__init__(parent)
        self.setWindowTitle('Mosaic')

        window_icon = utilities.resource_filename('mosaic.images', 'icon.png')
        self.setWindowIcon(QIcon(window_icon))
        self.resize(defaults.Settings().window_size, defaults.Settings().window_size + 63)

        # Initiates Qt objects to be used by MusicPlayer
        self.player = QMediaPlayer()
        self.playlist = QMediaPlaylist()
        self.playlist_location = defaults.Settings().playlist_path
        self.content = QMediaContent()
        self.menu = self.menuBar()
        self.toolbar = QToolBar()
        self.art = QLabel()
        self.pixmap = QPixmap()
        self.slider = QSlider(Qt.Horizontal)
        self.duration_label = QLabel()
        self.playlist_dock = QDockWidget('Playlist', self)
        self.library_dock = QDockWidget('Media Library', self)
        self.playlist_view = QListWidget()
        self.library_view = library.MediaLibraryView()
        self.library_model = library.MediaLibraryModel()
        self.preferences = configuration.PreferencesDialog()
        self.widget = QWidget()
        self.layout = QVBoxLayout(self.widget)
        self.duration = 0
        self.playlist_dock_state = None
        self.library_dock_state = None

        # Sets QWidget() as the central widget of the main window
        self.setCentralWidget(self.widget)
        self.layout.setContentsMargins(0, 0, 0, 0)
        self.art.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored)

        # Initiates the playlist dock widget and the library dock widget
        self.addDockWidget(defaults.Settings().dock_position, self.playlist_dock)
        self.playlist_dock.setWidget(self.playlist_view)
        self.playlist_dock.setVisible(defaults.Settings().playlist_on_start)
        self.playlist_dock.setFeatures(QDockWidget.DockWidgetClosable)

        self.addDockWidget(defaults.Settings().dock_position, self.library_dock)
        self.library_dock.setWidget(self.library_view)
        self.library_dock.setVisible(defaults.Settings().media_library_on_start)
        self.library_dock.setFeatures(QDockWidget.DockWidgetClosable)
        self.tabifyDockWidget(self.playlist_dock, self.library_dock)

        # Sets the range of the playback slider and sets the playback mode as looping
        self.slider.setRange(0, self.player.duration() / 1000)
        self.playlist.setPlaybackMode(QMediaPlaylist.Sequential)

        # OSX system menu bar causes conflicts with PyQt5 menu bar
        if sys.platform == 'darwin':
            self.menu.setNativeMenuBar(False)

        # Initiates Settings in the defaults module to give access to settings.toml
        defaults.Settings()

        # Signals that connect to other methods when they're called
        self.player.metaDataChanged.connect(self.display_meta_data)
        self.slider.sliderMoved.connect(self.seek)
        self.player.durationChanged.connect(self.song_duration)
        self.player.positionChanged.connect(self.song_position)
        self.player.stateChanged.connect(self.set_state)
        self.playlist_view.itemActivated.connect(self.activate_playlist_item)
        self.library_view.activated.connect(self.open_media_library)
        self.playlist.currentIndexChanged.connect(self.change_index)
        self.playlist.mediaInserted.connect(self.initialize_playlist)
        self.playlist_dock.visibilityChanged.connect(self.dock_visiblity_change)
        self.library_dock.visibilityChanged.connect(self.dock_visiblity_change)
        self.preferences.dialog_media_library.media_library_line.textChanged.connect(self.change_media_library_path)
        self.preferences.dialog_view_options.dropdown_box.currentIndexChanged.connect(self.change_window_size)
        self.art.mousePressEvent = self.press_playback

        # Creating the menu controls, media controls, and window size of the music player
        self.menu_controls()
        self.media_controls()
        self.load_saved_playlist()

    def menu_controls(self):
        """Initiate the menu bar and add it to the QMainWindow widget."""
        self.file = self.menu.addMenu('File')
        self.edit = self.menu.addMenu('Edit')
        self.playback = self.menu.addMenu('Playback')
        self.view = self.menu.addMenu('View')
        self.help_ = self.menu.addMenu('Help')

        self.file_menu()
        self.edit_menu()
        self.playback_menu()
        self.view_menu()
        self.help_menu()

    def media_controls(self):
        """Create the bottom toolbar and controls used for media playback."""
        self.addToolBar(Qt.BottomToolBarArea, self.toolbar)
        self.toolbar.setMovable(False)

        play_icon = utilities.resource_filename('mosaic.images', 'md_play.png')
        self.play_action = QAction(QIcon(play_icon), 'Play', self)
        self.play_action.triggered.connect(self.player.play)

        stop_icon = utilities.resource_filename('mosaic.images', 'md_stop.png')
        self.stop_action = QAction(QIcon(stop_icon), 'Stop', self)
        self.stop_action.triggered.connect(self.player.stop)

        previous_icon = utilities.resource_filename('mosaic.images', 'md_previous.png')
        self.previous_action = QAction(QIcon(previous_icon), 'Previous', self)
        self.previous_action.triggered.connect(self.previous)

        next_icon = utilities.resource_filename('mosaic.images', 'md_next.png')
        self.next_action = QAction(QIcon(next_icon), 'Next', self)
        self.next_action.triggered.connect(self.playlist.next)

        repeat_icon = utilities.resource_filename('mosaic.images', 'md_repeat_none.png')
        self.repeat_action = QAction(QIcon(repeat_icon), 'Repeat', self)
        self.repeat_action.setShortcut('R')
        self.repeat_action.triggered.connect(self.repeat_song)

        self.toolbar.addAction(self.play_action)
        self.toolbar.addAction(self.stop_action)
        self.toolbar.addAction(self.previous_action)
        self.toolbar.addAction(self.next_action)
        self.toolbar.addAction(self.repeat_action)
        self.toolbar.addWidget(self.slider)
        self.toolbar.addWidget(self.duration_label)

    def file_menu(self):
        """Add a file menu to the menu bar.

        The file menu houses the Open File, Open Multiple Files, Open Playlist,
        Open Directory, and Exit Application menu items.
        """
        self.open_action = QAction('Open File', self)
        self.open_action.setShortcut('O')
        self.open_action.triggered.connect(self.open_file)

        self.open_multiple_files_action = QAction('Open Multiple Files', self)
        self.open_multiple_files_action.setShortcut('M')
        self.open_multiple_files_action.triggered.connect(self.open_multiple_files)

        self.open_playlist_action = QAction('Open Playlist', self)
        self.open_playlist_action.setShortcut('CTRL+P')
        self.open_playlist_action.triggered.connect(self.open_playlist)

        self.open_directory_action = QAction('Open Directory', self)
        self.open_directory_action.setShortcut('D')
        self.open_directory_action.triggered.connect(self.open_directory)

        self.save_playlist_action = QAction('Save Playlist', self)
        self.save_playlist_action.setShortcut('CTRL+S')
        self.save_playlist_action.triggered.connect(self.save_playlist)

        self.exit_action = QAction('Quit', self)
        self.exit_action.setShortcut('CTRL+Q')
        self.exit_action.triggered.connect(self.closeEvent)

        self.file.addAction(self.open_action)
        self.file.addAction(self.open_multiple_files_action)
        self.file.addAction(self.open_playlist_action)
        self.file.addAction(self.open_directory_action)
        self.file.addSeparator()
        self.file.addAction(self.save_playlist_action)
        self.file.addSeparator()
        self.file.addAction(self.exit_action)

    def edit_menu(self):
        """Add an edit menu to the menu bar.

        The edit menu houses the preferences item that opens a preferences dialog
        that allows the user to customize features of the music player.
        """
        self.preferences_action = QAction('Preferences', self)
        self.preferences_action.setShortcut('CTRL+SHIFT+P')
        self.preferences_action.triggered.connect(lambda: self.preferences.exec_())

        self.edit.addAction(self.preferences_action)

    def playback_menu(self):
        """Add a playback menu to the menu bar.

        The playback menu houses
        """
        self.play_playback_action = QAction('Play', self)
        self.play_playback_action.setShortcut('P')
        self.play_playback_action.triggered.connect(self.player.play)

        self.stop_playback_action = QAction('Stop', self)
        self.stop_playback_action.setShortcut('S')
        self.stop_playback_action.triggered.connect(self.player.stop)

        self.previous_playback_action = QAction('Previous', self)
        self.previous_playback_action.setShortcut('B')
        self.previous_playback_action.triggered.connect(self.previous)

        self.next_playback_action = QAction('Next', self)
        self.next_playback_action.setShortcut('N')
        self.next_playback_action.triggered.connect(self.playlist.next)

        self.playback.addAction(self.play_playback_action)
        self.playback.addAction(self.stop_playback_action)
        self.playback.addAction(self.previous_playback_action)
        self.playback.addAction(self.next_playback_action)

    def view_menu(self):
        """Add a view menu to the menu bar.

        The view menu houses the Playlist, Media Library, Minimalist View, and Media
        Information menu items. The Playlist item toggles the playlist dock into and
        out of view. The Media Library items toggles the media library dock into and
        out of view. The Minimalist View item resizes the window and shows only the
        menu bar and player controls. The Media Information item opens a dialog that
        shows information relevant to the currently playing song.
        """
        self.dock_action = self.playlist_dock.toggleViewAction()
        self.dock_action.setShortcut('CTRL+ALT+P')

        self.library_dock_action = self.library_dock.toggleViewAction()
        self.library_dock_action.setShortcut('CTRL+ALT+L')

        self.minimalist_view_action = QAction('Minimalist View', self)
        self.minimalist_view_action.setShortcut('CTRL+ALT+M')
        self.minimalist_view_action.setCheckable(True)
        self.minimalist_view_action.triggered.connect(self.minimalist_view)

        self.view_media_info_action = QAction('Media Information', self)
        self.view_media_info_action.setShortcut('CTRL+SHIFT+M')
        self.view_media_info_action.triggered.connect(self.media_information_dialog)

        self.view.addAction(self.dock_action)
        self.view.addAction(self.library_dock_action)
        self.view.addSeparator()
        self.view.addAction(self.minimalist_view_action)
        self.view.addSeparator()
        self.view.addAction(self.view_media_info_action)

    def help_menu(self):
        """Add a help menu to the menu bar.

        The help menu houses the about dialog that shows the user information
        related to the application.
        """
        self.about_action = QAction('About', self)
        self.about_action.setShortcut('H')
        self.about_action.triggered.connect(lambda: about.AboutDialog().exec_())

        self.help_.addAction(self.about_action)

    def open_file(self):
        """Open the selected file and add it to a new playlist."""
        filename, success = QFileDialog.getOpenFileName(self, 'Open File', '', 'Audio (*.mp3 *.flac)', '', QFileDialog.ReadOnly)

        if success:
            file_info = QFileInfo(filename).fileName()
            playlist_item = QListWidgetItem(file_info)
            self.playlist.clear()
            self.playlist_view.clear()
            self.playlist.addMedia(QMediaContent(QUrl().fromLocalFile(filename)))
            self.player.setPlaylist(self.playlist)
            playlist_item.setToolTip(file_info)
            self.playlist_view.addItem(playlist_item)
            self.playlist_view.setCurrentRow(0)
            self.player.play()

    def open_multiple_files(self):
        """Open the selected files and add them to a new playlist."""
        filenames, success = QFileDialog.getOpenFileNames(self, 'Open Multiple Files', '', 'Audio (*.mp3 *.flac)', '', QFileDialog.ReadOnly)

        if success:
            self.playlist.clear()
            self.playlist_view.clear()
            for file in natsort.natsorted(filenames, alg=natsort.ns.PATH):
                file_info = QFileInfo(file).fileName()
                playlist_item = QListWidgetItem(file_info)
                self.playlist.addMedia(QMediaContent(QUrl().fromLocalFile(file)))
                self.player.setPlaylist(self.playlist)
                playlist_item.setToolTip(file_info)
                self.playlist_view.addItem(playlist_item)
                self.playlist_view.setCurrentRow(0)
                self.player.play()

    def open_playlist(self):
        """Load an M3U or PLS file into a new playlist."""
        playlist, success = QFileDialog.getOpenFileName(self, 'Open Playlist', '', 'Playlist (*.m3u *.pls)', '', QFileDialog.ReadOnly)

        if success:
            playlist = QUrl.fromLocalFile(playlist)
            self.playlist.clear()
            self.playlist_view.clear()
            self.playlist.load(playlist)
            self.player.setPlaylist(self.playlist)

            for song_index in range(self.playlist.mediaCount()):
                file_info = self.playlist.media(song_index).canonicalUrl().fileName()
                playlist_item = QListWidgetItem(file_info)
                playlist_item.setToolTip(file_info)
                self.playlist_view.addItem(playlist_item)

            self.playlist_view.setCurrentRow(0)
            self.player.play()

    def save_playlist(self):
        """Save the media in the playlist dock as a new M3U playlist."""
        playlist, success = QFileDialog.getSaveFileName(self, 'Save Playlist', '', 'Playlist (*.m3u)', '')
        if success:
            saved_playlist = "{}.m3u" .format(playlist)
            self.playlist.save(QUrl().fromLocalFile(saved_playlist), "m3u")

    def load_saved_playlist(self):
        """Load the saved playlist if user setting permits."""
        saved_playlist = "{}/.m3u" .format(self.playlist_location)
        if os.path.exists(saved_playlist):
            playlist = QUrl().fromLocalFile(saved_playlist)
            self.playlist.load(playlist)
            self.player.setPlaylist(self.playlist)

            for song_index in range(self.playlist.mediaCount()):
                file_info = self.playlist.media(song_index).canonicalUrl().fileName()
                playlist_item = QListWidgetItem(file_info)
                playlist_item.setToolTip(file_info)
                self.playlist_view.addItem(playlist_item)

            self.playlist_view.setCurrentRow(0)

    def open_directory(self):
        """Open the selected directory and add the files within to an empty playlist."""
        directory = QFileDialog.getExistingDirectory(self, 'Open Directory', '', QFileDialog.ReadOnly)

        if directory:
            self.playlist.clear()
            self.playlist_view.clear()
            for dirpath, __, files in os.walk(directory):
                for filename in natsort.natsorted(files, alg=natsort.ns.PATH):
                    file = os.path.join(dirpath, filename)
                    if filename.endswith(('mp3', 'flac')):
                        self.playlist.addMedia(QMediaContent(QUrl().fromLocalFile(file)))
                        playlist_item = QListWidgetItem(filename)
                        playlist_item.setToolTip(filename)
                        self.playlist_view.addItem(playlist_item)

            self.player.setPlaylist(self.playlist)
            self.playlist_view.setCurrentRow(0)
            self.player.play()

    def open_media_library(self, index):
        """Open a directory or file from the media library into an empty playlist."""
        self.playlist.clear()
        self.playlist_view.clear()

        if self.library_model.fileName(index).endswith(('mp3', 'flac')):
            self.playlist.addMedia(QMediaContent(QUrl().fromLocalFile(self.library_model.filePath(index))))
            self.playlist_view.addItem(self.library_model.fileName(index))

        elif self.library_model.isDir(index):
            directory = self.library_model.filePath(index)
            for dirpath, __, files in os.walk(directory):
                for filename in natsort.natsorted(files, alg=natsort.ns.PATH):
                    file = os.path.join(dirpath, filename)
                    if filename.endswith(('mp3', 'flac')):
                        self.playlist.addMedia(QMediaContent(QUrl().fromLocalFile(file)))
                        playlist_item = QListWidgetItem(filename)
                        playlist_item.setToolTip(filename)
                        self.playlist_view.addItem(playlist_item)

        self.player.setPlaylist(self.playlist)
        self.player.play()

    def display_meta_data(self):
        """Display the current song's metadata in the main window.

        If the current song contains metadata, its cover art is extracted and shown in
        the main window while the track number, artist, album, and track title are shown
        in the window title.
        """
        if self.player.isMetaDataAvailable():
            file_path = self.player.currentMedia().canonicalUrl().toLocalFile()
            (album, artist, title, track_number, *__, artwork) = metadata.metadata(file_path)

            try:
                self.pixmap.loadFromData(artwork)
            except TypeError:
                self.pixmap = QPixmap(artwork)

            meta_data = '{} - {} - {} - {}' .format(track_number, artist, album, title)

            self.setWindowTitle(meta_data)
            self.art.setScaledContents(True)
            self.art.setPixmap(self.pixmap)
            self.layout.addWidget(self.art)

    def initialize_playlist(self, start):
        """Display playlist and reset playback mode when media inserted into playlist."""
        if start == 0:
            if self.library_dock.isVisible():
                self.playlist_dock.setVisible(True)
                self.playlist_dock.show()
                self.playlist_dock.raise_()

            if self.playlist.playbackMode() != QMediaPlaylist.Sequential:
                self.playlist.setPlaybackMode(QMediaPlaylist.Sequential)
                repeat_icon = utilities.resource_filename('mosaic.images', 'md_repeat_none.png')
                self.repeat_action.setIcon(QIcon(repeat_icon))

    def press_playback(self, event):
        """Change the playback of the player on cover art mouse event.

        When the cover art is clicked, the player will play the media if the player is
        either paused or stopped. If the media is playing, the media is set
        to pause.
        """
        if event.button() == 1 and configuration.Playback().cover_art_playback.isChecked():
            if (self.player.state() == QMediaPlayer.StoppedState or
                    self.player.state() == QMediaPlayer.PausedState):
                self.player.play()
            elif self.player.state() == QMediaPlayer.PlayingState:
                self.player.pause()

    def seek(self, seconds):
        """Set the position of the song to the position dragged to by the user."""
        self.player.setPosition(seconds * 1000)

    def song_duration(self, duration):
        """Set the slider to the duration of the currently played media."""
        duration /= 1000
        self.duration = duration
        self.slider.setMaximum(duration)

    def song_position(self, progress):
        """Move the horizontal slider in sync with the duration of the song.

        The progress is relayed to update_duration() in order
        to display the time label next to the slider.
        """
        progress /= 1000

        if not self.slider.isSliderDown():
            self.slider.setValue(progress)

        self.update_duration(progress)

    def update_duration(self, current_duration):
        """Calculate the time played and the length of the song.

        Both of these times are sent to duration_label() in order to display the
        times on the toolbar.
        """
        duration = self.duration

        if current_duration or duration:
            time_played = QTime((current_duration / 3600) % 60, (current_duration / 60) % 60,
                                (current_duration % 60), (current_duration * 1000) % 1000)
            song_length = QTime((duration / 3600) % 60, (duration / 60) % 60, (duration % 60),
                                (duration * 1000) % 1000)

            if duration > 3600:
                time_format = "hh:mm:ss"
            else:
                time_format = "mm:ss"

            time_display = "{} / {}" .format(time_played.toString(time_format), song_length.toString(time_format))

        else:
            time_display = ""

        self.duration_label.setText(time_display)

    def set_state(self, state):
        """Change the icon in the toolbar in relation to the state of the player.

        The play icon changes to the pause icon when a song is playing and
        the pause icon changes back to the play icon when either paused or
        stopped.
        """
        if self.player.state() == QMediaPlayer.PlayingState:
            pause_icon = utilities.resource_filename('mosaic.images', 'md_pause.png')
            self.play_action.setIcon(QIcon(pause_icon))
            self.play_action.triggered.connect(self.player.pause)

        elif (self.player.state() == QMediaPlayer.PausedState or self.player.state() == QMediaPlayer.StoppedState):
            self.play_action.triggered.connect(self.player.play)
            play_icon = utilities.resource_filename('mosaic.images', 'md_play.png')
            self.play_action.setIcon(QIcon(play_icon))

    def previous(self):
        """Move to the previous song in the playlist.

        Moves to the previous song in the playlist if the current song is less
        than five seconds in. Otherwise, restarts the current song.
        """
        if self.player.position() <= 5000:
            self.playlist.previous()
        else:
            self.player.setPosition(0)

    def repeat_song(self):
        """Set the current media to repeat and change the repeat icon accordingly.

        There are four playback modes: repeat none, repeat all, repeat once, and shuffle.
        Clicking the repeat button cycles through each playback mode.
        """
        if self.playlist.playbackMode() == QMediaPlaylist.Sequential:
            self.playlist.setPlaybackMode(QMediaPlaylist.Loop)
            repeat_on_icon = utilities.resource_filename('mosaic.images', 'md_repeat_all.png')
            self.repeat_action.setIcon(QIcon(repeat_on_icon))

        elif self.playlist.playbackMode() == QMediaPlaylist.Loop:
            self.playlist.setPlaybackMode(QMediaPlaylist.CurrentItemInLoop)
            repeat_on_icon = utilities.resource_filename('mosaic.images', 'md_repeat_once.png')
            self.repeat_action.setIcon(QIcon(repeat_on_icon))

        elif self.playlist.playbackMode() == QMediaPlaylist.CurrentItemInLoop:
            self.playlist.setPlaybackMode(QMediaPlaylist.Random)
            repeat_icon = utilities.resource_filename('mosaic.images', 'md_shuffle.png')
            self.repeat_action.setIcon(QIcon(repeat_icon))

        elif self.playlist.playbackMode() == QMediaPlaylist.Random:
            self.playlist.setPlaybackMode(QMediaPlaylist.Sequential)
            repeat_icon = utilities.resource_filename('mosaic.images', 'md_repeat_none.png')
            self.repeat_action.setIcon(QIcon(repeat_icon))

    def activate_playlist_item(self, item):
        """Set the active media to the playlist item dobule-clicked on by the user."""
        current_index = self.playlist_view.row(item)
        if self.playlist.currentIndex() != current_index:
            self.playlist.setCurrentIndex(current_index)

        if self.player.state() != QMediaPlayer.PlayingState:
            self.player.play()

    def change_index(self, row):
        """Highlight the row in the playlist of the active media."""
        self.playlist_view.setCurrentRow(row)

    def minimalist_view(self):
        """Resize the window to only show the menu bar and audio controls."""
        if self.minimalist_view_action.isChecked():

            if self.playlist_dock.isVisible():
                self.playlist_dock_state = True
            if self.library_dock.isVisible():
                self.library_dock_state = True

            self.library_dock.close()
            self.playlist_dock.close()

            QTimer.singleShot(10, lambda: self.resize(500, 0))

        else:
            self.resize(defaults.Settings().window_size, defaults.Settings().window_size + 63)

            if self.library_dock_state:
                self.library_dock.setVisible(True)

            if self.playlist_dock_state:
                self.playlist_dock.setVisible(True)

    def dock_visiblity_change(self, visible):
        """Change the size of the main window when the docks are toggled."""
        if visible and self.playlist_dock.isVisible() and not self.library_dock.isVisible():
            self.resize(defaults.Settings().window_size + self.playlist_dock.width() + 6,
                        self.height())

        elif visible and not self.playlist_dock.isVisible() and self.library_dock.isVisible():
            self.resize(defaults.Settings().window_size + self.library_dock.width() + 6,
                        self.height())

        elif visible and self.playlist_dock.isVisible() and self.library_dock.isVisible():
            self.resize(defaults.Settings().window_size + self.library_dock.width() + 6,
                        self.height())

        elif (not visible and not self.playlist_dock.isVisible() and not
                self.library_dock.isVisible()):
            self.resize(defaults.Settings().window_size, defaults.Settings().window_size + 63)

    def media_information_dialog(self):
        """Show a dialog of the current song's metadata."""
        if self.player.isMetaDataAvailable():
            file_path = self.player.currentMedia().canonicalUrl().toLocalFile()
        else:
            file_path = None
        dialog = information.InformationDialog(file_path)
        dialog.exec_()

    def change_window_size(self):
        """Change the window size of the music player."""
        self.playlist_dock.close()
        self.library_dock.close()
        self.resize(defaults.Settings().window_size, defaults.Settings().window_size + 63)

    def change_media_library_path(self, path):
        """Change the media library path to the new path selected in the preferences dialog."""
        self.library_model.setRootPath(path)
        self.library_view.setModel(self.library_model)
        self.library_view.setRootIndex(self.library_model.index(path))

    def closeEvent(self, event):
        """Override the PyQt close event in order to handle save playlist on close."""
        playlist = "{}/.m3u" .format(self.playlist_location)
        if defaults.Settings().save_playlist_on_close:
            self.playlist.save(QUrl().fromLocalFile(playlist), "m3u")
        else:
            if os.path.exists(playlist):
                os.remove(playlist)
        QApplication.quit()
Ejemplo n.º 17
0
class jaabaGUI(QMainWindow):
    """ controller for the blob labeling GUI"""

    def __init__(self,parent=None):
        self.debugMode = True
        self.debugVideoPath = '/Users/071cht/Desktop/Lab/jaabagui/testt.mjpeg.avi'

        QMainWindow.__init__(self,parent)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        self.installEventFilter(self)
        self.setFocusPolicy(Qt.StrongFocus)
        #add new slider
        # self.positionSlider=QSlider(Qt.Horizontal)
        # self.positionSlider.setGeometry (800,800,100,30)
        # self.positionSlider.setRange(0, 0)
        # self.positionSlider.sliderMoved.connect(self.setPosition)

        #setup Video
        #video player
        self.mediaPlayer1 = QMediaPlayer(None, QMediaPlayer.VideoSurface)
        self.mediaPlayer2 = QMediaPlayer(None, QMediaPlayer.VideoSurface)
        self.mediaPlayer2.setNotifyInterval(10)
        #self.mediaPlayer.metaDataChanged.connect(self.metaDataChanged)
        self.mediaPlayer1.durationChanged.connect(self.durationChanged)
        self.mediaPlayer1.positionChanged.connect(self.positionChanged)
        self.mediaPlayer2.positionChanged.connect(self.positionChanged)
        #self.mediaPlayer2.positionChanged.connect(self.paintEvent)
        

        #visualizetion
        self.scene = QGraphicsScene()
        self.ui.graphicsView.setScene(self.scene)
        #self.scene.setBackgroundBrush(Qt.black)
        self.videoItem1 = QGraphicsVideoItem()
        self.videoItem2 = Video()
        self.scene.addItem(self.videoItem1)
        self.scene.addItem(self.videoItem2)
        self.mediaPlayer1.setVideoOutput(self.videoItem1)
        self.mediaPlayer2.setVideoOutput(self.videoItem2)

       

        #slider bar
        self.ui.horizontalSlider.setRange(0, 0)
        self.ui.horizontalSlider.sliderMoved.connect(self.setPosition)
        # self.ui.horizontalSlider.sliderPressed.connect(self.sliderPressed)

        #draw on video
        self.flyCanvas= TargetView()
        self.scene.addItem(self.flyCanvas)
        #give reference to target view
        self.flyCanvas.setWindowReference(self)

        #lineEdit signals:
        self.ui.lineEdit.returnPressed.connect(self.lineEditChanged)



        #callbacks
        self.ui.actionQuit.triggered.connect(self.quit)
        self.ui.actionLoad_Project.triggered.connect(self.loadVideo)
        self.ui.actionImport_Labels.triggered.connect(self.loadLabels)
        #self.ui.buttonPlay.clicked[bool].connect(self.setToggleText)
        self.ui.buttonPlay.clicked.connect(self.play)
        self.ui.actionSave.triggered.connect(self.saveLabels)
        ## print self.ui.graphicsView.sizeHint()

        #behavior Button
        self.ui.buttonBehavior.clicked.connect(self.behaviorButtonClick)
        self.ui.buttonNone.clicked.connect(self.noneButtonClick)

        #initialization
        self.loaded = False
        self.videoFilename = None
        self.frame_count=None
        self.width=None
        self.height=None
        self.frame_trans=None
        self.previous_frame=0
        self.current_frame=0
        self.behaviorButtonStart = False
        self.noneButtonStart = False
        self.currentFly=1

        #initialize flyInfo
        #self.setCurrentFly(self.currentFly)

        # register flyid changed callback
        self.flyCanvas.onCurrentFlyIdChanged(self.currentFlyIdChangedCallback)
        self.flyCanvas.setCurrentFlyId(self.currentFly)

        # when double click on video, change fly id in target view
        self.videoItem2.onDoubleClick(self.flyCanvas.setCurrentFlyIdByXY)

        ########################
        # DEBUG PART HERE!!!!! #
        ########################
        if (self.debugMode):
            self.debugLoadVideo()

    # add label UI related when load video   
    def showEvent(self, evt):
        super(jaabaGUI, self).showEvent(evt)
        ##### HERE THE WINDOW IS LOADED!!!!!!!!
        # self.loadLabelUI()

    def loadLabelUI(self):
         #labels
        self.labelScene = QGraphicsScene()

        self.ui.graphLabels.setScene(self.labelScene)
        # the size is only accurate after the window fully displayed
        labelUIWidth = self.ui.graphLabels.width()
        labelUIHeight = self.ui.graphLabels.height()-1

        self.labelScene.setSceneRect(0,0,labelUIWidth,labelUIHeight)

        
        self.labelUI = LabelUI()
        # visiableWidth = 850
        # height = 30
        # visiableFrameNum = 850

        self.labelUI.setWidthPerFrame(850.0/850.0)
        # print '850/500',850.0/850.0b
        # print 'length_perframe is ', self.labelUI.widthPerFrame 
        # 850 is the original length of graphLabel
        total_length= self.labelUI.widthPerFrame * self.frame_count
        self.labelUI.setVisiableSize(total_length,30)

        # set start position
        self.labelUI.setPos(labelUIWidth/2,0)


        print 'frame_count is ', self.frame_count
        print 'total length is', total_length
        
        self.labelScene.addItem(self.labelUI)

        # middle line ui
        self.labelUIMiddleLine = LabelUIMiddleLine()
        self.labelScene.addItem(self.labelUIMiddleLine)
        self.labelUIMiddleLine.setPos(labelUIWidth/2,0)
       


        # self.labelUI.setPos(QPointF(-100,0))
        self.writeLog('Label UI loaded')

    def eventFilter(self, obj, event):
  
    	if (event.type() == PyQt5.QtCore.QEvent.KeyPress):
    		# http://qt-project.org/doc/qt-4.8/qt.html#Key-enum
    		key = event.key()
    		
    		if (key == Qt.Key_Up) :
    			curr_frame= int(float(self.ui.lineEdit.text()))
    			curr_frame= curr_frame-30
    			media_position= int(round(curr_frame*self.frame_trans))

    			# print curr_frame, media_position
    			self.mediaPlayer1.setPosition(media_position) 
    			self.mediaPlayer2.setPosition(media_position)

    			# print 'down -30'
    		elif (key == Qt.Key_Right):
    			curr_frame= int(float(self.ui.lineEdit.text()))
    			# print 'right +1'
    			# print curr_frame
    			curr_frame= curr_frame+1
    			media_position= int(round(curr_frame*self.frame_trans))
    			# print 'curr_frame',curr_frame
    			# print 'frame_trans',self.frame_trans
    			# print ' curr_frame*self.frame_trans',curr_frame*self.frame_trans
    			# print 'media_position',media_position

    			# print curr_frame, media_position
    			self.mediaPlayer1.setPosition(media_position) 
    			self.mediaPlayer2.setPosition(media_position)
    			# self.mediaPlayerPositionChanged(media_position)
    		elif (key == Qt.Key_Left):
    			curr_frame= int(float(self.ui.lineEdit.text()))
    			curr_frame= curr_frame-1
    			media_position= int(round(curr_frame*self.frame_trans))
    			self.mediaPlayer1.setPosition(media_position) 
    			self.mediaPlayer2.setPosition(media_position)
    			# print 'left -1'
    		elif (key == Qt.Key_Down):
    			curr_frame= int(float(self.ui.lineEdit.text()))
    			curr_frame= curr_frame+30
    			media_position= int(round(curr_frame*self.frame_trans))
    			self.mediaPlayer1.setPosition(media_position) 
    			self.mediaPlayer2.setPosition(media_position)
    			# print 'up +30'
    		return True

    		

    	return False


    # ###actions starts from here###
    def quit(self):
        QApplication.quit()

    def loadVideo(self):
        
        # print QMediaPlayer.supportedMimeTypes()

        self.writeLog("Loading video...")

        self.videoFilename = QFileDialog.getOpenFileName(self, 'Open File', '.')[0]
        if not self.videoFilename:
            self.writeLog("User cancelled - no video loaded")
            return
        else:
       		cap=cv2.VideoCapture(self.videoFilename)
	    	self.frame_count=cap.get(cv2.CAP_PROP_FRAME_COUNT)
	    	self.width=cap.get(3)
	    	self.height=cap.get(4)

	        self.mediaPlayer2.setMedia(QMediaContent(QUrl.fromLocalFile(self.videoFilename )))
	        self.mediaPlayer1.setMedia(QMediaContent(QUrl.fromLocalFile(self.videoFilename )))
	        self.ui.buttonPlay.setEnabled(True)
            # self.mediaPlayer2.setVideoOutput(self.videoItem2)
            # self.mediaPlayer1.setVideoOutput(self.videoItem1)
            # size= self.videoItem2.nativeSize()
            # # print size
            ## print self.mediaPlayer.duration()
          
            ## print self.mediaPlayer.metaData()
        self.writeLog("Video loaded!")

        # init label related ui
        self.loadLabelUI()


    def debugLoadVideo(self):

        self.videoFilename = self.debugVideoPath

        cap=cv2.VideoCapture(self.videoFilename)
        self.frame_count=cap.get(cv2.CAP_PROP_FRAME_COUNT)
        self.width=cap.get(3)
        self.height=cap.get(4)

        self.mediaPlayer2.setMedia(QMediaContent(QUrl.fromLocalFile(self.videoFilename )))
        self.mediaPlayer1.setMedia(QMediaContent(QUrl.fromLocalFile(self.videoFilename )))
        self.ui.buttonPlay.setEnabled(True)
        self.writeLog("Video loaded!")

        QTimer.singleShot(1000, self.loadLabelUI)

    def play(self):
    	
        self.videoItem1.setAspectRatioMode(0)
        self.videoItem2.setAspectRatioMode(0)
        self.scene.setSceneRect(0,0,self.ui.graphicsView.width(),self.ui.graphicsView.height())
        self.videoItem1.setSize(QSizeF(self.ui.graphicsView.width()/2,self.ui.graphicsView.height()))
        self.videoItem2.setSize(QSizeF(self.ui.graphicsView.width()/2,self.ui.graphicsView.height()))
        self.videoItem1.setPos(QPointF(0,0))
        self.videoItem2.setPos(QPointF(self.ui.graphicsView.width()/2,0))
        self.flyCanvas.setPos(QPointF(self.ui.graphicsView.width()/2,0))

        # custom function setXYScale
        self.videoItem2.setXYScale(self.width,self.height,self.ui.graphicsView.width()/2,self.ui.graphicsView.height())
        self.flyCanvas.setXYScale(self.width,self.height,self.ui.graphicsView.width()/2,self.ui.graphicsView.height())




        if self.mediaPlayer1.state() == QMediaPlayer.PlayingState:
        	self.ui.buttonPlay.setIcon(self.ui.style().standardIcon(PyQt5.QtWidgets.QStyle.SP_MediaPlay))
        	self.ui.buttonPlay.setText("Play")
        	self.mediaPlayer1.pause()
        	self.writeLog("Video paused")
        else: 
        	self.ui.buttonPlay.setIcon(self.ui.style().standardIcon(PyQt5.QtWidgets.QStyle.SP_MediaPause))
	        self.ui.buttonPlay.setText("Stop")
	        
	        self.mediaPlayer1.play()
	        self.writeLog("Playing video")

        if self.mediaPlayer2.state() == QMediaPlayer.PlayingState:
            self.mediaPlayer2.pause()
        else: 
            self.mediaPlayer2.play()

    def loadLabels(self):

        self.writeLog("Loading labels from file...")
        self.labelFilename = QFileDialog.getOpenFileName(self, 'Open File', '.')[0]
        self.labelUI.labelData = pickle.load(open(self.labelFilename,"rb"))
        self.writeLog("Label loaded from file:" + self.labelFilename)

    def saveLabels(self):
        # Now it can only save to current file. Will add an poput window to choose path later
        pickle.dump( self.labelUI.labelData, open( "newLabels.p", "wb" ) )
  

    def setPosition(self, position):
    	self.mediaPlayer1.setPosition(position) 
    	self.mediaPlayer2.setPosition(position) 

    # when position of media changed, set slider and text box accordingly.
    def positionChanged(self, position):
        #test change labelui position
        # self.labelUI.startLabel();
        # self.labelUI.update()
        previous_frame=  self.previous_frame
        curr_frame= int(round(position/self.frame_trans))
        self.current_frame=curr_frame
        frame_change= previous_frame-curr_frame
        move_width= frame_change * self.labelUI.widthPerFrame
        self.previous_frame= curr_frame

        self.labelUI.moveBy(move_width,0)

        self.labelUI.setCurrentFrame(curr_frame)
        # enforce labelUI paint once
        self.labelUI.update()
       
        # self.labelUI.setPos(self.labelUI.mapToParent(1,0));
        # self.labelUI.update()

    	# # print 'triggered position'
    	# # print position
    	# # print 'cur position'
    	# # print self.mediaPlayer2.position()
    	self.updateLineEdit(position)
    	self.updateSliderAndGraph(position)
    	
       #  self.ui.horizontalSlider.setValue(position)

       #  if isinstance(self.frame_trans,float):
	      #   # # print type(position),position
	      #   # # print type(self.frame_trans),self.frame_trans 
	      #   # # print position/self.frame_trans
	     	# self.ui.lineEdit.setText(str(int(round(position/self.frame_trans))))
	     	# self.flyCanvas.getFrame(int(round(position/self.frame_trans)))
	     	# self.flyCanvas.isManualCalled = True;
	     	# self.flyCanvas.update()

       #  self.writeLog(str(position))    
       # # self.updateMediaControlUI(position)
       # # self.flyCanvas.update()

    def updateSliderAndGraph(self, position):
    	self.ui.horizontalSlider.setValue(position)
    	if isinstance(self.frame_trans,float):
    		self.flyCanvas.getFrame(int(round(position/self.frame_trans)))
    		self.flyCanvas.isManualCalled = True
    		self.flyCanvas.update()

        #self.writeLog(str(position)) 
    def updateLineEdit(self, position): 
        # # print self.width
        # # print self.height
    	if isinstance(self.frame_trans,float):
	        # # print type(position),position
	        # # print type(self.frame_trans),self.frame_trans 
	        # # print position/self.frame_trans
	     	self.ui.lineEdit.setText(str(int(round(position/self.frame_trans))))

    def durationChanged(self, duration):
	    self.ui.horizontalSlider.setRange(0, duration) 
	    self.frame_trans=self.mediaPlayer1.duration()/self.frame_count
	    ## print self.frame_trans

	#def eventFilter(self,source,event):
		#if (event.type()==PyQt5.QtCore.QEvent.MousePress and source is self.videoItem2):
		# 	pos=event.pos()
		# 	# print('mouse position: (%d,%d)' % (pos.x(),pos.y()))
	 #    return PyQt5.QtGui.QWidget.eventFilter(self, source, event)

    def writeLog(self,text):
        self.ui.log.setText(text)

    # def eventFilter (self.ui.lineEdit,event):
    #     if event.type()==PyQt5.QtCore.QEvent

    def lineEditChanged(self):
    	#set position of media
    	curr_frame= int(float(self.ui.lineEdit.text()))
    	media_position= int(round(curr_frame*self.frame_trans))
    	self.mediaPlayer1.setPosition(media_position) 
    	self.mediaPlayer2.setPosition(media_position)
    	# print 'setPosition'
    	# print media_position
    	# print 'after set'
    	# print self.mediaPlayer2.position()
    	# self.updateSliderAndGraph(media_position)


    def behaviorButtonClick(self):
        # flip flag
        self.behaviorButtonStart = not self.behaviorButtonStart

        # check click to start or stop
        if (self.behaviorButtonStart):
            # start labeling
            self.labelUI.startLabel(self.ui.comboBox.currentIndex(),'',self.current_frame)
            self.writeLog('start labeling')


        else:
            # stop lableing
            self.labelUI.stopLabel()
            self.writeLog('stop labeling')

    def noneButtonClick(self):
           # flip flag
        self.noneButtonStart = not self.noneButtonStart

        # check click to start or stop
        if (self.noneButtonStart):
            # start labeling
            self.labelUI.startLabel(self.ui.comboBox.currentIndex(),'_none',self.current_frame)
            self.writeLog('start labeling')
        else:
            # stop lableing
            self.labelUI.stopLabel()
            self.writeLog('stop labeling')


    # set CurrentFly when fly changed! 
    def setCurrentFly(self,fly):
        self.currentFly = fly
        self.ui.flyInfo.setPlainText('FlyID:' + str(self.currentFly))
        self.flyCanvas.currentFly=fly

    def currentFlyIdChangedCallback(self,fly):
        print 'callback!!!!!';
        self.currentFly = fly
        self.ui.flyInfo.setPlainText('FlyID:' + str(self.currentFly))
Ejemplo n.º 18
0
class VideoWindow(QMainWindow):

    def __init__(self, app, parent=None):
        super(VideoWindow, self).__init__(parent)
        self.app = app
        self.setWindowTitle("sofa")
        self.setWindowIcon(QIcon('src/static/img/tofu.png'))
        self.rate = 1
        self.isNewMark = False
        self.openedFile = None
        self.initUI()
        self.set_default_shortcuts()
        self.shortcuts = {}
        self.comm = SignalBus.instance()

    def initUI(self):
        videoWidget = self.create_player()
        self.errorLabel = QLabel()
        self.errorLabel.setSizePolicy(QSizePolicy.Preferred,
                QSizePolicy.Maximum)
        self.create_menu_bar()
        self.wid = QWidget(self)
        self.setCentralWidget(self.wid)
        self.set_layout(videoWidget, self.wid)
        self.mediaPlayer.setVideoOutput(videoWidget)
        self.mediaPlayer.stateChanged.connect(self.mediaStateChanged)
        self.mediaPlayer.positionChanged.connect(self.positionChanged)
        self.mediaPlayer.durationChanged.connect(self.durationChanged)
        self.mediaPlayer.error.connect(self.handleError)

    def create_player(self):
        self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.VideoSurface)

        videoWidget = QVideoWidget()
        self.clipsWidget = BadClipsWidget()
        self.create_control()

        self.playButton.clicked.connect(self.play)
        self.speedUpButton.clicked.connect(self.speed)
        self.slowDownButton.clicked.connect(self.slow)
        self.adv3Button.clicked.connect(partial(self.advance, 3))
        self.goBack3Button.clicked.connect(partial(self.back, 3))
        self.advanceButton.clicked.connect(partial(self.advance, 10))
        self.goBackButton.clicked.connect(partial(self.back, 10))
        self.positionSlider.sliderMoved.connect(self.setPosition)
        self.cutButton.clicked.connect(self.createMark)

        return videoWidget

    def set_default_shortcuts(self):
        self.playButton.setShortcut(QKeySequence(Qt.Key_Space))
        self.speedUpButton.setShortcut(QKeySequence(Qt.Key_Up))
        self.slowDownButton.setShortcut(QKeySequence(Qt.Key_Down))
        self.advanceButton.setShortcut(QKeySequence(Qt.Key_Right))
        self.goBackButton.setShortcut(QKeySequence(Qt.Key_Left))
        self.cutButton.setShortcut(QKeySequence(Qt.Key_C))

    def create_control(self):
        self.playButton = _create_button(
                self.style().standardIcon(QStyle.SP_MediaPlay))
        self.speedUpButton = _create_button(
                self.style().standardIcon(QStyle.SP_MediaSeekForward))
        self.slowDownButton = _create_button(
                self.style().standardIcon(QStyle.SP_MediaSeekBackward))
        self.adv3Button = _create_button(
                self.style().standardIcon(QStyle.SP_ArrowRight))
        self.advanceButton = _create_button(
                self.style().standardIcon(QStyle.SP_MediaSkipForward))
        self.goBack3Button = _create_button(
                self.style().standardIcon(QStyle.SP_ArrowLeft))
        self.goBackButton = _create_button(
                self.style().standardIcon(QStyle.SP_MediaSkipBackward))
        self.cutButton = _create_button(self.style().standardIcon(
            QStyle.SP_MessageBoxCritical))
        self.timeBox = QLabel(format_time(0), self)
        self.timeBox.setAlignment(Qt.AlignCenter)
        self.rateBox = QLabel(str(self.rate) + 'x', self)
        self.rateBox.setAlignment(Qt.AlignCenter)
        self.hlightSliderTips = HlightSliderTipsWidget()
        self.positionSlider = QSlider(Qt.Horizontal)
        self.positionSlider.setRange(0, 0)

    def create_menu_bar(self):
        openAction = create_action('open.png', '&Open', 'Ctrl+O', 'Open video',
                self.openFile, self)
        saveAction = create_action('save.png', '&Save Clips', 'Ctrl+S',
                'Save anonimized clips', self.saveClips, self)
        exitAction = create_action('exit.png', '&Exit', 'Ctrl+Q', 'Exit',
                self.exitCall, self)

        menuBar = self.menuBar()
        fileMenu = menuBar.addMenu('&File')
        fileMenu.addAction(openAction)
        fileMenu.addAction(saveAction)
        fileMenu.addAction(exitAction)

    def set_layout(self, videoWidget, wid):
        labellingLayout = QVBoxLayout()
        labellingLayout.addWidget(self.clipsWidget)

        controlLayout = self.make_control_layout()

        videoAreaLayout = QVBoxLayout()
        videoWidget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        videoAreaLayout.addWidget(videoWidget)
        videoAreaLayout.addLayout(controlLayout)
        videoAreaLayout.addWidget(self.errorLabel)

        layout = QHBoxLayout()
        layout.addLayout(videoAreaLayout, 4)
        layout.addLayout(labellingLayout)

        wid.setLayout(layout)

    def make_control_layout(self):
        buttonsLayout = QHBoxLayout()
        buttonsLayout.setContentsMargins(0, 0, 0, 0)
        buttonsLayout.addWidget(self.timeBox)
        buttonsLayout.addWidget(self.slowDownButton)
        buttonsLayout.addWidget(self.goBackButton)
        buttonsLayout.addWidget(self.goBack3Button)
        buttonsLayout.addWidget(self.playButton)
        buttonsLayout.addWidget(self.adv3Button)
        buttonsLayout.addWidget(self.advanceButton)
        buttonsLayout.addWidget(self.speedUpButton)
        buttonsLayout.addWidget(self.rateBox)
        cutLayout = QHBoxLayout()
        cutLayout.setContentsMargins(0, 0, 0, 0)
        cutLayout.addSpacerItem(QSpacerItem(200, 5, QSizePolicy.Minimum,
            QSizePolicy.Minimum))
        cutLayout.addWidget(self.cutButton)
        cutLayout.addSpacerItem(QSpacerItem(200, 5, QSizePolicy.Minimum,
            QSizePolicy.Minimum))
        layout = QVBoxLayout()
        layout.setContentsMargins(0, 0, 0, 0)
        layout.addWidget(self.positionSlider)
        layout.addWidget(self.hlightSliderTips)
        layout.addLayout(buttonsLayout)
        layout.addLayout(cutLayout)
        return layout

    def openFile(self):
        self.rawFileName, _ = QFileDialog.getOpenFileName(self, "Open video",
                QDir.homePath())
        if self.rawFileName != '':
            should_process = QMessageBox.question(self.wid, 'Open video',
                    'Do you want to pre process the video?',
                    QMessageBox.Yes | QMessageBox.No)
            if should_process == QMessageBox.Yes:
                self.fileName = TMP_VIDEO_PATH
                process = ProcVideoDialog(self.rawFileName, self.fileName, self)
                self.comm.videoProcessed.connect(self.openMedia)
            else:
                self.fileName = self.rawFileName
                self.processMetaData()
                self.openMedia()


    def processMetaData(self):
        '''
        Get array indicating "suspicious" frames
        '''
        # open metadata file
        self.metaDataFile = self.fileName.rsplit(".", 1)[0] + ".csv"
        # get only the array with "colors" (==0: green; !=0: red)
        self.colorsArray = get_metadata_colors(self.metaDataFile)
        self.hlightSliderTips.setColorsArray(self.colorsArray, useYellow=False)


    @pyqtSlot()
    def openMedia(self):
        self.mediaPlayer.setMedia(
                QMediaContent(QUrl.fromLocalFile(self.fileName)))
        self.openedFile = os.path.basename(self.fileName)
        self.setWindowTitle("sofa - " + self.openedFile)
        self.playButton.setEnabled(True)
        self.speedUpButton.setEnabled(True)
        self.slowDownButton.setEnabled(True)
        self.advanceButton.setEnabled(True)
        self.adv3Button.setEnabled(True)
        self.goBackButton.setEnabled(True)
        self.goBack3Button.setEnabled(True)
        self.cutButton.setEnabled(True)
        self.rate = 1

    def exitCall(self):
        if self.openedFile is not None:
            os.remove(self.fileName)
        sys.exit(self.app.exec_())

    def play(self):
        if self.mediaPlayer.state() == QMediaPlayer.PlayingState:
            self.mediaPlayer.pause()
        else:
            self.mediaPlayer.play()

    def slow(self):
        if self.mediaPlayer.state() == QMediaPlayer.PlayingState:
            self.rate -= 0.5
            # TODO: Workaround pt 1
            # https://forum.qt.io/topic/88490/change-playback-rate-at-...
            # ...runtime-problem-with-position-qmediaplayer/8
            currentPos = self.mediaPlayer.position()
            # TODO: Workaround pt 1
            self.mediaPlayer.setPlaybackRate(self.rate)
            # TODO: Workaround pt 2
            self.mediaPlayer.setPosition(currentPos)
            # TODO: Workaround pt 2: end
            self.rateBox.setText(str(self.rate)+'x')

    def speed(self):
        if self.mediaPlayer.state() == QMediaPlayer.PlayingState:
            self.rate += 0.5
            # TODO: Workaround pt 1
            # https://forum.qt.io/topic/88490/change-playback-rate-at-...
            # ...runtime-problem-with-position-qmediaplayer/8
            currentPos = self.mediaPlayer.position()
            # TODO: Workaround pt 1
            self.mediaPlayer.setPlaybackRate(self.rate)
            # TODO: Workaround pt 2
            self.mediaPlayer.setPosition(currentPos)
            # TODO: Workaround pt 2: end
            self.rateBox.setText(str(self.rate)+'x')

    def advance(self, t=10):
        currentPos = self.mediaPlayer.position()
        nextPos  = currentPos + t*1000
        self.setPosition(nextPos)

    def back(self, t=10):
        currentPos = self.mediaPlayer.position()
        nextPos  = max(currentPos - t*1000, 0)
        self.setPosition(nextPos)

    def mediaStateChanged(self, state):
        if self.mediaPlayer.state() == QMediaPlayer.PlayingState:
            self.playButton.setIcon(
                    self.style().standardIcon(QStyle.SP_MediaPause))
        else:
            self.playButton.setIcon(
                    self.style().standardIcon(QStyle.SP_MediaPlay))

    def positionChanged(self, position):
        self.positionSlider.setValue(position)
        self.hlightSliderTips.setValue(position)
        self.timeBox.setText(format_time(int(position/1000)))

    def durationChanged(self, duration):
        self.positionSlider.setRange(0, duration)
        self.hlightSliderTips.setRange(duration)

    def setPosition(self, position):
        self.mediaPlayer.setPosition(position)

    def handleError(self):
        self.playButton.setEnabled(False)
        self.speedUpButton.setEnabled(False)
        self.slowDownButton.setEnabled(False)
        self.advanceButton.setEnabled(False)
        self.goBackButton.setEnabled(False)
        self.errorLabel.setText("Error: " + self.mediaPlayer.errorString())

    def saveClips(self):
        prefix = os.path.splitext(os.path.basename(self.rawFileName))[0] + \
                '_slice_'
        dirPath = QFileDialog.getExistingDirectory(self, 'Select Dir')
        if dirPath != '':
            try:
                self.errorLabel.setText('Saving clips... please wait')
                video = VideoFileClip(self.fileName)
                marks = self.clipsWidget.get_marks()
                begin_time = 0.0
                for i, m in enumerate(marks):
                    end_time = float(m[0])
                    out_path = os.path.join(dirPath, prefix+str(i)+".mp4")
                    clip = video.subclip(begin_time, end_time)
                    clip.write_videofile(out_path)
                    begin_time = float(m[1])
                end_video = self.mediaPlayer.duration()/1000
                if begin_time < end_video and len(marks) > 0:
                    i = len(marks)
                    out_path = os.path.join(dirPath, prefix+str(i)+".mp4")
                    clip = video.subclip(begin_time)
                    clip.write_videofile(out_path)
                self.errorLabel.setText('Clips saved at ' + dirPath)
                QMessageBox.information(self.wid, 'Sucess',
                        'Clips succesfully saved')
            except:
                self.errorLabel.setText('Error: Could not save file.')
                QMessageBox.warning(self.wid, 'Error',
                        'Could not save file. Check permissions')

    @pyqtSlot()
    def createMark(self):
        state = self.mediaPlayer.state()
        if state == QMediaPlayer.PlayingState or state == \
                QMediaPlayer.PausedState:
            self.clipsWidget.new_mark(self.mediaPlayer.position()/1000,
                    self.isNewMark)
            self.isNewMark = not self.isNewMark
Ejemplo n.º 19
0
class PlaybackPanel(SpecialLabel):
    desktop_lyric_state_changed_signal = pyqtSignal(bool)
    playmode_changed_signal = pyqtSignal(int, int)
    media_player_notify_signal = pyqtSignal(int)
    muted_changed_signal = pyqtSignal(int)
    mark_favorite_completed_signal = pyqtSignal()
    current_media_changed_signal = pyqtSignal()
    music_ended_signal = pyqtSignal()
    update_window_lyric_signal = pyqtSignal(str, str)
    show_artist_info_signal = pyqtSignal(str)
    dont_hide_main_window_signal = pyqtSignal()

    def __init__(self, parent=None):
        super(PlaybackPanel, self).__init__(parent)
        self.initial_mediaplayer()
        self.create_actions()
        self.setup_ui()
        self.create_connections()
        self.initial_params()

    def create_connections(self):
        self.artistHeadLabel.clicked.connect(self.show_artist_info)
        self.desktopLyric.hide_desktop_lyric_signal.connect(
            self.desktop_lyric_closed)
        self.seekSlider.valueChanged.connect(self.slider_value_changed)
        self.seekSlider.sliderPressed.connect(self.slider_pressed)
        self.seekSlider.sliderReleased.connect(self.seek)
        self.mediaPlayer.positionChanged.connect(self.tick)
        self.mediaPlayer.mutedChanged.connect(self.muted_changed_signal.emit)
        self.mediaPlayer.stateChanged.connect(self.state_changed)
        self.mediaPlayer.durationChanged.connect(self.duration_changed)
        self.mediaPlayer.mediaStatusChanged.connect(self.media_status_changed)
        self.mediaPlayer.currentMediaChanged.connect(
            self.current_media_changed)

    def initial_mediaplayer(self):
        self.mediaPlayer = QMediaPlayer()
        self.mediaPlayer.setNotifyInterval(500)
        self.set_volume(globalSettings.Volume)

    def initial_params(self):
        self.playlist = None
        self.artistName = 'Zheng-Yejian'
        self.clickPlayFlag = False  #用来标志一首歌是否是主动点击选中的
        self.timerFlag = False
        self.timeStart = 0
        self.timeSpan = 0
        self.sourcePath = ''
        self.errorType = Configures.NoError
        self.currentSourceRow = -1
        self.nearPlayedSongs = []
        self.downloadDir = globalSettings.DownloadfilesPath
        self.songinfosManager = SonginfosManager()
        self.totalTime = Configures.ZeroTime
        self.playmode = Configures.PlaymodeRandom  #播放模式指示器
        playlistTemp = Playlist()
        playlistTemp.fill_list(Configures.PlaylistFavorite)
        self.lovedSongs = playlistTemp.get_titles()

    def set_playlist(self, playlist):
        self.playlist = playlist
        self.currentSourceRow = self.playlist.get_current_row()

    def create_actions(self):
        self.nextAction = QAction(QIcon(IconsHub.ControlNext),
                                  "下一首",
                                  self,
                                  enabled=True,
                                  triggered=self.next_song)

        self.playAction = QAction(QIcon(IconsHub.ControlPlay),
                                  "播放/暂停",
                                  self,
                                  enabled=True,
                                  triggered=self.play_music)

        self.previousAction = QAction(QIcon(IconsHub.ControlPrevious),
                                      "上一首",
                                      self,
                                      enabled=True,
                                      triggered=self.previous_song)

        self.stopAction = QAction(QIcon(IconsHub.ControlStop),
                                  "停止",
                                  self,
                                  enabled=True,
                                  triggered=self.stop_music_but_timing)

    def get_play_button_action(self):
        return self.playAction

    def get_previous_button_action(self):
        return self.previousAction

    def get_next_button_action(self):
        return self.nextAction

    def get_stop_button_action(self):
        return self.stopAction

    def set_download_dir(self, dir):
        self.downloadDir = dir

    def get_loved_songs(self):
        return self.lovedSongs

    def get_songinfos_manager(self):
        return self.songinfosManager

    def setup_ui(self):
        self.setFixedHeight(50)
        #桌面歌词标签
        self.desktopLyric = desktop_lyric.DesktopLyric()
        self.desktopLyric.set_color(globalSettings.DesktoplyricColors)
        #3个标签
        self.artistHeadLabel = LabelButton()
        self.artistHeadLabel.setToolTip(self.tr('查看歌手信息'))
        self.artistHeadLabel.setFixedSize(QSize(42, 42))
        self.artistHeadLabel.setScaledContents(True)
        self.artistHeadLabel.setPixmap(QPixmap(IconsHub.Anonymous))

        self.musicTitleLabel = NewLabel()
        self.musicTitleLabel.setObjectName('musicTitleLabel')
        self.musicTitleLabel.setFixedSize(QSize(370, 20))
        self.musicTitleLabel.setText("Zheng-Yejian._.XYPLAYER")
        self.timeLabel = QLabel("00:00/00:00")
        self.timeLabel.setObjectName('timeLabel')
        self.timeLabel.setFixedHeight(20)
        self.timeLabel.setAlignment(Qt.AlignRight and Qt.AlignVCenter)

        #五个基本按键
        self.playmodeButton = QToolButton(clicked=self.change_playmode)
        self.playmodeButton.setFocusPolicy(Qt.NoFocus)

        self.playmodeButton.setIcon(QIcon(IconsHub.PlaymodeRandom))
        self.playmodeButton.setIconSize(QSize(25, 25))
        self.playmodeButton.setToolTip('随机播放')

        self.favoriteButton = QToolButton(clicked=self.mark_as_favorite)
        self.favoriteButton.setFocusPolicy(Qt.NoFocus)
        self.favoriteButton.setToolTip('收藏')
        self.favoriteButton.setIcon(QIcon(IconsHub.Favorites))
        self.favoriteButton.setIconSize(QSize(20, 20))

        self.previousButton = QToolButton()
        self.previousButton.setFocusPolicy(Qt.NoFocus)
        self.previousButton.setIconSize(QSize(40, 40))
        self.previousButton.setShortcut(QKeySequence("Ctrl + Left"))
        self.previousButton.setDefaultAction(self.previousAction)

        self.playButton = QToolButton()
        self.playButton.setFocusPolicy(Qt.NoFocus)
        self.playButton.setIconSize(QSize(40, 40))
        self.playButton.setShortcut(QKeySequence("Ctrl + Down"))
        self.playButton.setDefaultAction(self.playAction)

        self.nextButton = QToolButton()
        self.nextButton.setFocusPolicy(Qt.NoFocus)
        self.nextButton.setIconSize(QSize(40, 40))
        self.nextButton.setFocusPolicy(Qt.NoFocus)
        self.nextButton.setShortcut(QKeySequence("Ctrl + Right"))
        self.nextButton.setDefaultAction(self.nextAction)

        self.desktopLyricButton = QToolButton(clicked=self.show_desktop_lyric)
        self.desktopLyricButton.setToolTip(self.tr("桌面歌词"))
        self.desktopLyricButton.setFocusPolicy(Qt.NoFocus)
        self.desktopLyricButton.setIcon(QIcon(IconsHub.DesktopLyric))
        self.desktopLyricButton.setIconSize(QSize(25, 25))

        self.seekSlider = QSlider(Qt.Horizontal)
        self.seekSlider.setObjectName('seekSlider')
        self.seekSlider.setFixedHeight(20)
        self.seekSlider.setFocusPolicy(Qt.NoFocus)
        self.seekSlider.setRange(0, 0)

        hbox1 = QHBoxLayout()
        hbox1.addWidget(self.favoriteButton)
        hbox1.addWidget(self.musicTitleLabel)
        hbox1.addStretch()
        hbox1.addWidget(self.timeLabel)
        vbox1 = QVBoxLayout()
        vbox1.addLayout(hbox1)
        vbox1.setSpacing(5)
        vbox1.addWidget(self.seekSlider)

        mainLayout = QHBoxLayout(self)
        mainLayout.setContentsMargins(2, 0, 0, 0)
        mainLayout.addWidget(self.artistHeadLabel)
        mainLayout.addWidget(self.previousButton)
        mainLayout.addWidget(self.playButton)
        mainLayout.addWidget(self.nextButton)
        mainLayout.addLayout(vbox1)
        mainLayout.addWidget(self.playmodeButton)
        mainLayout.addWidget(self.desktopLyricButton)

    def show_desktop_lyric(self):
        if self.desktopLyric.isHidden():
            beToOff = True
            self.desktopLyric.show()
            self.desktopLyric.original_place()
        else:
            beToOff = False
            self.desktopLyric.hide()
        self.desktop_lyric_state_changed_signal.emit(beToOff)

    def desktop_lyric_closed(self):
        self.desktop_lyric_state_changed_signal.emit(False)

    def change_playmode(self):
        oldPlaymode = self.playmode
        if self.playmode == Configures.PlaymodeRandom:
            self.set_new_playmode(Configures.PlaymodeOrder)
        elif self.playmode == Configures.PlaymodeOrder:
            self.set_new_playmode(Configures.PlaymodeSingle)
        elif self.playmode == Configures.PlaymodeSingle:
            self.set_new_playmode(Configures.PlaymodeRandom)
        self.playmode_changed_signal.emit(oldPlaymode, self.playmode)

    def set_new_playmode(self, playmode):
        self.playmode = playmode
        if playmode == Configures.PlaymodeRandom:
            iconPath = IconsHub.PlaymodeRandom
            toolTip = Configures.PlaymodeRandomText
        elif playmode == Configures.PlaymodeOrder:
            iconPath = IconsHub.PlaymodeOrder
            toolTip = Configures.PlaymodeOrderText
        else:
            iconPath = IconsHub.PlaymodeSingle
            toolTip = Configures.PlaymodeSingleText
        self.playmodeButton.setIcon(QIcon(iconPath))
        self.playmodeButton.setToolTip(toolTip)

    def ui_initial(self):
        self.mediaPlayer.stop()
        self.totalTime = '00:00'
        self.playAction.setIcon(QIcon(IconsHub.ControlPlay))
        self.musicTitleLabel.setText("Zheng-Yejian._.XYPLAYER")
        self.artistName = 'Zheng-Yejian'
        self.artistHeadLabel.setPixmap(QPixmap(IconsHub.Anonymous))
        self.seekSlider.setRange(0, 0)
        self.favoriteButton.setIcon(QIcon(IconsHub.Favorites))
        self.favoriteButton.setToolTip('收藏')
        self.timeLabel.setText("00:00/00:00")

    def set_volume(self, volume):
        self.mediaPlayer.setVolume(volume)

    def set_muted(self, muted):
        self.mediaPlayer.setMuted(muted)

    def tick(self):
        currentTime = self.mediaPlayer.position()
        self.seekSlider.setValue(currentTime)
        cTime = format_position_to_mmss(currentTime // 1000)
        self.timeLabel.setText(cTime + '/' + self.totalTime)
        self.media_player_notify_signal.emit(currentTime)

    def slider_value_changed(self, value):
        cTime = format_position_to_mmss(value // 1000)
        self.timeLabel.setText('%s/%s' % (cTime, self.totalTime))
        self.media_player_notify_signal.emit(value)

    def slider_pressed(self):
        self.mediaPlayer.positionChanged.disconnect(self.tick)

    def seek(self):
        if self.mediaPlayer.state() == QMediaPlayer.StoppedState:
            self.mediaPlayer.play()
            self.mediaPlayer.setPosition(self.seekSlider.value())
        else:
            self.mediaPlayer.setPosition(self.seekSlider.value())
            self.mediaPlayer.play()
        self.mediaPlayer.positionChanged.connect(self.tick)

    def duration_changed(self, duration):
        self.seekSlider.setMaximum(duration)
        exactTotalTime = format_position_to_mmss(self.mediaPlayer.duration() //
                                                 1000)
        self.timeLabel.setText('%s/%s' % (Configures.ZeroTime, exactTotalTime))
        if self.totalTime != exactTotalTime:
            self.totalTime = exactTotalTime
            self.playlist.set_music_time_at(self.currentSourceRow,
                                            exactTotalTime)

    def check_favorite(self):
        if self.currentSourceRow >= 0:
            if self.playlist.get_music_title_at(
                    self.currentSourceRow) in self.lovedSongs:
                self.favoriteButton.setIcon(QIcon(IconsHub.Favorites))
                self.favoriteButton.setToolTip('取消收藏')
            else:
                self.favoriteButton.setIcon(QIcon(IconsHub.FavoritesNo))
                self.favoriteButton.setToolTip('收藏')
            if self.playlist.get_name() == Configures.PlaylistFavorite:
                self.favoriteButton.setToolTip('收藏')

    def mark_as_favorite(self):
        if self.playlist.get_name(
        ) == Configures.PlaylistFavorite or not self.playlist.length(
        ) or self.currentSourceRow < 0:
            return
        path = self.playlist.get_music_path_at(self.currentSourceRow)
        title = self.playlist.get_music_title_at(self.currentSourceRow)
        if self.playlist.get_name() == Configures.PlaylistOnline:
            musicName = get_full_music_name_from_title(title)
            musicPath = os.path.join(self.downloadDir, musicName)
            musicPathO = os.path.join(Configures.MusicsDir, musicName)
            if not os.path.exists(musicPath) and not os.path.exists(
                    musicPathO):
                QMessageBox.information(self, '提示', '请先下载该歌曲再添加喜欢!')
                return
            if os.path.exists(musicPath):
                path = musicPath
            else:
                path = musicPathO
        elif not os.path.exists(path):
            QMessageBox.information(self, "提示",
                                    "路径'" + "%s" % path + "'无效,无法标记喜欢!")
            return
        playlistTemp = Playlist()
        playlistTemp.fill_list(Configures.PlaylistFavorite)
        if title in self.lovedSongs:
            playlistTemp.remove_item_at(self.lovedSongs.index(title))
            playlistTemp.commit_records()
            self.lovedSongs.remove(title)
            self.favoriteButton.setIcon(QIcon(IconsHub.FavoritesNo))
            self.favoriteButton.setToolTip("收藏")
        else:
            playlistTemp.add_item_from_path(path)
            playlistTemp.commit_records()
            self.lovedSongs.append(title)
            self.favoriteButton.setIcon(QIcon(IconsHub.Favorites))
            self.favoriteButton.setToolTip("取消收藏")
        self.mark_favorite_completed_signal.emit()

    def show_artist_info(self):
        if self.artistName:
            self.show_artist_info_signal.emit(self.artistName)

    def decide_to_play_or_pause(self, row):
        if row != self.currentSourceRow:
            self.set_media_source_at_row(row, clickPlayFlag=True)
        elif self.mediaPlayer.state() in (QMediaPlayer.PausedState,
                                          QMediaPlayer.StoppedState):
            self.mediaPlayer.play()
        elif self.mediaPlayer.state() == QMediaPlayer.PlayingState:
            self.mediaPlayer.pause()

    def set_media_source_at_row(self, row, clickPlayFlag=False):
        if not self.playlist.length() or row < 0:
            return
        self.stop_music()
        self.clickPlayFlag = clickPlayFlag
        self.playlist.set_current_row(row)
        sourcePath = self.playlist.get_music_path_at(row)
        self.title = self.playlist.get_music_title_at(row)
        self.sourceTrace = 'local' if self.playlist.get_music_id_at(
            row) == Configures.LocalMusicId else 'online'
        self.artistName, self.musicName = get_artist_and_musicname_from_title(
            self.title)
        self.playlistName = self.playlist.get_name()
        self.totalTime = self.playlist.get_music_time_at(row)
        self.album = self.playlist.get_music_album_at(row)
        self.errorType = Configures.NoError
        isAnUrl = False
        if not os.path.exists(sourcePath):
            if self.playlist.get_name() == Configures.PlaylistOnline:
                if sourcePath == Configures.NoLink:
                    musicId = self.playlist.get_music_id_at(row)
                    sourcePath = SearchOnline.get_song_link(musicId)
                    if sourcePath:
                        self.playlist.set_music_path_at(row, sourcePath)
                    else:
                        self.errorType = Configures.UrlError
                isAnUrl = True
            else:
                self.errorType = Configures.PathError
                sourcePath = "/usr/share/sounds/error_happened.ogg"
        if self.errorType == Configures.NoError:
            self.sourcePath = sourcePath
            self.musicFileName = get_base_name_from_path(sourcePath)
            self.playedDate = get_time_of_now()
            self.songinfosManager.update_datas_of_item(
                self.musicFileName, self.playedDate, self.musicName,
                self.artistName, self.totalTime, self.album, self.playlistName)
            if not self.timerFlag:
                self.timerFlag = True
                self.timeSpan = 0
            if isAnUrl:
                url = QUrl(sourcePath)
            else:
                url = QUrl.fromLocalFile(sourcePath)
            self.play_from_url(url)
        else:
            self.timerFlag = False
            self.dont_hide_main_window_signal.emit()
            if self.errorType == Configures.DisnetError:
                QMessageBox.critical(
                    self, "错误", "联网出错!\n无法联网播放歌曲'%s'!\n您最好在网络畅通时下载该曲目!" %
                    self.playlist.get_music_title_at(row))
            elif self.errorType == Configures.PathError:
                QMessageBox.information(
                    self, "提示", "路径'%s'无效,请尝试重新下载并添加对应歌曲!" %
                    self.playlist.get_music_path_at(row))

    def play_from_url(self, url):
        mediaContent = QMediaContent(url)
        self.mediaPlayer.setMedia(mediaContent)
        self.mediaPlayer.play()

    def state_changed(self, newState):
        if self and newState in [
                QMediaPlayer.PlayingState, QMediaPlayer.PausedState,
                QMediaPlayer.StoppedState
        ]:
            if not self.playlist.length():
                return
            iconPath = IconsHub.ControlPause
            if newState in [
                    QMediaPlayer.StoppedState, QMediaPlayer.PausedState
            ]:
                iconPath = IconsHub.ControlPlay
            icon = QIcon(iconPath)
            self.playAction.setIcon(icon)
            if self.timerFlag:
                if newState == QMediaPlayer.PlayingState:
                    self.timeStart = time.time()
                else:
                    self.timeSpan += (time.time() - self.timeStart)

    def media_status_changed(self, status):
        if status == QMediaPlayer.EndOfMedia:
            self.music_finished()

    def music_finished(self):
        if self.errorType == Configures.NoError:
            self.next_song()

    def play_music(self):
        if self.mediaPlayer.state() == QMediaPlayer.PlayingState:
            self.mediaPlayer.pause()
        else:
            self.mediaPlayer.play()

    def stop_music_but_timing(self):
        self.mediaPlayer.stop()
        self.seekSlider.setValue(0)
        self.media_player_notify_signal.emit(-0.5)

    def stop_music(self):
        self.stop_music_but_timing()
        if self.timerFlag:
            self.timerFlag = False
            InfosList = [
                self.playedDate, self.musicFileName, self.musicName,
                self.artistName, self.album,
                '%i' % change_mmss_to_seconds(self.totalTime),
                '%.1f' % self.timeSpan, self.playlistName, self.sourcePath,
                '%i' % (self.title in self.lovedSongs), self.sourceTrace,
                Configures.Playmodes[self.playmode],
                '%i' % self.clickPlayFlag
            ]
            log_playback_history(organized_list_as_str(InfosList))
            self.songinfosManager.update_time_span_relate_of_item(
                self.musicFileName, self.timeSpan, self.clickPlayFlag)
            self.clickPlayFlag = False

    def get_next_random_row(self):
        listTemp = list(self.playlist.get_ids() - set(self.nearPlayedSongs))
        ran = random.randint(0, len(listTemp) - 1)
        return self.playlist.get_items_queue().index(listTemp[ran])

    def get_next_single_row(self):
        nextRow = self.currentSourceRow
        if nextRow < 0:
            nextRow = 0
        return nextRow

    def get_next_order_row(self, reverse=False):
        if reverse:
            if self.currentSourceRow < 0:
                self.currentSourceRow = 0
            return (self.currentSourceRow - 1) % self.playlist.length()
        return (self.currentSourceRow + 1) % self.playlist.length()

    def previous_song(self):
        self.play_source_on_next_row(reverse=True)

    def next_song(self):
        self.play_source_on_next_row()

    def play_source_on_next_row(self, reverse=False):
        if not self.playlist.length():
            return
        if self.mediaPlayer.position() > 20:
            self.music_ended_signal.emit()
        nextRow = 0
        if self.playmode == Configures.PlaymodeRandom:
            nextRow = self.get_next_random_row()
        elif self.playmode == Configures.PlaymodeOrder:
            nextRow = self.get_next_order_row(reverse)
        elif self.playmode == Configures.PlaymodeSingle:
            nextRow = self.get_next_single_row()
        self.set_media_source_at_row(nextRow)

    def current_media_changed(self):
        if not self.playlist.length():
            return
        self.current_media_changed_signal.emit()
        self.update_parameters()
        self.update_near_played_queue()
        self.check_favorite()

    def update_parameters(self):
        self.currentSourceRow = self.playlist.get_current_row()
        self.musicTitleLabel.setText(self.title)
        self.playAction.setText(self.musicName)
        imagePath = SearchOnline.get_artist_image_path(self.artistName)
        if imagePath:
            pixmap = QPixmap(imagePath)
        else:
            pixmap = QPixmap(IconsHub.Anonymous)
        self.artistHeadLabel.setPixmap(pixmap)
        musicId = self.playlist.get_music_id_at(self.currentSourceRow)
        self.update_window_lyric_signal.emit(self.title, musicId)

    def update_near_played_queue(self):
        self.currentSourceId = self.playlist.get_music_path_at(
            self.currentSourceRow)
        if self.playlist.get_name() == Configures.PlaylistOnline:
            self.currentSourceId = self.playlist.get_music_id_at(
                self.currentSourceRow)
        if self.currentSourceId not in self.nearPlayedSongs:
            self.nearPlayedSongs.append(self.currentSourceId)
        while len(self.nearPlayedSongs) >= self.playlist.length() * 4 / 5:
            del self.nearPlayedSongs[0]

    def add_title_into_loved_songs(self, title):
        self.lovedSongs.append(title)
Ejemplo n.º 20
0
class MainWindow(QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        uic.loadUi('mainwindow.ui', self)
        # Pre-setting
        self.FullScreenBt.setVisible(False)
        #region = QRegion(QRect(0,0,60,60), QRegion.Ellipse)
        self.PlayBt.setIcon(QIcon('./play.svg'))
        self.PlayBt.setIconSize(QSize(58, 58))
        #self.PlayBt.setMask(region)
        self.PauseBt.setIcon(QIcon('./pause.svg'))
        self.PauseBt.setIconSize(QSize(58, 58))
        #self.PauseBt.setMask(region)
        self.StopBt.setIcon(QIcon('./stop.svg'))
        self.StopBt.setIconSize(QSize(58, 58))
        #self.StopBt.setMask(region)
        self.UploadBt.setIcon(QIcon('./download.svg'))
        self.UploadBt.setIconSize(QSize(58, 58))
        #self.UploadBt.setMask(region)

        self.player = QMediaPlayer(None, QMediaPlayer.VideoSurface)
        self.player.setVideoOutput(self.VideoScreen)

        self.slider.setValue(0)
        self.PlayBt.clicked.connect(self.Play)
        self.PauseBt.clicked.connect(self.Pause)
        self.StopBt.clicked.connect(self.Stop)
        self.UploadBt.clicked.connect(self.Upload)
        self.slider.sliderMoved.connect(self.setPosition)
        self.player.positionChanged.connect(self.setPositionOfSlider)
        self.FullScreenBt.clicked.connect(self.setFullscreen)

        self.PlayBt.setEnabled(False)
        self.PauseBt.setEnabled(False)
        self.StopBt.setEnabled(False)
        self.slider.setEnabled(False)
        self.FullScreenBt.setEnabled(False)

    def Play(self):
        if (self.player.position() == self.player.duration()):
            self.player.setPosition(0)
            self.slider.setValue(0)
        self.player.play()
        self.slider.setEnabled(True)
        self.PauseBt.setEnabled(True)
        self.StopBt.setEnabled(True)
        self.slider.setMaximum(self.player.duration())

    def Pause(self):
        self.player.pause()
        self.PauseBt.setEnabled(False)

    def Stop(self):
        self.player.stop()
        self.player.play()
        self.player.pause()
        self.PauseBt.setEnabled(True)

    def Upload(self):
        file = QFileDialog()
        file, trash = file.getOpenFileUrls()
        if file:
            print(file)
            self.player.setMedia(QMediaContent(file[0]))
            self.PlayBt.setEnabled(True)
            #self.FullScreenBt.setEnabled(True)
            self.player.setPosition(0)
            self.slider.setValue(0)
            self.player.play()
            self.player.pause()

    def setPosition(self):
        self.player.setPosition(self.slider.value())

    def setPositionOfSlider(self):
        self.slider.setValue(self.player.position())

    def setFullscreen(self):
        self.VideoScreen.setFullScreen(True)
Ejemplo n.º 21
0
class MyMainWindow(QMainWindow, Ui_musicPlayer):
    def __init__(self, parent=None):
        super(MyMainWindow, self).__init__(parent)
        self.setupUi(self)
        self.player = QMediaPlayer()
        # --计时器
        self.timer = QTimer(self)
        self.timer.start(1000)
        self.songs_list_select = []
        self.song_formats = ['mp3', 'm4a', 'flac', 'wav', 'ogg']
        self.settingfilename = 'setting.ini'
        self.cur_path = os.path.abspath(os.path.dirname(__file__))
        self.cur_playing_song = ''
        self.is_switching = False
        self.is_pause = True
        self.openDir.clicked.connect(self.open_Dir)
        self.playStop.clicked.connect(self.playMusic)
        self.horizontalSlider.sliderMoved[int].connect(
            lambda: self.player.setPosition(self.horizontalSlider.value()))
        self.songUp.clicked.connect(self.previewMusic)
        self.songDn.clicked.connect(self.nextMusic)
        self.listWidget.doubleClicked.connect(self.doubleClicked)
        self.timer.timeout.connect(self.playByMode)

    def loadsetting(self):
        if os.path.isfile(self.settingfilename):
            config = configparser.ConfigParser()
            config.read(self.settingfilename)
            self.cur_path = config.get('MusicPlayer', 'PATH')
            self.showMusicList()

    def savesetting(self):
        config = configparser.ConfigParser()
        config.read(self.settingfilename)
        if not os.path.isfile(self.settingfilename):
            config.add_section('MusicPlayer')
        config.set('MusicPlayer', 'PATH', self.cur_path)
        config.write(open(self.settingfilename, 'w'))

    '''提示'''

    def Tips(self, message):
        QMessageBox.about(self, "提示", message)

    def open_Dir(self):
        self.cur_path = QFileDialog.getExistingDirectory(
            self, "选取文件夹", self.cur_path)
        if self.cur_path:
            self.showMusicList()
            self.cur_playing_song = ''
            self.setCurPlaying()
            self.label.setText('00:00')
            self.label_2.setText('00:00')
            self.horizontalSlider.setSliderPosition(0)
            self.is_pause = True
            self.playStop.setText('播放')

    def showMusicList(self):
        self.listWidget.clear()
        # self.updateSetting()
        for song in os.listdir(self.cur_path):
            if song.split('.')[-1] in self.song_formats:
                self.songs_list_select.append([
                    song,
                    os.path.join(self.cur_path, song).replace('\\', '/')
                ])
                self.listWidget.addItem(song)
        self.listWidget.setCurrentRow(0)
        if self.songs_list_select:
            self.cur_playing_song = self.songs_list_select[
                self.listWidget.currentRow()][-1]

    '''根据播放模式播放音乐'''

    def playByMode(self):
        if (not self.is_pause) and (not self.is_switching):
            self.horizontalSlider.setMinimum(0)
            self.horizontalSlider.setMaximum(self.player.duration())
            self.horizontalSlider.setValue(self.horizontalSlider.value() +
                                           1000)
            self.label.setText(
                time.strftime('%M:%S',
                              time.localtime(self.player.position() / 1000)))
            self.label_2.setText(
                time.strftime('%M:%S',
                              time.localtime(self.player.duration() / 1000)))

            if (self.playType.currentIndex()
                    == 0) and (not self.is_pause) and (not self.is_switching):
                if self.listWidget.count() == 0:
                    return
                if self.player.position() == self.player.duration():
                    self.nextMusic()
            elif (self.playType.currentIndex()
                  == 1) and (not self.is_pause) and (not self.is_switching):
                if self.listWidget.count() == 0:
                    return
                if self.player.position() == self.player.duration():
                    self.is_switching = True
                    self.setCurPlaying()
                    self.horizontalSlider.setValue(0)
                    self.playMusic()
                    self.is_switching = False
            elif (self.playType.currentIndex()
                  == 2) and (not self.is_pause) and (not self.is_switching):
                if self.listWidget.count() == 0:
                    return
                if self.player.position() == self.player.duration():
                    self.is_switching = True
                    self.listWidget.setCurrentRow(
                        random.randint(0,
                                       self.qlist.count() - 1))
                    self.setCurPlaying()
                    self.horizontalSlider.setValue(0)
                    self.playMusic()
                    self.is_switching = False

    '''双击播放音乐'''

    def doubleClicked(self):
        self.horizontalSlider.setValue(0)
        self.is_switching = True
        self.setCurPlaying()
        self.playMusic()
        self.is_switching = False

    '''设置当前播放的音乐'''

    def setCurPlaying(self):
        self.cur_playing_song = self.songs_list_select[
            self.listWidget.currentRow()][-1]
        self.player.setMedia(QMediaContent(QUrl(self.cur_playing_song)))

    '''播放音乐'''

    def playMusic(self):
        if self.listWidget.count() == 0:
            self.Tips('当前路径内无可播放的音乐文件')
            return
        if not self.player.isAudioAvailable():
            self.setCurPlaying()
        if self.is_switching or self.is_pause:
            self.player.play()
            self.is_pause = False
            self.playStop.setText('暂停')
        elif (not self.is_pause) and (not self.is_switching):
            self.player.pause()
            self.is_pause = True
            self.playStop.setText('播放')

    '''上一首'''

    def previewMusic(self):
        self.horizontalSlider.setValue(0)
        if self.listWidget.count() == 0:
            self.Tips('当前路径内无可播放的音乐文件')
            return
        pre_row = self.listWidget.currentRow(
        ) - 1 if self.listWidget.currentRow(
        ) != 0 else self.listWidget.count() - 1
        self.listWidget.setCurrentRow(pre_row)
        self.is_switching = True
        self.setCurPlaying()
        self.playMusic()
        self.is_switching = False

    '''下一首'''

    def nextMusic(self):
        self.horizontalSlider.setValue(0)
        if self.listWidget.count() == 0:
            self.Tips('当前路径内无可播放的音乐文件')
            return
        next_row = self.listWidget.currentRow(
        ) + 1 if self.listWidget.currentRow(
        ) != self.listWidget.count() - 1 else 0
        self.listWidget.setCurrentRow(next_row)
        self.is_switching = True
        self.setCurPlaying()
        self.playMusic()
        self.is_switching = False
Ejemplo n.º 22
0
class Player(QWidget):
    audio_path = "audio"
    lyrics_path = "lyrics"
    timings_path = os.path.join("lyrics", "timing")
    settings_path = "settings.json"

    fullScreenChanged = pyqtSignal(bool)

    def __init__(self, parent=None):
        super(Player, self).__init__(parent)

        self.setWindowTitle("SongScreen")

        self.setFocusPolicy(Qt.StrongFocus)

        self.colorDialog = None
        self.trackInfo = ""
        self.statusInfo = ""
        self.duration = 0

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

        self.player.durationChanged.connect(self.durationChanged)
        self.player.positionChanged.connect(self.positionChanged)
        self.player.metaDataChanged.connect(self.metaDataChanged)
        # self.playlist.currentIndexChanged.connect(self.playlistPositionChanged)
        self.player.mediaStatusChanged.connect(self.statusChanged)
        self.player.bufferStatusChanged.connect(self.bufferingProgress)
        self.player.videoAvailableChanged.connect(self.videoAvailableChanged)
        self.player.error.connect(self.displayErrorMessage)

        # self.videoWidget = VideoWidget()
        # self.player.setVideoOutput(self.videoWidget)

        self.slider = MediaProgressWidget()  # QSlider(Qt.Horizontal)
        self.markers = []

        self.songtext_widget = SongTextWidget()
        self.songtext_widget.show()

        # self.playlistModel = PlaylistModel()
        # self.playlistModel.setPlaylist(self.playlist)
        #
        # self.playlistView = QListView()
        # self.playlistView.setModel(self.playlistModel)
        # self.playlistView.setCurrentIndex(
        #     self.playlistModel.index(self.playlist.currentIndex(), 0))
        #
        # self.playlistView.activated.connect(self.jump)

        self.slider.setRange(0, self.player.duration() / 1000)

        self.labelDuration = QLabel()
        self.slider.sliderMoved.connect(self.seek)

        # openButton = QPushButton("Open", clicked=self.open)

        controls = PlayerControlsWidget()
        controls.setState(self.player.state())
        controls.setVolume(self.player.volume())
        # controls.setMuted(controls.isMuted())

        controls.play.connect(self.player.play)
        controls.pause.connect(self.player.pause)
        controls.stop.connect(self.stop_clicked)
        # controls.stop.connect(self.videoWidget.update)
        # controls.next.connect(self.playlist.next)
        # controls.previous.connect(self.previousClicked)
        controls.changeVolume.connect(self.player.setVolume)
        # controls.changeMuting.connect(self.player.setMuted)
        # controls.changeRate.connect(self.player.setPlaybackRate)

        self.player.stateChanged.connect(controls.setState)
        self.player.stateChanged.connect(self.setState)
        self.player.volumeChanged.connect(controls.setVolume)
        # self.player.mutedChanged.connect(controls.setMuted)

        # self.fullScreenButton = QPushButton("FullScreen")
        # self.fullScreenButton.setCheckable(True)
        #
        # self.colorButton = QPushButton("Color Options...")
        # self.colorButton.setEnabled(False)
        # self.colorButton.clicked.connect(self.showColorDialog)

        displayLayout = QHBoxLayout()
        # displayLayout.addWidget(self.videoWidget, 2)
        # displayLayout.addWidget(self.songtext_widget)
        # displayLayout.addWidget(self.playlistView)

        self.song_select_widget = SongSelectWidget()
        self.song_select_widget.song_selected.connect(self.load_song)

        self.screen_select_widget = ScreenSelectWidget()
        self.screen_select_widget.screen_selected.connect(self.display_lyrics_on_screen)
        self.screen_select_widget.active_screen = QApplication.desktop().screenNumber(self.songtext_widget)

        self.settings_button = QPushButton()
        self.settings_button.setText(self.tr("Settings..."))
        self.settings_button.clicked.connect(self.show_settings)

        sidebarLayout = QVBoxLayout()
        sidebarLayout.setContentsMargins(10, 1, 0, 1);

        sidebarLayout.addWidget(self.settings_button)
        sidebarLayout.addStretch(1);
        sidebarLayout.addWidget(self.screen_select_widget)

        displayLayout.addWidget(self.song_select_widget)
        displayLayout.addLayout(sidebarLayout)

        controlLayout = QHBoxLayout()
        controlLayout.setContentsMargins(0, 0, 0, 0)
        # controlLayout.addWidget(openButton)
        # controlLayout.addStretch(1)
        controlLayout.addWidget(controls)
        controlLayout.addStretch(1)
        controlLayout.addWidget(self.labelDuration)
        # controlLayout.addWidget(self.fullScreenButton)
        # controlLayout.addWidget(self.colorButton)

        layout = QVBoxLayout()
        layout.addLayout(displayLayout)
        hLayout = QHBoxLayout()
        hLayout.addWidget(self.slider)
        # hLayout.addWidget(self.labelDuration)
        layout.addLayout(hLayout)
        layout.addLayout(controlLayout)

        self.setLayout(layout)

        if not self.player.isAvailable():
            QMessageBox.warning(self, "Service not available",
                                "The QMediaPlayer object does not have a valid service.\n"
                                "Please check the media service plugins are installed.")

            controls.setEnabled(False)
            self.playlistView.setEnabled(False)
            # openButton.setEnabled(False)
            self.colorButton.setEnabled(False)
            self.fullScreenButton.setEnabled(False)

        self.metaDataChanged()

        self._loading_audio = False
        self._finished_song = False
        self._lyrics_fading = False

        self._song_number = -1

        self.settings = {
            'font_size': 40,
            'line_increment': 2,
            'lyrics_language': '',
        }
        self._load_settings()

        self.settings_widget = SettingsWidget(self.settings, self.lyrics_path)
        self.settings_widget.font_size_changed.connect(self.songtext_widget.set_font_size)
        self.settings_widget.line_increment_changed.connect(self.songtext_widget.set_line_increment)
        self.settings_widget.language_changed.connect(self._language_changed)

        self.song_select_widget.reset(self.available_song_numbers)

    @property
    def lyrics_language_path(self):
        path = QStandardPaths.locate(QStandardPaths.AppDataLocation, self.lyrics_path, QStandardPaths.LocateDirectory)
        return os.path.join(path, self.settings['lyrics_language'])

    @property
    def available_song_numbers(self):
        audios = set(
            [int(os.path.splitext(filename)[0]) for filename in os.listdir(self.audio_path) if filename[0] != '.'])
        try:
            lyrics = set(
                [int(os.path.splitext(filename)[0])
                 for filename in os.listdir(self.lyrics_language_path)
                 if filename[0] != '.']
            )
        except (ValueError, FileNotFoundError):
            lyrics = set()

        return sorted(list(audios.intersection(lyrics)))

    def show_settings(self):
        self.settings_widget.hide()
        self.settings_widget.show()

    def display_lyrics_on_screen(self, screen_number):
        desktop = QApplication.desktop()

        if screen_number >= desktop.screenCount():
            screen_number = desktop.screenNumber(self)

        rect = desktop.availableGeometry(screen_number)

        for _ in range(3):
            if screen_number != desktop.screenNumber(self):
                self.songtext_widget.setWindowFlags(Qt.FramelessWindowHint)
                self.songtext_widget.hide()
                self.songtext_widget.move(rect.x(), rect.y())
                self.songtext_widget.resize(rect.width(), rect.height())
                self.songtext_widget.showFullScreen()
            else:
                self.songtext_widget.setWindowFlags(Qt.WindowTitleHint)
                self.songtext_widget.hide()
                self.songtext_widget.move(rect.x(), rect.y())
                self.songtext_widget.resize(self.songtext_widget.minimumSize())
                self.songtext_widget.show()

        self.screen_select_widget.active_screen = screen_number

        self.activateWindow()

    def load_song(self, song_number):
        if self._song_number == song_number:
            self.seek(0)
        else:
            if self._song_number > 0:
                self._save_timings()

            self._song_number = song_number
            self.slider.dirty = False
            self._load_audio()
            self._load_lyrics()

            # self.player.play()

    def _load_audio(self):
        filename = os.path.join(self.audio_path, "{:03}.mp3".format(self._song_number))
        self.playlist.clear()
        fileInfo = QFileInfo(filename)
        if fileInfo.exists():
            url = QUrl.fromLocalFile(fileInfo.absoluteFilePath())
            if fileInfo.suffix().lower() == 'm3u':
                self.playlist.load(url)
            else:
                self.playlist.addMedia(QMediaContent(url))
                self._loading_audio = True

            self.player.play()

    def _load_lyrics(self):
        with open(os.path.join(self.lyrics_language_path, "{}.json".format(self._song_number)), 'r') as f:
            song_markers = json.load(f)

            self.markers = []

            for m in song_markers['markers']:
                marker = MediaMarker(self.slider, m['name'])
                marker.text = m['text']
                marker.progress = 0.0
                self.markers.append(marker)

            self.songtext_widget.title = "{}  {}".format(self._song_number, song_markers['title'])
            self.songtext_widget.markers = self.markers
            self.songtext_widget.fade_in()

        try:
            with open(os.path.join(self.timings_path, "{}.json".format(self._song_number)), 'r') as f:
                timings = json.load(f)
                for m, t in zip(self.markers, timings):
                    m.progress = t
        except FileNotFoundError:
            pass

        self.slider.markers = self.markers

    def _language_changed(self, _):
        available_song_numbers = self.available_song_numbers
        self.song_select_widget.reset(available_song_numbers)
        if self._song_number in available_song_numbers:
            self._load_lyrics()

    # def open(self):
    #     fileNames, _ = QFileDialog.getOpenFileNames(self, "Open Files")
    #     self.addToPlaylist(fileNames)
    #
    # def addToPlaylist(self, fileNames):
    #     for name in fileNames:
    #         fileInfo = QFileInfo(name)
    #         if fileInfo.exists():
    #             url = QUrl.fromLocalFile(fileInfo.absoluteFilePath())
    #             if fileInfo.suffix().lower() == 'm3u':
    #                 self.playlist.load(url)
    #             else:
    #                 self.playlist.addMedia(QMediaContent(url))
    #         else:
    #             url = QUrl(name)
    #             if url.isValid():
    #                 self.playlist.addMedia(QMediaContent(url))

    def durationChanged(self, duration):
        duration /= 1000

        self.duration = duration
        self.slider.setMaximum(duration)

        if self._loading_audio:
            self._loading_audio = False

            line_total = 0
            for marker in self.markers:
                line_total += marker.linecount - 1

            silence_ratio = 5.0 / self.duration
            offset = 1.8 / line_total

            linecount = 0
            for marker in self.markers:
                if marker.progress == 0.0:
                    marker.progress = offset + (1 - offset) * (1 - silence_ratio) * linecount / line_total
                linecount += marker.linecount - 1

            self.player.pause()

    @property
    def _should_fade_out(self):
        return self.player.position() / 1000 >= self.duration - 5

    def positionChanged(self, progress):
        progress /= 1000

        if not self.slider.isSliderDown():
            self.slider.setValue(progress)

        self.updateDurationInfo(progress)

        if self.duration > 0:
            # if self.player.state() == QMediaPlayer.PlayingState:
            self.songtext_widget.progress = progress / self.duration

            if self._should_fade_out:
                self._fade_out_lyrics()

    def _fade_out_lyrics(self):
        if not self._lyrics_fading:
            self._lyrics_fading = True
            self.songtext_widget.fade_out()

    def metaDataChanged(self):
        if self.player.isMetaDataAvailable():
            self.setTrackInfo("%s - %s" % (
                self.player.metaData(QMediaMetaData.AlbumArtist),
                self.player.metaData(QMediaMetaData.Title)))

    def previousClicked(self):
        # Go to the previous track if we are within the first 5 seconds of
        # playback.  Otherwise, seek to the beginning.
        if self.player.position() <= 5000:
            self.playlist.previous()
        else:
            self.player.setPosition(0)

    def jump(self, index):
        if index.isValid():
            self.playlist.setCurrentIndex(index.row())
            self.player.play()

    def seek(self, seconds):
        self.player.setPosition(seconds * 1000)

    def setState(self, status):

        if status == QMediaPlayer.StoppedState:
            self._finished_song = True

        elif status == QMediaPlayer.PlayingState:
            if self._finished_song or (self._lyrics_fading and not self._should_fade_out):
                self._finished_song = False
                self._lyrics_fading = False
                self.songtext_widget.fade_in()

    def stop_clicked(self):
        self.player.stop()
        self._fade_out_lyrics()

    def statusChanged(self, status):
        self.handleCursor(status)

        if status == QMediaPlayer.LoadingMedia:
            self.setStatusInfo("Loading...")
        elif status == QMediaPlayer.StalledMedia:
            self.setStatusInfo("Media Stalled")
        elif status == QMediaPlayer.EndOfMedia:
            QApplication.alert(self)
        elif status == QMediaPlayer.InvalidMedia:
            self.displayErrorMessage()
        else:
            self.setStatusInfo("")

    def handleCursor(self, status):
        if status in (QMediaPlayer.LoadingMedia, QMediaPlayer.BufferingMedia, QMediaPlayer.StalledMedia):
            self.setCursor(Qt.BusyCursor)
        else:
            self.unsetCursor()

    def bufferingProgress(self, progress):
        self.setStatusInfo("Buffering %d%" % progress)

    def videoAvailableChanged(self, available):
        if available:
            self.fullScreenButton.clicked.connect(
                self.videoWidget.setFullScreen)
            self.videoWidget.fullScreenChanged.connect(
                self.fullScreenButton.setChecked)

            if self.fullScreenButton.isChecked():
                self.videoWidget.setFullScreen(True)
        else:
            self.fullScreenButton.clicked.disconnect(
                self.videoWidget.setFullScreen)
            self.videoWidget.fullScreenChanged.disconnect(
                self.fullScreenButton.setChecked)

            self.videoWidget.setFullScreen(False)

        self.colorButton.setEnabled(available)

    def setTrackInfo(self, info):
        self.trackInfo = info

        # if self.statusInfo != "":
        #     self.setWindowTitle("%s | %s" % (self.trackInfo, self.statusInfo))
        # else:
        #     self.setWindowTitle(self.trackInfo)

    def setStatusInfo(self, info):
        self.statusInfo = info

        # if self.statusInfo != "":
        #     self.setWindowTitle("%s | %s" % (self.trackInfo, self.statusInfo))
        # else:
        #     self.setWindowTitle(self.trackInfo)

    def displayErrorMessage(self):
        self.setStatusInfo(self.player.errorString())

    def updateDurationInfo(self, currentInfo):
        duration = self.duration
        if currentInfo or duration:
            currentTime = QTime((currentInfo / 3600) % 60, (currentInfo / 60) % 60,
                                currentInfo % 60, (currentInfo * 1000) % 1000)
            totalTime = QTime((duration / 3600) % 60, (duration / 60) % 60,
                              duration % 60, (duration * 1000) % 1000);

            format = 'hh:mm:ss' if duration > 3600 else 'mm:ss'
            tStr = currentTime.toString(format) + " / " + totalTime.toString(format)
        else:
            tStr = ""

        self.labelDuration.setText(tStr)

    def showColorDialog(self):
        if self.colorDialog is None:
            brightnessSlider = QSlider(Qt.Horizontal)
            brightnessSlider.setRange(-100, 100)
            brightnessSlider.setValue(self.videoWidget.brightness())
            brightnessSlider.sliderMoved.connect(
                self.videoWidget.setBrightness)
            self.videoWidget.brightnessChanged.connect(
                brightnessSlider.setValue)

            contrastSlider = QSlider(Qt.Horizontal)
            contrastSlider.setRange(-100, 100)
            contrastSlider.setValue(self.videoWidget.contrast())
            contrastSlider.sliderMoved.connect(self.videoWidget.setContrast)
            self.videoWidget.contrastChanged.connect(contrastSlider.setValue)

            hueSlider = QSlider(Qt.Horizontal)
            hueSlider.setRange(-100, 100)
            hueSlider.setValue(self.videoWidget.hue())
            hueSlider.sliderMoved.connect(self.videoWidget.setHue)
            self.videoWidget.hueChanged.connect(hueSlider.setValue)

            saturationSlider = QSlider(Qt.Horizontal)
            saturationSlider.setRange(-100, 100)
            saturationSlider.setValue(self.videoWidget.saturation())
            saturationSlider.sliderMoved.connect(
                self.videoWidget.setSaturation)
            self.videoWidget.saturationChanged.connect(
                saturationSlider.setValue)

            layout = QFormLayout()
            layout.addRow("Brightness", brightnessSlider)
            layout.addRow("Contrast", contrastSlider)
            layout.addRow("Hue", hueSlider)
            layout.addRow("Saturation", saturationSlider)

            button = QPushButton("Close")
            layout.addRow(button)

            self.colorDialog = QDialog(self)
            self.colorDialog.setWindowTitle("Color Options")
            self.colorDialog.setLayout(layout)

            button.clicked.connect(self.colorDialog.close)

        self.colorDialog.show()

    def closeEvent(self, close_event):
        self._save_timings()
        self._save_settings()
        self.songtext_widget.close()
        self.settings_widget.close()

    def keyPressEvent(self, key_event):
        if key_event.key() == Qt.Key_Space:
            key_event.accept()
            if self.player.state() == QMediaPlayer.PlayingState:
                self.player.pause()
            elif self.player.state() in [QMediaPlayer.PausedState, QMediaPlayer.StoppedState]:
                self.player.play()
        elif key_event.key() == Qt.Key_M:
            key_event.accept()
            self.slider.set_closest_marker_to_current_progress()

    def _save_timings(self):
        if self.slider.dirty:
            with open(os.path.join(self.timings_path, "{}.json".format(self._song_number)), 'w') as f:
                json.dump([marker.progress for marker in self.markers], f, indent=2)

    def _save_settings(self):
        # TODO : refactor and use QSettings directly

        # with open(self.settings_path, 'w') as f:
        self.settings.update({
            'lyrics_screen': QApplication.desktop().screenNumber(self.songtext_widget),
            'control_window_position': self.pos(),
        })

        # json.dump(self.settings, f, indent=2)

        settings = QSettings("Maccesch", "SongScreen")

        for key, value in self.settings.items():
            settings.setValue(key, value)

    def _load_settings(self):
        # try:
        #     with open(self.settings_path, 'r') as f:
        #         settings = json.load(f)
        settings = QSettings("Maccesch", "SongScreen")

        if settings.contains('lyrics_screen'):
            self.display_lyrics_on_screen(settings.value('lyrics_screen'))

        if settings.contains('control_window_position'):
            self.move(settings.value('control_window_position'))

        for key in settings.allKeys():
            self.settings[key] = settings.value(key)

        # self.settings.update(settings)

        self.songtext_widget.set_font_size(self.settings['font_size'])
        self.songtext_widget.set_line_increment(self.settings['line_increment'])

        # except (FileNotFoundError, ValueError):
        #     pass

        if not os.path.exists(self.lyrics_language_path) or not self.settings['lyrics_language']:
            languages = list(
                filter(lambda p: os.path.isdir(os.path.join(self.lyrics_path, p)) and p != "timings",
                       os.listdir(self.lyrics_path))
            )
            self.settings['lyrics_language'] = languages[0] if languages else ""
Ejemplo n.º 23
0
class AudioPlayer(QObject):

    songPositionChanged = pyqtSignal(int)
    songDurationChanged = pyqtSignal(int)
    stateChanged = pyqtSignal(int)
    playlistChanged = pyqtSignal(QMediaPlaylist, int)

    currentSongChanged = pyqtSignal(str, str, bytes)
    currentSelectionChanged = pyqtSignal(UUID, int)

    customPlaylistCreated = pyqtSignal(UUID, str)
    libraryPlaylistCreated = pyqtSignal(UUID)

    addedToLibraryPlaylist = pyqtSignal(UUID, list)
    addedToCustomPlaylist = pyqtSignal(UUID, list)

    updatedLibraryPlaylist = pyqtSignal(UUID, list)

    playlistRemoved = pyqtSignal(UUID)

    def __init__(self, volumeLevel=40, playbackMode=QMediaPlaylist.Sequential,
                 parent=None):
        super(AudioPlayer, self).__init__(parent)

        self.__player = QMediaPlayer()
        self.__player.setVolume(volumeLevel)

        self.__player.currentMediaChanged.connect(self._onMediaChanged)
        self.__player.stateChanged.connect(
            lambda state: self.stateChanged.emit(int(state)))
        self.__player.positionChanged.connect(
            lambda x: self.songPositionChanged.emit(x))
        self.__player.durationChanged.connect(
            lambda x: self.songDurationChanged.emit(x))

        self.__playlistManager = PlaylistManger()

        self.__playlistManager.customPlaylistCreated.connect(
            lambda uuid, name: self.customPlaylistCreated.emit(uuid, name))
        self.__playlistManager.libraryPlaylistCreated.connect(
            lambda p: self.libraryPlaylistCreated.emit(p))
        
        self.__playlistManager.currentPlaylistChanged.connect(
            self._onChangedPlaylist)
        self.__playlistManager.currentPlaylistChanged.connect(
            lambda p, i: self.playlistChanged.emit(p, i))

        self.__playlistManager.playlistRemoved.connect(
            lambda uuid: self.playlistRemoved.emit(uuid))

        self.__playlistManager.addedToLibraryPlaylist.connect(
            lambda uuid, l: self.addedToLibraryPlaylist.emit(uuid, l))
        self.__playlistManager.addedToCustomPlaylist.connect(
            lambda uuid, l: self.addedToCustomPlaylist.emit(uuid, l))

        self.__playlistManager.updatedLibraryPlaylist.connect(
            lambda uuid, l: self.updatedLibraryPlaylist.emit(uuid, l))

    def createCustomPlaylist(self, name=None, urls=None):
        self.__playlistManager.createCustomPlaylist(name, urls)

    def createLibraryPlaylist(self, urls=None):
        self.__playlistManager.createLibraryPlaylist(urls)

    def addToLibraryPlaylist(self, url=None):
        self.__playlistManager.addToLibraryPlaylist(url)

    def updateLibraryPlaylist(self, url=None):
        self.__playlistManager.updateLibraryPlaylist(url)

    def renamePlaylist(self, uuid, newName):
        self.__playlistManager.renamePlaylist(uuid, newName)

    def addSongsToCustomPlaylist(self, uuid, urls=[]):
        self.__playlistManager.addSongsToCustomPlaylist(uuid, urls)

    def removeSong(self, uuid, row):
        self.__playlistManager.removeSong(uuid, row)

    def setPlaylist(self, uuid, index=0):
        if (self.__player.playlist() and
                self.__playlistManager.isCurrentPlaylist(uuid)):
            if index == self.__player.playlist().currentIndex():
                if self.__player.state() == QMediaPlayer.PlayingState:
                    self.__player.pause()
                else:
                    self.__player.play()
            else:
                self.__player.playlist().setCurrentIndex(index)
        else:
            self.__playlistManager.setPlaylist(uuid, index)

    def hasLibraryPlaylist(self):
        return self.__playlistManager.hasLibraryPlaylist()

    def removePlaylist(self, uuid):
        self.__playlistManager.removePlaylist(uuid)

    def getCurrentPlaylist(self):
        self.__playlistManager.getCurrentPlaylist()

    def getCurrentQMediaPlaylist(self):
        self.__player.playlist()

    def isPlayerAvailable(self):
        return self.__player.isAvailable()

    def getDuration(self):
        return self.__player.duration()

    def getPlayer(self):
        return self.__player

    def getState(self):
        return self.__player.state()

    def play(self):
        if self.__player.playlist():
            self.__player.play()

    def pause(self):
        if self.__player.playlist():
            self.__player.pause()

    def stop(self):
        if self.__player.playlist():
            self.__player.stop()

    def previousEnhanced(self, sameSongMillis):
        if self.__player.position() <= sameSongMillis:
            self.previous()
        else:
            self.__player.setPosition(0)

    def previous(self):
        if self.__player.playlist():
            self.__player.playlist().previous()

    def next(self):
        if self.__player.playlist():
            self.__player.playlist().next()

    def setVolume(self, value):
        self.__player.setVolume(value)

    def setPosition(self, milliseconds):
        self.__player.setPosition(milliseconds)

    def playlistCurrentIndex(self):
        if self.__player.playlist():
            return self.__player.playlist().currentIndex()

    def setCurrentPlaylistIndex(self, index):
        if self.__player.playlist():
            self.__player.playlist().setCurrentIndex(index)

    def _onChangedPlaylist(self, playlist, index, playIt=False):
        self.__player.setPlaylist(playlist)
        if playlist:
            playlist.setCurrentIndex(index)
        if playIt:
            self.play()

    def _onMediaChanged(self, media):
        if media.isNull() and self.__player.playlist():
            self.__player.playlist().setCurrentIndex(0)
            media = self.__player.playlist().media(0)
        if media.isNull():
            return

        title, artist, cover = self.__playlistManager.getBasicSongInfo(media)

        self.currentSongChanged.emit(title, artist, cover)

        uuid = self.__playlistManager.getCurrentPlaylistUuid()
        index = self.__playlistManager.getCurrentSongIndex()
        self.currentSelectionChanged.emit(uuid, index)

    # def saveSettings(self):
    #     # settings = QSettings(QSettings.IniFormat, QSettings.UserScope,
    #     #                      QCoreApplication.organizationName(),
    #     #                      QCoreApplication.applicationName())

    #     # settings.beginGroup("music_player")

    #     # # if self.__playlistManager.getLibraryPlaylist():
    #     # #     libraryDirectories = self.__playlistManager.getLibraryPlaylist().getDirectories()
    #     # #     settings.beginWriteArray('library_playlist',
    #     # #                              len(libraryDirectories))
    #     # #     for index, value in enumerate(libraryDirectories):
    #     # #         settings.setArrayIndex(index)
    #     # #         settings.setValue("url", value)
    #     # #     settings.endArray()

    #     # customPlaylists = self.__playlistManager.getCustomPlaylists()
    #     # settings.beginWriteArray('custom_playlists',
    #     #                          len(customPlaylists))
    #     # for index, value in enumerate(customPlaylists):
    #     #     settings.setArrayIndex(index)
    #     #     playlistName = settings.value('name', value.getName())
    #     #     playlistUrls = value.getAddedSongUrls()
    #     #     settings.beginWriteArray(playlistName,
    #     #                              len(playlistUrls))
    #     #     for i, v in enumerate(playlistUrls):
    #     #         settings.setArrayIndex(i)
    #     #         settings.setValue("url", v)
    #     #     settings.endArray()
    #     # settings.endArray()

    #     # settings.endGroup()
    #     # if self.__playlistManager.getLibraryPlaylist():
    #     #     libraryDirectories = self.__playlistManager.getLibraryPlaylist().getDirectories()
    #     #     settings.beginWriteArray('library_playlist',
    #     #                              len(libraryDirectories))
    #     #     for index, value in enumerate(libraryDirectories):
    #     #         settings.setArrayIndex(index)
    #     #         settings.setValue("url", value)
    #     #     settings.endArray()

    #     customPlaylists = self.__playlistManager.getCustomPlaylists()
    #     for playlist in customPlaylists:
    #         playlistName = playlist.getName()
    #         for url in playlist:
    #             pass

    # def restoreSettings(self):
    #     settings = QSettings(QSettings.IniFormat, QSettings.UserScope,
    #                          QCoreApplication.organizationName(),
    #                          QCoreApplication.applicationName())

    #     settings.beginGroup("music_player")

    #     # size = settings.beginReadArray('library_playlist')
    #     # libraryDirectories = []
    #     # for i in range(size):
    #     #     settings.setArrayIndex(i)
    #     #     libraryDirectories.append(settings.value("url"))
    #     # settings.endArray()

    #     customPlaylists = {}
    #     size = settings.beginReadArray('custom_playlists')
    #     for i in range(size):
    #         urls = []
    #         settings.setArrayIndex(i)
    #         playlistName = settings.value('name')
    #         print(playlistName)
    #         size2 = settings.beginReadArray(playlistName)
    #         for j in range(size2):
    #             settings.setArrayIndex(j)
    #             url = settings.value("url")
    #             urls.append(url)
    #         settings.endArray()
    #         customPlaylists[playlistName] = urls
    #     settings.endArray()

    #     settings.endGroup()

    #     print('-------')
    #     print(customPlaylists)





        # settings = QSettings(QCoreApplication.organizationName(),
        #                      QCoreApplication.applicationName())
        # settings.beginGroup("music_player")

        # size = settings.beginReadArray('library_playlist')
        # if not size == 0:
        #     for i in range(0, size):
        #         settings.setArrayIndex(i)
        #         url = settings.value("url")
        # settings.endArray()

        # if url:
        #     from audio.playlist_models import DirectoryPlaylist

        #     playlist = DirectoryPlaylist()
        #     playlist.add_directory(url)
        #     self.addAndSetPlaylist(playlist, 2)

        # settings.endGroup()
        pass
Ejemplo n.º 24
0
class BasicVideoWidget(QVideoWidget):
    def __init__(self, *args, **kwargs):
        super(BasicVideoWidget, self).__init__(*args, **kwargs)
        self.mediaPlayer = QMediaPlayer(parent=self)
        self.setMediaObject(self.mediaPlayer)

        self.playlist = QMediaPlaylist()
        self.playlist.setPlaybackMode(QMediaPlaylist.Loop)
        self.mediaPlayer.setPlaylist(self.playlist)

        self.mediaPlayer.positionChanged.connect(self._positionChanged)
        self.mediaPlayer.mutedChanged.connect(self.mutedChanged)
        self.mediaPlayer.durationChanged.connect(self._durationChanged)
        self.mediaPlayer.stateChanged.connect(self.stateChanged)
        self.mediaPlayer.seekableChanged.connect(self.seekableChanged)

    def loadUrl(self, url):
        mc = QMediaContent(url)
        self.playlist.clear()
        self.playlist.addMedia(mc)

    def load(self, path):
        self.loadUrl(QUrl.fromLocalFile(os.path.abspath(path)))

    @Slot()
    def play(self):
        self.mediaPlayer.play()

    @Slot()
    def pause(self):
        self.mediaPlayer.pause()

    @Slot()
    def stop(self):
        self.mediaPlayer.stop()

    @Slot(bool)
    def setMuted(self, b):
        self.mediaPlayer.setMuted(b)

    mutedChanged = Signal(bool)

    @Slot()
    def playPause(self):
        if self.mediaPlayer.state() != QMediaPlayer.PlayingState:
            self.mediaPlayer.play()
        else:
            self.mediaPlayer.pause()

    def state(self):
        return self.mediaPlayer.state()

    stateChanged = Signal(QMediaPlayer.State)

    def duration(self):
        return self.mediaPlayer.duration()

    durationChanged = Signal(int)

    @Slot(int)
    def setPosition(self, p):
        self.mediaPlayer.setPosition(p)

    def position(self):
        return self.mediaPlayer.position()

    @Slot('qint64')
    def _positionChanged(self, p):
        self.positionChanged.emit(p)

    positionChanged = Signal(int)

    @Slot('qint64')
    def _durationChanged(self, p):
        self.durationChanged.emit(p)

    seekableChanged = Signal(bool)

    def isSeekable(self):
        return self.mediaPlayer.isSeekable()
Ejemplo n.º 25
0
class Player(Qt.QWidget):
    """docstring for Player"""
    fullScreenChanged = Qt.pyqtSignal(bool)

    def __init__(self, playlist, parent=None):
        # create player
        super(Player, self).__init__(parent)

        self.trackInfo = ''
        self.statusInfo = ''
        self.duration = 0

        # create player object
        self.player = QMediaPlayer()
        self.playlist = QMediaPlaylist()
        self.name = 'Current playlist'
        self.player.setPlaylist(self.playlist)

        self.player.durationChanged.connect(self.durationChanged)
        self.player.positionChanged.connect(self.positionChanged)
        self.player.metaDataChanged.connect(self.metaDataChanged)
        self.playlist.currentIndexChanged.connect(self.playlistPositionChanged)

        self.player.mediaStatusChanged.connect(self.statusChanged)
        self.player.bufferStatusChanged.connect(self.bufferingProgress)
        # self.player.videoAvailableChanged.connect(self.videoAvailableChanged)
        self.player.error.connect(self.displayErrorMessage)

        # connect with VideoWidget
        # self.videoWidget = VideoWidget()
        # self.player.setVideoOutput(self.videoWidget)

        # connect with PlaylistModel
        self.playlistModel = PlaylistModel()
        self.playlistModel.setPlaylist(self.playlist)

        self.playlistView = Qt.QListView()
        self.playlistView.setModel(self.playlistModel)
        self.playlistView.setCurrentIndex(self.playlistModel.index(
            self.playlist.currentIndex(), 0))

        # change to next song
        self.playlistView.activated.connect(self.jump)

        self.slider = Qt.QSlider(QtCore.Qt.Horizontal)
        self.slider.setRange(0, self.player.duration() / 1000)

        self.labelDuration = Qt.QLabel()
        self.slider.sliderMoved.connect(self.seek)

        # create histogram
        self.labelHistogram = Qt.QLabel()
        self.labelHistogram.setText('Histogram: ')
        self.histogram = HistogramWidget()
        histogramLayout = Qt.QHBoxLayout()
        histogramLayout.addWidget(self.labelHistogram)
        histogramLayout.addWidget(self.histogram, 1)

        # create videoProbe
        self.videoProbe = Qt.QVideoProbe()
        self.videoProbe.videoFrameProbed.connect(self.histogram.processFrame)
        self.videoProbe.setSource(self.player)

        # add control
        controls = Controllers()
        controls.setState(self.player.state())
        controls.setVolume(self.player.volume())
        controls.setMuted(controls.isMuted())

        # connect player's controls with Controllers
        controls.play.connect(self.player.play)
        controls.pause.connect(self.player.pause)
        controls.stop.connect(self.player.stop)
        controls.next.connect(self.playlist.next)
        controls.previous.connect(self.previousAction)
        controls.changeVolume.connect(self.player.setVolume)
        controls.changeMuting.connect(self.player.setMuted)
        # setPlaybackRate is from QMediaPlayer
        controls.changeSpeed.connect(self.player.setPlaybackRate)
        # controls.stop.connect(self.videoWidget.update)

        self.player.stateChanged.connect(controls.setState)
        self.player.volumeChanged.connect(controls.setVolume)
        self.player.mutedChanged.connect(controls.setMuted)

        # create fullScreenButton
        # self.fullScreenButton = Qt.QPushButton('FullScreen')
        # self.fullScreenButton.setCheckable(True)

        # displayLayout
        displayLayout = Qt.QHBoxLayout()
        # displayLayout.addWidget(self.videoWidget, 2)
        displayLayout.addWidget(self.playlistView)

        # controlLayout
        controlLayout = Qt.QHBoxLayout()
        controlLayout.setContentsMargins(0, 0, 0, 0)
        # connect controlLayout with controls
        controlLayout.addWidget(controls)
        controlLayout.addStretch(1)
        # connect controlLayout with fullScreenButton
        # controlLayout.addWidget(self.fullScreenButton)

        # visualize player
        layout = Qt.QVBoxLayout()
        layout.addLayout(displayLayout)

        # layout for sliding song playing
        hLayout = Qt.QHBoxLayout()
        hLayout.addWidget(self.slider)
        hLayout.addWidget(self.labelDuration)

        layout.addLayout(hLayout)
        layout.addLayout(controlLayout)
        layout.addLayout(histogramLayout)

        # set icon
        self.setWindowIcon(Qt.QIcon('favicon.ico'))

        # create menus
        toolBar = Qt.QToolBar()

        # create basic actions
        self.createActions()

        # create simple button to repeat song
        self.repeatButton = Qt.QToolButton()
        self.repeatButton.setDefaultAction(self.repeatAct)

        # create playOnceButton
        self.playOnceButton = Qt.QToolButton()
        self.playOnceButton.setDefaultAction(self.playOnceAct)
        self.playOnceButton.setEnabled(False)

        # create shuffleButton
        self.shuffleButton = Qt.QToolButton()
        self.shuffleButton.setDefaultAction(self.shuffleAct)

        # create sequentialButton
        self.sequentialButton = Qt.QToolButton()
        self.sequentialButton.setDefaultAction(self.sequentialAct)

        # create fileButton for fileMenu
        fileButton = Qt.QToolButton()
        fileButton.setText('File')
        fileButton.setPopupMode(Qt.QToolButton.MenuButtonPopup)
        fileButton.setMenu(self.popFileMenu())

        # create editButton for editMenu
        closeButton = Qt.QToolButton()
        closeButton.setText('Edit')
        closeButton.setDefaultAction(self.fileCloseAct)

        # display in toolBar these buttons
        toolBar.addWidget(self.repeatButton)
        toolBar.addWidget(self.playOnceButton)
        toolBar.addWidget(self.shuffleButton)
        toolBar.addWidget(self.sequentialButton)
        toolBar.addWidget(fileButton)
        toolBar.addWidget(closeButton)

        # add toolBar to layout of the player
        layout.addWidget(toolBar)
        layout.addWidget(Qt.QGroupBox())

        self.setWindowTitle("Python Music Player")
        self.setLayout(layout)

        if not self.player.isAvailable():
            Qt.QMessageBox(self, 'Unavailable service')
            # self.displayErrorMessage()
            controls.setEnabled(False)
            self.playlistView.setEnabled(False)
            self.fullScreenButton.setEnabled(False)

        self.metaDataChanged()

        self.addToPlaylist(playlist)

    # create fileMenu
    def popFileMenu(self):
        aMenu = Qt.QMenu(self)
        aMenu.addAction(self.fileOpenAct)
        aMenu.addAction(self.fileCloseAct)
        return aMenu

    def createActions(self):
        self.repeatAct = Qt.QAction('Repeat', self, triggered=self.repeatSong)
        self.playOnceAct = Qt.QAction(
            'Play once', self, triggered=self.playOnceSong)
        self.shuffleAct = Qt.QAction(
            'Shuffle', self, triggered=self.playlist.shuffle)
        self.sequentialAct = Qt.QAction(
            'Sequential', self, triggered=self.playSequential)
        self.fileOpenAct = Qt.QAction('Open', self, triggered=self.open)
        self.fileOpenAct.setShortcut('Ctrl+O')

        self.fileCloseAct = Qt.QAction('Close', self, triggered=self.close)
        self.fileCloseAct.setShortcut('Ctrl+Q')

    def repeatSong(self):
        self.playlist.setPlaybackMode(QMediaPlaylist.CurrentItemInLoop)
        self.repeatButton.setEnabled(False)
        self.playOnceButton.setEnabled(True)

    def playOnceSong(self):
        self.playlist.setPlaybackMode(QMediaPlaylist.Sequential)
        self.playOnceButton.setEnabled(False)
        self.repeatButton.setEnabled(True)

    # unproperly used
    def playSequential(self):
        self.playlist.setPlaybackMode(QMediaPlaylist.Sequential)

    # get and display song duration
    def durationChanged(self, duration):
        duration /= 1000

        self.duration = duration
        self.slider.setMaximum(duration)

    # change slider position
    def positionChanged(self, progress):
        progress /= 1000

        if not self.slider.isSliderDown():
            self.slider.setValue(progress)

        self.updateDurationInfo(progress)

    def updateDurationInfo(self, currentInfo):
        duration = self.duration
        if currentInfo or duration:
            currentTime = QtCore.QTime(
                (currentInfo / 3600) % 60,  # hours
                (currentInfo / 60) % 60,  # minutes
                currentInfo % 60,  # seconds
                (currentInfo * 1000) % 1000)  # miliseconds
            totalTime = QtCore.QTime(
                (duration / 3600) % 60,  # hours
                (duration / 60) % 60,  # minutes
                duration % 60,  # seconds
                (duration * 1000) % 1000)  # miliseconds
            formating = 'hh:mm:ss' if duration > 3600 else 'mm:ss'
            toString = (currentTime.toString(formating) + ' / ' +
                        totalTime.toString(formating))
        else:
            toString = ''

        self.labelDuration.setText(toString)

    def metaDataChanged(self):
        if self.player.isMetaDataAvailable():
            self.setTrackInfo('{0} - {1}'.format(
                self.player.metaData(Qt.QMediaMetaData.AlbumArtist),
                self.player.metaData(Qt.QMediaMetaData.Title)))

    def setTrackInfo(self, info):
        self.trackInfo = info

        if self.statusInfo:
            self.setWindowTitle('{0} | {1}'.format(
                self.trackInfo, self.statusInfo))
        else:
            self.setWindowTitle(self.trackInfo)

    def playlistPositionChanged(self, position):
        self.playlistView.setCurrentIndex(
            self.playlistModel.index(position, 0))

    def statusChanged(self, status):
        self.handleCursor(status)

        if status == QMediaPlayer.LoadingMedia:
            self.setStatusInfo('Loading...')
        elif status == QMediaPlayer.StalledMedia:
            self.setStatusInfo('Media Stalled')
        elif status == QMediaPlayer.EndOfMedia:
            Qt.QApplication.alert(self)
        elif status == QMediaPlayer.InvalidMedia:
            self.displayErrorMessage()
        else:
            self.setStatusInfo('')

    def handleCursor(self, status):
        if status in [QMediaPlayer.LoadingMedia, QMediaPlayer.BufferingMedia,
                      QMediaPlayer.StalledMedia]:
            self.setCursor(QtCore.Qt.BusyCursor)
        else:
            self.unsetCursor()

    def setStatusInfo(self, info):
        self.statusInfo = info

        if self.statusInfo:
            self.setWindowTitle('{0} | {1}'.format(
                self.trackInfo, self.statusInfo))
        else:
            self.setWindowTitle(self.trackInfo)

    def bufferingProgress(self, progress):
        self.setStatusInfo('Buffering {0}'.format(progress))

    def displayErrorMessage(self):
        self.statusInfo(self.player.errorString())

    def jump(self, index):
        if index.isValid():
            self.playlist.setCurrentIndex(index.row())
            self.player.play()

    def seek(self, seconds):
        self.player.setPosition(seconds * 1000)

    def previousAction(self):
        self.playlist.previous()

    def close(self):
        choice = Qt.QMessageBox.question(
            self,
            'Close',
            'Close the app?',
            Qt.QMessageBox.Yes | Qt.QMessageBox.No)

        if choice == Qt.QMessageBox.Yes:
            sys.exit()

    def open(self):
        names, _ = Qt.QFileDialog.getOpenFileNames(self, 'Open Files')
        # ['/home/milka/Documents/MusicPlayer/song.mp3']
        self.addToPlaylist(names)

    def addToPlaylist(self, names):
        for name in names:
            fileInfo = Qt.QFileInfo(name)
            if fileInfo.exists():
                url = QtCore.QUrl.fromLocalFile(fileInfo.absoluteFilePath())

                # save_to_db song url
                create_song(
                    url.path(), self.duration, playlist_name=self.name)

                if fileInfo.suffix().lower() == 'm3u':
                    self.playlist.load(url)
                else:
                    self.playlist.addMedia(Qt.QMediaContent(url))
            else:
                url = QtCore.QUrl(name)
                if url.isValid():
                    self.playlist.addMedia(Qt.QMediaContent(url))
Ejemplo n.º 26
0
class MainWindowAction(QMainWindow, Ui_MainWindow):
    def __init__(self, parent=None):
        super(MainWindowAction, self).__init__(parent)

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

        self.local_music_path = []

        self.setupUi(self)
        self.init()
        self.show()

    def init(self):
        # self.setWindowFlags(Qt.FramelessWindowHint)

        self.loadParams()

        self.playlist.setPlaybackMode(self.playlist.Loop)

        self.player.setPlaylist(self.playlist)
        self.player.play()

        exit_normal_icon_path = QUrl.fromLocalFile(EXIT_ICON_PATH)
        self.exit_normal_icon = QIcon(EXIT_ICON_PATH)

        self.exitButton.setStyleSheet(EXIT_BUTTON_STYLE)

        self.exitButton.clicked.connect(self.close)
        self.minButton.clicked.connect(self.showMinimized)
        # self.playButton.clicked.connect(self.playControl)

        self.nextButton.clicked.connect(self.playlist.next)
        self.prevButton.clicked.connect(self.playlist.previous)
        self.playButton.clicked.connect(self.controlPlay)

        self.player.currentMediaChanged.connect(self.initProgressBar)
        self.player.stateChanged.connect(self.changePlayState)
        self.player.positionChanged.connect(self.changeBar)

        self.playProgressBar.sliderReleased.connect(self.changePlayPosition)

    def loadParams(self):
        with open(CONFIG_PATH, 'r') as file:
            params = json.load(file)

            self.local_music_dirs = params['initParams']['LocalMusicDirs']
            last_playlist = params['lastPlayParams']['Playlist']

            self.initPlayList(last_playlist)

    def initPlayList(self, playlist_name):
        playlist_path = './PlayList/' + playlist_name + '.json'
        with open(playlist_path, 'r', encoding='UTF-8') as file:
            music_list = json.load(file)
            music_path_list = music_list['Songs']

        for music_path in music_path_list:
            path = QUrl.fromLocalFile(music_path)
            music = QMediaContent(path)
            self.playlist.addMedia(music)

    def controlPlay(self):
        if self.player.state() == self.player.PlayingState:
            self.player.pause()
            # self.playButton.setText("Play")
        elif self.player.state() == self.player.PausedState:
            self.player.play()
        elif self.player.state() == self.player.StoppedState:
            if self.player.mediaStatus() in [
                    self.player.LoadingMedia, self.player.LoadedMedia,
                    self.player.BufferedMedia, self.player.BufferingMedia
            ]:
                self.player.play()

    def changePlayState(self):
        if self.player.state() == self.player.PlayingState:
            self.playButton.setText("Pause")
        else:
            self.playButton.setText("Play")

    def initProgressBar(self):
        print(self.playlist.currentMedia().resources()[0].url().fileName())
        self.playProgressBar.setValue(0)

    def changeBar(self):

        if self.player.state() == self.player.PlayingState:
            duration = self.player.duration()
            if duration > 0:
                value = self.player.position() * 100 // duration
                self.playProgressBar.setValue(value)

    def changePlayPosition(self):
        self.player.pause()

        duration = self.player.duration()
        value = self.playProgressBar.value() * duration // 100

        self.player.setPosition(value)

        self.player.play()
Ejemplo n.º 27
0
class MyWidget(QMainWindow):
    def __init__(self):
        super().__init__()
        #  !Костыль
        #  Запрещаю менять размер окна, т.к. не хочу работать с layout`ами
        self.setFixedSize(656, 532)
        self.setWindowIcon(QIcon('icons/icon.ico'))

        #  Добавляем эквалайзер громкости
        self.equalizer = QVolumeEq((255, 255, 102), (255, 26, 10), bg_color=(0, 0, 0, 20))
        self.equalizer.setParent(self)
        self.equalizer.move(20, 391)
        self.equalizer.resize(341, 31)

        uic.loadUi('icons/djap.ui', self)

        self.lightThemeAction.triggered.connect(self.change_theme)
        self.darkThemeAction.triggered.connect(self.change_theme)

        #  Создаём организатор плейлистов
        self.playlist_handler = QPlaylistHandler()
        self.playlist_handler.setParent(self)
        self.playlist_handler.move(380, 40)

        #  Настраиваем меню
        self.saveOption.triggered.connect(self.playlist_handler.save_playlist)
        self.saveAsOption.triggered.connect(self.playlist_handler.save_playlist_as)
        self.deleteOption.triggered.connect(self.playlist_handler.delete_playlist)
        self.aboutOption.triggered.connect(self.about)
        self.helpOption.triggered.connect(self.help)
        self.repeatModeOption.triggered.connect(self.playlist_handler.change_playmode)
        self.oneModeOption.triggered.connect(self.playlist_handler.change_playmode)
        self.randomModeOption.triggered.connect(self.playlist_handler.change_playmode)

        #  Реализация проигрывателя и основного плейлиста
        self.player = QMediaPlayer()
        self.player.durationChanged.connect(self.update_song)
        self.player.setVolume(25)
        self.player.positionChanged.connect(self.update_timeline_position)
        self.queue = QMediaPlaylist(self.player)
        self.player.setPlaylist(self.queue)

        self.queue.setPlaybackMode(QMediaPlaylist.Loop)
        self.is_looped_queue = True

        #  Загрузка музыки из плейлиста
        self.load_songs_from_playlist()

        #  Подключаем кнопки к их функциям
        self.is_playing = False
        self.playBtn.clicked.connect(self.play_or_pause)
        self.queue.currentMediaChanged.connect(self.check_to_stop)

        self.nextBtn.clicked.connect(self.next_audio)
        self.prevBtn.clicked.connect(self.prev_audio)

        self.is_looped_current_track = False
        self.loopBtn.clicked.connect(self.loop_or_unloop_current_track)

        #  Настройка слайдера звука
        self.volumeSlider.hide()
        self.volumeSlider.setValue(25)
        self.equalizer.setValue(25)
        self.volumeSlider.sliderReleased.connect(self.volumeSlider.hide)
        self.volumeSlider.valueChanged.connect(self.change_volume)
        self.volumeBtn.clicked.connect(self.change_volume)

        #  Настройка таймлайна
        self.is_timeline_dragged = False
        self.timeline.sliderReleased.connect(self.timeline_changed)
        self.timeline.sliderPressed.connect(self.timeline_is_dragged)

        #  !Костыль
        #  Имитируем запуск аудиодорожки, чтобы подгрузить данные
        self.play_or_pause()
        self.play_or_pause()
        self.icon_changed()

    def palette(self):
        """Функция для создания темы"""
        con = sqlite3.connect('user_data.sqlite')
        cur = con.cursor()
        if int(cur.execute('SELECT * FROM theme').fetchone()[0]):
            palette = QPalette()
            palette.setColor(QPalette.Window, QColor(240, 240, 240))
            palette.setColor(QPalette.WindowText, Qt.black)
            palette.setColor(QPalette.Base, Qt.white)
            palette.setColor(QPalette.AlternateBase, QColor(246, 246, 246))
            palette.setColor(QPalette.ToolTipBase, QColor(255, 255, 240))
            palette.setColor(QPalette.ToolTipText, Qt.black)
            palette.setColor(QPalette.Text, Qt.black)
            palette.setColor(QPalette.Button, QColor(240, 240, 240))
            palette.setColor(QPalette.ButtonText, Qt.black)
            palette.setColor(QPalette.BrightText, Qt.white)
            palette.setColor(QPalette.Highlight, QColor(0, 120, 215).lighter())
            palette.setColor(QPalette.HighlightedText, Qt.white)
        else:
            palette = QPalette()
            palette.setColor(QPalette.Window, QColor(53, 53, 53))
            palette.setColor(QPalette.WindowText, Qt.white)
            palette.setColor(QPalette.Base, QColor(15, 15, 15))
            palette.setColor(QPalette.AlternateBase, QColor(53, 53, 53))
            palette.setColor(QPalette.ToolTipBase, Qt.white)
            palette.setColor(QPalette.ToolTipText, Qt.white)
            palette.setColor(QPalette.Text, Qt.white)
            palette.setColor(QPalette.Button, QColor(53, 53, 53))
            palette.setColor(QPalette.ButtonText, Qt.white)
            palette.setColor(QPalette.BrightText, Qt.red)
            palette.setColor(QPalette.Highlight, QColor(142, 45, 197).lighter())
            palette.setColor(QPalette.HighlightedText, Qt.black)
        return palette

    def change_theme(self):
        """Функция для смены темы"""
        con = sqlite3.connect('user_data.sqlite')
        cur = con.cursor()
        if self.sender() == self.lightThemeAction:
            cur.execute('UPDATE theme SET isit = 1')
        else:
            cur.execute('UPDATE theme SET isit = 0')
        con.commit()

        QMessageBox.warning(self, 'DJust Audio Player', 'Чтобы изменения вступили в силу, '
                                                        'перезапустите приложение.', QMessageBox.Ok)

    def help(self):
        """Функция для показа формы справки"""
        self.help = QHelp()

    def about(self):
        """Функция для показа формы О программе"""
        self.about = QAbout()

    def delete_song_from_mediaplayer(self, index):
        """Удалить трек из медиаплеера"""
        self.queue.removeMedia(index)

    def add_song_to_mediaplayer(self, url):
        """Добавить трек в медиаплеер"""
        self.queue.addMedia(QMediaContent(QUrl(url)))

    def change_track_by_click(self, row):
        """Функция для смены трека по нажатию в списке"""
        self.queue.setCurrentIndex(row)

    def check_to_stop(self):
        """Проверяем, чтобы плеер не играл с пустым плейлистом"""
        if self.queue.isEmpty() and self.is_playing:
            self.play_or_pause()

    def load_songs_from_playlist(self):
        """Загрузка музыки из БД в плейлист"""
        self.queue.clear()
        for url in self.playlist_handler.urls():
            self.queue.addMedia(QMediaContent(QUrl(url)))

    def icon_changed(self):
        """Функция для вывода обложки трека"""

        def noicon():
            """В случае отсутствия обложки эта функция ставить свою заглушку"""
            try:
                pixmap = QPixmap()
                if pixmap.load('icons/noicon.png'):
                    self.audioPic.setPixmap(pixmap)
            except Exception as e:
                print(e.__class__.__name__, ': ', e, sep='')

        try:
            #  Читаем метаданные трека
            n = self.queue.currentIndex()
            url = self.playlist_handler.urls()[n if n > -1 else 0]
            file = File(url)
            for i in file.tags.keys():
                if 'APIC:' in i:
                    artwork = file.tags[i].data
                    break
            else:
                raise KeyError
            #  Переводим их в байтовый массив
            ba = QByteArray(artwork)
            #  И загружаем на форму, если это возможно
            pixmap = QPixmap()
            if pixmap.loadFromData(ba):
                self.audioPic.setPixmap(pixmap.scaled(341, 341, Qt.IgnoreAspectRatio))
            else:
                raise KeyError
        except Exception as e:
            #  print(e.__class__.__name__, ': ', e, sep='')
            noicon()

    def timeline_is_dragged(self):
        """Мини-функция для изменения переменной"""
        #  При вызове этой функции мы понимаем, что пользователь
        #  взаимодействует с таймлайном трека
        self.is_timeline_dragged = True

    def timeline_changed(self):
        """Функция для пользовательской перемотки данного трека"""
        #  Перематываем позицию плеера
        self.player.setPosition(self.timeline.value() * 1000)

        #  Пользователь отпустил язычок слайдера и больше не взаимодействует с таймлайном
        self.is_timeline_dragged = False

        #  Вызываем обновление временной шкалы, т.к. произошла перемотка
        self.update_timeline_position()

    def update_song(self):
        """Изменение данных о треке"""
        #  !Костыль
        #  Проматываем несколько миллисекунд, чтобы избежать повреждённых треков
        self.player.setPosition(10)

        #  Меняем обложку
        self.icon_changed()

        #  Выделяем в списке новый трек
        self.playlist_handler.set_current_select(self.queue.currentIndex())

        #  Меняем название окна в соответствии с играющим треком
        title = self.queue.currentMedia().canonicalUrl().path().split('/')[-1]
        if title:
            self.setWindowTitle('DJust Audio Player | %s' % title)
        else:
            self.setWindowTitle('DJust Audio Player')

        #  Изменяем длину таймлайна на длину трека
        self.timeline.setMaximum(self.player.duration() // 1000)

        #  Выводим длину трека в минутах/секундах на экран
        minutes, seconds = self.player.duration() // 1000 // 60, self.player.duration() // 1000 % 60
        self.endTimeLabel.setText(str(minutes) + ':{:02d}'.format(seconds))

    def update_timeline_position(self):
        """Функция для обновления временной шкалы"""
        #  Выводим текущее положение плеера в минутах/секундах
        minutes, seconds = self.player.position() // 1000 // 60, self.player.position() // 1000 % 60
        self.currentTimeLabel.setText(str(minutes) + ':{:02d}'.format(seconds))

        #  Чтобы не "вырывать" язычок слайдера из рук пользователя,
        #  проверяем, что пользователь НЕ взаимодейтсвует с таймлайном.
        if not self.is_timeline_dragged:
            self.timeline.setValue(minutes * 60 + seconds)

    def loop_or_unloop_current_track(self):
        """Мини-функция для зацикливания данного трека"""
        if not self.is_looped_current_track:
            #  Зацикливаем
            self.is_looped_current_track = True
            self.queue.setPlaybackMode(QMediaPlaylist.CurrentItemInLoop)
            #  Меняем картинку на перечёркнутый круг
            self.loopBtn.setStyleSheet('background-image: url(icons/unloop.png)')
        else:
            #  убираем цикл
            self.is_looped_current_track = False
            self.queue.setPlaybackMode(self.playlist_handler.mode)
            self.loopBtn.setStyleSheet('background-image: url(icons/loop.png)')

    def next_audio(self):
        """Функция для перемотки на следующий в списке трек"""
        if self.queue.mediaCount() - 1 == self.queue.currentIndex():
            #  Если трек ппоследний в списке, возвращаемся к первому
            self.queue.setCurrentIndex(0)
        else:
            #  Иначе просто перемещаемся к следующему
            self.queue.next()

    def prev_audio(self):
        """Функция для перемотки на предыдущий в списке трек"""
        if 0 == self.queue.currentIndex():
            #  Если трек первый в списке, возвращаемся к последнему
            self.queue.setCurrentIndex(self.queue.mediaCount() - 1)
        else:
            #  Иначе просто возвращаемся к предыдущему
            self.queue.previous()

    def play_or_pause(self):
        """Функция для запуска или остановки проигрывателя"""
        if self.queue.isEmpty():
            #  Меняем картинку на стрелочку (проигрывание)
            self.is_playing = False
            self.playBtn.setStyleSheet('background-image: url(icons/play.png)')
            #  Ставим на паузу
            self.player.pause()
            return
        if self.is_playing:
            #  Меняем картинку на стрелочку (проигрывание)
            self.is_playing = False
            self.playBtn.setStyleSheet('background-image: url(icons/play.png)')
            #  Ставим на паузу
            self.player.pause()
        else:
            #  Меняем картинку на 2 палочки (пауза)
            self.is_playing = True
            self.playBtn.setStyleSheet('background-image: url(icons/pause.png)')
            #  Запускаем звук
            self.player.play()

    def change_volume(self):
        """Мини-Функция для передачи уровня громкости в плеер"""
        #  Функцию использует несколько объектов сразу, проверяем вызывателя
        if self.sender() == self.volumeBtn:
            #  Если функцию вызвала кнопка, то включаем/выключаем отображение слайдера
            if not self.volumeSlider.isHidden():
                self.volumeSlider.hide()
            else:
                self.volumeSlider.show()
        else:
            #  Иначе функцию вызвал сам слайдер. Значит, меняем значение
            self.player.setVolume(self.volumeSlider.value())
            self.equalizer.setValue(self.volumeSlider.value())
Ejemplo n.º 28
0
class VideoPlayer(QWidget):

    def __init__(self, aPath, parent=None):
        super(VideoPlayer, self).__init__(parent)

        self.setAttribute( Qt.WA_NoSystemBackground, True )

        self.colorDialog = None

        self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.VideoSurface)
        self.mediaPlayer.setVolume(80)
        self.videoWidget = QVideoWidget(self)
        
        self.lbl = QLineEdit('00:00:00')
        self.lbl.setReadOnly(True)
        self.lbl.setEnabled(False)
        self.lbl.setFixedWidth(60)
        self.lbl.setUpdatesEnabled(True)
        self.lbl.setStyleSheet(stylesheet(self))
        
        self.elbl = QLineEdit('00:00:00')
        self.elbl.setReadOnly(True)
        self.elbl.setEnabled(False)
        self.elbl.setFixedWidth(60)
        self.elbl.setUpdatesEnabled(True)
        self.elbl.setStyleSheet(stylesheet(self))

        self.playButton = QPushButton()
        self.playButton.setEnabled(False)
        self.playButton.setFixedWidth(32)
        self.playButton.setStyleSheet("background-color: black")
        self.playButton.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay))
        self.playButton.clicked.connect(self.play)

        self.positionSlider = QSlider(Qt.Horizontal, self)
        self.positionSlider.setStyleSheet (stylesheet(self)) 
        self.positionSlider.setRange(0, 100)
        self.positionSlider.sliderMoved.connect(self.setPosition)
        self.positionSlider.sliderMoved.connect(self.handleLabel)
        self.positionSlider.setSingleStep(2)
        self.positionSlider.setPageStep(20)
        self.positionSlider.setAttribute(Qt.WA_TranslucentBackground, True)
        
        controlLayout = QHBoxLayout()
        controlLayout.setContentsMargins(5, 0, 5, 0)
        controlLayout.addWidget(self.playButton)
        controlLayout.addWidget(self.lbl)
        controlLayout.addWidget(self.positionSlider)
        controlLayout.addWidget(self.elbl)

        layout = QVBoxLayout()
        layout.setContentsMargins(0, 0, 0, 0)
        layout.addWidget(self.videoWidget)
        layout.addLayout(controlLayout)

        self.setLayout(layout)
        
        self.myinfo = "©2016\nAxel Schneider\n\nMouse Wheel = Zoom\nUP = Volume Up\nDOWN = Volume Down\n" + \
				"LEFT = < 1 Minute\nRIGHT = > 1 Minute\n" + \
				"SHIFT+LEFT = < 10 Minutes\nSHIFT+RIGHT = > 10 Minutes\nf = Fullscreen On/Off"

        self.widescreen = True

        self.setAcceptDrops(True)
        self.setWindowTitle("QT5 Player")
        self.setWindowFlags(Qt.WindowStaysOnTopHint | Qt.FramelessWindowHint)
        self.setGeometry(700, 400, 400, 290)
        self.setContextMenuPolicy(QtCore.Qt.CustomContextMenu);
        self.customContextMenuRequested[QtCore.QPoint].connect(self.contextMenuRequested)
        self.hideSlider()
        self.show()
        self.playFromURL()
		
		#### shortcuts ####
        self.shortcut = QShortcut(QKeySequence("q"), self)
        self.shortcut.activated.connect(self.handleQuit)
        self.shortcut = QShortcut(QKeySequence("u"), self)
        self.shortcut.activated.connect(self.playFromURL)
        self.shortcut = QShortcut(QKeySequence("o"), self)
        self.shortcut.activated.connect(self.openFile)
        self.shortcut = QShortcut(QKeySequence(" "), self)
        self.shortcut.activated.connect(self.play)
        self.shortcut = QShortcut(QKeySequence("f"), self)
        self.shortcut.activated.connect(self.handleFullscreen)
        self.shortcut = QShortcut(QKeySequence("i"), self)
        self.shortcut.activated.connect(self.handleInfo)
        self.shortcut = QShortcut(QKeySequence("s"), self)
        self.shortcut.activated.connect(self.toggleSlider)
        self.shortcut = QShortcut(QKeySequence(Qt.Key_Right), self)
        self.shortcut.activated.connect(self.forwardSlider)
        self.shortcut = QShortcut(QKeySequence(Qt.Key_Left), self)
        self.shortcut.activated.connect(self.backSlider)
        self.shortcut = QShortcut(QKeySequence(Qt.Key_Up), self)
        self.shortcut.activated.connect(self.volumeUp)
        self.shortcut = QShortcut(QKeySequence(Qt.Key_Down), self)
        self.shortcut.activated.connect(self.volumeDown)	
        self.shortcut = QShortcut(QKeySequence(Qt.ShiftModifier +  Qt.Key_Right) , self)
        self.shortcut.activated.connect(self.forwardSlider10)
        self.shortcut = QShortcut(QKeySequence(Qt.ShiftModifier +  Qt.Key_Left) , self)
        self.shortcut.activated.connect(self.backSlider10)
        self.shortcut = QShortcut(QKeySequence("c") , self)
        self.shortcut.activated.connect(self.showColorDialog)

        self.mediaPlayer.setVideoOutput(self.videoWidget)
        self.mediaPlayer.stateChanged.connect(self.mediaStateChanged)
        self.mediaPlayer.positionChanged.connect(self.positionChanged)
        self.mediaPlayer.positionChanged.connect(self.handleLabel)
        self.mediaPlayer.durationChanged.connect(self.durationChanged)
        self.mediaPlayer.error.connect(self.handleError)

    def openFile(self):
        fileName, _ = QFileDialog.getOpenFileName(self, "Open Movie",
                QDir.homePath(), "Videos (*.mp4 *.ts *.avi *.mpeg *.mpg *.mkv *.VOB *.m4v)")

        if fileName != '':
            self.loadFilm(fileName)
            print("File loaded")

    def playFromURL(self):
        self.mediaPlayer.pause()
        clip = QApplication.clipboard()
        myurl = clip.text()
        if myurl.startswith("http"):
            self.mediaPlayer.setMedia(QMediaContent(QUrl(myurl)))
        elif myurl.startswith("/"):
            self.mediaPlayer.setMedia(QMediaContent(QUrl.fromLocalFile(myurl)))
        else:
            return
        self.playButton.setEnabled(True)
        self.mediaPlayer.play()
        self.hideSlider()
        print(myurl)

    def play(self):
        if self.mediaPlayer.state() == QMediaPlayer.PlayingState:
            self.mediaPlayer.pause()
        else:
            self.mediaPlayer.play()
    
    def mediaStateChanged(self, state):
        if self.mediaPlayer.state() == QMediaPlayer.PlayingState:
            self.playButton.setIcon(
                    self.style().standardIcon(QStyle.SP_MediaPause))
        else:
            self.playButton.setIcon(
                    self.style().standardIcon(QStyle.SP_MediaPlay))

    def positionChanged(self, position):
        self.positionSlider.setValue(position)
        
    def durationChanged(self, duration):
        self.positionSlider.setRange(0, duration)
        mtime = QTime(0,0,0,0)
        mtime = mtime.addMSecs(self.mediaPlayer.duration())
        self.elbl.setText(mtime.toString())

    def setPosition(self, position):
        self.mediaPlayer.setPosition(position)

    def handleError(self):
        self.playButton.setEnabled(False)
        print("Error: " + self.mediaPlayer.errorString())

    def handleQuit(self):
        self.mediaPlayer.stop()
        print("Goodbye ...")
        app.quit()
	
    def contextMenuRequested(self,point):
        menu = QtWidgets.QMenu()
        actionFile = menu.addAction("open File (o)")
        actionclipboard = menu.addSeparator() 
        actionURL = menu.addAction("URL / File from Clipboard (u)")
        actionclipboard = menu.addSeparator() 
        actionToggle = menu.addAction("show / hide Slider (s)") 
        actionFull = menu.addAction("Fullscreen (f)")
        action169 = menu.addAction("16 : 9")
        action43 = menu.addAction("4 : 3")
        actionColors = menu.addAction("Color Options (c)")
        actionSep = menu.addSeparator()
        actionInfo = menu.addAction("Info (i)")
        actionsep2 = menu.addSeparator() 
        actionQuit = menu.addAction("Exit (q)") 

        actionFile.triggered.connect(self.openFile)
        actionQuit.triggered.connect(self.handleQuit)
        actionFull.triggered.connect(self.handleFullscreen)
        actionInfo.triggered.connect(self.handleInfo)
        actionToggle.triggered.connect(self.toggleSlider)
        actionURL.triggered.connect(self.playFromURL)
        action169.triggered.connect(self.screen169)
        action43.triggered.connect(self.screen43)
        actionColors.triggered.connect(self.showColorDialog)
        menu.exec_(self.mapToGlobal(point))

    def wheelEvent(self,event):
        mwidth = self.frameGeometry().width()
        mheight = self.frameGeometry().height()
        mleft = self.frameGeometry().left()
        mtop = self.frameGeometry().top()
        mscale = event.angleDelta().y() / 5
        if self.widescreen == True:
            self.setGeometry(mleft, mtop, mwidth + mscale, (mwidth + mscale) / 1.778) 
        else:
            self.setGeometry(mleft, mtop, mwidth + mscale, (mwidth + mscale) / 1.33)            

    def screen169(self):
        self.widescreen = True
        mwidth = self.frameGeometry().width()
        mheight = self.frameGeometry().height()
        mleft = self.frameGeometry().left()
        mtop = self.frameGeometry().top()
        mratio = 1.778
        self.setGeometry(mleft, mtop, mwidth, mwidth / mratio)

    def screen43(self):
        self.widescreen = False
        mwidth = self.frameGeometry().width()
        mheight = self.frameGeometry().height()
        mleft = self.frameGeometry().left()
        mtop = self.frameGeometry().top()
        mratio = 1.33
        self.setGeometry(mleft, mtop, mwidth, mwidth / mratio)

    def handleFullscreen(self):
        if self.windowState() & QtCore.Qt.WindowFullScreen:
            self.showNormal()
            print("no Fullscreen")
        else:
            self.showFullScreen()
            print("Fullscreen entered")

    def handleInfo(self):
            msg = QMessageBox()
            msg.setWindowFlags(Qt.WindowStaysOnTopHint | Qt.SplashScreen)
            msg.setGeometry(self.frameGeometry().left() + 30, self.frameGeometry().top() + 30, 300, 400)
            msg.setIcon(QMessageBox.Information)
            msg.setText("QT5 Player")
            msg.setInformativeText(self.myinfo)
            msg.setStandardButtons(QMessageBox.Close)
            msg.exec()
            
    def toggleSlider(self):	
        if self.positionSlider.isVisible():
            self.hideSlider()
        else:
            self.showSlider()
	
    def hideSlider(self):
            self.playButton.hide()
            self.lbl.hide()
            self.positionSlider.hide()
            self.elbl.hide()
            mwidth = self.frameGeometry().width()
            mheight = self.frameGeometry().height()
            mleft = self.frameGeometry().left()
            mtop = self.frameGeometry().top()
            if self.widescreen == True:
                self.setGeometry(mleft, mtop, mwidth, mwidth / 1.778) 
            else:
                self.setGeometry(mleft, mtop, mwidth, mwidth / 1.33)
	
    def showSlider(self):
            self.playButton.show()
            self.lbl.show()
            self.positionSlider.show()
            self.elbl.show()
            mwidth = self.frameGeometry().width()
            mheight = self.frameGeometry().height()
            mleft = self.frameGeometry().left()
            mtop = self.frameGeometry().top()
            self.positionSlider.setFocus()
            if self.widescreen == True:
                self.setGeometry(mleft, mtop, mwidth, mwidth / 1.55) 
            else:
                self.setGeometry(mleft, mtop, mwidth, mwidth / 1.33)
	
    def forwardSlider(self):
        self.mediaPlayer.setPosition(self.mediaPlayer.position() + 1000*60)

    def forwardSlider10(self):
            self.mediaPlayer.setPosition(self.mediaPlayer.position() + 10000*60)

    def backSlider(self):
        self.mediaPlayer.setPosition(self.mediaPlayer.position() - 1000*60)

    def backSlider10(self):
        self.mediaPlayer.setPosition(self.mediaPlayer.position() - 10000*60)
		
    def volumeUp(self):
        self.mediaPlayer.setVolume(self.mediaPlayer.volume() + 10)
        print("Volume: " + str(self.mediaPlayer.volume()))
	
    def volumeDown(self):
        self.mediaPlayer.setVolume(self.mediaPlayer.volume() - 10)
        print("Volume: " + str(self.mediaPlayer.volume()))
		
    def mouseMoveEvent(self, event):   
        if event.buttons() == Qt.LeftButton:
            self.move(event.globalPos() \
						- QPoint(self.frameGeometry().width() / 2, \
						self.frameGeometry().height() / 2))
            event.accept() 
		
    def dragEnterEvent(self, event):
        if event.mimeData().hasUrls():
            event.accept()
        elif event.mimeData().hasFormat('text/plain'):
            event.accept()
        else:
            event.ignore()

########### drag files #############
    def dropEvent(self, event):
        if event.mimeData().hasUrls():
            f = str(event.mimeData().urls()[0].toLocalFile())
            self.loadFilm(f)
        elif event.mimeData().hasText():
            f = str(event.mimeData().text())
            self.mediaPlayer.setMedia(QMediaContent(QUrl(f)))
            self.mediaPlayer.play()
	
    def loadFilm(self, f):
            self.mediaPlayer.setMedia(QMediaContent(QUrl.fromLocalFile(f)))
            self.playButton.setEnabled(True)
            self.mediaPlayer.play()
            print(str(self.mediaPlayer.media().canonicalResource().resolution()))
	  
    def openFileAtStart(self, filelist):
            matching = [s for s in filelist if ".myformat" in s]
            if len(matching) > 0:
                self.loadFilm(matching)

##################### update Label ##################################
    def handleLabel(self):
            self.lbl.clear()
            mtime = QTime(0,0,0,0)
            self.time = mtime.addMSecs(self.mediaPlayer.position())
            self.lbl.setText(self.time.toString())
###################################################################

    def showColorDialog(self):
        if self.colorDialog is None:
            brightnessSlider = QSlider(Qt.Horizontal)
            brightnessSlider.setRange(-100, 100)
            brightnessSlider.setValue(self.videoWidget.brightness())
            brightnessSlider.sliderMoved.connect(
                    self.videoWidget.setBrightness)
            self.videoWidget.brightnessChanged.connect(
                    brightnessSlider.setValue)

            contrastSlider = QSlider(Qt.Horizontal)
            contrastSlider.setRange(-100, 100)
            contrastSlider.setValue(self.videoWidget.contrast())
            contrastSlider.sliderMoved.connect(self.videoWidget.setContrast)
            self.videoWidget.contrastChanged.connect(contrastSlider.setValue)

            hueSlider = QSlider(Qt.Horizontal)
            hueSlider.setRange(-100, 100)
            hueSlider.setValue(self.videoWidget.hue())
            hueSlider.sliderMoved.connect(self.videoWidget.setHue)
            self.videoWidget.hueChanged.connect(hueSlider.setValue)

            saturationSlider = QSlider(Qt.Horizontal)
            saturationSlider.setRange(-100, 100)
            saturationSlider.setValue(self.videoWidget.saturation())
            saturationSlider.sliderMoved.connect(
                    self.videoWidget.setSaturation)
            self.videoWidget.saturationChanged.connect(
                    saturationSlider.setValue)

            layout = QFormLayout()
            layout.addRow("Brightness", brightnessSlider)
            layout.addRow("Contrast", contrastSlider)
            layout.addRow("Hue", hueSlider)
            layout.addRow("Saturation", saturationSlider)

            button = QPushButton("Close Window")
            button.setFixedWidth(120)
            layout.addRow(button)

            self.colorDialog = QDialog(self)
            self.colorDialog.setWindowTitle("Color Options")
            self.colorDialog.setLayout(layout)

            button.clicked.connect(self.colorDialog.close)
            self.colorDialog.setGeometry(300, 250, 300, 100)

        self.colorDialog.show()
Ejemplo n.º 29
0
class MP3Player(QWidget):
    def __init__(self):
        super().__init__()

        self.startTimeLabel = QLabel('00:00')
        self.endTimeLabel = QLabel('00:00')
        self.slider = QSlider(Qt.Horizontal, self)
        self.PlayModeBtn = QPushButton(self)
        self.playBtn = QPushButton(self)
        self.prevBtn = QPushButton(self)
        self.nextBtn = QPushButton(self)
        self.openBtn = QPushButton(self)
        self.musicList = QListWidget()
        self.song_formats = ['mp3', 'm4a', 'flac', 'wav', 'ogg']
        self.songs_list = []
        self.cur_playing_song = ''
        self.is_pause = True
        self.player = QMediaPlayer()
        self.is_switching = False
        self.playMode = 0
        self.settingfilename = 'config.ini'
        self.textLable = QLabel('前进的路上,也要记得欣赏沿途的风景呀!')
        self.infoLabel = QLabel('Mculover666 v2.0.0')

        self.playBtn.setStyleSheet(
            "QPushButton{border-image: url(resource/image/play.png)}")
        self.playBtn.setFixedSize(48, 48)
        self.nextBtn.setStyleSheet(
            "QPushButton{border-image: url(resource/image/next.png)}")
        self.nextBtn.setFixedSize(48, 48)
        self.prevBtn.setStyleSheet(
            "QPushButton{border-image: url(resource/image/prev.png)}")
        self.prevBtn.setFixedSize(48, 48)
        self.openBtn.setStyleSheet(
            "QPushButton{border-image: url(resource/image/open.png)}")
        self.openBtn.setFixedSize(24, 24)
        self.PlayModeBtn.setStyleSheet(
            "QPushButton{border-image: url(resource/image/sequential.png)}")
        self.PlayModeBtn.setFixedSize(24, 24)

        self.timer = QTimer(self)
        self.timer.start(1000)
        self.timer.timeout.connect(self.playByMode)

        self.hBoxSlider = QHBoxLayout()
        self.hBoxSlider.addWidget(self.startTimeLabel)
        self.hBoxSlider.addWidget(self.slider)
        self.hBoxSlider.addWidget(self.endTimeLabel)

        self.hBoxButton = QHBoxLayout()
        self.hBoxButton.addWidget(self.PlayModeBtn)
        self.hBoxButton.addStretch(1)
        self.hBoxButton.addWidget(self.prevBtn)
        self.hBoxButton.addWidget(self.playBtn)
        self.hBoxButton.addWidget(self.nextBtn)
        self.hBoxButton.addStretch(1)
        self.hBoxButton.addWidget(self.openBtn)

        self.vBoxControl = QVBoxLayout()
        self.vBoxControl.addLayout(self.hBoxSlider)
        self.vBoxControl.addLayout(self.hBoxButton)

        self.hBoxAbout = QHBoxLayout()
        self.hBoxAbout.addWidget(self.textLable)
        self.hBoxAbout.addStretch(1)
        self.hBoxAbout.addWidget(self.infoLabel)

        self.vboxMain = QVBoxLayout()
        self.vboxMain.addWidget(self.musicList)
        self.vboxMain.addLayout(self.vBoxControl)
        self.vboxMain.addLayout(self.hBoxAbout)

        self.setLayout(self.vboxMain)

        self.openBtn.clicked.connect(self.openMusicFloder)
        self.playBtn.clicked.connect(self.playMusic)
        self.prevBtn.clicked.connect(self.prevMusic)
        self.nextBtn.clicked.connect(self.nextMusic)
        self.musicList.itemDoubleClicked.connect(self.doubleClicked)
        self.slider.sliderMoved[int].connect(
            lambda: self.player.setPosition(self.slider.value()))
        self.PlayModeBtn.clicked.connect(self.playModeSet)

        self.loadingSetting()

        self.initUI()

    # 初始化界面
    def initUI(self):
        self.resize(600, 400)
        self.center()
        self.setWindowTitle('音乐播放器')
        self.setWindowIcon(QIcon('resource/image/favicon.ico'))
        self.show()

    # 窗口显示居中
    def center(self):
        qr = self.frameGeometry()
        cp = QDesktopWidget().availableGeometry().center()
        qr.moveCenter(cp)
        self.move(qr.topLeft())

    # 打开文件夹
    def openMusicFloder(self):
        self.cur_path = QFileDialog.getExistingDirectory(self, "选取音乐文件夹", './')
        if self.cur_path:
            self.showMusicList()
            self.cur_playing_song = ''
            self.startTimeLabel.setText('00:00')
            self.endTimeLabel.setText('00:00')
            self.slider.setSliderPosition(0)
            self.updateSetting()
            self.is_pause = True
            self.playBtn.setStyleSheet(
                "QPushButton{border-image: url(resource/image/play.png)}")

    # 显示音乐列表
    def showMusicList(self):
        self.musicList.clear()
        for song in os.listdir(self.cur_path):
            if song.split('.')[-1] in self.song_formats:
                self.songs_list.append([
                    song,
                    os.path.join(self.cur_path, song).replace('\\', '/')
                ])
                self.musicList.addItem(song)
        self.musicList.setCurrentRow(0)
        if self.songs_list:
            self.cur_playing_song = self.songs_list[
                self.musicList.currentRow()][-1]

    # 提示
    def Tips(self, message):
        QMessageBox.about(self, "提示", message)

    # 设置当前播放的音乐
    def setCurPlaying(self):
        self.cur_playing_song = self.songs_list[
            self.musicList.currentRow()][-1]
        self.player.setMedia(QMediaContent(QUrl(self.cur_playing_song)))

    # 播放/暂停播放
    def playMusic(self):
        if self.musicList.count() == 0:
            self.Tips('当前路径内无可播放的音乐文件')
            return
        if not self.player.isAudioAvailable():
            self.setCurPlaying()
        if self.is_pause or self.is_switching:
            self.player.play()
            self.is_pause = False
            self.playBtn.setStyleSheet(
                "QPushButton{border-image: url(resource/image/pause.png)}")
        elif (not self.is_pause) and (not self.is_switching):
            self.player.pause()
            self.is_pause = True
            self.playBtn.setStyleSheet(
                "QPushButton{border-image: url(resource/image/play.png)}")

    # 上一曲
    def prevMusic(self):
        self.slider.setValue(0)
        if self.musicList.count() == 0:
            self.Tips('当前路径内无可播放的音乐文件')
            return
        pre_row = self.musicList.currentRow() - 1 if self.musicList.currentRow(
        ) != 0 else self.musicList.count() - 1
        self.musicList.setCurrentRow(pre_row)
        self.is_switching = True
        self.setCurPlaying()
        self.playMusic()
        self.is_switching = False

    # 下一曲
    def nextMusic(self):
        self.slider.setValue(0)
        if self.musicList.count() == 0:
            self.Tips('当前路径内无可播放的音乐文件')
            return
        next_row = self.musicList.currentRow(
        ) + 1 if self.musicList.currentRow(
        ) != self.musicList.count() - 1 else 0
        self.musicList.setCurrentRow(next_row)
        self.is_switching = True
        self.setCurPlaying()
        self.playMusic()
        self.is_switching = False

    # 双击歌曲名称播放音乐
    def doubleClicked(self):
        self.slider.setValue(0)
        self.is_switching = True
        self.setCurPlaying()
        self.playMusic()
        self.is_switching = False

    # 根据播放模式自动播放,并刷新进度条
    def playByMode(self):
        # 刷新进度条
        if (not self.is_pause) and (not self.is_switching):
            self.slider.setMinimum(0)
            self.slider.setMaximum(self.player.duration())
            self.slider.setValue(self.slider.value() + 1000)
        self.startTimeLabel.setText(
            time.strftime('%M:%S',
                          time.localtime(self.player.position() / 1000)))
        self.endTimeLabel.setText(
            time.strftime('%M:%S',
                          time.localtime(self.player.duration() / 1000)))
        # 顺序播放
        if (self.playMode
                == 0) and (not self.is_pause) and (not self.is_switching):
            if self.musicList.count() == 0:
                return
            if self.player.position() == self.player.duration():
                self.nextMusic()
        # 单曲循环
        elif (self.playMode
              == 1) and (not self.is_pause) and (not self.is_switching):
            if self.musicList.count() == 0:
                return
            if self.player.position() == self.player.duration():
                self.is_switching = True
                self.setCurPlaying()
                self.slider.setValue(0)
                self.playMusic()
                self.is_switching = False
        # 随机播放
        elif (self.playMode
              == 2) and (not self.is_pause) and (not self.is_switching):
            if self.musicList.count() == 0:
                return
            if self.player.position() == self.player.duration():
                self.is_switching = True
                self.musicList.setCurrentRow(
                    random.randint(0,
                                   self.musicList.count() - 1))
                self.setCurPlaying()
                self.slider.setValue(0)
                self.playMusic()
                self.is_switching = False

    # 更新配置文件
    def updateSetting(self):
        config = configparser.ConfigParser()
        config.read(self.settingfilename)
        if not os.path.isfile(self.settingfilename):
            config.add_section('MP3Player')
        config.set('MP3Player', 'PATH', self.cur_path)
        config.write(open(self.settingfilename, 'w'))

    # 加载配置文件
    def loadingSetting(self):
        config = configparser.ConfigParser()
        config.read(self.settingfilename)
        if not os.path.isfile(self.settingfilename):
            return
        self.cur_path = config.get('MP3Player', 'PATH')
        self.showMusicList()

    # 播放模式设置
    def playModeSet(self):
        # 设置为单曲循环模式
        if self.playMode == 0:
            self.playMode = 1
            self.PlayModeBtn.setStyleSheet(
                "QPushButton{border-image: url(resource/image/circulation.png)}"
            )
        # 设置为随机播放模式
        elif self.playMode == 1:
            self.playMode = 2
            self.PlayModeBtn.setStyleSheet(
                "QPushButton{border-image: url(resource/image/random.png)}")
        # 设置为顺序播放模式
        elif self.playMode == 2:
            self.playMode = 0
            self.PlayModeBtn.setStyleSheet(
                "QPushButton{border-image: url(resource/image/sequential.png)}"
            )

    # 确认用户是否要真正退出
    def closeEvent(self, event):
        reply = QMessageBox.question(self, 'Message', "确定要退出吗?",
                                     QMessageBox.Yes | QMessageBox.No,
                                     QMessageBox.No)
        if reply == QMessageBox.Yes:
            event.accept()
        else:
            event.ignore()
Ejemplo n.º 30
0
class MainWindow(QMainWindow):
    def __init__(self):
        QMainWindow.__init__(self)
        self.ui = loadUi('forms/mainwindow.ui', self)
        # self.ui = Ui_MainWindow()
        # self.ui.setupUi(self)
        self.input_name = None
        self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.VideoSurface)
        self.videoWidget = VideoWidget(self)
        self.detector = CellDetector()
        layout = QVBoxLayout()
        layout.setContentsMargins(0, 0, 0, 0)
        layout.addWidget(self.videoWidget)
        self.ui.videoFrame.setLayout(layout)
        self.ui.playButton.setEnabled(False)
        self.ui.playButton.setIcon(self.style().standardIcon(
            QStyle.SP_MediaPlay))
        self.ui.playButton.clicked.connect(self.play)
        self.ui.openButton.clicked.connect(self.openFile)
        self.ui.saveButton.clicked.connect(self.saveFile)
        self.ui.saveButton.setEnabled(False)
        self.ui.timeSlider.sliderMoved.connect(self.setPosition)
        self.ui.modeCheckBox.stateChanged.connect(self.switchMode)
        self.ui.statusbar: QStatusBar
        self.ui.statusbar.showMessage("Init Model ...")
        # self.ui.statusbar.setLayout()
        self.mediaPlayer.setVideoOutput(self.videoWidget.videoSurface())
        self.mediaPlayer.stateChanged.connect(self.mediaStateChanged)
        self.mediaPlayer.positionChanged.connect(self.positionChanged)
        self.mediaPlayer.durationChanged.connect(self.durationChanged)
        self.mediaPlayer.setMuted(True)
        # shortcut
        QShortcut(QKeySequence('Space'), self).activated.connect(self.play)
        # s_max = self.maximumSize()
        # # self.ui.statusBar.setSizeGripEnabled(False)
        # self.show()
        # self.setFixedSize(s_max)

    def showEvent(self, *args, **kwargs):
        self.detector.onInitModelSuccess.connect(
            lambda: self.ui.statusbar.showMessage("Ready"))
        self.detector.initModel()

    def closeEvent(self, *args, **kwargs):
        QApplication.closeAllWindows()

    def switchMode(self, state):
        self.detector.setMode(state)
        self.startProcess()

    def startProcess(self):
        if self.input_name:
            self.ui.listWidget.clear()
            self.sum_cells = 0
            self.log = []
            self.mediaPlayer.setMedia(
                QMediaContent(QUrl.fromLocalFile(self.input_name)))
            self.cap = cv2.VideoCapture(self.input_name)
            VideoInfo.init(self.cap)
            self.frameCount = int(self.cap.get(cv2.CAP_PROP_FRAME_COUNT))
            fps = np.ceil(self.cap.get(cv2.CAP_PROP_FPS))
            window_time = 2  # sec
            dialog = ProcessDialog(self)
            dialog.setMaximum(self.frameCount)
            map_worker = ObjectMapper(self.frameCount, fps)
            map_worker.onUpdateObject.connect(self.updateObject)
            map_worker.onUpdateProgress.connect(dialog.updateProgress)
            ppc_worker = PreprocessThread(self.input_name)
            ppc_worker.onFrameChanged.connect(map_worker.updateOpticalFlow)
            ppc_worker.onFrameChanged.connect(self.detector.updateOpticalFlow)
            ppc_worker.onBufferReady.connect(self.detector.detect)
            ppc_worker.onUpdateProgress.connect(dialog.updateProgress)
            map_worker.onNewDetectedCells.connect(self.updateDetectLog)
            map_worker.finished.connect(dialog.close)
            dialog.closed.connect(ppc_worker.quit)
            dialog.closed.connect(map_worker.quit)
            self.detector.onDetectSuccess.connect(map_worker.queueOutput)
            # ppc_worker.finished.connect(dialog.close)
            # dialog.onReady2Read.connect(self.setOutput)
            dialog.show()
            map_worker.start()
            ppc_worker.start()
            dialog.exec_()
            self.ui.playButton.setEnabled(True)
            self.ui.saveButton.setEnabled(True)

    def openFile(self):
        file_name = QFileDialog.getOpenFileName(self, "Open Video")[0]
        if os.path.exists(file_name):
            self.input_name = file_name
            self.startProcess()

    def saveFile(self):
        dialog = SaveDialog()
        dialog.exec_()
        head, tail = os.path.split(self.input_name)
        file_prefix = tail.split('.')[0]
        worker = VideoWriterThread(self.cap, self.frame_objects, self.log,
                                   file_prefix, dialog.getSaveDirectory(),
                                   dialog.isSaveImage, dialog.isSaveVideo)
        worker.start()

    def updateObject(self, frame_objects):
        self.frame_objects = frame_objects
        duration = self.mediaPlayer.duration()
        self.videoWidget.setOutput(frame_objects, duration / self.frameCount)
        self.ui.playButton.setEnabled(True)
        self.ui.saveButton.setEnabled(True)

    def updateDetectLog(self, detected_frame_id, cell_map, cell_count):
        # append log
        widget = QCustomQWidget()
        self.sum_cells += cell_count
        self.cap.set(cv2.CAP_PROP_POS_FRAMES, detected_frame_id)
        _, image = self.cap.read()
        _, min, sec = getHHMMSSFormat(self.mediaPlayer.duration() /
                                      self.frameCount * detected_frame_id)
        time_text = '{:02}-{:02}'.format(min, sec)
        self.log.append({
            "image": image.copy(),
            "detect_time": time_text,
            "cells": cell_map
        })
        drawBoxes(image, cell_map, (0, 255, 0))
        icon = imutils.resize(image, height=64)
        icon = toQImage(icon)
        widget.setPreviewImg(icon)
        widget.setCount(cell_count)
        widget.setDetectionFramePosition(self.mediaPlayer.duration() /
                                         self.frameCount * detected_frame_id)
        widget.setTimeText('{:02}:{:02}'.format(min, sec))
        # widget.onDoubleClick.connect(self.positionChanged)
        widget.onDoubleClick.connect(self.setPosition)
        list_widget_item = QListWidgetItem(self.ui.listWidget)
        list_widget_item.setSizeHint(widget.size())
        self.ui.listWidget.addItem(list_widget_item)
        self.ui.listWidget.setItemWidget(list_widget_item, widget)
        self.ui.totalNumber.display(self.sum_cells)

    def play(self):
        if self.mediaPlayer.state() == QMediaPlayer.PlayingState:
            self.mediaPlayer.pause()
        else:
            self.mediaPlayer.play()

    def mediaStateChanged(self, state):
        if state == QMediaPlayer.PlayingState:
            self.ui.playButton.setIcon(self.style().standardIcon(
                QStyle.SP_MediaPause))
        else:
            self.ui.playButton.setIcon(self.style().standardIcon(
                QStyle.SP_MediaPlay))

    def positionChanged(self, position):
        self.ui.timeSlider.setValue(position)
        duration = self.mediaPlayer.duration()
        _, dmin, dsec = getHHMMSSFormat(duration)
        _, pmin, psec = getHHMMSSFormat(position)
        self.ui.timeLabel.setText('{:02}:{:02}/{:02}:{:02}'.format(
            int(pmin), int(psec), int(dmin), int(dsec)))

    def durationChanged(self, duration):
        self.ui.timeSlider.setRange(0, duration)
        _, dmin, dsec = getHHMMSSFormat(duration)
        self.ui.timeLabel.setText('00:00/{:02}:{:02}'.format(
            int(dmin), int(dsec)))

    def setPosition(self, position):
        self.mediaPlayer.setPosition(position)
Ejemplo n.º 31
0
class Ui_Form(object):
    def setupUi(self, Form):
        Form.setObjectName("Form")
        Form.resize(1200, 720)
        Form.setMinimumSize(QtCore.QSize(200, 199))
        Form.setStyleSheet("background-color:black;")

        self.isOnline = False
        self.isMini = False
        self.isOnTop = True
        self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.VideoSurface)

        self.verticalLayout_2 = QtWidgets.QVBoxLayout(Form)
        self.verticalLayout_2.setContentsMargins(0, 0, 0, 0)
        self.verticalLayout_2.setSpacing(0)
        self.verticalLayout_2.setObjectName("verticalLayout_2")

        self.mainFrame = QtWidgets.QFrame(Form)
        self.mainFrame.setMinimumSize(QtCore.QSize(200, 82))
        self.mainFrame.setFrameShape(QtWidgets.QFrame.StyledPanel)
        self.mainFrame.setFrameShadow(QtWidgets.QFrame.Raised)
        self.mainFrame.setObjectName("mainFrame")
        self.verticalLayout = QtWidgets.QVBoxLayout(self.mainFrame)
        self.verticalLayout.setContentsMargins(0, 0, 0, 0)
        self.verticalLayout.setSpacing(0)
        self.verticalLayout.setObjectName("verticalLayout")
        self.frame_3 = QtWidgets.QFrame(self.mainFrame)
        sizePolicy = QtWidgets.QSizePolicy(
            QtWidgets.QSizePolicy.MinimumExpanding,
            QtWidgets.QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.frame_3.sizePolicy().hasHeightForWidth())
        self.frame_3.setSizePolicy(sizePolicy)
        self.frame_3.setFrameShape(QtWidgets.QFrame.StyledPanel)
        self.frame_3.setFrameShadow(QtWidgets.QFrame.Raised)
        self.frame_3.setObjectName("frame_3")
        self.horizontalLayout_6 = QtWidgets.QHBoxLayout(self.frame_3)
        self.horizontalLayout_6.setContentsMargins(0, 0, 0, 0)
        self.horizontalLayout_6.setObjectName("horizontalLayout_6")
        self.Player_name = QtWidgets.QLabel(self.frame_3)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding,
                                           QtWidgets.QSizePolicy.Preferred)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.Player_name.sizePolicy().hasHeightForWidth())
        self.Player_name.setSizePolicy(sizePolicy)
        self.Player_name.setStyleSheet("QLabel\n"
                                       "    {\n"
                                       "    font: 12pt \"Helvetica\";\n"
                                       "    color: white;\n"
                                       "    border: 0px solid #076100;\n"
                                       "    }")
        self.Player_name.setObjectName("status_label")
        self.horizontalLayout_6.addWidget(self.Player_name)
        spacerItem = QtWidgets.QSpacerItem(40, 20,
                                           QtWidgets.QSizePolicy.Expanding,
                                           QtWidgets.QSizePolicy.Minimum)
        self.horizontalLayout_6.addItem(spacerItem)
        self.minimize_button = QtWidgets.QPushButton(self.frame_3)
        self.minimize_button.setCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor))
        self.minimize_button.setText("")
        icon = QtGui.QIcon()
        icon.addPixmap(QtGui.QPixmap("icon_sets/minimize.png"),
                       QtGui.QIcon.Normal, QtGui.QIcon.Off)
        self.minimize_button.setIconSize(QSize(25, 17))
        self.minimize_button.setMaximumSize(QSize(25, 17))
        self.minimize_button.setIcon(icon)
        self.minimize_button.setIconSize(QtCore.QSize(27, 20))
        # self.minimize_button.setFlat(True)
        self.minimize_button.setObjectName("minimize_button")
        self.horizontalLayout_6.addWidget(self.minimize_button)
        self.maximize_button = QtWidgets.QPushButton(self.frame_3)
        self.maximize_button.setCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor))
        self.maximize_button.setText("")
        icon1 = QtGui.QIcon()
        icon1.addPixmap(QtGui.QPixmap("icon_sets/maximize.png"),
                        QtGui.QIcon.Normal, QtGui.QIcon.Off)
        self.maximize_button.setIcon(icon1)
        self.maximize_button.setIconSize(QSize(25, 17))
        self.maximize_button.setMaximumSize(QSize(25, 17))
        self.maximize_button.setIconSize(QtCore.QSize(27, 20))
        # self.maximize_button.setFlat(True)
        self.maximize_button.setObjectName("maximize_button")
        self.horizontalLayout_6.addWidget(self.maximize_button)
        self.cross_button = QtWidgets.QPushButton(self.frame_3)
        self.cross_button.setCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor))
        self.cross_button.setText("")
        self.cross_button.setIconSize(QSize(25, 17))
        self.cross_button.setMaximumSize(QSize(25, 17))
        icon2 = QtGui.QIcon()
        icon2.addPixmap(QtGui.QPixmap("icon_sets/cross.png"),
                        QtGui.QIcon.Normal, QtGui.QIcon.Off)
        self.cross_button.setIcon(icon2)
        self.cross_button.setIconSize(QtCore.QSize(27, 20))
        # self.cross_button.setFlat(True)
        self.cross_button.setObjectName("cross_button")
        self.horizontalLayout_6.addWidget(self.cross_button)
        self.verticalLayout.addWidget(self.frame_3)

        self.video_playback = Videowidget(self.frame_3)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum,
                                           QtWidgets.QSizePolicy.Minimum)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(200)
        sizePolicy.setHeightForWidth(
            self.video_playback.sizePolicy().hasHeightForWidth())
        self.video_playback.setSizePolicy(sizePolicy)
        self.video_playback.setMinimumSize(QtCore.QSize(200, 100))
        self.video_playback.setMouseTracking(False)
        self.video_playback.setTabletTracking(False)
        self.video_playback.setAcceptDrops(False)
        self.video_playback.setAutoFillBackground(False)
        self.video_playback.setObjectName("video_playback")
        self.video_playback.setStyleSheet("background-color:grey")

        self.verticalLayout.addWidget(self.video_playback)
        self.pos_frame = QtWidgets.QFrame(self.mainFrame)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred,
                                           QtWidgets.QSizePolicy.Preferred)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(10)
        sizePolicy.setHeightForWidth(
            self.pos_frame.sizePolicy().hasHeightForWidth())
        self.pos_frame.setSizePolicy(sizePolicy)
        self.pos_frame.setFrameShape(QtWidgets.QFrame.StyledPanel)
        self.pos_frame.setFrameShadow(QtWidgets.QFrame.Raised)
        self.pos_frame.setObjectName("pos_frame")
        self.horizontalLayout = QtWidgets.QHBoxLayout(self.pos_frame)
        self.horizontalLayout.setObjectName("horizontalLayout")

        self.position_slider = PosSlider(self.pos_frame)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum,
                                           QtWidgets.QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(100)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.position_slider.sizePolicy().hasHeightForWidth())
        self.position_slider.setSizePolicy(sizePolicy)
        self.position_slider.setMouseTracking(True)
        self.position_slider.setAutoFillBackground(False)
        self.position_slider.setStyleSheet(
            "QSlider::handle:horizontal \n"
            "    {\n"
            "    background: transparent;\n"
            "    width: 8px;\n"
            "    }\n"
            "QSlider::groove:horizontal {\n"
            "    border: 1px solid white;\n"
            "    height: 8px;\n"
            "    background: qlineargradient(y1: 0, y2: 1,stop: 0 #2e3436, stop: 1.0 #000000);\n"
            "}\n"
            " QSlider::sub-page:horizontal {\n"
            "    background:qlineargradient( y1: 0, y2: 1,\n"
            "        stop: 0 #42a6db, stop: 1 #0074e0); \n"
            "    border: 1px solid white;\n"
            "    height: 8px;\n"
            "}\n"
            "QSlider::handle:horizontal:hover {\n"
            "    background: black;\n"
            "    height: 8px;\n"
            "    width: 8px;\n"
            "    border: 1px solid white;\n"
            "    }\n"
            "")
        self.position_slider.setOrientation(QtCore.Qt.Horizontal)
        self.position_slider.setInvertedAppearance(False)
        self.position_slider.setInvertedControls(False)
        self.position_slider.setObjectName("position_slider")
        self.horizontalLayout.addWidget(self.position_slider)

        self.time_status = QtWidgets.QLabel(self.pos_frame)
        font = QtGui.QFont()
        font.setFamily("Arial Rounded MT Bold")
        font.setPointSize(8)
        font.setBold(False)
        font.setItalic(False)
        font.setWeight(50)
        self.time_status.setFont(font)
        self.time_status.setStyleSheet(
            "QLabel\n"
            "    {\n"
            "    \n"
            "    font: 8pt \"Arial Rounded MT Bold\";\n"
            "    color: white;\n"
            "    border: 0px solid #076100;\n"
            "\n"
            "    }")
        self.time_status.setObjectName("time_status")
        self.horizontalLayout.addWidget(self.time_status)

        self.backslash = QtWidgets.QLabel(self.pos_frame)
        font = QtGui.QFont()
        font.setFamily("Arial Rounded MT Bold")
        font.setPointSize(8)
        font.setBold(False)
        font.setItalic(False)
        font.setWeight(50)
        self.backslash.setFont(font)
        self.backslash.setStyleSheet(
            "QLabel\n"
            "    {\n"
            "    \n"
            "    font: 8pt \"Arial Rounded MT Bold\";\n"
            "    color: white;\n"
            "    border: 0px solid #076100;\n"
            "\n"
            "    }")
        self.backslash.setObjectName("backslash")
        self.horizontalLayout.addWidget(self.backslash)

        self.duration_status = QtWidgets.QLabel(self.pos_frame)
        font = QtGui.QFont()
        font.setFamily("Arial Rounded MT Bold")
        font.setPointSize(8)
        font.setBold(False)
        font.setItalic(False)
        font.setWeight(50)
        self.duration_status.setFont(font)
        self.duration_status.setStyleSheet(
            "QLabel\n"
            "    {\n"
            "    \n"
            "    font: 8pt \"Arial Rounded MT Bold\";\n"
            "    color: white;\n"
            "    border: 0px solid #076100;\n"
            "\n"
            "    }")
        self.duration_status.setObjectName("duration_status")
        self.horizontalLayout.addWidget(self.duration_status)
        self.verticalLayout.addWidget(self.pos_frame)

        self.frame_2 = QtWidgets.QFrame(self.mainFrame)
        sizePolicy = QtWidgets.QSizePolicy(
            QtWidgets.QSizePolicy.MinimumExpanding,
            QtWidgets.QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(22)
        # sizePolicy.setHeightForWidth(self.frame_2.sizePolicy().hasHeightForWidth())

        self.frame_2.setSizePolicy(sizePolicy)
        self.frame_2.setContentsMargins(0, 0, 0, 0)
        self.frame_2.setFrameShape(QtWidgets.QFrame.StyledPanel)
        self.frame_2.setFrameShadow(QtWidgets.QFrame.Raised)
        self.frame_2.setObjectName("frame_2")
        self.frame_2.setStyleSheet("")
        self.horizontalLayout_4 = QtWidgets.QHBoxLayout(self.frame_2)
        self.horizontalLayout_4.setObjectName("horizontalLayout_4")

        self.play_button = QtWidgets.QPushButton(self.frame_2)
        self.play_button.setEnabled(False)
        self.play_button.setCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor))
        self.play_button.setStyleSheet(
            "QPushButton[play=true]{image:url(icon_sets/play/play.png);width:22px;height:22px}\n"
            "QPushButton[play=false]{image:url(icon_sets/pause/pause.png);width:22px;height:22px }\n"
        )
        self.play_button.setProperty("play", True)
        self.play_button.setText("")
        self.play_button.setObjectName("play_button")
        self.horizontalLayout_4.addWidget(self.play_button)

        self.playback_button = QtWidgets.QPushButton(self.frame_2)
        self.playback_button.setCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor))
        self.playback_button.setStyleSheet(
            "QPushButton{image:url(icon_sets/playback/playback.png);width:22px;height:22px }\n"
        )
        self.playback_button.setText("")
        self.playback_button.setObjectName("playback_button")
        self.horizontalLayout_4.addWidget(self.playback_button)

        self.always_on_top_button = QtWidgets.QPushButton(self.frame_2)
        self.always_on_top_button.setCursor(
            QtGui.QCursor(QtCore.Qt.ArrowCursor))
        self.always_on_top_button.setStyleSheet(
            "QPushButton[top=false]{image : url(icon_sets/always_on_top/top_off.png) }\n"
            "QPushButton[top=true]{image : url(icon_sets/always_on_top/top_on.png) }\n"
        )
        self.always_on_top_button.setProperty("top", True)
        self.always_on_top_button.setText("")
        self.always_on_top_button.setObjectName("always_on_top_button")
        self.horizontalLayout_4.addWidget(self.always_on_top_button)

        self.miniplayer_button = QtWidgets.QPushButton(self.frame_2)
        self.miniplayer_button.setCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor))
        self.miniplayer_button.setStyleSheet(
            "QPushButton[mini=false]{image : url(icon_sets/standard_player/standard.png) }\n"
            # "QPushButton[mini=false]:hover{ image:url(icon_sets/standard_player/.png) }\n"
            "QPushButton[mini=true]{image : url(icon_sets/mini_player/mini.png) }\n"
            # "QPushButton[mini=true]:hover{ image:url(icon_sets/mini_player/.png) }\n"
        )
        self.miniplayer_button.setProperty("mini", False)
        self.miniplayer_button.setContentsMargins(0, 0, 0, 0)
        self.miniplayer_button.setText("")
        self.miniplayer_button.setObjectName("miniplayer_button")
        self.horizontalLayout_4.addWidget(self.miniplayer_button)

        self.open_File_button = QtWidgets.QPushButton(self.frame_2)
        self.open_File_button.setCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor))
        self.open_File_button.setStyleSheet(
            "QPushButton{image:url(icon_sets/new_file/new_file.png);width:22px;height:22px }\n"
        )
        self.open_File_button.setText("")
        self.open_File_button.setObjectName("playback_button")
        self.horizontalLayout_4.addWidget(self.open_File_button)

        spacerItem1 = QtWidgets.QSpacerItem(40, 20,
                                            QtWidgets.QSizePolicy.Expanding,
                                            QtWidgets.QSizePolicy.Minimum)
        self.horizontalLayout_4.addItem(spacerItem1)

        self.screenshot_button = QtWidgets.QPushButton(self.frame_2)
        self.screenshot_button.setCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor))
        self.screenshot_button.setStyleSheet(
            "QPushButton{image : url(icon_sets/snapshot/snapshot.png);width:22px;height:22px} \n"
        )
        self.screenshot_button.setText("")
        self.screenshot_button.setObjectName("screenshot_button")
        self.horizontalLayout_4.addWidget(self.screenshot_button)
        ''' Video Setting button for Video subs and dubs'''
        # self.video_setting_button = QtWidgets.QPushButton(self.frame_2)
        # self.video_setting_button.setCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor))
        # self.video_setting_button.setText("")
        # self.video_setting_button.setIconSize(QtCore.QSize(22, 22))
        # self.video_setting_button.setStyleSheet("QPushButton{image : url(icon_sets/video_setting/video_settings.png) }\n"
        #                                         )
        # self.video_setting_button.setObjectName("video_setting_button")
        # self.horizontalLayout_4.addWidget(self.video_setting_button)

        self.setting_button = QtWidgets.QPushButton(self.frame_2)
        self.setting_button.setCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor))
        self.setting_button.setStyleSheet(
            "QPushButton{image : url(icon_sets/settings/settings.png) }\n")
        self.setting_button.setText("")
        self.setting_button.setObjectName("setting_button")
        self.horizontalLayout_4.addWidget(self.setting_button)

        self.Quality_box = QtWidgets.QComboBox(self.frame_2)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum,
                                           QtWidgets.QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.Quality_box.sizePolicy().hasHeightForWidth())
        self.Quality_box.setSizePolicy(sizePolicy)
        self.Quality_box.setStyleSheet(
            "QComboBox\n"
            "    {\n"
            "	border-image :url(icon_sets/quality/border.png);\n"
            "    color: #fcffff;\n"
            "    font-size: 8pt;\n"
            "    font-weight: bold;\n"
            #    "    width: 41px;\n"
            "    background-color: #000000;\n"
            "    }\n"
            "    QComboBox QAbstractItemView \n"
            "    {\n"
            "    background: #fcffff;\n"
            "    border: 2px solid darkgray;\n"
            "    selection-background-color: #000000;\n"
            "    }\n"
            "QComboBox::drop-down {\n"
            "    border: 0px;\n"
            "    subcontrol-origin: padding;\n"
            "    subcontrol-position: top right;\n"
            "\n"
            "    border-top-right-radius: 3px;\n"
            "    border-bottom-right-radius: 3px;\n"
            "}\n")
        self.Quality_box.setIconSize(QtCore.QSize(0, 0))
        self.Quality_box.setDuplicatesEnabled(False)
        self.Quality_box.setObjectName("comboBox")
        self.Quality_box.addItem("     -")
        self.horizontalLayout_4.addWidget(self.Quality_box)

        self.volume_button = QtWidgets.QPushButton(self.frame_2)
        self.volume_button.setCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor))
        self.volume_button.setText("")
        icon9 = QtGui.QIcon()
        icon9.addPixmap(QtGui.QPixmap("icon_sets/volume/volume1.png"),
                        QtGui.QIcon.Normal, QtGui.QIcon.Off)
        self.volume_button.setIcon(icon9)
        self.volume_button.setIconSize(QtCore.QSize(22, 22))
        self.volume_button.setCheckable(True)
        # self.volume_button.setFlat(True)
        self.volume_button.setObjectName("volume_button")
        self.horizontalLayout_4.addWidget(self.volume_button)

        self.volumeslider = VolSlider(self.frame_2)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred,
                                           QtWidgets.QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.volumeslider.sizePolicy().hasHeightForWidth())
        self.volumeslider.setSizePolicy(sizePolicy)
        self.volumeslider.setAutoFillBackground(False)
        self.volumeslider.setStyleSheet(
            "QSlider::handle:horizontal \n"
            "    {\n"
            "    background: transparent;\n"
            "    width: 5px;\n"
            "    }\n"
            "QSlider::groove:horizontal {\n"
            "    border: 1px solid #444444;\n"
            "    height: 5px;\n"
            "    background: qlineargradient(y1: 0, y2: 1,stop: 0 grey, stop: 1.0 grey);\n"
            "}\n"
            " QSlider::sub-page:horizontal {\n"
            "    background:qlineargradient( y1: 0, y2: 1,\n"
            "        stop: 0 #42a6db, stop: 1 #0074e0); \n"
            "    border: 1px solid #777;\n"
            "    height: 5px;\n"
            "}\n"
            "QSlider::handle:horizontal:hover {\n"
            "    background: black;\n"
            "    height: 5px;\n"
            "    width: 5px;\n"
            "    border: 1px solid #0074e0;\n"
            "    }\n"
            "QSlider::sub-page:horizontal:disabled{background:qlineargradient( y1: 0, y2: 1,\n"
            "        stop: 0 #909090, stop: 1 #A8A8A8 );}\n"
            "")
        self.volumeslider.setOrientation(QtCore.Qt.Horizontal)
        self.volumeslider.setObjectName("volume_slider")
        self.horizontalLayout_4.addWidget(self.volumeslider)

        self.volume_percentage = QtWidgets.QLabel(self.frame_2)
        self.volume_percentage.setStyleSheet(
            "QLabel\n"
            "    {\n"
            "    font: 7pt \"Arial Rounded MT Bold\";\n"
            "    color: white;\n"
            "    border: 0px solid #076100;\n"
            "    }")
        self.volume_percentage.setObjectName("volume_status")
        self.volume_percentage.setMinimumWidth(35)
        self.volume_percentage.setText(" 75 %")
        self.horizontalLayout_4.addWidget(self.volume_percentage)

        self.verticalLayout.addWidget(self.frame_2)

        self.frame = QtWidgets.QFrame(self.mainFrame)
        font = QtGui.QFont()
        font.setFamily("Lucida Console")
        self.frame.setFont(font)
        self.frame.setFrameShape(QtWidgets.QFrame.StyledPanel)
        self.frame.setFrameShadow(QtWidgets.QFrame.Raised)
        self.frame.setObjectName("frame")
        self.horizontalLayout_5 = QtWidgets.QHBoxLayout(self.frame)
        self.horizontalLayout_5.setObjectName("horizontalLayout_5")

        sizegrip_2 = QtWidgets.QSizeGrip(Form)
        sizegrip_2.setStyleSheet("image:url(icon_sets/.png)")
        self.horizontalLayout_5.addWidget(
            sizegrip_2, 0, QtCore.Qt.AlignBottom | QtCore.Qt.AlignLeft)

        # self.enter_url_label = QtWidgets.QLabel(self.frame)
        # font = QtGui.QFont()
        # font.setFamily("Arial Rounded MT Bold")
        # font.setPointSize(8)
        # font.setBold(False)
        # font.setItalic(False)
        # font.setWeight(50)
        # self.enter_url_label.setFont(font)
        # self.enter_url_label.setStyleSheet("QLabel\n"
        #                                    "    {\n"
        #                                    "    \n"
        #                                    "    font: 8pt \"Arial Rounded MT Bold\";\n"
        #                                    "    color: white;\n"
        #                                    "    border: 0px solid #076100;\n"
        #                                    "    }")
        # self.enter_url_label.setObjectName("enter_url_label")
        # self.horizontalLayout_5.addWidget(self.enter_url_label)

        self.url_box = QtWidgets.QComboBox(self.frame)
        sizePolicy = QtWidgets.QSizePolicy(
            QtWidgets.QSizePolicy.MinimumExpanding,
            QtWidgets.QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(200)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.url_box.sizePolicy().hasHeightForWidth())
        self.url_box.setSizePolicy(sizePolicy)
        self.url_box.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor))
        self.url_box.setMouseTracking(False)
        self.url_box.setAcceptDrops(False)
        self.url_box.setWhatsThis("")
        self.url_box.setAccessibleDescription("")
        self.url_box.setAutoFillBackground(True)
        self.url_box.setStyleSheet("QComboBox\n"
                                   "    {\n"
                                   "    border: 2px solid #0074e0;\n"
                                   "    color: #fcffff;\n"
                                   "    font-size: 8pt;\n"
                                   "    font-weight: bold;\n"
                                   "    background-color: #000000;\n"
                                   "    border-radius: 6px;\n"
                                   "    }\n"
                                   "    QComboBox QAbstractItemView \n"
                                   "    {\n"
                                   "    background: #fcffff;\n"
                                   "    border: 2px solid darkgray;\n"
                                   "    selection-background-color: #000000;\n"
                                   "    }\n"
                                   "QComboBox::down-arrow {\n"
                                   "     image: url(icon_sets/url/url4.png)\n"
                                   "}\n"
                                   "QComboBox::drop-down {\n"
                                   "    subcontrol-origin: padding;\n"
                                   "    subcontrol-position: top right;\n"
                                   "    width: 20px;\n"
                                   " \n"
                                   "    border-top-right-radius: 3px;\n"
                                   "    border-bottom-right-radius: 3px;\n"
                                   "}")
        self.url_box.setInputMethodHints(QtCore.Qt.ImhUrlCharactersOnly)
        self.url_box.setEditable(True)
        self.url_box.setCurrentText("")
        self.url_box.setMaxVisibleItems(100)
        self.url_box.setMaxCount(100)
        self.url_box.setInsertPolicy(QtWidgets.QComboBox.InsertAtCurrent)
        self.url_box.setSizeAdjustPolicy(
            QtWidgets.QComboBox.AdjustToContentsOnFirstShow)
        self.url_box.setMinimumContentsLength(2)
        self.url_box.setIconSize(QtCore.QSize(20, 20))
        self.url_box.setDuplicatesEnabled(False)
        self.url_box.setFrame(True)
        self.url_box.setObjectName("url_box")
        self.horizontalLayout_5.addWidget(self.url_box)
        self.verticalLayout.addWidget(self.frame)

        sizegrip_1 = QtWidgets.QSizeGrip(Form)
        sizegrip_1.setStyleSheet(
            "image:url(icon_sets/size.png);width:15; height:18;")
        self.horizontalLayout_5.addWidget(
            sizegrip_1, 0, QtCore.Qt.AlignBottom | QtCore.Qt.AlignRight)

        self.verticalLayout_2.addWidget(self.mainFrame)

        self.retranslateUi(Form)
        self.url_box.setCurrentIndex(-1)
        QtCore.QMetaObject.connectSlotsByName(Form)

    def retranslateUi(self, Form):
        _translate = QtCore.QCoreApplication.translate
        Form.setWindowTitle(_translate("Form", "Q-Stream Player"))
        self.Player_name.setText(_translate("Form", "Q-Stream Player"))
        self.time_status.setText(_translate("Form", "00:00:00"))
        self.backslash.setText(_translate("Form", "/"))
        self.duration_status.setText(_translate("Form", "00:00:00"))
        # self.enter_url_label.setText(_translate("Form", statusList[4]))

        # Set intial Volume
        self.volumeslider.setRange(0, 100)
        self.volumeslider.setValue(75)
        self.mediaPlayer.setVolume(75)
        self.position_slider.setRange(0, 100)

        # connecting buttons
        self.miniplayer_button.clicked.connect(self.setupMiniPlayer)
        self.position_slider.sliderMoved.connect(self.setPosition)
        self.position_slider.sliderMoved.connect(self.handleLabel)
        self.volume_button.clicked.connect(self.mute)
        self.volumeslider.valueChanged.connect(self.setVolume)
        self.screenshot_button.clicked.connect(self.screenshot)
        self.playback_button.clicked.connect(self.stopplayback)
        self.always_on_top_button.clicked.connect(self.checkOnTop)
        self.play_button.clicked.connect(self.play)
        self.open_File_button.clicked.connect(self.openFile)
        # self.video_setting_button.clicked.connect(self.handleQuality)
        self.setting_button.clicked.connect(self.handleSetting)
        self.Quality_box.currentTextChanged.connect(self.handleQuality)
        self.cross_button.clicked.connect(self.exit)
        self.maximize_button.clicked.connect(self.max)
        self.minimize_button.clicked.connect(self.min)

        # Shortcuts
        shortcut = QShortcut(QKeySequence('Esc'), self.video_playback)
        shortcut.activated.connect(self.EscFun)
        shortcut = QShortcut(QKeySequence('Space'), self.video_playback)
        shortcut.activated.connect(self.play)
        shortcut = QShortcut(QKeySequence('f'), self.video_playback)
        shortcut.activated.connect(self.fullscreen_video)
        shortcut = QShortcut(QKeySequence('c'), self.video_playback)
        shortcut.activated.connect(self.setupMiniPlayer)
        shortcut = QShortcut(QKeySequence('o'), self.video_playback)
        shortcut.activated.connect(self.openFile)
        shortcut = QShortcut(QKeySequence('a'), self.video_playback)
        shortcut.activated.connect(self.checkOnTop)
        shortcut = QShortcut(QKeySequence("Return"), self.video_playback)
        shortcut.activated.connect(self.playOnline)
        shortcut = QShortcut(QKeySequence('m'), self.video_playback)
        shortcut.activated.connect(self.mute)
        shortcut = QShortcut(QKeySequence(Qt.Key_Right), self.video_playback)
        shortcut.activated.connect(self.forwardSlider)
        shortcut = QShortcut(QKeySequence(Qt.Key_Left), self.video_playback)
        shortcut.activated.connect(self.backSlider)
        self.volupshortcut = QShortcut(QKeySequence(Qt.Key_Up),
                                       self.video_playback)
        self.volupshortcut.activated.connect(self.volumeUp)
        self.voldownshortcut = QShortcut(QKeySequence(Qt.Key_Down),
                                         self.video_playback)
        self.voldownshortcut.activated.connect(self.volumeDown)
        shortcut = QShortcut(QKeySequence(Qt.ControlModifier + Qt.Key_Right),
                             self.video_playback)
        shortcut.activated.connect(self.forwardSlider10)
        shortcut = QShortcut(QKeySequence(Qt.ControlModifier + Qt.Key_Left),
                             self.video_playback)
        shortcut.activated.connect(self.backSlider10)
        shortcut = QShortcut(QKeySequence(Qt.AltModifier + Qt.Key_Left),
                             self.video_playback)
        shortcut.activated.connect(self.backSlider5)
        shortcut = QShortcut(QKeySequence(Qt.AltModifier + Qt.Key_Right),
                             self.video_playback)
        shortcut.activated.connect(self.forwardSlider5)

        # loading history to Url Box
        items = self.load()
        self.url_box.addItems(items)
        self.url_box.setCurrentIndex(-1)

        # icon size
        # iconSize = QSize(5,5)
        # self.play_button.setIconSize(iconSize)
        # self.playback_button.setIconSize(iconSize)
        # self.screenshot_button.setIconSize(iconSize)
        # self.always_on_top_button.setIconSize(iconSize)
        # self.miniplayer_button.setIconSize(iconSize)
        # self.setting_button.setIconSize(iconSize)
        # self.volume_button.setIconSize(iconSize)

        # button size
        btnSize = QSize(22, 22)
        self.play_button.setMaximumSize(btnSize)
        self.playback_button.setMaximumSize(btnSize)
        self.screenshot_button.setMaximumSize(btnSize)
        self.always_on_top_button.setMaximumSize(btnSize)
        self.miniplayer_button.setMaximumSize(btnSize)
        # self.video_setting_button.setMaximumSize(btnSize)
        self.setting_button.setMaximumSize(btnSize)
        self.volume_button.setMaximumSize(btnSize)

        # set margin
        self.horizontalLayout.setContentsMargins(10, 5, 9, 0)
        self.horizontalLayout_4.setContentsMargins(9, 0, 9, 0)
        self.horizontalLayout_4.setSpacing(4)
        self.horizontalLayout_5.setContentsMargins(0, 5, 5, 5)
        self.horizontalLayout_6.setContentsMargins(9, 0, 9, 0)

        # Media player settings
        self.mediaPlayer.setVideoOutput(self.video_playback)
        self.mediaPlayer.stateChanged.connect(self.mediaStateChanged)
        self.mediaPlayer.positionChanged.connect(self.positionChanged)
        self.mediaPlayer.positionChanged.connect(self.handleLabel)
        self.mediaPlayer.durationChanged.connect(self.durationChanged)

    def handleLabel(self):
        self.time_status.clear()
        mtime = QtCore.QTime(0, 0, 0, 0)
        self.time = mtime.addMSecs(self.mediaPlayer.position())
        self.time_status.setText(self.time.toString())

    def hide_all(self):
        self.frame_3.close()
        # self.frame.close()
        self.url_box.close()
        self.playback_button.close()
        self.screenshot_button.close()
        self.Quality_box.close()
        self.volume_button.close()
        # self.video_setting_button.close()
        # self.setting_button.close()

    def show_all(self):
        self.frame_3.show()
        # self.frame.show()
        self.url_box.show()
        self.playback_button.show()
        self.screenshot_button.show()
        self.Quality_box.show()
        self.volume_button.show()
        # self.video_setting_button.show()
        self.setting_button.show()

    def checkOnTop(self):
        self.isOnTop = not self.isOnTop
        if self.isOnTop:
            self.always_on_top_button.setProperty("top", True)
            self.always_on_top_button.setStyle(
                self.always_on_top_button.style())
            Form.setWindowFlags(Form.windowFlags()
                                | QtCore.Qt.WindowStaysOnTopHint)
        else:
            self.always_on_top_button.setProperty("top", False)
            self.always_on_top_button.setStyle(
                self.always_on_top_button.style())
            Form.setWindowFlags(Form.windowFlags()
                                & ~QtCore.Qt.WindowStaysOnTopHint)
        Form.show()

    def miniProperty(self):
        self.video_playback.setMinimumSize(QSize(200, 100))
        self.video_playback.resize(QSize(550, 270))
        Form.resize(QSize(550, 270))
        Form.setMinimumSize(QSize(200, 175))
        self.mainFrame.setMinimumSize(QSize(200, 60))
        self.mainFrame.resize(QSize(200, 53))

    def standardProperty(self):
        self.video_playback.setMinimumSize(QSize(200, 100))
        self.mainFrame.setMinimumSize(QSize(200, 82))
        Form.setMinimumSize(QSize(200, 202))
        Form.resize(550, 369)

    def setupMiniPlayer(self):
        self.isMini = not self.isMini
        if self.isMini:
            self.miniplayer_button.setProperty("mini", True)
            self.miniplayer_button.setStyle(self.miniplayer_button.style())
            self.hide_all()
            self.miniProperty()

        else:
            self.miniplayer_button.setProperty("mini", False)
            self.miniplayer_button.setStyle(self.miniplayer_button.style())
            self.standardProperty()

            self.show_all()

    def load(self):
        scorefile = "db.bat"
        if os.path.exists(scorefile):
            with open(scorefile, 'rb') as sf:
                scores = pickle.load(sf)
        else:
            scores = []

        with open(scorefile, "wb") as sf:
            pickle.dump(scores, sf)
        return scores

    def scor_func(self, url):
        scorefile = "db.bat"
        if os.path.exists(scorefile):
            with open(scorefile, 'rb') as sf:
                scores = pickle.load(sf)
        else:
            scores = []
        scores.append(url)

        with open(scorefile, "wb") as sf:
            if len(scores) > 100:
                print("here", scores)
                scores = scores[1:]
            pickle.dump(scores, sf)
        return scores

    def mute(self):
        if self.mediaPlayer.isMuted():
            print('[ ! Full Volume]')
            self.mediaPlayer.setMuted(False)
            icon9 = QtGui.QIcon()
            icon9.addPixmap(QtGui.QPixmap("icon_sets/volume/volume1.png"),
                            QtGui.QIcon.Normal, QtGui.QIcon.Off)
            self.volume_button.setIcon(icon9)
            self.volume_button.setIconSize(QSize(22, 22))
            self.volumeslider.setEnabled(True)
            # shortcut Enable
            self.volupshortcut.setEnabled(True)
            self.voldownshortcut.setEnabled(True)

        else:
            print('[ ! Mute Volume]')
            self.mediaPlayer.setMuted(True)
            icon9 = QtGui.QIcon()
            icon9.addPixmap(QtGui.QPixmap("icon_sets/volume/volume2.png"),
                            QtGui.QIcon.Normal, QtGui.QIcon.Off)
            self.volume_button.setIcon(icon9)
            self.volume_button.setIconSize(QSize(22, 22))
            self.volumeslider.setEnabled(False)
            # shrotcut disable
            self.volupshortcut.setEnabled(False)
            self.voldownshortcut.setEnabled(False)

    def play(self):
        if self.mediaPlayer.isVideoAvailable():
            if self.mediaPlayer.state() == QMediaPlayer.PlayingState:
                print("[ ! PAUSE PRESSED ]")
                self.mediaPlayer.pause()
            else:
                print("[ ! PLAY PRESSED ]")
                self.mediaPlayer.play()

    def playOnline(self):
        if self.url_box.currentText() != '':
            print('[ ! GETTING VIDEO ONLINE ]')
            fileName = self.url_box.currentText()
            res = requests.get('https://mediaplayerserver.herokuapp.com/',
                               params={"key": fileName})
            try:
                self.streams = json.loads(res.text)
                try:
                    self.mediaPlayer.setMedia(
                        QMediaContent(QUrl(self.streams['best'])))
                    self.play_video()
                    self.isOnline = True
                    self.addQuality()
                    if self.url_box.findText(fileName, Qt.MatchExactly) < 0:
                        self.url_box.addItem(fileName)
                        self.scor_func(fileName)
                except KeyError:
                    print("[ ! Error Video Not Supported By platform]")
            except json.JSONDecodeError:
                print("[ ! Error NoPluginError]")
            finally:
                self.url_box.setCurrentText("")

    def openFile(self):
        print('[ ! OPEN FILE ]')
        username = getpass.getuser()
        if sys.platform == 'win32':
            path = 'C:/Users/' + username + '/Videos/'
        elif sys.platform == 'linux' or sys.platform == 'Darwin':
            path = '/home/' + username + '/Videos/'

        formats = str.join(' ', [
            '*.%s' % str(fmt).strip('b').strip("'")
            for fmt in QtGui.QMovie.supportedFormats()
        ])

        fileName, _ = QFileDialog.getOpenFileName(
            self.video_playback, "Select media file", path,
            "Video Files (*.mp4 *.flv *.ts *.mts *.avi *.mkv)")
        if fileName != '':
            self.mediaPlayer.setMedia(
                QMediaContent(QUrl.fromLocalFile(fileName)))
            self.play_video()

    # def decodeLink(self,url):
    #     try:
    #         streams = streamlink.streams(url)
    #         keys = [k for k in streams.keys()]
    #         data = dict()
    #         for k in keys:
    #             data[k] = streams[k].url
    #         return data

    #     except streamlink.NoPluginError:
    #         return None

    # def playOnline(self):
    #         if self.url_box.currentText() != '':
    #             print('[ ! GETTING VIDEO ONLINE ]')
    #             fileName = self.url_box.currentText()
    #             self.streams = self.decodeLink(fileName)
    #             try:
    #                 self.mediaPlayer.setMedia(QMediaContent(QUrl(self.streams['best'])))
    #                 self.play_video()
    #                 self.isOnline = True
    #                 self.addQuality()
    #                 if self.url_box.findText(fileName, Qt.MatchExactly) < 0:
    #                     self.url_box.addItem(fileName)
    #                     self.scor_func(fileName)
    #             except KeyError:
    #                 print("[ ! Error Video Not Supported By platform]")
    #             finally:
    #                 self.url_box.setCurrentText("")

    def play_video(self):
        print('[ ! PLAYING VIDEO ]')
        self.play_button.setEnabled(True)
        if self.mediaPlayer.state() == QMediaPlayer.PlayingState:
            self.mediaPlayer.pause()
        else:
            self.mediaPlayer.play()

    def mediaStateChanged(self, state):
        print('[ ! CHANGING MEDIA STATE ]')
        if self.mediaPlayer.state() == QMediaPlayer.PlayingState:
            self.play_button.setProperty('play', False)
            self.play_button.setStyle(self.play_button.style())
        else:
            self.play_button.setProperty('play', True)
            self.play_button.setStyle(self.play_button.style())

    def stopplayback(self):
        print('[ ! STOP PLAYBACK VIDEO ]')
        self.mediaPlayer.stop()
        self.play_video()

    def positionChanged(self, position):
        print('[ ! POSITION CHANGED ]')
        self.position_slider.setValue(position)

    def durationChanged(self, duration):
        print('[ ! DURATION CHANGED ]')
        self.position_slider.setRange(0, duration)
        self.duration_status.clear()
        mtime = QtCore.QTime(0, 0, 0, 0)
        time = mtime.addMSecs(self.mediaPlayer.duration())
        self.duration_status.setText(time.toString())

    def setPosition(self, position):
        print('[ ! POSITION SET ]')
        self.mediaPlayer.setPosition(position)

    def setVolumePos(self, remain):
        print('[ ! REMANING VOLUME ]')
        print(remain)
        self.volumeslider.setRange(remain, 100)

    def setVolume(self, vol):
        print('[ ! SET VOLUME ]')
        print("set volume  = " + str(vol))
        if vol >= 0 and vol <= 100:
            self.volume_percentage.setText(" " + str(vol) + " %")
        if vol <= 0:
            icon9 = QtGui.QIcon()
            icon9.addPixmap(QtGui.QPixmap("icon_sets/volume/volume2.png"),
                            QtGui.QIcon.Normal, QtGui.QIcon.Off)
            self.volume_button.setIcon(icon9)
        else:
            icon9 = QtGui.QIcon()
            icon9.addPixmap(QtGui.QPixmap("icon_sets/volume/volume1.png"),
                            QtGui.QIcon.Normal, QtGui.QIcon.Off)
            self.volume_button.setIcon(icon9)

        self.volumeslider.setValue(vol)
        self.mediaPlayer.setVolume(vol)

    def screenshot(self):

        print('[ ! SCREENSHOT ]')
        wincen = Form.geometry()
        topX = wincen.topLeft().x()
        topY = wincen.topLeft().y()
        geo = self.video_playback.geometry()
        image = pyautogui.screenshot(region=(topX, topY + 38, geo.width(),
                                             geo.height() - 35))

        filename = "screenshot" + str(uuid.uuid4()) + ".png"
        username = getpass.getuser()

        if sys.platform == 'win32':
            path = 'C:/Users/' + username + '/Pictures/' + filename
        elif sys.platform == 'linux' or sys.platform == 'Darwin':
            path = '/home/' + username + '/Pictures/' + filename
        image.save(path)

    def EscFun(self):
        if self.video_playback.isFullScreen():
            Form.show()
            self.video_playback.setFullScreen(False)

    def fullscreen_video(self):
        if self.mediaPlayer.isVideoAvailable():
            if self.video_playback.isFullScreen():
                self.video_playback.setFullScreen(False)
                print('[ ! Normal Screen ]')
                Form.show()
            else:
                print('[ ! Full Screen ]')
                self.video_playback.setFullScreen(True)
                Form.hide()

    def getFormat(self):
        li = [k for k in self.streams.keys()]
        for q in li:
            if q.startswith('audio'):
                li.remove(q)
                try:
                    li.remove('audio_opus')
                except ValueError:
                    pass
        return li

    def changeQuality(self, quality):
        pos = self.mediaPlayer.position()
        try:
            self.mediaPlayer.setMedia(
                QMediaContent(QUrl(self.streams[quality])))
        except KeyError:
            pass
        self.setPosition(pos)
        self.mediaPlayer.play()

    def handleSetting(self):
        from setting import SettingDialog
        dlg = SettingDialog()
        dlg.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint)
        dlg.exec_()

    def addQuality(self):
        self.Quality_box.clear()
        self.Quality_box.addItems(self.getFormat())

    def handleQuality(self):
        if self.isOnline:
            self.changeQuality(self.Quality_box.currentText())

    def forwardSlider(self):
        self.mediaPlayer.setPosition(self.mediaPlayer.position() + 1000)

    def forwardSlider10(self):
        self.mediaPlayer.setPosition(self.mediaPlayer.position() + 10000)

    def forwardSlider5(self):
        self.mediaPlayer.setPosition(self.mediaPlayer.position() + 5000)

    def backSlider(self):
        self.mediaPlayer.setPosition(self.mediaPlayer.position() - 1000)

    def backSlider10(self):
        self.mediaPlayer.setPosition(self.mediaPlayer.position() - 10000)

    def backSlider5(self):
        self.mediaPlayer.setPosition(self.mediaPlayer.position() - 5000)

    def volumeUp(self):
        self.setVolume(self.mediaPlayer.volume() + 10)
        print("Volume: " + str(self.mediaPlayer.volume()))

    def volumeDown(self):
        self.setVolume(self.mediaPlayer.volume() - 10)
        print("Volume: " + str(self.mediaPlayer.volume()))

    def max(self):
        if not Form.isMaximized():
            print("[! Window is Maximized]")
            Form.showMaximized()
        else:
            print("[! Window is Normal]")
            Form.showNormal()

    def min(self):
        if not Form.isMinimized():
            print("[! Window is Minimized]")
            Form.showMinimized()
        else:
            print("[! Window is Normal]")
            Form.showNormal()

    def exit(self):
        self.mediaPlayer.stop()
        sys.exit()
class ApplicationWindow(QMainWindow):
    ## Accessing files in Processed Stuff ##
    QDir.setCurrent(QCoreApplication.applicationDirPath())
    processedVideoPath = QDir.currentPath() + "/ProcessedStuff/horses_1_predicted.mp4";
    textFilePath = QDir.currentPath() + "/ProcessedStuff/labels_example.txt";
    
    # Environmental Variable
    # os.environ['PYTHONPATH'] = "$(pwd)/detection:$(pwd)/detection/slim"
    # subprocess.check_call(['sqsub', '-np', sys.argv[1], 'application.py'],
    #                   env=dict(os.environ, SQSUB_VAR="visible in this subprocess"))

    ## Important variables ##
    videoLoaded = False
    fileReceived = False
    playing = False
    fileName = None
    labels = []
    nextLine = 0

    def __init__(self):
        # Create the Qt5 application backend
        super(ApplicationWindow, self).__init__()

        # Load in and display the UI
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        ## CONNECT EVENTS (like button presses) to functions ##
        self.ui.button_play_pause.clicked.connect(self.playPauseButtonClicked)
        self.ui.button_load.clicked.connect(self.loadButtonClicked)
        self.ui.button_track.clicked.connect(self.trackButtonClicked)

        # Configure the original video widget
        self.original_video_player = QMediaPlayer(None, QMediaPlayer.VideoSurface)
        self.original_video_player.durationChanged.connect(self.durationChanged)
        self.original_video_player.setVideoOutput(self.ui.original_video_widget)

        # Configure the processed video widget
        self.video_player = QMediaPlayer(None, QMediaPlayer.VideoSurface)
        self.video_player.setNotifyInterval(30)
        self.video_player.durationChanged.connect(self.durationChanged)
        self.video_player.positionChanged.connect(self.positionChanged)
        self.video_player.stateChanged.connect(self.stopped)
        self.video_player.setVideoOutput(self.ui.video_widget)

        # Configure the video slider
        self.ui.video_slider.sliderPressed.connect(self.sliderPressed)
        self.ui.video_slider.sliderReleased.connect(self.sliderReleased)

        # Update states
        self.updateStates()

    ##  CALLBACK FUNCTIONS ##
    def playPauseButtonClicked(self):
        if self.playing:
            print("Pause!")
            self.pause()
        else:
            print("Play!")
            self.play()

    def saveButtonClicked(self):
        print("Save!")

    def loadButtonClicked(self):
        print("Load!")
        # fileName, _ = QFileDialog.getOpenFileName(
        #     self,
        #     "Choose a video",
        #     QStandardPaths.writableLocation(QStandardPaths.DocumentsLocation),
        #     "Vide files (*mp4 *mp3)")
        # file = open("ProcessedStuff/labels_example.txt","w") 
        # file.write("labels = []\n")
        # file.close()
        fileName, _ = QFileDialog.getOpenFileName(self, "Open Files")

        if fileName != "":
            self.ui.file_info.setText(fileName)
            print("Video filepath: " + fileName)
            self.fileName = fileName
            self.fileReceived = True
            self.nextLine = 0
            self.updateStates()

    def trackButtonClicked(self):
        print("Track!")

        # Do processing and call following method when completed #
        detection.detection_code(self.fileName)
        self.processingFinished()

    def sliderReleased(self):
        newPosition = self.ui.video_slider.value()
        self.setPosition(newPosition)

    def sliderPressed(self):
        self.pause()

    def durationChanged(self):
        self.videoLoaded = True
        self.updateStates()
        self.ui.video_slider.setMaximum(self.video_player.duration())

    def positionChanged(self):
        if not self.playing:
            return
        position = self.video_player.position()
        # Update video progress bar
        self.ui.video_slider.setValue(position)
        # Update information label
        self.updateLabel(position)

    def stopped(self):
        if self.video_player.state() == QMediaPlayer.StoppedState:
            self.playing = False
            self.ui.label_info.setText("")

    ## Helper Functions ##
    def play(self):
        self.original_video_player.play()
        self.video_player.play()
        self.playing = True

    def pause(self):
        self.playing = False
        self.original_video_player.pause()
        self.video_player.pause()

    def setPosition(self, position):
        self.resetNextLine(position)
        self.updateLabel(position)
        self.original_video_player.setPosition(position)
        self.video_player.setPosition(position)
        self.play()

    def updateStates(self):
        self.ui.button_play_pause.setEnabled(self.videoLoaded)
        self.ui.video_slider.setEnabled(self.videoLoaded)
        self.ui.button_track.setEnabled(self.fileReceived and not self.playing)

    def processingFinished(self):
        print("Text file location: " + self.textFilePath)
        file = open(self.textFilePath, "r")
        self.labels = [line.split(',') for line in file]
        file.close()
        print(self.processedVideoPath)
        self.video_player.setMedia(QMediaContent(QUrl.fromLocalFile(self.processedVideoPath)))
        self.original_video_player.setMedia(QMediaContent(QUrl.fromLocalFile(self.fileName)))
        self.play()

    # When the user changes the slider the next line changes
    def resetNextLine(self, position):
        while (position < int(self.labels[self.nextLine][0])):
            self.nextLine -= 1
            if (self.nextLine <= 0):
                break
        if self.nextLine+1<=len(self.labels)-1:
            while (position >= int(self.labels[self.nextLine+1][0])):
                self.nextLine += 1
                if (self.nextLine >= len(self.labels)-1):
                    break

    def updateLabel(self, position):
        if position >= int(self.labels[self.nextLine][0]):
            label = self.labels[self.nextLine]
            messageStr = "Count: " + label[1]
            for i in range(2,len(label),2):
                messageStr += ("\n%s. %s %s" % (i-int(i/2),label[i],label[i+1]))
            self.ui.label_info.setText(messageStr)
            if self.nextLine < len(self.labels)-1:
                self.nextLine += 1
Ejemplo n.º 33
0
class QgsFmvPlayer(QMainWindow, Ui_PlayerWindow):
    """ Video Player Class """
    def __init__(self, iface, path=None, parent=None):
        """ Constructor """
        super(QgsFmvPlayer, self).__init__(parent)
        self.setupUi(self)
        self.parent = parent
        self.iface = iface
        self.fileName = None
        self.metadataDlg = None
        self.createingMosaic = False
        self.currentInfo = 0.0

        self.RecGIF = QMovie(":/imgFMV/images/record.gif")

        self.videoWidget.customContextMenuRequested[QPoint].connect(
            self.contextMenuRequested)

        self.duration = 0
        self.playerMuted = False
        self.HasFileAudio = False

        self.player = QMediaPlayer(None, QMediaPlayer.VideoSurface)
        self.player.setNotifyInterval(1000)  # One second
        self.pass_time = 0.1
        self.playlist = QMediaPlaylist()

        #         self.player.setVideoOutput(
        #             self.videoWidget)  # Standar Surface

        self.player.setVideoOutput(
            self.videoWidget.videoSurface())  # Custom Surface

        self.player.durationChanged.connect(self.durationChanged)
        self.player.positionChanged.connect(self.positionChanged)
        self.player.mediaStatusChanged.connect(self.statusChanged)

        self.player.stateChanged.connect(self.setCurrentState)

        self.playerState = QMediaPlayer.StoppedState
        self.playFile(path)

        self.sliderDuration.setRange(0, self.player.duration() / 1000)

        self.volumeSlider.setValue(self.player.volume())
        self.volumeSlider.enterEvent = self.showVolumeTip

        if self.metadataDlg is None:
            self.metadataDlg = QgsFmvMetadata(parent=self, player=self)
            self.addDockWidget(Qt.RightDockWidgetArea, self.metadataDlg)
            self.metadataDlg.setMinimumWidth(500)
            self.metadataDlg.hide()

    def HasMetadata(self, videoPath):
        """ Check if video have Metadata or not """
        try:
            p = _spawn([
                '-i', videoPath, '-map', 'data-re', '-codec', 'copy', '-f',
                'data', '-'
            ])

            stdout_data, _ = p.communicate()

            if stdout_data == b'':
                qgsu.showUserAndLogMessage(QCoreApplication.translate(
                    "QgsFmvPlayer", "This video don't have Metadata ! : "),
                                           level=QGis.Info)
                return False

            return True
        except Exception as e:
            qgsu.showUserAndLogMessage(QCoreApplication.translate(
                "QgsFmvPlayer", "Metadata Callback Failed! : "),
                                       str(e),
                                       level=QGis.Info)

    def HasAudio(self, videoPath):
        """ Check if video have Metadata or not """
        try:
            p = _spawn([
                '-i', videoPath, '-show_streams', '-select_streams', 'a',
                '-loglevel', 'error'
            ],
                       type="ffprobe")

            stdout_data, _ = p.communicate()

            if stdout_data == b'':
                qgsu.showUserAndLogMessage(QCoreApplication.translate(
                    "QgsFmvPlayer", "This video don't have Audio ! : "),
                                           level=QGis.Info)
                return False

            return True
        except Exception as e:
            qgsu.showUserAndLogMessage(QCoreApplication.translate(
                "QgsFmvPlayer", "Audio check Failed! : "),
                                       str(e),
                                       level=QGis.Info)

    def callBackMetadata(self, currentTime, nextTime):
        """ Metadata CallBack """
        try:
            # TODO : Speed this function
            #             stdout_data = _check_output(['-i', self.fileName,
            #                         '-ss', currentTime,
            #                         '-to', nextTime,
            #                         '-f', 'data', '-'])

            t = callBackMetadataThread(cmds=[
                '-i', self.fileName, '-ss', currentTime, '-to', nextTime,
                '-map', 'data-re', '-f', 'data', '-'
            ])
            t.start()
            t.join(1)
            if t.is_alive():
                t.p.terminate()
                t.join()
            if t.stdout == b'':
                return

            for packet in StreamParser(t.stdout):
                try:
                    self.addMetadata(packet.MetadataList())
                    UpdateLayers(packet,
                                 parent=self,
                                 mosaic=self.createingMosaic)
                    self.iface.mapCanvas().refresh()
                    QApplication.processEvents()
                    return
                except Exception as e:
                    None
        except Exception as e:
            qgsu.showUserAndLogMessage(QCoreApplication.translate(
                "QgsFmvPlayer", "Metadata Callback Failed! : "),
                                       str(e),
                                       level=QGis.Info)

    def addMetadata(self, packet):
        ''' Add Metadata to List '''
        self.clearMetadata()
        row = 0
        for key in sorted(packet.keys()):
            self.metadataDlg.VManager.insertRow(row)
            self.metadataDlg.VManager.setItem(row, 0,
                                              QTableWidgetItem(str(key)))
            self.metadataDlg.VManager.setItem(
                row, 1, QTableWidgetItem(str(packet[key][0])))
            self.metadataDlg.VManager.setItem(
                row, 2, QTableWidgetItem(str(packet[key][1])))
            row += 1
        self.metadataDlg.VManager.setVisible(False)
        self.metadataDlg.VManager.resizeColumnsToContents()
        self.metadataDlg.VManager.setVisible(True)
        self.metadataDlg.VManager.verticalScrollBar().setSliderPosition(
            self.sliderPosition)

    def clearMetadata(self):
        ''' Clear Metadata List '''
        try:
            self.sliderPosition = self.metadataDlg.VManager.verticalScrollBar(
            ).sliderPosition()
            self.metadataDlg.VManager.setRowCount(0)
        except:
            None

    def saveInfoToJson(self):
        """ Save video Info to json """
        if not self.KillAllProcessors():
            return
        out_json, _ = QFileDialog.getSaveFileName(self, "Save File", "",
                                                  "Json Files (*.json)")
        if out_json == "":
            return
        try:
            self.VPProbeToJson = Converter()
            self.VPTProbeToJson = QThread()

            self.VPProbeToJson.moveToThread(self.VPTProbeToJson)

            self.VPProbeToJson.finished.connect(self.QThreadFinished)

            self.VPProbeToJson.error.connect(self.QThreadError)

            self.VPProbeToJson.progress.connect(
                self.progressBarProcessor.setValue)

            self.VPTProbeToJson.start(QThread.LowPriority)

            QMetaObject.invokeMethod(self.VPProbeToJson, 'probeToJson',
                                     Qt.QueuedConnection,
                                     Q_ARG(str, self.fileName),
                                     Q_ARG(str, out_json))

        except Exception as e:
            qgsu.showUserAndLogMessage(
                QCoreApplication.translate("QgsFmvPlayer",
                                           "Error saving Json"))
            self.QThreadFinished("probeToJson", "Closing ProbeToJson")

    def showVideoInfo(self):
        ''' Show default probe info '''
        try:

            self.VPProbe = Converter()
            self.VPTProbe = QThread()

            self.VPProbe.moveToThread(self.VPTProbe)

            self.VPProbe.finishedJson.connect(self.QThreadFinished)

            self.VPProbe.error.connect(self.QThreadError)

            self.VPProbe.progress.connect(self.progressBarProcessor.setValue)

            self.VPTProbe.start(QThread.LowPriority)

            QMetaObject.invokeMethod(self.VPProbe, 'probeShow',
                                     Qt.QueuedConnection,
                                     Q_ARG(str, self.fileName))

        except Exception as e:
            qgsu.showUserAndLogMessage(
                QCoreApplication.translate("QgsFmvPlayer", "Error Info Show"))
            self.QThreadFinished("probeShow", "Closing Probe")
        return

    def state(self):
        ''' Return Current State '''
        return self.playerState

    def setCurrentState(self, state):
        ''' Set Current State '''
        if state != self.playerState:
            self.playerState = state

            if state == QMediaPlayer.StoppedState:
                self.btn_play.setIcon(QIcon(":/imgFMV/images/play-arrow.png"))

        return

    def showColorDialog(self):
        ''' Show Color dialog '''
        self.ColorDialog = ColorDialog(parent=self)
        self.ColorDialog.setWindowFlags(Qt.Window | Qt.WindowCloseButtonHint)
        # Fail if not uncheked
        self.actionMagnifying_glass.setChecked(False)
        self.actionZoom_Rectangle.setChecked(False)
        self.ColorDialog.exec_()
        return

    def createMosaic(self, value):
        ''' Function for create Video Mosaic '''
        home = os.path.expanduser("~")

        qgsu.createFolderByName(home, "QGIS_FMV")
        homefmv = os.path.join(home, "QGIS_FMV")
        root, ext = os.path.splitext(os.path.basename(self.fileName))
        qgsu.createFolderByName(homefmv, root)
        self.createingMosaic = value
        # Create Group
        CreateGroupByName()
        return

    def contextMenuRequested(self, point):
        ''' Context Menu Video '''
        menu = QMenu()

        #         actionColors = menu.addAction(
        #             QCoreApplication.translate("QgsFmvPlayer", "Color Options"))
        #         actionColors.setShortcut("Ctrl+May+C")
        #         actionColors.triggered.connect(self.showColorDialog)

        actionMute = menu.addAction(
            QCoreApplication.translate("QgsFmvPlayer", "Mute/Unmute"))
        actionMute.setShortcut("Ctrl+May+U")
        actionMute.triggered.connect(self.setMuted)

        menu.addSeparator()
        actionAllFrames = menu.addAction(
            QCoreApplication.translate("QgsFmvPlayer", "Extract All Frames"))
        actionAllFrames.setShortcut("Ctrl+May+A")
        actionAllFrames.triggered.connect(self.ExtractAllFrames)

        actionCurrentFrames = menu.addAction(
            QCoreApplication.translate("QgsFmvPlayer",
                                       "Extract Current Frame"))
        actionCurrentFrames.setShortcut("Ctrl+May+Q")
        actionCurrentFrames.triggered.connect(self.ExtractCurrentFrame)

        menu.addSeparator()
        actionShowMetadata = menu.addAction(
            QCoreApplication.translate("QgsFmvPlayer", "Show Metadata"))
        actionShowMetadata.setShortcut("Ctrl+May+M")
        actionShowMetadata.triggered.connect(self.OpenQgsFmvMetadata)

        menu.exec_(self.mapToGlobal(point))

    # Start Snnipet FILTERS
    def grayFilter(self, value):
        self.UncheckFilters(self.sender(), value)
        self.videoWidget.SetGray(value)
        self.videoWidget.UpdateSurface()
        return

    def edgeFilter(self, value):
        self.UncheckFilters(self.sender(), value)
        self.videoWidget.SetEdgeDetection(value)
        self.videoWidget.UpdateSurface()
        return

    def invertColorFilter(self, value):
        self.UncheckFilters(self.sender(), value)
        self.videoWidget.SetInvertColor(value)
        self.videoWidget.UpdateSurface()
        return

    def autoContrastFilter(self, value):
        self.UncheckFilters(self.sender(), value)
        self.videoWidget.SetAutoContrastFilter(value)
        self.videoWidget.UpdateSurface()
        return

    def monoFilter(self, value):
        self.UncheckFilters(self.sender(), value)
        self.videoWidget.SetMonoFilter(value)
        self.videoWidget.UpdateSurface()
        return

    def magnifier(self, value):
        self.UncheckUtils(self.sender(), value)
        self.videoWidget.SetMagnifier(value)
        self.videoWidget.UpdateSurface()
        return

    def zoomRect(self, value):
        self.UncheckUtils(self.sender(), value)
        self.videoWidget.SetZoomRect(value)
        self.videoWidget.UpdateSurface()
        return

    def UncheckUtils(self, sender, value):
        #         p = self.player.position()
        #         self.player.setVideoOutput(
        #             self.videoWidget.videoSurface())  # Custom surface
        #         self.player.setPosition(p)
        QApplication.processEvents()
        name = sender.objectName()
        self.actionMagnifying_glass.setChecked(
            True if name == "actionMagnifying_glass" else False)
        self.actionZoom_Rectangle.setChecked(True if name ==
                                             "actionZoom_Rectangle" else False)

        sender.setChecked(value)
        return

    def UncheckFilters(self, sender, value):
        #         p = self.player.position()
        #         self.player.setVideoOutput(
        #             self.videoWidget.videoSurface())  # Custom surface
        #         self.player.setPosition(p)
        #         QApplication.processEvents()
        name = sender.objectName()

        self.actionGray.setChecked(True if name == "actionGray" else False)
        self.actionInvert_Color.setChecked(True if name ==
                                           "actionInvert_Color" else False)
        self.actionMono_Filter.setChecked(True if name ==
                                          "actionMono_Filter" else False)
        self.actionCanny_edge_detection.setChecked(
            True if name == "actionCanny_edge_detection" else False)
        self.actionAuto_Contrast_Filter.setChecked(
            True if name == "actionAuto_Contrast_Filter" else False)

        self.videoWidget.SetGray(True if name == "actionGray" else False)
        self.videoWidget.SetEdgeDetection(
            True if name == "actionCanny_edge_detection" else False)
        self.videoWidget.SetInvertColor(True if name ==
                                        "actionInvert_Color" else False)
        self.videoWidget.SetMonoFilter(True if name ==
                                       "actionMono_Filter" else False)
        self.videoWidget.SetAutoContrastFilter(
            True if name == "actionAuto_Contrast_Filter" else False)

        sender.setChecked(value)
        return

    # End Snnipet FILTERS

    def isMuted(self):
        ''' Is muted video property'''
        return self.playerMuted

    def setMuted(self):
        ''' Muted video '''
        if self.player.isMuted():
            self.btn_volume.setIcon(QIcon(":/imgFMV/images/volume_up.png"))
            self.player.setMuted(False)
            self.volumeSlider.setEnabled(True)
        else:
            self.btn_volume.setIcon(QIcon(":/imgFMV/images/volume_off.png"))
            self.player.setMuted(True)
            self.volumeSlider.setEnabled(False)
        return

    def stop(self):
        ''' Stop video'''
        self.player.stop()
        self.videoWidget.update()
        return

    def volume(self):
        ''' Volume Slider '''
        return self.volumeSlider.value()

    def setVolume(self, volume):
        ''' Tooltip and set value'''
        self.player.setVolume(volume)
        self.showVolumeTip(volume)
        if 0 < volume <= 30:
            self.btn_volume.setIcon(QIcon(":/imgFMV/images/volume_30.png"))
        elif 30 < volume <= 60:
            self.btn_volume.setIcon(QIcon(":/imgFMV/images/volume_60.png"))
        elif 60 < volume <= 100:
            self.btn_volume.setIcon(QIcon(":/imgFMV/images/volume_up.png"))
        elif volume == 0:
            self.btn_volume.setIcon(QIcon(":/imgFMV/images/volume_off.png"))

    def EndMedia(self):
        ''' Button end video position '''
        if self.player.isVideoAvailable():
            self.player.setPosition(self.player.duration())
            self.videoWidget.update()
        return

    def StartMedia(self):
        ''' Button start video position '''
        if self.player.isVideoAvailable():
            self.player.setPosition(0)
            self.videoWidget.update()
        return

    def forwardMedia(self):
        ''' Button forward Video '''
        forwardTime = int(self.player.position()) + 10 * 1000
        if forwardTime > int(self.player.duration()):
            forwardTime = int(self.player.duration())
        self.player.setPosition(forwardTime)

    def rewindMedia(self):
        ''' Button rewind Video '''
        rewindTime = int(self.player.position()) - 10 * 1000
        if rewindTime < 0:
            rewindTime = 0
        self.player.setPosition(rewindTime)

    def AutoRepeat(self, checked):
        ''' Button AutoRepeat Video '''
        if checked:
            self.playlist.setPlaybackMode(QMediaPlaylist.Loop)
        else:
            self.playlist.setPlaybackMode(QMediaPlaylist.Sequential)
        return

    def showVolumeTip(self, _):
        ''' Volume Slider Tooltip Trick '''
        self.style = self.volumeSlider.style()
        self.opt = QStyleOptionSlider()
        self.volumeSlider.initStyleOption(self.opt)
        rectHandle = self.style.subControlRect(self.style.CC_Slider, self.opt,
                                               self.style.SC_SliderHandle)
        self.tip_offset = QPoint(5, 15)
        pos_local = rectHandle.topLeft() + self.tip_offset
        pos_global = self.volumeSlider.mapToGlobal(pos_local)
        QToolTip.showText(pos_global,
                          str(self.volumeSlider.value()) + " %", self)

    def showMoveTip(self, currentInfo):
        ''' Player Silder Move Tooptip Trick '''
        self.style = self.sliderDuration.style()
        self.opt = QStyleOptionSlider()
        self.sliderDuration.initStyleOption(self.opt)
        rectHandle = self.style.subControlRect(self.style.CC_Slider, self.opt,
                                               self.style.SC_SliderHandle)
        self.tip_offset = QPoint(5, 15)
        pos_local = rectHandle.topLeft() + self.tip_offset
        pos_global = self.sliderDuration.mapToGlobal(pos_local)

        tStr = _seconds_to_time(currentInfo)

        QToolTip.showText(pos_global, tStr, self)

    def durationChanged(self, duration):
        ''' Duration video change signal '''
        duration /= 1000
        self.duration = duration
        self.sliderDuration.setMaximum(duration)

    def positionChanged(self, progress):
        ''' Current Video position change '''
        progress /= 1000

        if not self.sliderDuration.isSliderDown():
            self.sliderDuration.setValue(progress)

        self.updateDurationInfo(progress)

    def updateDurationInfo(self, currentInfo):
        ''' Update labels duration Info and CallBack Metadata '''
        duration = self.duration
        self.currentInfo = currentInfo
        if currentInfo or duration:

            totalTime = _seconds_to_time(duration)
            currentTime = _seconds_to_time(currentInfo)
            tStr = currentTime + " / " + totalTime

            nextTime = currentInfo + self.pass_time
            currentTimeInfo = _seconds_to_time_frac(currentInfo)
            nextTimeInfo = _seconds_to_time_frac(nextTime)
            # Metadata CallBack
            self.callBackMetadata(currentTimeInfo, nextTimeInfo)

        else:
            tStr = ""

        self.labelDuration.setText(tStr)

    def handleCursor(self, status):
        ''' Change cursor '''
        if status in (QMediaPlayer.LoadingMedia, QMediaPlayer.BufferingMedia,
                      QMediaPlayer.StalledMedia):
            self.setCursor(Qt.BusyCursor)
        else:
            self.unsetCursor()

    def statusChanged(self, status):
        ''' Signal Status video change '''
        self.handleCursor(status)
        if status == QMediaPlayer.LoadingMedia:
            self.videoAvailableChanged(False)
        elif status == QMediaPlayer.StalledMedia:
            self.videoAvailableChanged(False)
        if status == QMediaPlayer.EndOfMedia:
            self.videoAvailableChanged(True)
        elif status == QMediaPlayer.InvalidMedia:
            qgsu.showUserAndLogMessage(QCoreApplication.translate(
                "QgsFmvPlayer", self.player.errorString()),
                                       level=QGis.Warning)
            self.videoAvailableChanged(False)
        else:
            self.videoAvailableChanged(True)

    def playFile(self, videoPath):
        ''' Play file from path '''
        try:
            RemoveVideoLayers()
            RemoveGroupByName()
            self.fileName = videoPath
            self.playlist = QMediaPlaylist()
            url = QUrl.fromLocalFile(videoPath)
            self.playlist.addMedia(QMediaContent(url))
            self.playlist.setPlaybackMode(QMediaPlaylist.Sequential)
            self.player.setPlaylist(self.playlist)

            self.setWindowTitle("Playing : " +
                                os.path.basename(os.path.normpath(videoPath)))

            if self.HasMetadata(videoPath):
                CreateVideoLayers()
                self.clearMetadata()
                self.lb_cursor_coord.setText(
                    "<span style='font-size:10pt; font-weight:bold;'>Lon :</span>"
                    +
                    "<span style='font-size:9pt; font-weight:normal;'>Null</span>"
                    +
                    "<span style='font-size:10pt; font-weight:bold;'> Lat :</span>"
                    +
                    "<span style='font-size:9pt; font-weight:normal;'>Null</span>"
                )
            else:
                self.btn_GeoReferencing.setEnabled(False)

            self.HasFileAudio = True
            if not self.HasAudio(videoPath):
                self.actionAudio.setEnabled(False)
                self.actionSave_Audio.setEnabled(False)
                self.HasFileAudio = False

            self.playClicked(True)

        except Exception as e:
            qgsu.showUserAndLogMessage(QCoreApplication.translate(
                "QgsFmvPlayer", 'Open Video File : '),
                                       str(e),
                                       level=QGis.Warning)

    def ReciconUpdate(self, frame):
        self.btn_Rec.setIcon(QIcon(self.RecGIF.currentPixmap()))

    def RecordVideo(self, value):
        ''' Cut Video '''
        currentTime = _seconds_to_time(self.currentInfo)

        if value is False:
            self.endRecord = currentTime
            _, file_extension = os.path.splitext(self.fileName)
            out, _ = QFileDialog.getSaveFileName(self, "Save As", "",
                                                 file_extension)
            if not out:
                self.RecGIF.frameChanged.disconnect(self.ReciconUpdate)
                self.RecGIF.stop()
                self.btn_Rec.setIcon(QIcon(":/imgFMV/images/record.png"))
                return False

            lfn = out.lower()
            if not lfn.endswith((file_extension)):
                out += file_extension

            p = _spawn([
                '-i', self.fileName, '-ss', self.startRecord, '-to',
                self.endRecord, '-c', 'copy', out
            ])
            p.communicate()
            qgsu.showUserAndLogMessage(
                QCoreApplication.translate("QgsFmvPlayer",
                                           "Save file succesfully!"))

            self.RecGIF.frameChanged.disconnect(self.ReciconUpdate)
            self.RecGIF.stop()
            self.btn_Rec.setIcon(QIcon(":/imgFMV/images/record.png"))
        else:
            self.startRecord = currentTime
            self.RecGIF.frameChanged.connect(self.ReciconUpdate)
            self.RecGIF.start()
        return

    def videoAvailableChanged(self, available):
        ''' Buttons for video available '''
        # self.btn_Color.setEnabled(available)
        self.btn_CaptureFrame.setEnabled(available)
        self.gb_PlayerControls.setEnabled(available)
        return

    def toggleGroup(self, state):
        ''' Toggle GroupBox '''
        sender = self.sender()
        if state:
            sender.setFixedHeight(sender.sizeHint().height())
        else:
            sender.setFixedHeight(15)

    def playClicked(self, state):
        ''' Stop and Play video '''
        if self.playerState in (QMediaPlayer.StoppedState,
                                QMediaPlayer.PausedState):
            self.btn_play.setIcon(QIcon(":/imgFMV/images/pause.png"))
            self.player.play()
        elif self.playerState == QMediaPlayer.PlayingState:
            self.btn_play.setIcon(QIcon(":/imgFMV/images/play-arrow.png"))
            self.player.pause()

    def seek(self, seconds):
        '''Slider Move'''
        self.player.setPosition(seconds * 1000)
        self.showMoveTip(seconds)

    def convertVideo(self):
        '''Convert Video To Other Format '''
        if not self.KillAllProcessors():
            return
        sel = "mp4 Files (*.mp4)"
        out, _ = QFileDialog.getSaveFileName(
            self, "Save Video as...", None,
            "ogg files (*.ogg);;avi Files (*.avi);;mkv Files (*.mkv);;webm Files (*.webm);;flv Files (*.flv);;mov Files (*.mov);;mp4 Files (*.mp4);;mpg Files (*.mpg);;mp3 Files (*.mp3)",
            sel)

        if not out:
            return False

        lfn = out.lower()
        if not lfn.endswith(('.ogg', '.avi', '.mkv', '.webm', '.flv', '.mov',
                             '.mp4', '.mp3', '.mpg')):
            # The default.
            out += '.mp4'

        try:
            self.VPConverter = Converter()
            self.VPTConverter = QThread()

            self.VPConverter.moveToThread(self.VPTConverter)

            self.VPConverter.finished.connect(self.QThreadFinished)

            self.VPConverter.error.connect(self.QThreadError)

            self.VPConverter.progress.connect(
                self.progressBarProcessor.setValue)

            self.VPTConverter.start(QThread.LowPriority)

            # TODO : Make Correct format Conversion and embebed metadata
            info = self.VPConverter.probeInfo(self.fileName)
            if info is not None:
                if self.HasFileAudio:
                    audio_codec = info.audio.codec
                    audio_samplerate = info.audio.audio_samplerate
                    audio_channels = info.audio.audio_channels

                video_codec = info.video.codec
                video_width = info.video.video_width
                video_height = info.video.video_height
                video_fps = info.video.video_fps

            _, out_ext = os.path.splitext(out)

            if self.HasFileAudio:
                options = {
                    'format': out_ext[1:],
                    'audio': {
                        'codec': audio_codec,
                        'samplerate': audio_samplerate,
                        'channels': audio_channels
                    },
                    'video': {
                        'codec': video_codec,
                        'width': video_width,
                        'height': video_height,
                        'fps': video_fps
                    }
                }
            else:
                options = {
                    'format': out_ext[1:],
                    'video': {
                        'codec': video_codec,
                        'width': video_width,
                        'height': video_height,
                        'fps': video_fps
                    }
                }
            QMetaObject.invokeMethod(self.VPConverter, 'convert',
                                     Qt.QueuedConnection,
                                     Q_ARG(str,
                                           self.fileName), Q_ARG(str, out),
                                     Q_ARG(dict, options), Q_ARG(bool, False))

        except Exception as e:
            qgsu.showUserAndLogMessage(
                QCoreApplication.translate("QgsFmvPlayer",
                                           "Error converting video "))
            self.QThreadFinished("convert", "Closing convert")

    def ShowPlot(self, bitrate_data, frame_count, output=None):
        ''' Show plot,because show not work using threading '''
        matplot.figure().canvas.set_window_title(self.fileName)
        matplot.title("Stream Bitrate vs Time")
        matplot.xlabel("Time (sec)")
        matplot.ylabel("Frame Bitrate (kbit/s)")
        matplot.grid(True)
        # map frame type to color
        frame_type_color = {
            # audio
            'A': 'yellow',
            # video
            'I': 'red',
            'P': 'green',
            'B': 'blue'
        }

        global_peak_bitrate = 0.0
        global_mean_bitrate = 0.0

        # render charts in order of expected decreasing size
        for frame_type in ['I', 'P', 'B', 'A']:

            # skip frame type if missing
            if frame_type not in bitrate_data:
                continue

            # convert list of tuples to numpy 2d array
            frame_list = bitrate_data[frame_type]
            frame_array = numpy.array(frame_list)

            # update global peak bitrate
            peak_bitrate = frame_array.max(0)[1]
            if peak_bitrate > global_peak_bitrate:
                global_peak_bitrate = peak_bitrate

            # update global mean bitrate (using piecewise mean)
            mean_bitrate = frame_array.mean(0)[1]
            global_mean_bitrate += mean_bitrate * \
                (len(frame_list) / frame_count)

            # plot chart using gnuplot-like impulses
            matplot.vlines(frame_array[:, 0], [0],
                           frame_array[:, 1],
                           color=frame_type_color[frame_type],
                           label="{} Frames".format(frame_type))

        self.progressBarProcessor.setValue(90)
        # calculate peak line position (left 15%, above line)
        peak_text_x = matplot.xlim()[1] * 0.15
        peak_text_y = global_peak_bitrate + \
            ((matplot.ylim()[1] - matplot.ylim()[0]) * 0.015)
        peak_text = "peak ({:.0f})".format(global_peak_bitrate)

        # draw peak as think black line w/ text
        matplot.axhline(global_peak_bitrate, linewidth=2, color='black')
        matplot.text(peak_text_x,
                     peak_text_y,
                     peak_text,
                     horizontalalignment='center',
                     fontweight='bold',
                     color='black')

        # calculate mean line position (right 85%, above line)
        mean_text_x = matplot.xlim()[1] * 0.85
        mean_text_y = global_mean_bitrate + \
            ((matplot.ylim()[1] - matplot.ylim()[0]) * 0.015)
        mean_text = "mean ({:.0f})".format(global_mean_bitrate)

        # draw mean as think black line w/ text
        matplot.axhline(global_mean_bitrate, linewidth=2, color='black')
        matplot.text(mean_text_x,
                     mean_text_y,
                     mean_text,
                     horizontalalignment='center',
                     fontweight='bold',
                     color='black')

        matplot.legend()
        if output != "":
            matplot.savefig(output)
        else:
            matplot.show()

        self.progressBarProcessor.setValue(100)

    def CreateBitratePlot(self):
        ''' Create video Plot Bitrate Thread '''
        if not self.KillAllProcessors():
            return
        try:
            self.VPBitratePlot = CreatePlotsBitrate()
            self.VPTBitratePlot = QThread()

            self.VPBitratePlot.moveToThread(self.VPTBitratePlot)

            self.VPBitratePlot.finished.connect(self.QThreadFinished)

            self.VPBitratePlot.return_fig.connect(self.ShowPlot)

            self.VPBitratePlot.error.connect(self.QThreadError)

            self.VPBitratePlot.progress.connect(
                self.progressBarProcessor.setValue)

            self.VPTBitratePlot.start(QThread.LowPriority)

            sender = self.sender().objectName()

            if sender == "actionAudio":
                QMetaObject.invokeMethod(self.VPBitratePlot, 'CreatePlot',
                                         Qt.QueuedConnection,
                                         Q_ARG(str, self.fileName),
                                         Q_ARG(str, None), Q_ARG(str, 'audio'))

            elif sender == "actionVideo":
                QMetaObject.invokeMethod(self.VPBitratePlot, 'CreatePlot',
                                         Qt.QueuedConnection,
                                         Q_ARG(str, self.fileName),
                                         Q_ARG(str, None), Q_ARG(str, 'video'))

            elif sender == "actionSave_Audio":
                selfilter = "Portable Network Graphics (*.png)"
                fileaudio, _ = QFileDialog.getSaveFileName(
                    self, "Save Audio Bitrate Plot", "",
                    "EPS Encapsulated Postscript (*.eps);;"
                    "PGF code for LaTex (*.pgf);;"
                    "Portable document format(*pdf);;"
                    "Portable Network Graphics (*.png);;"
                    "Postscript (*.ps);;"
                    "Raw RGBA bitmap (*.raw*.rgba);;"
                    "Scalable vector graphics (*.svg*.svgz)", selfilter)
                if fileaudio == "":
                    return

                QMetaObject.invokeMethod(self.VPBitratePlot, 'CreatePlot',
                                         Qt.QueuedConnection,
                                         Q_ARG(str, self.fileName),
                                         Q_ARG(str, fileaudio),
                                         Q_ARG(str, 'audio'))

            elif sender == "actionSave_Video":
                selfilter = "Portable Network Graphics (*.png)"
                filevideo, _ = QFileDialog.getSaveFileName(
                    self, "Save Video Bitrate Plot", "",
                    "EPS Encapsulated Postscript (*.eps);;"
                    "PGF code for LaTex (*.pgf);;"
                    "Portable document format(*pdf);;"
                    "Portable Network Graphics (*.png);;"
                    "Postscript (*.ps);;"
                    "Raw RGBA bitmap (*.raw*.rgba);;"
                    "Scalable vector graphics (*.svg*.svgz)", selfilter)
                if filevideo == "":
                    return

                QMetaObject.invokeMethod(self.VPBitratePlot, 'CreatePlot',
                                         Qt.QueuedConnection,
                                         Q_ARG(str, self.fileName),
                                         Q_ARG(str, filevideo),
                                         Q_ARG(str, 'video'))

        except Exception as e:
            qgsu.showUserAndLogMessage(
                QCoreApplication.translate("QgsFmvPlayer",
                                           "Failed creating Plot Bitrate"))

    def ExtractAllFrames(self):
        """ Extract All Video Frames Thread """
        if not self.KillAllProcessors():
            return

        options = QFileDialog.DontResolveSymlinks | QFileDialog.ShowDirsOnly
        directory = QFileDialog.getExistingDirectory(
            self,
            QCoreApplication.translate("QgsFmvPlayer", "Save images"),
            '',
            options=options)

        if directory:

            self.VPExtractFrames = ExtractFramesProcessor()
            self.VPTExtractAllFrames = QThread()

            self.VPExtractFrames.moveToThread(self.VPTExtractAllFrames)
            self.VPExtractFrames.finished.connect(self.QThreadFinished)
            self.VPExtractFrames.error.connect(self.QThreadError)
            self.VPExtractFrames.progress.connect(
                self.progressBarProcessor.setValue)
            self.VPTExtractAllFrames.start(QThread.LowPriority)

            QMetaObject.invokeMethod(self.VPExtractFrames,
                                     'ExtractFrames', Qt.QueuedConnection,
                                     Q_ARG(str, directory),
                                     Q_ARG(str, self.fileName))
        return

    def ExtractCurrentFrame(self):
        """ Extract Current Frame Thread """
        image = self.videoWidget.GetCurrentFrame()
        out_image, _ = QFileDialog.getSaveFileName(
            self, "Save Current Frame", "",
            "Image File (*.png *.jpg *.bmp *.tiff)")

        if out_image == "":
            return

        if out_image:
            t = threading.Thread(target=self.SaveCapture,
                                 args=(
                                     image,
                                     out_image,
                                 ))
            t.start()
        return

    def SaveCapture(self, image, output):
        ''' Save Current Image '''
        image.save(output)
        QApplication.processEvents()
        return

    def QThreadFinished(self, process, msg, outjson=None):
        ''' Finish Threads '''
        if process == "ExtractFramesProcessor":
            self.VPExtractFrames.deleteLater()
            self.VPTExtractAllFrames.terminate()
            self.VPTExtractAllFrames.deleteLater()
        elif process == "CreatePlotsBitrate":
            self.VPBitratePlot.deleteLater()
            self.VPTBitratePlot.terminate()
            self.VPTBitratePlot.deleteLater()
        elif process == "convert":
            self.VPConverter.deleteLater()
            self.VPTConverter.terminate()
            self.VPTConverter.deleteLater()
        elif process == "probeToJson":
            self.VPProbeToJson.deleteLater()
            self.VPTProbeToJson.terminate()
            self.VPTProbeToJson.deleteLater()
        elif process == "probeShow":
            self.VPProbe.deleteLater()
            self.VPTProbe.terminate()
            self.VPTProbe.deleteLater()
            self.showVideoInfoDialog(outjson)

        QApplication.processEvents()
        self.progressBarProcessor.setValue(0)
        return

    def QThreadError(self, processor, e, exception_string):
        """ Threads Errors"""
        qgsu.showUserAndLogMessage(QCoreApplication.translate(
            "QgsFmvPlayer", processor),
                                   'Failed!\n'.format(exception_string),
                                   level=QGis.Warning)

        self.QThreadFinished(processor, "Closing Processor")

        return

    def OpenQgsFmvMetadata(self):
        """ Open Metadata Dock """
        if self.metadataDlg is None:
            self.metadataDlg = QgsFmvMetadata(parent=self, player=self)
            self.addDockWidget(Qt.RightDockWidgetArea, self.metadataDlg)
            self.metadataDlg.show()
        else:
            self.metadataDlg.show()
        return

    def KillAllProcessors(self):
        """Kill All Processors"""
        """ Extract all frames Processors """
        try:
            if self.VPTExtractAllFrames.isRunning():
                ret = qgsu.CustomMessage(
                    QCoreApplication.translate(
                        "QgsFmvPlayer", "HEY...Active background process!"),
                    QCoreApplication.translate("QgsFmvPlayer",
                                               "Do you really want close?"))
                if ret == QMessageBox.Yes:
                    self.QThreadFinished("ExtractFramesProcessor",
                                         "Closing Extract Frames Processor")
                else:
                    return False
        except:
            None
        """ Bitrates Processors"""
        try:
            if self.VPTBitratePlot.isRunning():
                ret = qgsu.CustomMessage(
                    QCoreApplication.translate(
                        "QgsFmvPlayer", "HEY...Active background process!"),
                    QCoreApplication.translate("QgsFmvPlayer",
                                               "Do you really want close?"))
                if ret == QMessageBox.Yes:
                    self.QThreadFinished("CreatePlotsBitrate",
                                         "Closing Plot Bitrate")
                else:
                    return False
        except:
            None
        """ Converter Processors """
        try:
            if self.VPTConverter.isRunning():
                ret = qgsu.CustomMessage(
                    QCoreApplication.translate(
                        "QgsFmvPlayer", "HEY...Active background process!"),
                    QCoreApplication.translate("QgsFmvPlayer",
                                               "Do you really want close?"))
                if ret == QMessageBox.Yes:
                    self.QThreadFinished("convert", "Closing convert")
                else:
                    return False
        except:
            None
        """ probeToJson Processors """
        try:
            if self.VPTProbeToJson.isRunning():
                ret = qgsu.CustomMessage(
                    QCoreApplication.translate(
                        "QgsFmvPlayer", "HEY...Active background process!"),
                    QCoreApplication.translate("QgsFmvPlayer",
                                               "Do you really want close?"))
                if ret == QMessageBox.Yes:
                    self.QThreadFinished("probeToJson", "Closing Info to Json")
                else:
                    return False
        except:
            None
        """ probeShow Processors """
        try:
            if self.VPTProbe.isRunning():
                ret = qgsu.CustomMessage(
                    QCoreApplication.translate(
                        "QgsFmvPlayer", "HEY...Active background process!"),
                    QCoreApplication.translate("QgsFmvPlayer",
                                               "Do you really want close?"))
                if ret == QMessageBox.Yes:
                    self.QThreadFinished("probeShow",
                                         "Closing Show Video Info")
                else:
                    return False
        except:
            None
        return True

    def showVideoInfoDialog(self, outjson):
        """ Show Video Information Dialog """
        view = QTreeView()
        model = QJsonModel()
        view.setModel(model)
        model.loadJsonFromConsole(outjson)

        self.VideoInfoDialog = QDialog(self)
        self.VideoInfoDialog.setWindowTitle("Video Information : " +
                                            self.fileName)
        self.VideoInfoDialog.setWindowIcon(
            QIcon(":/imgFMV/images/video_information.png"))

        self.verticalLayout = QVBoxLayout(self.VideoInfoDialog)
        self.verticalLayout.addWidget(view)
        view.expandAll()
        view.header().setSectionResizeMode(QHeaderView.ResizeToContents)

        self.VideoInfoDialog.setWindowFlags(Qt.Window
                                            | Qt.WindowCloseButtonHint)
        self.VideoInfoDialog.setObjectName("VideoInfoDialog")
        self.VideoInfoDialog.resize(500, 400)
        self.VideoInfoDialog.show()

    def closeEvent(self, evt):
        """ Close Event """
        if self.KillAllProcessors() is False:
            evt.ignore()
            return

        self.player.stop()
        self.parent._PlayerDlg = None
        self.parent.ToggleActiveFromTitle()
        RemoveVideoLayers()
        RemoveGroupByName()

        # Restore Filters State
        self.videoWidget.RestoreFilters()
        # QApplication.processEvents()
        del self.player
Ejemplo n.º 34
0
class VideoPlayer(QWidget):
    def __init__(self, aPath, parent=None):
        super(VideoPlayer, self).__init__(parent)

        self.setAttribute(Qt.WA_NoSystemBackground, True)
        self.setAcceptDrops(True)
        self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.StreamPlayback)
        self.mediaPlayer.mediaStatusChanged.connect(self.printMediaData)
        self.mediaPlayer.setVolume(80)
        self.videoWidget = QVideoWidget(self)

        self.lbl = QLineEdit('00:00:00')
        self.lbl.setReadOnly(True)
        self.lbl.setFixedWidth(70)
        self.lbl.setUpdatesEnabled(True)
        self.lbl.setStyleSheet(stylesheet(self))

        self.elbl = QLineEdit('00:00:00')
        self.elbl.setReadOnly(True)
        self.elbl.setFixedWidth(70)
        self.elbl.setUpdatesEnabled(True)
        self.elbl.setStyleSheet(stylesheet(self))

        self.playButton = QPushButton()
        self.playButton.setEnabled(False)
        self.playButton.setFixedWidth(32)
        self.playButton.setStyleSheet("background-color: black")
        self.playButton.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay))
        self.playButton.clicked.connect(self.play)

        self.positionSlider = QSlider(Qt.Horizontal, self)
        self.positionSlider.setStyleSheet(stylesheet(self))
        self.positionSlider.setRange(0, 100)
        self.positionSlider.sliderMoved.connect(self.setPosition)
        self.positionSlider.sliderMoved.connect(self.handleLabel)
        self.positionSlider.setSingleStep(2)
        self.positionSlider.setPageStep(20)
        self.positionSlider.setAttribute(Qt.WA_TranslucentBackground, True)

        self.clip = QApplication.clipboard()
        self.process = QProcess(self)
        self.process.readyRead.connect(self.dataReady)
        #        self.process.started.connect(lambda: print("grabbing YouTube URL"))
        self.process.finished.connect(self.playFromURL)

        self.myurl = ""

        controlLayout = QHBoxLayout()
        controlLayout.setContentsMargins(5, 0, 5, 0)
        controlLayout.addWidget(self.playButton)
        controlLayout.addWidget(self.lbl)
        controlLayout.addWidget(self.positionSlider)
        controlLayout.addWidget(self.elbl)

        layout = QVBoxLayout()
        layout.setContentsMargins(0, 0, 0, 0)
        layout.addWidget(self.videoWidget)
        layout.addLayout(controlLayout)

        self.setLayout(layout)

        self.myinfo = "©2016\nAxel Schneider\n\nMouse Wheel = Zoom\nUP = Volume Up\nDOWN = Volume Down\n" + \
            "LEFT = < 1 Minute\nRIGHT = > 1 Minute\n" + \
                "SHIFT+LEFT = < 10 Minutes\nSHIFT+RIGHT = > 10 Minutes"

        self.widescreen = True

        #### shortcuts ####
        self.shortcut = QShortcut(QKeySequence("q"), self)
        self.shortcut.activated.connect(self.handleQuit)
        self.shortcut = QShortcut(QKeySequence("u"), self)
        self.shortcut.activated.connect(self.playFromURL)

        self.shortcut = QShortcut(QKeySequence("y"), self)
        self.shortcut.activated.connect(self.getYTUrl)

        self.shortcut = QShortcut(QKeySequence("o"), self)
        self.shortcut.activated.connect(self.openFile)
        self.shortcut = QShortcut(QKeySequence(" "), self)
        self.shortcut.activated.connect(self.play)
        self.shortcut = QShortcut(QKeySequence("f"), self)
        self.shortcut.activated.connect(self.handleFullscreen)
        self.shortcut = QShortcut(QKeySequence("i"), self)
        self.shortcut.activated.connect(self.handleInfo)
        self.shortcut = QShortcut(QKeySequence("s"), self)
        self.shortcut.activated.connect(self.toggleSlider)
        self.shortcut = QShortcut(QKeySequence(Qt.Key_Right), self)
        self.shortcut.activated.connect(self.forwardSlider)
        self.shortcut = QShortcut(QKeySequence(Qt.Key_Left), self)
        self.shortcut.activated.connect(self.backSlider)
        self.shortcut = QShortcut(QKeySequence(Qt.Key_Up), self)
        self.shortcut.activated.connect(self.volumeUp)
        self.shortcut = QShortcut(QKeySequence(Qt.Key_Down), self)
        self.shortcut.activated.connect(self.volumeDown)
        self.shortcut = QShortcut(
            QKeySequence(Qt.ShiftModifier + Qt.Key_Right), self)
        self.shortcut.activated.connect(self.forwardSlider10)
        self.shortcut = QShortcut(QKeySequence(Qt.ShiftModifier + Qt.Key_Left),
                                  self)
        self.shortcut.activated.connect(self.backSlider10)

        self.mediaPlayer.setVideoOutput(self.videoWidget)
        self.mediaPlayer.stateChanged.connect(self.mediaStateChanged)
        self.mediaPlayer.positionChanged.connect(self.positionChanged)
        self.mediaPlayer.positionChanged.connect(self.handleLabel)
        self.mediaPlayer.durationChanged.connect(self.durationChanged)
        self.mediaPlayer.error.connect(self.handleError)

        print("QT5 Player started")
        self.suspend_screensaver()
        #        msg = QMessageBox.information(self, "Qt5Player", "press o to open file")
        self.loadFilm("/home/brian/Dokumente/Qt5PlayerIntro.m4v")

    def playFromURL(self):
        self.mediaPlayer.pause()
        self.myurl = self.clip.text()
        self.mediaPlayer.setMedia(QMediaContent(QUrl(self.myurl)))
        self.playButton.setEnabled(True)
        self.mediaPlayer.play()
        self.hideSlider()
        print(self.myurl)

    def getYTUrl(self):
        cmd = "youtube-dl -g -f best " + self.clip.text()
        print("grabbing YouTube URL")
        self.process.start(cmd)

    def dataReady(self):
        self.myurl = str(self.process.readAll(), encoding='utf8').rstrip()  ###
        self.myurl = self.myurl.partition("\n")[0]
        print(self.myurl)
        self.clip.setText(self.myurl)
        self.playFromURL()

    def suspend_screensaver(self):
        'suspend linux screensaver'
        proc = subprocess.Popen(
            'gsettings set org.gnome.desktop.screensaver idle-activation-enabled false',
            shell=True)
        proc.wait()

    def resume_screensaver(self):
        'resume linux screensaver'
        proc = subprocess.Popen(
            'gsettings set org.gnome.desktop.screensaver idle-activation-enabled true',
            shell=True)
        proc.wait()

    def openFile(self):
        fileName, _ = QFileDialog.getOpenFileName(
            self, "Open Movie",
            QDir.homePath() + "/Videos",
            "Media (*.webm *.mp4 *.ts *.avi *.mpeg *.mpg *.mkv *.VOB *.m4v *.3gp *.mp3 *.m4a *.wav *.ogg *.flac *.m3u *.m3u8)"
        )

        if fileName != '':
            self.loadFilm(fileName)
            print("File loaded")

    def play(self):
        if self.mediaPlayer.state() == QMediaPlayer.PlayingState:
            self.mediaPlayer.pause()
        else:
            self.mediaPlayer.play()

    def mediaStateChanged(self, state):
        if self.mediaPlayer.state() == QMediaPlayer.PlayingState:
            self.playButton.setIcon(self.style().standardIcon(
                QStyle.SP_MediaPause))
        else:
            self.playButton.setIcon(self.style().standardIcon(
                QStyle.SP_MediaPlay))

    def positionChanged(self, position):
        self.positionSlider.setValue(position)

    def durationChanged(self, duration):
        self.positionSlider.setRange(0, duration)
        mtime = QTime(0, 0, 0, 0)
        mtime = mtime.addMSecs(self.mediaPlayer.duration())
        self.elbl.setText(mtime.toString())

    def setPosition(self, position):
        self.mediaPlayer.setPosition(position)

    def handleError(self):
        self.playButton.setEnabled(False)
        print("Error: ", self.mediaPlayer.errorString())

    def handleQuit(self):
        self.mediaPlayer.stop()
        self.resume_screensaver()
        print("Goodbye ...")
        app.quit()

    def contextMenuRequested(self, point):
        menu = QMenu()
        actionFile = menu.addAction(QIcon.fromTheme("video-x-generic"),
                                    "open File (o)")
        actionclipboard = menu.addSeparator()
        actionURL = menu.addAction(QIcon.fromTheme("browser"),
                                   "URL from Clipboard (u)")
        actionclipboard = menu.addSeparator()
        actionYTurl = menu.addAction(QIcon.fromTheme("youtube"),
                                     "URL from YouTube (y)")
        actionclipboard = menu.addSeparator()
        actionToggle = menu.addAction(QIcon.fromTheme("next"),
                                      "show / hide Slider (s)")
        actionFull = menu.addAction(QIcon.fromTheme("view-fullscreen"),
                                    "Fullscreen (f)")
        action169 = menu.addAction(QIcon.fromTheme("tv-symbolic"), "16 : 9")
        action43 = menu.addAction(QIcon.fromTheme("tv-symbolic"), "4 : 3")
        actionSep = menu.addSeparator()
        actionInfo = menu.addAction(QIcon.fromTheme("help-about"), "Info (i)")
        action5 = menu.addSeparator()
        actionQuit = menu.addAction(QIcon.fromTheme("application-exit"),
                                    "Exit (q)")

        actionFile.triggered.connect(self.openFile)
        actionQuit.triggered.connect(self.handleQuit)
        actionFull.triggered.connect(self.handleFullscreen)
        actionInfo.triggered.connect(self.handleInfo)
        actionToggle.triggered.connect(self.toggleSlider)
        actionURL.triggered.connect(self.playFromURL)
        actionYTurl.triggered.connect(self.getYTUrl)
        action169.triggered.connect(self.screen169)
        action43.triggered.connect(self.screen43)
        menu.exec_(self.mapToGlobal(point))

    def wheelEvent(self, event):
        mwidth = self.frameGeometry().width()
        mheight = self.frameGeometry().height()
        mleft = self.frameGeometry().left()
        mtop = self.frameGeometry().top()
        mscale = event.angleDelta().y() / 5
        if self.widescreen == True:
            self.setGeometry(mleft, mtop, mwidth + mscale,
                             (mwidth + mscale) / 1.778)
        else:
            self.setGeometry(mleft, mtop, mwidth + mscale,
                             (mwidth + mscale) / 1.33)

    def screen169(self):
        self.widescreen = True
        mwidth = self.frameGeometry().width()
        mheight = self.frameGeometry().height()
        mleft = self.frameGeometry().left()
        mtop = self.frameGeometry().top()
        mratio = 1.778
        self.setGeometry(mleft, mtop, mwidth, mwidth / mratio)

    def screen43(self):
        self.widescreen = False
        mwidth = self.frameGeometry().width()
        mheight = self.frameGeometry().height()
        mleft = self.frameGeometry().left()
        mtop = self.frameGeometry().top()
        mratio = 1.33
        self.setGeometry(mleft, mtop, mwidth, mwidth / mratio)

    def handleFullscreen(self):
        if self.windowState() & Qt.WindowFullScreen:
            QApplication.setOverrideCursor(Qt.ArrowCursor)
            self.showNormal()
            print("no Fullscreen")
        else:
            self.showFullScreen()
            QApplication.setOverrideCursor(Qt.BlankCursor)
            print("Fullscreen entered")

    def handleInfo(self):
        msg = QMessageBox.about(self, "QT5 Player", self.myinfo)

    def toggleSlider(self):
        if self.positionSlider.isVisible():
            self.hideSlider()
        else:
            self.showSlider()

    def hideSlider(self):
        self.playButton.hide()
        self.lbl.hide()
        self.positionSlider.hide()
        self.elbl.hide()
        mwidth = self.frameGeometry().width()
        mheight = self.frameGeometry().height()
        mleft = self.frameGeometry().left()
        mtop = self.frameGeometry().top()
        if self.widescreen == True:
            self.setGeometry(mleft, mtop, mwidth, mwidth / 1.778)
        else:
            self.setGeometry(mleft, mtop, mwidth, mwidth / 1.33)

    def showSlider(self):
        self.playButton.show()
        self.lbl.show()
        self.positionSlider.show()
        self.elbl.show()
        mwidth = self.frameGeometry().width()
        mheight = self.frameGeometry().height()
        mleft = self.frameGeometry().left()
        mtop = self.frameGeometry().top()
        if self.widescreen == True:
            self.setGeometry(mleft, mtop, mwidth, mwidth / 1.55)
        else:
            self.setGeometry(mleft, mtop, mwidth, mwidth / 1.33)

    def forwardSlider(self):
        self.mediaPlayer.setPosition(self.mediaPlayer.position() + 1000 * 60)

    def forwardSlider10(self):
        self.mediaPlayer.setPosition(self.mediaPlayer.position() + 10000 * 60)

    def backSlider(self):
        self.mediaPlayer.setPosition(self.mediaPlayer.position() - 1000 * 60)

    def backSlider10(self):
        self.mediaPlayer.setPosition(self.mediaPlayer.position() - 10000 * 60)

    def volumeUp(self):
        self.mediaPlayer.setVolume(self.mediaPlayer.volume() + 10)
        print("Volume: " + str(self.mediaPlayer.volume()))

    def volumeDown(self):
        self.mediaPlayer.setVolume(self.mediaPlayer.volume() - 10)
        print("Volume: " + str(self.mediaPlayer.volume()))

    def mouseMoveEvent(self, event):
        if event.buttons() == Qt.LeftButton:
            self.move(event.globalPos() \
                      - QPoint(self.frameGeometry().width() / 2, \
                                 self.frameGeometry().height() / 2))
            event.accept()

    def dragEnterEvent(self, event):
        if event.mimeData().hasUrls():
            event.accept()
        elif event.mimeData().hasText():
            event.accept()
        else:
            event.ignore()

    def dropEvent(self, event):
        if event.mimeData().hasUrls():
            url = event.mimeData().urls()[0].toString()
            print("url = ", url)
            self.mediaPlayer.stop()
            self.mediaPlayer.setMedia(QMediaContent(QUrl(url)))
            self.playButton.setEnabled(True)
            self.mediaPlayer.play()
        elif event.mimeData().hasText():
            mydrop = event.mimeData().text()
            ### YouTube url
            if "youtube" in mydrop:
                print("is YouTube", mydrop)
                self.clip.setText(mydrop)
                self.getYTUrl()
            else:
                ### normal url
                print("generic url = ", mydrop)
                self.mediaPlayer.setMedia(QMediaContent(QUrl(mydrop)))
                self.playButton.setEnabled(True)
                self.mediaPlayer.play()
                self.hideSlider()

    def loadFilm(self, f):
        self.mediaPlayer.setMedia(QMediaContent(QUrl.fromLocalFile(f)))
        self.playButton.setEnabled(True)
        self.mediaPlayer.play()

    def printMediaData(self):
        if self.mediaPlayer.mediaStatus() == 6:
            if self.mediaPlayer.isMetaDataAvailable():
                res = str(self.mediaPlayer.metaData("Resolution")).partition(
                    "PyQt5.QtCore.QSize(")[2].replace(", ",
                                                      " x ").replace(")", "")
                print("%s%s" % ("Video Resolution = ", res))
            else:
                print("no metaData available")

    def openFileAtStart(self, filelist):
        matching = [s for s in filelist if ".myformat" in s]
        if len(matching) > 0:
            self.loadFilm(matching)

##################### update Label ##################################

    def handleLabel(self):
        self.lbl.clear()
        mtime = QTime(0, 0, 0, 0)
        self.time = mtime.addMSecs(self.mediaPlayer.position())
        self.lbl.setText(self.time.toString())
Ejemplo n.º 35
0
class Music(QtWidgets.QMainWindow):
    def __init__(self):
        super().__init__()
        self.setFixedSize(400,200)
        self.setWindowTitle("🎧+📚=😊")
        self.setWindowOpacity(0.8)

        self.init_ui()
        self.custom_style()
        self.play_status = False # 播放状态初始化为否
        self.player = QMediaPlayer(self)

        self.timer = QtCore.QTimer()
        self.timer.setInterval(1000)
        self.timer.start()
        self.timer.timeout.connect(self.check_music_status)


    # 设置样式
    def custom_style(self):
        self.setStyleSheet('''
            #main_widget{
                border-radius:5px;
                background:black;
            }
            #play_btn,#pervious_btn,#next_btn{
                border:none;
            }
            #play_btn:hover,#pervious_btn:hover,#next_btn:hover{
                background:	#696969;
                border-radius:5px;
                cursor:pointer;
            }
        ''')
        self.close_btn.setStyleSheet('''
            QPushButton{
                background:#F76677;
                border-radius:5px;
                }
            QPushButton:hover{
                background:red;
                }''')
        self.status_label.setStyleSheet('''
            QLabel{
                background:#FFD85A;
                border-radius:5px;
                }
        ''')

    def init_ui(self):
        # 窗口布局

        self.main_widget = QtWidgets.QWidget()
        self.main_widget.setObjectName("main_widget")
        self.main_layout = QtWidgets.QGridLayout()
        self.main_widget.setLayout(self.main_layout)

        # 标题 半成,接口部分未找到适合的
        '''
        slogan=requests.get('https://api.xygeng.cn/one').json()['data']['content']
        self.title_lable = QtWidgets.QLabel(slogan)
        self.title_lable.setFont(font)
       '''
        self.title_lable = QtWidgets.QLabel('🌥WindPlayer')
        self.title_lable.setStyleSheet('''
        QLabel{
                color:"gray";
                }
        ''')
        self.title_lable.setFont(font)
        self.title_lable.setAlignment(QtCore.Qt.AlignCenter)
        # 关闭按钮
        self.close_btn = QtWidgets.QPushButton("")  # 关闭按钮
        self.close_btn.clicked.connect(self.close_btn_event)
        self.close_btn.setFixedSize(15,15)

        # 音乐状态按钮
        self.status_label = QtWidgets.QLabel("")
        # self.swith_btn.clicked.connect(self.swith_background) #此处还未完成 Darkmode 和 LightMode 的切换
        self.status_label.setFixedSize(15,15)

        # 播放按钮
        play_icon = qta.icon("fa.play-circle-o",)
        self.play_btn = QtWidgets.QPushButton(play_icon,"")
        self.play_btn.setIconSize(QtCore.QSize(80, 80))
        self.play_btn.setFixedSize(82,82)
        self.play_btn.setObjectName("play_btn")
        self.play_btn.clicked.connect(self.play_music)
        self.play_btn.setStyleSheet('''
                    QPushButton{
                        background:black;
                        border-radius:5px;
                        }
                    QPushButton:hover{
                        background:	#696969;
                        }''')


        # 下一首按钮
        next_icon = qta.icon("fa.chevron-right")
        self.next_btn = QtWidgets.QPushButton(next_icon,"")
        self.next_btn.setIconSize(QtCore.QSize(80,80))
        self.next_btn.setFixedSize(82,82)
        self.next_btn.setObjectName("next_btn")
        self.next_btn.clicked.connect(self.next_music)
        self.next_btn.setStyleSheet('''
            QPushButton{
                background:black;
                border-radius:5px;
                }
            QPushButton:hover{
                background:	#696969;
                }''')

        # 进度条
        self.process_bar = QtWidgets.QProgressBar()
        self.process_value = 0
        self.process_bar.setValue(self.process_value)
        self.process_bar.setFixedHeight(5)
        self.process_bar.setTextVisible(False)
        self.process_bar.setStyleSheet('''QProgressBar {   border: 2px solid grey;   border-radius: 5px;   background-color: #FFFFFF;}QProgressBar::chunk {   background-color: #05B8CC;   width: 28px;}QProgressBar {   border: 2px solid grey;   border-radius: 5px;   text-align: center;}
        ''')

        self.main_layout.addWidget(self.close_btn,0,0,1,1)
        self.main_layout.addWidget(self.title_lable,0,1,1,1)
        self.main_layout.addWidget(self.status_label,1,0,1,1)
        self.main_layout.addWidget(self.play_btn, 1, 1, 1, 1)
        self.main_layout.addWidget(self.next_btn, 1, 2, 1, 1)
        self.main_layout.addWidget(self.process_bar,2,0,1,3)

        self.setCentralWidget(self.main_widget)
        self.setWindowFlag(QtCore.Qt.FramelessWindowHint)  # 隐藏边框

    # 关闭程序
    def close_btn_event(self):
        self.close()
    # 夜间模式切换 (未完成 )
    def swich_background(self):
        self.main_widget.setStyleSheet('''
        QWidget{
        "background-color: black"}
        ''')
    # 鼠标长按事件
    def mousePressEvent(self, event):
        if event.button() == QtCore.Qt.LeftButton:
            self.m_drag = True
            self.m_DragPosition = event.globalPos() - self.pos()
            event.accept()
            self.setCursor(QtGui.QCursor(QtCore.Qt.OpenHandCursor))

    # 鼠标移动事件
    def mouseMoveEvent(self, QMouseEvent):
        if QtCore.Qt.LeftButton and self.m_drag:
            self.move(QMouseEvent.globalPos() - self.m_DragPosition)
            QMouseEvent.accept()

    # 鼠标释放事件
    def mouseReleaseEvent(self, QMouseEvent):
        self.m_drag = False
        self.setCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor))

    # 播放音乐
    def play_music(self):
        try:
            # 播放音乐
            if self.play_status is False:
                self.play_status = True # 设置播放状态为是
                self.play_btn.setIcon(qta.icon("fa.pause-circle")) # 设置播放图标
                player_status = self.player.mediaStatus() # 获取播放器状态
                # print("当前播放状态:",player_status)
                if player_status == 6:
                    # 设置状态标签为绿色
                    self.status_label.setStyleSheet('''QLabel{background:#72EA72;border-radius:5px;}''')
                    self.player.play()
                else:
                    self.next_music()
            # 暂停音乐
            else:
                # 设置状态为蓝色
                self.status_label.setStyleSheet('''QLabel{background:#0099CC;border-radius:5px;}''')
                self.play_status = False
                self.play_btn.setIcon(qta.icon("fa.play-circle"))
                self.player.pause()
        except Exception as e:
            print(repr(e))

    # 下一首音乐
    def next_music(self):
        try:
            # 设置状态为黄色
            self.status_label.setStyleSheet('''
                QLabel{
                    background:#FFBF00;
                    border-radius:5px;
                    }
            ''')
            self.play_status = True # 设置播放状态为是
            self.play_btn.setIcon(qta.icon("fa.pause-circle")) # 修改播放图标
            self.process_value = 0 # 重置进度值

            # 获取网络歌曲
            self.get_music_thread = GetMusicThread()
            self.get_music_thread.finished_signal.connect(self.init_player)
            self.get_music_thread.start()
        except Exception as e:
            print(traceback.print_exc())

    # 设置播放器
    def init_player(self,url):
        # print("获取到音乐链接:",url)
        content = QMediaContent(QtCore.QUrl(url))
        self.player.setMedia(content)
        self.player.setVolume(50)
        self.player.play()
        self.duration = self.player.duration()  # 音乐的时长
        # 设置状态为绿色
        self.status_label.setStyleSheet('''
            QLabel{
                background:#72EA72;
                border-radius:5px;
                }
        ''')

        # 进度条计时器
        self.process_timer = QtCore.QTimer()
        self.process_timer.setInterval(1000)
        self.process_timer.start()
        self.process_timer.timeout.connect(self.process_timer_status)


    # 定时器
    def check_music_status(self):
        player_status = self.player.mediaStatus()
        player_duration = self.player.duration()
        # print("音乐时间:",player_duration)
        # print("当前播放器状态",player_status)
        if player_status == 7:
            self.next_music()

        if player_duration > 0:
            self.duration = player_duration

    # 进度条定时器
    def process_timer_status(self):
        try:
            if self.play_status is True:
                self.process_value +=float(100 / (self.duration/1000))
                #print("当前进度:",self.process_value)
                self.process_bar.setValue(self.process_value)
        except Exception as e:
            print('')
Ejemplo n.º 36
0
class VideoPlayer(QWidget):
    def __init__(self, aPath, parent=None):
        super(VideoPlayer, self).__init__(parent)

        #self.setAttribute(Qt.WA_NoSystemBackground, True)

        self.colorDialog = None

        self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.VideoSurface)
        self.mediaPlayer.setVolume(80)
        self.videoWidget = QVideoWidget(self)

        self.lbl = QLineEdit('00:00:00')
        self.lbl.setReadOnly(True)
        self.lbl.setEnabled(False)
        self.lbl.setFixedWidth(60)
        self.lbl.setUpdatesEnabled(True)
        #self.lbl.setStyleSheet(stylesheet(self))

        self.elbl = QLineEdit('00:00:00')
        self.elbl.setReadOnly(True)
        self.elbl.setEnabled(False)
        self.elbl.setFixedWidth(60)
        self.elbl.setUpdatesEnabled(True)
        #self.elbl.setStyleSheet(stylesheet(self))

        self.playButton = QPushButton()
        self.playButton.setEnabled(False)
        self.playButton.setFixedWidth(32)
        #self.playButton.setStyleSheet("background-color: black")
        self.playButton.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay))
        self.playButton.clicked.connect(self.play)

        ### pointA button
        self.apointButton = QPushButton()
        self.apointButton.setEnabled(False)
        self.apointButton.setFixedWidth(32)
        #self.apointButton.setStyleSheet("background-color: black")
        self.apointButton.setIcon(self.style().standardIcon(
            QStyle.SP_MediaSeekForward))
        self.apointButton.clicked.connect(self.setPointA)

        ### pointB button
        self.bpointButton = QPushButton()
        self.bpointButton.setEnabled(False)
        self.bpointButton.setFixedWidth(32)
        #self.bpointButton.setStyleSheet("background-color: black")
        self.bpointButton.setIcon(self.style().standardIcon(
            QStyle.SP_MediaSeekBackward))
        self.bpointButton.clicked.connect(self.setPointB)

        ### cut button
        self.cutButton = QPushButton()
        self.cutButton.setEnabled(False)
        self.cutButton.setFixedWidth(32)
        self.cutButton.setIcon(self.style().standardIcon(
            QStyle.SP_DriveFDIcon))
        self.cutButton.clicked.connect(self.cut)

        self.positionSlider = QSlider(Qt.Horizontal, self)
        self.positionSlider.setStyleSheet(stylesheet(self))
        self.positionSlider.setRange(0, 100)
        self.positionSlider.sliderMoved.connect(self.setPosition)
        self.positionSlider.sliderMoved.connect(self.handle_label)
        self.positionSlider.setSingleStep(2)
        self.positionSlider.setPageStep(20)
        #self.positionSlider.setAttribute(Qt.WA_NoSystemBackground, True)

        controlLayout = QHBoxLayout()
        controlLayout.setContentsMargins(5, 0, 5, 0)
        controlLayout.addWidget(self.playButton)
        controlLayout.addWidget(self.apointButton)
        controlLayout.addWidget(self.bpointButton)
        controlLayout.addWidget(self.cutButton)
        controlLayout.addWidget(self.lbl)
        controlLayout.addWidget(self.positionSlider)
        controlLayout.addWidget(self.elbl)

        layout0 = QVBoxLayout()
        layout0.setContentsMargins(0, 0, 0, 0)
        layout0.addWidget(self.videoWidget)
        layout0.addLayout(controlLayout)

        self.setLayout(layout0)

        self.widescreen = True

        self.setAcceptDrops(True)
        self.setWindowTitle("QT5 Player")
        #self.setWindowFlags(Qt.WindowStaysOnTopHint | Qt.FramelessWindowHint)
        self.setGeometry(300, 200, 400, 290)
        self.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
        self.customContextMenuRequested[QtCore.QPoint].connect(
            self.contextMenuRequested)
        #self.hideSlider()
        self.show()
        #self.playFromURL()

        ### shortcuts ###
        self.shortcut = QShortcut(QKeySequence('q'), self)
        self.shortcut.activated.connect(self.handleQuit)
        self.shortcut = QShortcut(QKeySequence('o'), self)
        self.shortcut.activated.connect(self.openFile)
        self.shortcut = QShortcut(QKeySequence(' '), self)
        self.shortcut.activated.connect(self.play)
        self.shortcut = QShortcut(QKeySequence('s'), self)
        self.shortcut.activated.connect(self.toggleSlider)
        self.shortcut = QShortcut(QKeySequence('v'), self)
        self.shortcut.activated.connect(self.setPointA)
        self.shortcut = QShortcut(QKeySequence('b'), self)
        self.shortcut.activated.connect(self.setPointB)
        self.shortcut = QShortcut(QKeySequence(Qt.Key_Right), self)
        self.shortcut.activated.connect(self.forwardSlider)
        self.shortcut = QShortcut(QKeySequence(Qt.Key_Left), self)
        self.shortcut.activated.connect(self.backSlider)
        self.shortcut = QShortcut(QKeySequence(Qt.Key_Up), self)
        self.shortcut.activated.connect(self.volumeUp)
        self.shortcut = QShortcut(QKeySequence(Qt.Key_Down), self)
        self.shortcut.activated.connect(self.volumeDown)
        self.shortcut = QShortcut(
            QKeySequence(Qt.ShiftModifier + Qt.Key_Right), self)
        self.shortcut.activated.connect(self.forwardSlider10)
        self.shortcut = QShortcut(QKeySequence(Qt.ShiftModifier + Qt.Key_Left),
                                  self)
        self.shortcut.activated.connect(self.backSlider10)

        self.mediaPlayer.setVideoOutput(self.videoWidget)
        self.mediaPlayer.stateChanged.connect(self.mediaStateChanged)
        self.mediaPlayer.positionChanged.connect(self.positionChanged)
        self.mediaPlayer.positionChanged.connect(self.handle_label)
        self.mediaPlayer.durationChanged.connect(self.durationChanged)
        self.mediaPlayer.error.connect(self.handleError)

        self.apoint = 0
        self.bpoint = 0
        self.inputfile = pathlib.Path()
        # self.outputfile = pathlib.Path()

    def openFile(self):
        fileName, _ = QFileDialog.getOpenFileName(
            self, 'Open Movie',
            QDir.homePath() + '/Desktop',
            'Videos (*.mp4 *.ts *.avi *.mpeg *.mpg *.mkv *.VOB *.m4v)')
        if fileName != '':
            self.load_film(fileName)
            print("File loaded")
            print(fileName)
            self.inputfile = pathlib.Path(fileName)

    def getclipFileName(self):
        clipFileName = QFileDialog.getSaveFileName(
            self, 'Save Clip',
            QDir.homePath() + '/Desktop', 'all files(*.*)')
        return clipFileName

    #def playFromURL(self):

    def play(self):
        if self.mediaPlayer.state() == QMediaPlayer.PlayingState:
            self.mediaPlayer.pause()
        else:
            self.mediaPlayer.play()

    def mediaStateChanged(self, state):
        if self.mediaPlayer.state() == QMediaPlayer.PlayingState:
            self.playButton.setIcon(self.style().standardIcon(
                QStyle.SP_MediaPause))
        else:
            self.playButton.setIcon(self.style().standardIcon(
                QStyle.SP_MediaPlay))

    def positionChanged(self, position):
        self.positionSlider.setValue(position)

    def durationChanged(self, duration):
        self.positionSlider.setRange(0, duration)
        mtime = QTime(0, 0, 0, 0)
        mtime = mtime.addMSecs(self.mediaPlayer.duration())
        self.elbl.setText(mtime.toString())

    def setPosition(self, position):
        self.mediaPlayer.setPosition(position)

    # cut point A function
    def setPointA(self):
        self.apoint = self.time.toString()
        print('A Point ' + self.apoint)

    # cut point B function
    def setPointB(self):
        self.play()
        self.bpoint = self.time.toString()
        print('B Point ' + self.bpoint)

    # cut
    def cut(self):
        print("Input: ", self.inputfile.resolve())
        length = self.lengthCalculation(self.apoint, self.bpoint)
        output_file = os.path.splitext(str(
            self.inputfile.resolve()))[0] + '__' + re.sub(
                ':', '_', self.apoint) + '__' + re.sub(
                    ':', '_', self.bpoint
                ) + self.inputfile.suffix  # no ':' allowed in a windows path.
        print("Output:", output_file)
        command = "ffmpeg -i " + "\"" + str(
            self.inputfile.resolve()
        ) + "\"" + " -ss " + self.apoint + " -t " + length + " -c:v copy -c:a copy " + "\"" + output_file + "\""
        print("Executing:\n", command, "\n")
        run(command, shell=True)

    # cut length calculation
    def twodigi(self, str0):
        if len(str0) == 1:
            str0 = '0' + str0
        return str0

    def lengthCalculation(self, start, end):
        start_s = int(start[:2]) * 3600 + int(start[3:5]) * 60 + int(start[6:])
        # print(start_s)
        end_s = int(end[:2]) * 3600 + int(end[3:5]) * 60 + int(end[6:])
        # print(end_s)
        length_s = end_s - start_s
        # print(length_s)
        hr = self.twodigi(str(length_s // 3600))
        mn = self.twodigi(str((length_s % 3600) // 60))
        sc = self.twodigi(str(length_s % 60))
        length = hr + ':' + mn + ':' + sc
        print(length)
        return length

    def handleError(self):
        self.playButton.setEnabled(False)
        self.apointButton.setEnabled(False)
        self.bpointButton.setEnabled(False)
        self.cutButton.setEnabled(False)
        print("Error: " + self.mediaPlayer.errorString())

    def handleQuit(self):
        self.mediaPlayer.stop()
        print('Quit.')
        app.quit()

    def contextMenuRequested(self, point):
        menu = QtWidgets.QMenu()
        actionFile = menu.addAction('Open File (o)')
        actionFile.triggered.connect(self.openFile)

        actionToggle = menu.addAction('show / hide Slider (s)')
        actionToggle.triggered.connect(self.toggleSlider)

        action169 = menu.addAction('16 : 9')
        action169.triggered.connect(self.screen169)

        action43 = menu.addAction('4 : 3')
        action43.triggered.connect(self.screen43)

        actionQuit = menu.addAction('Exit (q)')
        actionQuit.triggered.connect(self.handleQuit)

        menu.exec_(self.mapToGlobal(point))

    def wheelEvent(self, event):
        mwidth = self.frameGeometry().width()
        #mheight = self.frameGeometry().height()
        mleft = self.frameGeometry().left()
        mtop = self.frameGeometry().top()
        mscale = event.angleDelta().y() / 5
        if self.widescreen == True:
            self.setGeometry(mleft, mtop, mwidth + mscale,
                             (mwidth + mscale) / 1.778)
        else:
            self.setGeometry(mleft, mtop, mwidth + mscale,
                             (mwidth + mscale) / 1.33)

    def screen169(self):
        self.widescreen = True
        mwidth = self.frameGeometry().width()
        #mheight = self.frameGeometry().height()
        mleft = self.frameGeometry().left()
        mtop = self.frameGeometry().top()
        mratio = 1.778
        self.setGeometry(mleft, mtop, mwidth, mwidth / mratio)

    def screen43(self):
        self.widescreen = False
        mwidth = self.frameGeometry().width()
        #mheight = self.frameGeometry().height()
        mleft = self.frameGeometry().left()
        mtop = self.frameGeometry().top()
        mratio = 1.33
        self.setGeometry(mleft, mtop, mwidth, mwidth / mratio)

    def handleFullscreen(self):
        pass

    def handleInfo(self):
        pass

    def toggleSlider(self):
        if self.positionSlider.isVisible():
            self.hideSlider()
        else:
            self.showSlider()

    def hideSlider(self):
        self.playButton.hide()
        self.lbl.hide()
        self.positionSlider.hide()
        self.elbl.hide()
        mwidth = self.frameGeometry().width()
        mleft = self.frameGeometry().left()
        mtop = self.frameGeometry().top()
        if self.widescreen == True:
            self.setGeometry(mleft, mtop, mwidth, mwidth / 1.778)
        else:
            self.setGeometry(mleft, mtop, mwidth, mwidth / 1.33)

    def showSlider(self):
        self.playButton.show()
        self.lbl.show()
        self.positionSlider.show()
        self.elbl.show()
        mwidth = self.frameGeometry().width()
        mleft = self.frameGeometry().left()
        mtop = self.frameGeometry().top()
        self.positionSlider.setFocus()
        if self.widescreen == True:
            self.setGeometry(mleft, mtop, mwidth, mwidth / 1.55)
        else:
            self.setGeometry(mleft, mtop, mwidth, mwidth / 1.33)

    def forwardSlider(self):
        self.mediaPlayer.setPosition(self.mediaPlayer.position() + 100 * 60)

    def forwardSlider10(self):
        self.mediaPlayer.setPosition(self.mediaPlayer.position() + 250 * 60)

    def backSlider(self):
        self.mediaPlayer.setPosition(self.mediaPlayer.position() - 100 * 60)

    def backSlider10(self):
        self.mediaPlayer.setPosition(self.mediaPlayer.position() - 250 * 60)

    def volumeUp(self):
        self.mediaPlayer.setVolume(self.mediaPlayer.volume() + 10)

    def volumeDown(self):
        self.mediaPlayer.setVolume(self.mediaPlayer.volume() - 10)

    '''
    def mouseMoveEvent(self, event):
        if event.buttons() == Qt.LeftButton:
            #self.move(event.globalPos() - QPoint(self.frameGeometry().width() / 2, self.frameGeometry().height() / 2))
            self.move(event.globalPos() - QPoint(self.geometry().left(),self.geometry().top()))
            event.accept()
    '''

    def dragEnterEvent(self, event):
        if event.mimeData().hasUrls():
            event.accept()
        elif event.mimeData().hasFormat('text/plain'):
            event.accept()
        else:
            event.ignore()

    def dropEvent(self, event):
        if event.mimeData().hasUrls():
            f = str(event.mimeData().urls()[0].toLocalFile())
            self.load_film(f)
            self.inputfile = pathlib.Path(f)
        elif event.mimeData().hasText():
            f = str(event.mimeData().text())
            self.mediaPlayer.setMedia(QMediaContent(QUrl(f)))
            self.inputfile = pathlib.Path(f)
            self.mediaPlayer.play()

    def load_film(self, f):
        self.mediaPlayer.setMedia(QMediaContent(QUrl.fromLocalFile(f)))
        self.playButton.setEnabled(True)
        self.apointButton.setEnabled(True)
        self.bpointButton.setEnabled(True)
        self.cutButton.setEnabled(True)
        self.mediaPlayer.play()

    def open_file_at_start(self, filelist):
        matching = [s for s in filelist if '.myformat' in s]
        if len(matching) > 0:
            self.load_film(matching)

    def handle_label(self):
        self.lbl.clear()
        mtime = QTime(0, 0, 0, 0)
        self.time = mtime.addMSecs(self.mediaPlayer.position())
        self.lbl.setText(self.time.toString())
Ejemplo n.º 37
0
class PlaybackPanel(SpecialLabel):
    desktop_lyric_state_changed_signal = pyqtSignal(bool)
    playmode_changed_signal = pyqtSignal(int, int)
    media_player_notify_signal = pyqtSignal(int)
    muted_changed_signal = pyqtSignal(int)
    mark_favorite_completed_signal = pyqtSignal()
    current_media_changed_signal = pyqtSignal()
    music_ended_signal = pyqtSignal()
    update_window_lyric_signal = pyqtSignal(str, str)
    show_artist_info_signal = pyqtSignal(str)
    dont_hide_main_window_signal = pyqtSignal()

    def __init__(self, parent=None):
        super(PlaybackPanel, self).__init__(parent)
        self.initial_mediaplayer()
        self.create_actions()
        self.setup_ui()
        self.create_connections()
        self.initial_params()

    def create_connections(self):
        self.artistHeadLabel.clicked.connect(self.show_artist_info)
        self.desktopLyric.hide_desktop_lyric_signal.connect(self.desktop_lyric_closed)
        self.seekSlider.valueChanged.connect(self.slider_value_changed)
        self.seekSlider.sliderPressed.connect(self.slider_pressed)
        self.seekSlider.sliderReleased.connect(self.seek)
        self.mediaPlayer.positionChanged.connect(self.tick)
        self.mediaPlayer.mutedChanged.connect(self.muted_changed_signal.emit)
        self.mediaPlayer.stateChanged.connect(self.state_changed)
        self.mediaPlayer.durationChanged.connect(self.duration_changed)
        self.mediaPlayer.mediaStatusChanged.connect(self.media_status_changed)
        self.mediaPlayer.currentMediaChanged.connect(self.current_media_changed)

    def initial_mediaplayer(self):
        self.mediaPlayer = QMediaPlayer()
        self.mediaPlayer.setNotifyInterval(500)
        self.set_volume(globalSettings.Volume)

    def initial_params(self):
        self.playlist = None
        self.artistName = "Zheng-Yejian"
        self.clickPlayFlag = False  # 用来标志一首歌是否是主动点击选中的
        self.timerFlag = False
        self.timeStart = 0
        self.timeSpan = 0
        self.sourcePath = ""
        self.errorType = Configures.NoError
        self.currentSourceRow = -1
        self.nearPlayedSongs = []
        self.downloadDir = globalSettings.DownloadfilesPath
        self.songinfosManager = SonginfosManager()
        self.totalTime = Configures.ZeroTime
        self.playmode = Configures.PlaymodeRandom  # 播放模式指示器
        playlistTemp = Playlist()
        playlistTemp.fill_list(Configures.PlaylistFavorite)
        self.lovedSongs = playlistTemp.get_titles()

    def set_playlist(self, playlist):
        self.playlist = playlist
        self.currentSourceRow = self.playlist.get_current_row()

    def create_actions(self):
        self.nextAction = QAction(QIcon(IconsHub.ControlNext), "下一首", self, enabled=True, triggered=self.next_song)

        self.playAction = QAction(QIcon(IconsHub.ControlPlay), "播放/暂停", self, enabled=True, triggered=self.play_music)

        self.previousAction = QAction(
            QIcon(IconsHub.ControlPrevious), "上一首", self, enabled=True, triggered=self.previous_song
        )

        self.stopAction = QAction(
            QIcon(IconsHub.ControlStop), "停止", self, enabled=True, triggered=self.stop_music_but_timing
        )

    def get_play_button_action(self):
        return self.playAction

    def get_previous_button_action(self):
        return self.previousAction

    def get_next_button_action(self):
        return self.nextAction

    def get_stop_button_action(self):
        return self.stopAction

    def set_download_dir(self, dir):
        self.downloadDir = dir

    def get_loved_songs(self):
        return self.lovedSongs

    def get_songinfos_manager(self):
        return self.songinfosManager

    def setup_ui(self):
        self.setFixedHeight(50)
        # 桌面歌词标签
        self.desktopLyric = desktop_lyric.DesktopLyric()
        self.desktopLyric.set_color(globalSettings.DesktoplyricColors)
        # 3个标签
        self.artistHeadLabel = LabelButton()
        self.artistHeadLabel.setToolTip(self.tr("查看歌手信息"))
        self.artistHeadLabel.setFixedSize(QSize(42, 42))
        self.artistHeadLabel.setScaledContents(True)
        self.artistHeadLabel.setPixmap(QPixmap(IconsHub.Anonymous))

        self.musicTitleLabel = NewLabel()
        self.musicTitleLabel.setObjectName("musicTitleLabel")
        self.musicTitleLabel.setFixedSize(QSize(370, 20))
        self.musicTitleLabel.setText("Zheng-Yejian._.XYPLAYER")
        self.timeLabel = QLabel("00:00/00:00")
        self.timeLabel.setObjectName("timeLabel")
        self.timeLabel.setFixedHeight(20)
        self.timeLabel.setAlignment(Qt.AlignRight and Qt.AlignVCenter)

        # 五个基本按键
        self.playmodeButton = QToolButton(clicked=self.change_playmode)
        self.playmodeButton.setFocusPolicy(Qt.NoFocus)

        self.playmodeButton.setIcon(QIcon(IconsHub.PlaymodeRandom))
        self.playmodeButton.setIconSize(QSize(25, 25))
        self.playmodeButton.setToolTip("随机播放")

        self.favoriteButton = QToolButton(clicked=self.mark_as_favorite)
        self.favoriteButton.setFocusPolicy(Qt.NoFocus)
        self.favoriteButton.setToolTip("收藏")
        self.favoriteButton.setIcon(QIcon(IconsHub.Favorites))
        self.favoriteButton.setIconSize(QSize(20, 20))

        self.previousButton = QToolButton()
        self.previousButton.setFocusPolicy(Qt.NoFocus)
        self.previousButton.setIconSize(QSize(40, 40))
        self.previousButton.setShortcut(QKeySequence("Ctrl + Left"))
        self.previousButton.setDefaultAction(self.previousAction)

        self.playButton = QToolButton()
        self.playButton.setFocusPolicy(Qt.NoFocus)
        self.playButton.setIconSize(QSize(40, 40))
        self.playButton.setShortcut(QKeySequence("Ctrl + Down"))
        self.playButton.setDefaultAction(self.playAction)

        self.nextButton = QToolButton()
        self.nextButton.setFocusPolicy(Qt.NoFocus)
        self.nextButton.setIconSize(QSize(40, 40))
        self.nextButton.setFocusPolicy(Qt.NoFocus)
        self.nextButton.setShortcut(QKeySequence("Ctrl + Right"))
        self.nextButton.setDefaultAction(self.nextAction)

        self.desktopLyricButton = QToolButton(clicked=self.show_desktop_lyric)
        self.desktopLyricButton.setToolTip(self.tr("桌面歌词"))
        self.desktopLyricButton.setFocusPolicy(Qt.NoFocus)
        self.desktopLyricButton.setIcon(QIcon(IconsHub.DesktopLyric))
        self.desktopLyricButton.setIconSize(QSize(25, 25))

        self.seekSlider = QSlider(Qt.Horizontal)
        self.seekSlider.setObjectName("seekSlider")
        self.seekSlider.setFixedHeight(20)
        self.seekSlider.setFocusPolicy(Qt.NoFocus)
        self.seekSlider.setRange(0, 0)

        hbox1 = QHBoxLayout()
        hbox1.addWidget(self.favoriteButton)
        hbox1.addWidget(self.musicTitleLabel)
        hbox1.addStretch()
        hbox1.addWidget(self.timeLabel)
        vbox1 = QVBoxLayout()
        vbox1.addLayout(hbox1)
        vbox1.setSpacing(5)
        vbox1.addWidget(self.seekSlider)

        mainLayout = QHBoxLayout(self)
        mainLayout.setContentsMargins(2, 0, 0, 0)
        mainLayout.addWidget(self.artistHeadLabel)
        mainLayout.addWidget(self.previousButton)
        mainLayout.addWidget(self.playButton)
        mainLayout.addWidget(self.nextButton)
        mainLayout.addLayout(vbox1)
        mainLayout.addWidget(self.playmodeButton)
        mainLayout.addWidget(self.desktopLyricButton)

    def show_desktop_lyric(self):
        if self.desktopLyric.isHidden():
            beToOff = True
            self.desktopLyric.show()
            self.desktopLyric.original_place()
        else:
            beToOff = False
            self.desktopLyric.hide()
        self.desktop_lyric_state_changed_signal.emit(beToOff)

    def desktop_lyric_closed(self):
        self.desktop_lyric_state_changed_signal.emit(False)

    def change_playmode(self):
        oldPlaymode = self.playmode
        if self.playmode == Configures.PlaymodeRandom:
            self.set_new_playmode(Configures.PlaymodeOrder)
        elif self.playmode == Configures.PlaymodeOrder:
            self.set_new_playmode(Configures.PlaymodeSingle)
        elif self.playmode == Configures.PlaymodeSingle:
            self.set_new_playmode(Configures.PlaymodeRandom)
        self.playmode_changed_signal.emit(oldPlaymode, self.playmode)

    def set_new_playmode(self, playmode):
        self.playmode = playmode
        if playmode == Configures.PlaymodeRandom:
            iconPath = IconsHub.PlaymodeRandom
            toolTip = Configures.PlaymodeRandomText
        elif playmode == Configures.PlaymodeOrder:
            iconPath = IconsHub.PlaymodeOrder
            toolTip = Configures.PlaymodeOrderText
        else:
            iconPath = IconsHub.PlaymodeSingle
            toolTip = Configures.PlaymodeSingleText
        self.playmodeButton.setIcon(QIcon(iconPath))
        self.playmodeButton.setToolTip(toolTip)

    def ui_initial(self):
        self.mediaPlayer.stop()
        self.totalTime = "00:00"
        self.playAction.setIcon(QIcon(IconsHub.ControlPlay))
        self.musicTitleLabel.setText("Zheng-Yejian._.XYPLAYER")
        self.artistName = "Zheng-Yejian"
        self.artistHeadLabel.setPixmap(QPixmap(IconsHub.Anonymous))
        self.seekSlider.setRange(0, 0)
        self.favoriteButton.setIcon(QIcon(IconsHub.Favorites))
        self.favoriteButton.setToolTip("收藏")
        self.timeLabel.setText("00:00/00:00")

    def set_volume(self, volume):
        self.mediaPlayer.setVolume(volume)

    def set_muted(self, muted):
        self.mediaPlayer.setMuted(muted)

    def tick(self):
        currentTime = self.mediaPlayer.position()
        self.seekSlider.setValue(currentTime)
        cTime = format_position_to_mmss(currentTime // 1000)
        self.timeLabel.setText(cTime + "/" + self.totalTime)
        self.media_player_notify_signal.emit(currentTime)

    def slider_value_changed(self, value):
        cTime = format_position_to_mmss(value // 1000)
        self.timeLabel.setText("%s/%s" % (cTime, self.totalTime))
        self.media_player_notify_signal.emit(value)

    def slider_pressed(self):
        self.mediaPlayer.positionChanged.disconnect(self.tick)

    def seek(self):
        if self.mediaPlayer.state() == QMediaPlayer.StoppedState:
            self.mediaPlayer.play()
            self.mediaPlayer.setPosition(self.seekSlider.value())
        else:
            self.mediaPlayer.setPosition(self.seekSlider.value())
            self.mediaPlayer.play()
        self.mediaPlayer.positionChanged.connect(self.tick)

    def duration_changed(self, duration):
        self.seekSlider.setMaximum(duration)
        exactTotalTime = format_position_to_mmss(self.mediaPlayer.duration() // 1000)
        self.timeLabel.setText("%s/%s" % (Configures.ZeroTime, exactTotalTime))
        if self.totalTime != exactTotalTime:
            self.totalTime = exactTotalTime
            self.playlist.set_music_time_at(self.currentSourceRow, exactTotalTime)

    def check_favorite(self):
        if self.currentSourceRow >= 0:
            if self.playlist.get_music_title_at(self.currentSourceRow) in self.lovedSongs:
                self.favoriteButton.setIcon(QIcon(IconsHub.Favorites))
                self.favoriteButton.setToolTip("取消收藏")
            else:
                self.favoriteButton.setIcon(QIcon(IconsHub.FavoritesNo))
                self.favoriteButton.setToolTip("收藏")
            if self.playlist.get_name() == Configures.PlaylistFavorite:
                self.favoriteButton.setToolTip("收藏")

    def mark_as_favorite(self):
        if (
            self.playlist.get_name() == Configures.PlaylistFavorite
            or not self.playlist.length()
            or self.currentSourceRow < 0
        ):
            return
        path = self.playlist.get_music_path_at(self.currentSourceRow)
        title = self.playlist.get_music_title_at(self.currentSourceRow)
        if self.playlist.get_name() == Configures.PlaylistOnline:
            musicName = get_full_music_name_from_title(title)
            musicPath = os.path.join(self.downloadDir, musicName)
            musicPathO = os.path.join(Configures.MusicsDir, musicName)
            if not os.path.exists(musicPath) and not os.path.exists(musicPathO):
                QMessageBox.information(self, "提示", "请先下载该歌曲再添加喜欢!")
                return
            if os.path.exists(musicPath):
                path = musicPath
            else:
                path = musicPathO
        elif not os.path.exists(path):
            QMessageBox.information(self, "提示", "路径'" + "%s" % path + "'无效,无法标记喜欢!")
            return
        playlistTemp = Playlist()
        playlistTemp.fill_list(Configures.PlaylistFavorite)
        if title in self.lovedSongs:
            playlistTemp.remove_item_at(self.lovedSongs.index(title))
            playlistTemp.commit_records()
            self.lovedSongs.remove(title)
            self.favoriteButton.setIcon(QIcon(IconsHub.FavoritesNo))
            self.favoriteButton.setToolTip("收藏")
        else:
            playlistTemp.add_item_from_path(path)
            playlistTemp.commit_records()
            self.lovedSongs.append(title)
            self.favoriteButton.setIcon(QIcon(IconsHub.Favorites))
            self.favoriteButton.setToolTip("取消收藏")
        self.mark_favorite_completed_signal.emit()

    def show_artist_info(self):
        if self.artistName:
            self.show_artist_info_signal.emit(self.artistName)

    def decide_to_play_or_pause(self, row):
        if row != self.currentSourceRow:
            self.set_media_source_at_row(row, clickPlayFlag=True)
        elif self.mediaPlayer.state() in (QMediaPlayer.PausedState, QMediaPlayer.StoppedState):
            self.mediaPlayer.play()
        elif self.mediaPlayer.state() == QMediaPlayer.PlayingState:
            self.mediaPlayer.pause()

    def set_media_source_at_row(self, row, clickPlayFlag=False):
        if not self.playlist.length() or row < 0:
            return
        self.stop_music()
        self.clickPlayFlag = clickPlayFlag
        self.playlist.set_current_row(row)
        sourcePath = self.playlist.get_music_path_at(row)
        self.title = self.playlist.get_music_title_at(row)
        self.sourceTrace = "local" if self.playlist.get_music_id_at(row) == Configures.LocalMusicId else "online"
        self.artistName, self.musicName = get_artist_and_musicname_from_title(self.title)
        self.playlistName = self.playlist.get_name()
        self.totalTime = self.playlist.get_music_time_at(row)
        self.album = self.playlist.get_music_album_at(row)
        self.errorType = Configures.NoError
        isAnUrl = False
        if not os.path.exists(sourcePath):
            if self.playlist.get_name() == Configures.PlaylistOnline:
                if sourcePath == Configures.NoLink:
                    musicId = self.playlist.get_music_id_at(row)
                    sourcePath = SearchOnline.get_song_link(musicId)
                    if sourcePath:
                        self.playlist.set_music_path_at(row, sourcePath)
                    else:
                        self.errorType = Configures.UrlError
                isAnUrl = True
            else:
                self.errorType = Configures.PathError
                sourcePath = "/usr/share/sounds/error_happened.ogg"
        if self.errorType == Configures.NoError:
            self.sourcePath = sourcePath
            self.musicFileName = get_base_name_from_path(sourcePath)
            self.playedDate = get_time_of_now()
            self.songinfosManager.update_datas_of_item(
                self.musicFileName,
                self.playedDate,
                self.musicName,
                self.artistName,
                self.totalTime,
                self.album,
                self.playlistName,
            )
            if not self.timerFlag:
                self.timerFlag = True
                self.timeSpan = 0
            if isAnUrl:
                url = QUrl(sourcePath)
            else:
                url = QUrl.fromLocalFile(sourcePath)
            self.play_from_url(url)
        else:
            self.timerFlag = False
            self.dont_hide_main_window_signal.emit()
            if self.errorType == Configures.DisnetError:
                QMessageBox.critical(
                    self, "错误", "联网出错!\n无法联网播放歌曲'%s'!\n您最好在网络畅通时下载该曲目!" % self.playlist.get_music_title_at(row)
                )
            elif self.errorType == Configures.PathError:
                QMessageBox.information(self, "提示", "路径'%s'无效,请尝试重新下载并添加对应歌曲!" % self.playlist.get_music_path_at(row))

    def play_from_url(self, url):
        mediaContent = QMediaContent(url)
        self.mediaPlayer.setMedia(mediaContent)
        self.mediaPlayer.play()

    def state_changed(self, newState):
        if self and newState in [QMediaPlayer.PlayingState, QMediaPlayer.PausedState, QMediaPlayer.StoppedState]:
            if not self.playlist.length():
                return
            iconPath = IconsHub.ControlPause
            if newState in [QMediaPlayer.StoppedState, QMediaPlayer.PausedState]:
                iconPath = IconsHub.ControlPlay
            icon = QIcon(iconPath)
            self.playAction.setIcon(icon)
            if self.timerFlag:
                if newState == QMediaPlayer.PlayingState:
                    self.timeStart = time.time()
                else:
                    self.timeSpan += time.time() - self.timeStart

    def media_status_changed(self, status):
        if status == QMediaPlayer.EndOfMedia:
            self.music_finished()

    def music_finished(self):
        if self.errorType == Configures.NoError:
            self.next_song()

    def play_music(self):
        if self.mediaPlayer.state() == QMediaPlayer.PlayingState:
            self.mediaPlayer.pause()
        else:
            self.mediaPlayer.play()

    def stop_music_but_timing(self):
        self.mediaPlayer.stop()
        self.seekSlider.setValue(0)
        self.media_player_notify_signal.emit(-0.5)

    def stop_music(self):
        self.stop_music_but_timing()
        if self.timerFlag:
            self.timerFlag = False
            InfosList = [
                self.playedDate,
                self.musicFileName,
                self.musicName,
                self.artistName,
                self.album,
                "%i" % change_mmss_to_seconds(self.totalTime),
                "%.1f" % self.timeSpan,
                self.playlistName,
                self.sourcePath,
                "%i" % (self.title in self.lovedSongs),
                self.sourceTrace,
                Configures.Playmodes[self.playmode],
                "%i" % self.clickPlayFlag,
            ]
            log_playback_history(organized_list_as_str(InfosList))
            self.songinfosManager.update_time_span_relate_of_item(self.musicFileName, self.timeSpan, self.clickPlayFlag)
            self.clickPlayFlag = False

    def get_next_random_row(self):
        listTemp = list(self.playlist.get_ids() - set(self.nearPlayedSongs))
        ran = random.randint(0, len(listTemp) - 1)
        return self.playlist.get_items_queue().index(listTemp[ran])

    def get_next_single_row(self):
        nextRow = self.currentSourceRow
        if nextRow < 0:
            nextRow = 0
        return nextRow

    def get_next_order_row(self, reverse=False):
        if reverse:
            if self.currentSourceRow < 0:
                self.currentSourceRow = 0
            return (self.currentSourceRow - 1) % self.playlist.length()
        return (self.currentSourceRow + 1) % self.playlist.length()

    def previous_song(self):
        self.play_source_on_next_row(reverse=True)

    def next_song(self):
        self.play_source_on_next_row()

    def play_source_on_next_row(self, reverse=False):
        if not self.playlist.length():
            return
        if self.mediaPlayer.position() > 20:
            self.music_ended_signal.emit()
        nextRow = 0
        if self.playmode == Configures.PlaymodeRandom:
            nextRow = self.get_next_random_row()
        elif self.playmode == Configures.PlaymodeOrder:
            nextRow = self.get_next_order_row(reverse)
        elif self.playmode == Configures.PlaymodeSingle:
            nextRow = self.get_next_single_row()
        self.set_media_source_at_row(nextRow)

    def current_media_changed(self):
        if not self.playlist.length():
            return
        self.current_media_changed_signal.emit()
        self.update_parameters()
        self.update_near_played_queue()
        self.check_favorite()

    def update_parameters(self):
        self.currentSourceRow = self.playlist.get_current_row()
        self.musicTitleLabel.setText(self.title)
        self.playAction.setText(self.musicName)
        imagePath = SearchOnline.get_artist_image_path(self.artistName)
        if imagePath:
            pixmap = QPixmap(imagePath)
        else:
            pixmap = QPixmap(IconsHub.Anonymous)
        self.artistHeadLabel.setPixmap(pixmap)
        musicId = self.playlist.get_music_id_at(self.currentSourceRow)
        self.update_window_lyric_signal.emit(self.title, musicId)

    def update_near_played_queue(self):
        self.currentSourceId = self.playlist.get_music_path_at(self.currentSourceRow)
        if self.playlist.get_name() == Configures.PlaylistOnline:
            self.currentSourceId = self.playlist.get_music_id_at(self.currentSourceRow)
        if self.currentSourceId not in self.nearPlayedSongs:
            self.nearPlayedSongs.append(self.currentSourceId)
        while len(self.nearPlayedSongs) >= self.playlist.length() * 4 / 5:
            del self.nearPlayedSongs[0]

    def add_title_into_loved_songs(self, title):
        self.lovedSongs.append(title)
Ejemplo n.º 38
0
class Player(QMediaPlayer):
    def __init__(self, parent=None):
        super(Player, self).__init__(parent)
        self.parent = parent
        self.player = QMediaPlayer()
        self.queueList = QMediaPlaylist()
        self.player.setPlaylist(self.queueList)
        self.queueData = []
        self.position = 0
        self.volume = 100

        self.player.mediaStatusChanged.connect(self.qmp_mediaStatusChanged)
        self.player.positionChanged.connect(self.qmp_positionChanged)
        self.player.durationChanged.connect(self.durationChanged)
        self.queueList.currentIndexChanged.connect(self.playlistPosChanged)

    def add(self, data):
        """Add track to the queue"""
        queueData = {
            'pc_title': data['pc_title'],
            'title': data['title'],
            'url': data['url'],
            'date': data['date_format'],
            'description': data['description']
        }
        self.queueData.append(queueData)
        self.queueList.addMedia(QMediaContent(QUrl(data['url'])))

    def playPause(self):
        icon = QIcon.fromTheme("media-playback-pause")

        if self.player.state() == QMediaPlayer.StoppedState:
            if self.player.mediaStatus() == QMediaPlayer.NoMedia:
                if self.queueList.mediaCount() != 0:
                    self.player.play()
            elif self.player.mediaStatus() == QMediaPlayer.LoadedMedia:
                self.queueList.setCurrentIndex(self.position)
                self.player.play()
            elif self.player.mediaStatus() == QMediaPlayer.BufferedMedia:
                self.player.play()
        elif self.player.state() == QMediaPlayer.PlayingState:
            icon = QIcon.fromTheme("media-playback-start")
            self.player.pause()
        elif self.player.state() == QMediaPlayer.PausedState:
            self.player.play()

        self.parent.playBtn.setIcon(icon)

    def startPlay(self):
        data = self.queueData[0]
        self.queueList.setCurrentIndex(0)
        self.parent.curPCLabel.setText(data['pc_title'])
        self.parent.curTrackName.setText(data['title'])
        self.player.play()
        icon = QIcon.fromTheme("media-playback-pause")
        self.parent.playBtn.setIcon(icon)

    def stop(self):
        self.player.stop()
        icon = QIcon.fromTheme("media-playback-start")
        self.parent.playBtn.setIcon(icon)

    def setPosition(self, pos):
        self.player.setPosition(pos)

    def durationChanged(self, duration):
        total_time = '0:00:00'
        duration = self.player.duration()
        total_time = ms_to_time(duration)
        self.parent.timeSlider.setMaximum(duration)
        self.currentTrackDuration = duration
        self.parent.totalTimeLabel.setText(total_time)

    def qmp_mediaStatusChanged(self, status):
        icon = QIcon.fromTheme("media-playback-pause")
        if self.player.state() == QMediaPlayer.StoppedState:
            icon = QIcon.fromTheme("media-playback-start")
        elif self.player.state() == QMediaPlayer.PausedState:
            icon = QIcon.fromTheme("media-playback-start")

        self.parent.playBtn.setIcon(icon)

    def qmp_positionChanged(self, position, senderType=False):
        self.currentTime = position
        current_time = '0:00:00'

        if position != -1:
            current_time = ms_to_time(position)
            self.parent.timeLabel.setText(current_time)

        self.parent.timeSlider.blockSignals(True)
        self.parent.timeSlider.setValue(position)
        self.parent.timeSlider.blockSignals(False)

    def playlistPosChanged(self):
        pos = self.queueList.currentIndex()
        data = self.queueData[pos]
        self.parent.curPCLabel.setText(data['pc_title'])
        self.parent.curTrackName.setText(data['title'])
        windowTitle = '{0} - {1}'.format(data['pc_title'], data['title'])
        self.parent.setWindowTitle(windowTitle)
        if self.queueList.mediaCount() > 1:
            if pos < self.queueList.mediaCount() - 1:
                self.parent.queueNextBtn.setEnabled(True)
            else:
                self.parent.queueNextBtn.setEnabled(False)

            if pos > 0:
                self.parent.queuePrevBtn.setEnabled(True)
            else:
                self.parent.queuePrevBtn.setEnabled(False)

            if pos < self.queueList.mediaCount():
                prevPos = 0
                if self.position < pos:
                    prevPos = pos - 1
                else:
                    prevPos = pos + 1
                prevItem = self.parent.queueList.item(prevPos)
                prevWidget = self.parent.queueList.itemWidget(prevItem)
                if prevItem:
                    prevWidget.statusIcon.setPixmap(QPixmap())

        self.position = pos
        item = self.parent.queueList.item(pos)
        widget = self.parent.queueList.itemWidget(item)
        if widget:
            icon = QIcon.fromTheme("media-playback-start")
            widget.statusIcon.setPixmap(icon.pixmap(16, 16))

    def setVolume(self, volume):
        self.player.setVolume(volume)

    def rev10Secs(self):
        position = self.player.position()
        new_pos = position - 10000
        self.player.setPosition(new_pos)

    def for10Secs(self):
        position = self.player.position()
        new_pos = position + 10000
        self.player.setPosition(new_pos)

    def delete(self, position):
        """ Delete the track and her data from position"""
        self.queueData.pop(position)
        self.queueList.removeMedia(position)
        if (position == self.position):
            self.playlistPosChanged()
Ejemplo n.º 39
0
class Window(QMainWindow):

    def __init__(self):
        super().__init__()

        self.title = "Python Annotator for VideoS"
        # self.top = 100
        # self.left = 100
        # self.width = 300
        # self.height = 400
        # self.setWindowState = "Qt.WindowMaximized"
        iconName = "home.png"
        self.InitWindow()

    def InitWindow(self):
        self.setWindowTitle(self.title)
        # self.setWindowIcon(QtGui.QIcon(iconName))
        self.setWindowState(QtCore.Qt.WindowMaximized)

        self.UiComponents()

        self.show()

    def UiComponents(self):

        self.rowNo = 1
        self.colNo = 0
        self.fName = ""
        self.fName2 = ""
        self.fileNameExist = ""
        self.dropDownName = ""

        self.model = QStandardItemModel()

        self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.VideoSurface)
        self.tableWidget = QTableWidget()
        self.tableWidget.cellClicked.connect(self.checkTableFrame)

        self.videoWidget = QVideoWidget()
        self.frameID=0


        self.insertBaseRow()

        openButton = QPushButton("Open...")
        openButton.clicked.connect(self.openFile)

        self.playButton = QPushButton()
        self.playButton.setEnabled(False)
        self.playButton.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay))
        self.playButton.clicked.connect(self.play)

        self.lbl = QLabel('00:00:00')
        self.lbl.setFixedWidth(60)
        self.lbl.setUpdatesEnabled(True)
        # self.lbl.setStyleSheet(stylesheet(self))

        self.elbl = QLabel('00:00:00')
        self.elbl.setFixedWidth(60)
        self.elbl.setUpdatesEnabled(True)
        # self.elbl.setStyleSheet(stylesheet(self))


        self.nextButton = QPushButton("-->")
        self.nextButton.clicked.connect(self.next)

        self.delButton = QPushButton("Delete")
        self.delButton.clicked.connect(self.delete)

        self.exportButton = QPushButton("Export")
        self.exportButton.clicked.connect(self.export)

        self.importButton = QPushButton("Import")
        self.importButton.clicked.connect(self.importCSV)

        # self.ctr = QLineEdit()
        # self.ctr.setPlaceholderText("Extra")

        self.startTime = QLineEdit()
        self.startTime.setPlaceholderText("Select Start Time")

        self.endTime = QLineEdit()
        self.endTime.setPlaceholderText("Select End Time")

        self.iLabel = QComboBox(self)
        self.iLabel.addItem("1. Eye Contact")
        self.iLabel.addItem("2. Pointing")
        self.iLabel.addItem("3. Response to Names")
        self.iLabel.addItem("4. Following Pointing")
        self.iLabel.addItem("5. Babbling")
        self.iLabel.addItem("6. Question-Answering")
        self.iLabel.addItem("7. Showing")
        self.iLabel.addItem("8. Following Instructions")
        self.iLabel.activated[str].connect(self.style_choice)

        # self.iLabel = QLineEdit()
        # self.iLabel.setPlaceholderText("Label")

        self.positionSlider = QSlider(Qt.Horizontal)
        self.positionSlider.setRange(0, 100)
        self.positionSlider.sliderMoved.connect(self.setPosition)
        self.positionSlider.sliderMoved.connect(self.handleLabel)
        self.positionSlider.setSingleStep(2)
        self.positionSlider.setPageStep(20)
        self.positionSlider.setAttribute(Qt.WA_TranslucentBackground, True)

        self.errorLabel = QLabel()
        self.errorLabel.setSizePolicy(QSizePolicy.Preferred,
                QSizePolicy.Maximum)

        # Main plotBox
        plotBox = QHBoxLayout()

        controlLayout = QHBoxLayout()
        # controlLayout.setContentsMargins(0, 0, 0, 0)
        controlLayout.addWidget(openButton)
        controlLayout.addWidget(self.playButton)
        controlLayout.addWidget(self.lbl)
        controlLayout.addWidget(self.positionSlider)
        controlLayout.addWidget(self.elbl)

        wid = QWidget(self)
        self.setCentralWidget(wid)

        # Left Layout{
        # layout.addWidget(self.videoWidget)

        layout = QVBoxLayout()
        layout.addWidget(self.videoWidget, 3)
        # layout.addLayout(self.grid_root)
        layout.addLayout(controlLayout)
        layout.addWidget(self.errorLabel)

        plotBox.addLayout(layout, 3)
        # }

        # Right Layout {
        inputFields = QHBoxLayout()
        inputFields.addWidget(self.startTime)
        inputFields.addWidget(self.endTime)
        inputFields.addWidget(self.iLabel)
        # inputFields.addWidget(self.ctr)

        feats = QHBoxLayout()
        feats.addWidget(self.nextButton)
        feats.addWidget(self.delButton)
        feats.addWidget(self.exportButton)
        feats.addWidget(self.importButton)

        layout2 = QVBoxLayout()
        layout2.addWidget(self.tableWidget)
        layout2.addLayout(inputFields, 1)
        layout2.addLayout(feats, 2)
        # layout2.addWidget(self.nextButton)
        # }

        plotBox.addLayout(layout2, 1)

        # self.setLayout(layout)
        wid.setLayout(plotBox)

        self.shortcut = QShortcut(QKeySequence("["), self)
        self.shortcut.activated.connect(self.addStartTime)
        self.shortcut = QShortcut(QKeySequence("]"), self)
        self.shortcut.activated.connect(self.addEndTime)
        self.shortcut = QShortcut(QKeySequence("L"), self)
        self.shortcut.activated.connect(self.openFile)
        self.shortcut = QShortcut(QKeySequence("C"), self)
        self.shortcut.activated.connect(self.clearTable)

        self.shortcut = QShortcut(QKeySequence(Qt.Key_Right), self)
        self.shortcut.activated.connect(self.forwardSlider)
        self.shortcut = QShortcut(QKeySequence(Qt.Key_Left), self)
        self.shortcut.activated.connect(self.backSlider)
        self.shortcut = QShortcut(QKeySequence(Qt.Key_Up), self)
        self.shortcut.activated.connect(self.volumeUp)
        self.shortcut = QShortcut(QKeySequence(Qt.Key_Down), self)
        self.shortcut.activated.connect(self.volumeDown)
        self.shortcut = QShortcut(QKeySequence(Qt.ShiftModifier +  Qt.Key_Right) , self)
        self.shortcut.activated.connect(self.forwardSlider10)
        self.shortcut = QShortcut(QKeySequence(Qt.ShiftModifier +  Qt.Key_Left) , self)
        self.shortcut.activated.connect(self.backSlider10)

        self.mediaPlayer.setVideoOutput(self.videoWidget)
        self.mediaPlayer.stateChanged.connect(self.mediaStateChanged)
        self.mediaPlayer.positionChanged.connect(self.positionChanged)
        self.mediaPlayer.positionChanged.connect(self.handleLabel)
        self.mediaPlayer.durationChanged.connect(self.durationChanged)
        self.mediaPlayer.error.connect(self.handleError)

    def openFile(self):
        fileName, _ = QFileDialog.getOpenFileName(self, "Open Movie",
                QDir.homePath())

        if fileName != '':
            self.fileNameExist = fileName
            self.mediaPlayer.setMedia(
                    QMediaContent(QUrl.fromLocalFile(fileName)))
            self.playButton.setEnabled(True)
        self.videopath = QUrl.fromLocalFile(fileName)
        self.errorLabel.setText(fileName)
        self.errorLabel.setStyleSheet('color: black')

    def play(self):
        # self.is_playing_video = not self.is_playing_video
        if self.mediaPlayer.state() == QMediaPlayer.PlayingState:
            self.mediaPlayer.pause()
        else:
            self.mediaPlayer.play()
            # self._play_video()
            # self.errorLabel.setText("Start: " + " -- " + " End:")

    def _play_video(self):
        if self.is_playing_video and self.video_fps:
            frame_idx = min(self.render_frame_idx+1, self.frame_count)
            print(frame_idx)

            if frame_idx == self.frame_count:
                self.on_play_video_clicked()
            else:
                self.target_frame_idx = frame_idx

    def style_choice(self, text):
        self.dropDownName = text
        QApplication.setStyle(QStyleFactory.create(text))


    def addStartTime(self):
        self.startTime.setText(self.lbl.text())

    def addEndTime(self):
        self.endTime.setText(self.lbl.text())

    def next(self):
        self.tableWidget.setItem(self.rowNo, self.colNo, QTableWidgetItem(self.startTime.text()))
        self.colNo += 1
        self.tableWidget.setItem(self.rowNo, self.colNo, QTableWidgetItem(self.endTime.text()))
        self.colNo += 1
        self.tableWidget.setItem(self.rowNo, self.colNo, QTableWidgetItem(str(self.iLabel.currentIndex()+1)))
        self.colNo += 1
        self.tableWidget.setItem(self.rowNo, self.colNo, QTableWidgetItem(self.iLabel.currentText().split(' ')[1]))
        self.colNo = 0
        self.rowNo += 1
        # print(self.ctr.text(), self.startTime.text(), self.iLabel.text(), self.rowNo, self.colNo)
        # print(self.iLabel.currentIndex())

    def delete(self):
        # print("delete")
        index_list = []
        for model_index in self.tableWidget.selectionModel().selectedRows():
            index = QtCore.QPersistentModelIndex(model_index)
            index_list.append(index)

        self.rowNo = self.rowNo - len(index_list)

        for index in index_list:
            self.tableWidget.removeRow(index.row())

    def clearTable(self):
        while self.tableWidget.rowCount() > 0:
            self.tableWidget.removeRow(0)
        self.insertBaseRow()
        print("Clearing")

    def export(self):
        self.fName = ((self.fileNameExist.rsplit('/', 1)[1]).rsplit('.',1))[0]
        path, _ = QFileDialog.getSaveFileName(self, 'Save File', QDir.homePath() + "/"+self.fName+".csv", "CSV Files(*.csv *.txt)")
        if path:
            with open(path, 'w') as stream:
                print("saving", path)
                writer = csv.writer(stream)
                # writer = csv.writer(stream, delimiter=self.delimit)
                for row in range(self.tableWidget.rowCount()):
                    rowdata = []
                    for column in range(self.tableWidget.columnCount()):
                        item = self.tableWidget.item(row, column)
                        if item is not None and item is not "":
                            rowdata.append(item.text())
                        else:
                            break
                    writer.writerow(rowdata)
        # self.isChanged = False
        # self.setCurrentFile(path)

    def importCSV(self):
        # if fName2 != "":
            # self.fName2 = ((self.fileNameExist.rsplit('/', 1)[1]).rsplit('.',1))[0]
            # path, _ = QFileDialog.getSaveFileName(self, 'Save File', QDir.homePath() + "/"+self.fName2+".csv", "CSV Files(*.csv *.txt)")
        # else:
        self.clearTable()
        path, _ = QFileDialog.getOpenFileName(self, 'Save File', QDir.homePath() , "CSV Files(*.csv *.txt)")
        print(path)
        if path:
            with open(path, 'r') as stream:
                print("loading", path)
                reader = csv.reader(stream)
                # reader = csv.reader(stream, delimiter=';', quoting=csv.QUOTE_ALL)
                # reader = csv.reader(stream, delimiter=';', quoting=csv.QUOTE_ALL)
                # for row in reader:
                for i, row in enumerate(reader):
                    if i == 0:
                        continue
                    else:
                        if(len(row) == 4):
                            st, et, li, ln = row
                            self.tableWidget.setItem(self.rowNo, self.colNo, QTableWidgetItem(st))
                            self.colNo += 1
                            self.tableWidget.setItem(self.rowNo, self.colNo, QTableWidgetItem(et))
                            self.colNo += 1
                            self.tableWidget.setItem(self.rowNo, self.colNo, QTableWidgetItem(str(li)))
                            self.colNo += 1
                            self.tableWidget.setItem(self.rowNo, self.colNo, QTableWidgetItem(ln))
                            self.rowNo += 1
                            self.colNo = 0

    def insertBaseRow(self):
        self.tableWidget.setColumnCount(4) #, Start Time, End Time, TimeStamp
        self.tableWidget.setRowCount(50)
        self.rowNo = 1
        self.colNo = 0
        self.tableWidget.setItem(0, 0, QTableWidgetItem("Start Time"))
        self.tableWidget.setItem(0, 1, QTableWidgetItem("End Time"))
        self.tableWidget.setItem(0, 2, QTableWidgetItem("Label Index"))
        self.tableWidget.setItem(0, 3, QTableWidgetItem("Label Name"))

    def checkTableFrame(self, row, column):
        if ((row > 0) and (column < 2)):
            # print("Row %d and Column %d was clicked" % (row, column))
            item = self.tableWidget.item(row, column)
            if (item != (None and "")):
                try:
                    itemFrame = item.text()
                    itemFrame = itemFrame.split(":")
                    frameTime = int(itemFrame[2]) + int(itemFrame[1])*60 + int(itemFrame[0])*3600
                    elblFrames = self.elbl.text().split(":")
                    elblFrameTime = int(elblFrames[2]) + int(elblFrames[1])*60 + int(elblFrames[0])*3600
                    # print("Elbl FT ", str(elblFrameTime))
                    # print("FT ", str(frameTime))
                    # print(frameTime)
                    self.mediaPlayer.setPosition(frameTime*1000+1*60)
                except:
                    self.errorLabel.setText("Some Video Error - Please Recheck Video Imported!")
                    self.errorLabel.setStyleSheet('color: red')

    def mediaStateChanged(self, state):
        if self.mediaPlayer.state() == QMediaPlayer.PlayingState:
            self.playButton.setIcon(
                    self.style().standardIcon(QStyle.SP_MediaPause))
        else:
            self.playButton.setIcon(
                    self.style().standardIcon(QStyle.SP_MediaPlay))

    def positionChanged(self, position):
        self.positionSlider.setValue(position)

    def durationChanged(self, duration):
        self.positionSlider.setRange(0, duration)
        mtime = QTime(0,0,0,0)
        mtime = mtime.addMSecs(self.mediaPlayer.duration())
        self.elbl.setText(mtime.toString())

    def setPosition(self, position):
        self.mediaPlayer.setPosition(position)

    def handleError(self):
        self.playButton.setEnabled(False)
        self.errorLabel.setText("Error: " + self.mediaPlayer.errorString())
        self.errorLabel.setStyleSheet('color: red')

    def forwardSlider(self):
        self.mediaPlayer.setPosition(self.mediaPlayer.position() + 1*60)

    def forwardSlider10(self):
            self.mediaPlayer.setPosition(self.mediaPlayer.position() + 1000*60)

    def backSlider(self):
        self.mediaPlayer.setPosition(self.mediaPlayer.position() - 1*60)

    def backSlider10(self):
        self.mediaPlayer.setPosition(self.mediaPlayer.position() - 1000*60)

    def volumeUp(self):
        self.mediaPlayer.setVolume(self.mediaPlayer.volume() + 10)
        print("Volume: " + str(self.mediaPlayer.volume()))

    def volumeDown(self):
        self.mediaPlayer.setVolume(self.mediaPlayer.volume() - 10)
        print("Volume: " + str(self.mediaPlayer.volume()))

    # def mouseMoveEvent(self, event):
        # if event.buttons() == Qt.LeftButton:
        #     self.move(event.globalPos() \- QPoint(self.frameGeometry().width() / 2, \
        #                 self.frameGeometry().height() / 2))
        #     event.accept()

    def dragEnterEvent(self, event):
        if event.mimeData().hasUrls():
            event.accept()
        else:
            event.ignore()

    ##################### update Label ##################################
    def handleLabel(self):
        self.lbl.clear()
        mtime = QTime(0,0,0,0)
        self.time = mtime.addMSecs(self.mediaPlayer.position())
        self.lbl.setText(self.time.toString())

    def dropEvent(self, event):
        f = str(event.mimeData().urls()[0].toLocalFile())
        self.loadFilm(f)

    def clickFile(self):
        print("File Clicked")

    def clickExit(self):
        sys.exit()
Ejemplo n.º 40
0
class MyWin(QtWidgets.QMainWindow):

    lbs = []
    rbs = [[''] * 10] * 15  # emply list 15x10
    bgrs = []
    labels = []
    variants = []
    correct = []
    value = []
    tp = []
    picName = []
    lblPic = []
    logStr = ''
    triggeredNum = 0
    minNum = 0
    name1 = ''
    group1 = ''
    timeRes = 0
    timesListening = 4

    def __init__(self, parent=None):
        QtWidgets.QWidget.__init__(self, parent)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        while self.name1 == '' or self.group1 == '':
            dialog = StartDialog(self)
            if dialog.exec_():
                self.name1 = dialog.lineEdit.text()
                self.group1 = dialog.lineEdit_2.text()

        self.duration = 0
        self.playerState = QMediaPlayer.StoppedState
        self.timerAud = QtCore.QTimer(self)
        self.player = QMediaPlayer()
        self.playlist = QMediaPlaylist()
        self.player.setPlaylist(self.playlist)

        # frame with buttons play and stop, and duration label
        self.frame = QtWidgets.QFrame(self.ui.scrollAreaWidgetContents)
        self.frame.setFrameShape(QtWidgets.QFrame.StyledPanel)
        self.frame.setFrameShadow(QtWidgets.QFrame.Raised)
        self.frame.setObjectName("frame")
        self.horizontalLayout = QtWidgets.QHBoxLayout(self.frame)
        self.horizontalLayout.setObjectName("horizontalLayout")
        self.pushButton = QtWidgets.QPushButton(self.frame)
        self.pushButton.setObjectName("pushButton")
        self.horizontalLayout.addWidget(self.pushButton)
        self.pushButton_3 = QtWidgets.QPushButton(self.frame)
        self.pushButton_3.setObjectName("pushButton_3")
        self.horizontalLayout.addWidget(self.pushButton_3)
        self.labelDuration = QtWidgets.QLabel(self.frame)
        self.labelDuration.setText('0')
        self.horizontalLayout.addWidget(self.labelDuration)

        # creating timer
        self.timer = QtCore.QTimer(self)
        # xml handling (read & mix)
        self.mixXml()
        # read to DOM
        self.readToDom()
        # assigning layout to the scrollarea
        self.verticalLayout = QtWidgets.QVBoxLayout(
            self.ui.scrollAreaWidgetContents)
        self.verticalLayout.setObjectName("verticalLayout")
        # adding title
        self.trTitle = QtWidgets.QLabel(self.ui.scrollAreaWidgetContents)
        self.trTitle.setAlignment(QtCore.Qt.AlignLeading | QtCore.Qt.AlignLeft
                                  | QtCore.Qt.AlignTop)
        self.trTitle.setText('')
        # adding standart widgets for listening
        self.verticalLayout.addWidget(self.trTitle)
        self.lblAud = QtWidgets.QLabel(self.ui.scrollAreaWidgetContents)
        self.lblAud.setAlignment(QtCore.Qt.AlignLeading | QtCore.Qt.AlignLeft
                                 | QtCore.Qt.AlignTop)
        self.lblAud.setText('')
        self.horizontalSlider = QtWidgets.QSlider(
            self.ui.scrollAreaWidgetContents)
        self.horizontalSlider.setOrientation(QtCore.Qt.Horizontal)
        self.horizontalSlider.setObjectName("horizontalSlider")

        # adding frame
        self.verticalLayout.addWidget(self.lblAud)
        self.verticalLayout.addWidget(self.horizontalSlider)
        self.verticalLayout.addWidget(self.frame)

        self.pushButton.setIcon(self.style().standardIcon(
            QtWidgets.QStyle.SP_MediaPlay))
        self.pushButton_3.setIcon(self.style().standardIcon(
            QtWidgets.QStyle.SP_MediaStop))
        self.pushButton_3.setEnabled(False)

        # adding widgets to the scrollarea
        self.addWidgetsToInterface()
        self.timer.timeout.connect(lambda: self.updater(self.timeSeconds))
        # starting timer
        self.timer.start(1000)

        self.player.durationChanged.connect(self.durationChanged1)
        self.player.positionChanged.connect(self.positionChanged1)
        self.player.stateChanged.connect(self.setState)

        self.horizontalSlider.setRange(0, self.player.duration() / 1000)

        self.pushButton.clicked.connect(self.play1)
        self.pushButton_3.clicked.connect(self.stop1)

        self.horizontalSlider.sliderMoved.connect(self.changePosition)

        self.ui.pushButton.clicked.connect(self.finish)

    def open1(self, filename):
        self.audiofile = filename
        fileInfo = QtCore.QFileInfo(self.audiofile)
        url = QtCore.QUrl.fromLocalFile(fileInfo.absoluteFilePath())
        self.playlist.addMedia(QMediaContent(url))
        self.pushButton.setEnabled(True)

    def play1(self):
        if self.playerState in (QMediaPlayer.StoppedState,
                                QMediaPlayer.PausedState):
            self.player.play()
        elif self.playerState == QMediaPlayer.PlayingState:
            self.player.pause()

    def stop1(self):
        self.player.stop()

    def positionChanged1(self, progress):
        progress = progress / 1000
        if not self.horizontalSlider.isSliderDown():
            self.horizontalSlider.setValue(progress)
        self.updateDurationInfo(progress)

    def durationChanged1(self, duration):
        duration = duration / 1000
        self.duration = duration
        self.horizontalSlider.setMaximum(duration)

    def updateDurationInfo(self, currentInfo):
        duration = self.duration
        if currentInfo or duration:
            currentTime = QtCore.QTime(
                (currentInfo / 3600) % 60, (currentInfo / 60) % 60,
                currentInfo % 60, (currentInfo * 1000) % 1000)
            totalTime = QtCore.QTime((duration / 3600) % 60,
                                     (duration / 60) % 60, duration % 60,
                                     (duration * 1000) % 1000)
            format1 = 'hh:mm:ss' if duration > 3600 else 'mm:ss'
            tStr = currentTime.toString(format1) + " / " + totalTime.toString(
                format1)
        else:
            tStr = ''
        if (self.timesListening - 1) < 0:
            self.labelDuration.setText(tStr +
                                       ' -осталось количество прослушиваний ' +
                                       '0')
        else:
            self.labelDuration.setText(tStr +
                                       ' -осталось количество прослушиваний ' +
                                       str(self.timesListening - 1))

    def setState(self, state):
        if state != self.playerState:
            self.playerState = state
            if state == QMediaPlayer.StoppedState:
                self.timesListening -= 1
                if self.timesListening <= 0:
                    self.pushButton.clicked.connect(self.stop1)
                self.horizontalSlider.setEnabled(False)
                self.pushButton_3.setEnabled(False)
                self.pushButton.setIcon(self.style().standardIcon(
                    QtWidgets.QStyle.SP_MediaPlay))
            elif state == QMediaPlayer.PlayingState:
                self.horizontalSlider.setEnabled(True)
                self.pushButton_3.setEnabled(True)
                self.pushButton.setIcon(self.style().standardIcon(
                    QtWidgets.QStyle.SP_MediaPause))
            elif state == QMediaPlayer.PausedState:
                self.horizontalSlider.setEnabled(False)
                self.pushButton_3.setEnabled(True)
                self.pushButton.setIcon(self.style().standardIcon(
                    QtWidgets.QStyle.SP_MediaPlay))

    def changePosition(self, seconds):
        if self.playerState == QMediaPlayer.PausedState:
            pass
        elif self.playerState == QMediaPlayer.PlayingState:
            self.player.setPosition(seconds * 1000)

    def finish(self):
        self.timeRes = self.timeSeconds
        self.timeSeconds = 0

    def mixXml(self):
        # read xml and mix the lines
        self.linesMixed = []
        self.r = open("db6.xml", 'r', encoding='utf-8')
        self.fileRead = self.r.readlines()
        for line in range(2, len(self.fileRead) - 1):
            self.linesMixed.append(self.fileRead[line])
        random.shuffle(self.linesMixed)
        self.r.close()

        # write temporary xml with new mixed lines
        self.w = open("temp.xml", 'w', encoding='utf-8')
        self.w.write('''<?xml version="1.0" encoding="utf-8"?>\n<content>\n''')
        for line in self.linesMixed:
            self.w.write('%s' % line)
        self.w.write('</content>')
        self.w.close()

    def readToDom(self):
        # read to DOM
        self.dom = xml.dom.minidom.parse('temp.xml')
        self.collection = self.dom.documentElement
        # reading timeout to a variable
        self.timeSeconds = int(
            self.collection.getElementsByTagName("time")[0].childNodes[0].data)
        # reading title
        self.title = self.collection.getElementsByTagName(
            "ttl")[0].childNodes[0].data
        self.questAudio = self.collection.getElementsByTagName(
            "aud")[0].childNodes[0].data
        aud = self.collection.getElementsByTagName("aud")[0]
        audFile = aud.getAttribute('src')
        self.open1(audFile)
        self.timeConstant = self.timeSeconds
        self.linesArr = self.collection.getElementsByTagName("q")
        for line in range(0, len(self.linesArr)):
            # label's text
            self.labels.append(self.linesArr[line].childNodes[0].data)
            # variants' text
            self.variants.append(
                self.linesArr[line].getAttribute('ans').split('**?**'))
            # correct answer
            self.correct.append(self.linesArr[line].getAttribute('cor'))
            # value
            self.value.append(int(self.linesArr[line].getAttribute('pnt')))
            # reading type
            self.tp.append(self.linesArr[line].getAttribute('type'))
            # adding picture name if any
            if self.linesArr[line].hasAttribute('pic'):
                self.picName.append(self.linesArr[line].getAttribute('pic'))
            else:
                self.picName.append('empty')
        # Mix variants
        for variant in self.variants:
            random.shuffle(variant)
        # Deleting temporary file
        os.remove('temp.xml')

    def addWidgetsToInterface(self):
        # adding widgets to the scrollarea
        self.trTitle.setText("Тренажер %s" % self.title)
        self.lblAud.setText("<b>%s</b>" % self.questAudio)
        for line in range(0, len(self.labels)):
            self.lbs.append(QtWidgets.QLabel(self.ui.scrollAreaWidgetContents))
            self.lbs[line].setAlignment(QtCore.Qt.AlignLeading
                                        | QtCore.Qt.AlignLeft
                                        | QtCore.Qt.AlignTop)
            self.lbs[line].setText('<b>%s</b>' % self.labels[line])
            self.verticalLayout.addWidget(self.lbs[line])
            # adding picture
            if self.picName[line] != 'empty':
                self.lblPic.append(
                    QtWidgets.QLabel(self.ui.scrollAreaWidgetContents))
                self.lblPic[line].setAlignment(QtCore.Qt.AlignLeading
                                               | QtCore.Qt.AlignLeft
                                               | QtCore.Qt.AlignTop)
                self.lblPic[line].setPixmap(
                    QtGui.QPixmap(os.getcwd() + "/" + self.picName[line]))
                self.verticalLayout.addWidget(self.lblPic[line])
            else:
                self.lblPic.append(
                    QtWidgets.QLabel(self.ui.scrollAreaWidgetContents))
            # adding button group
            self.bgrs.append(QtWidgets.QButtonGroup(self.ui.centralwidget))
            if self.tp[line] == 'chb':
                self.bgrs[line].setExclusive(False)
                self.correct[line] = self.correct[line].split('**?**')
            # click counter
            self.bgrs[line].buttonClicked.connect(self.increaseNum)
            for v in range(0, len(self.variants[line])):
                # check br/chb
                if self.tp[line] == 'rb':
                    self.rbs[line][v] = QtWidgets.QRadioButton(
                        self.ui.scrollAreaWidgetContents)
                elif self.tp[line] == 'chb':
                    self.rbs[line][v] = QtWidgets.QCheckBox(
                        self.ui.scrollAreaWidgetContents)
                self.bgrs[line].addButton(self.rbs[line][v])
                self.rbs[line][v].setText(self.variants[line][v])
                self.verticalLayout.addWidget(self.rbs[line][v])

    def increaseNum(self):
        self.triggeredNum += 1

    def check(self):
        counter = 0
        for group in range(0, len(self.bgrs)):
            # adding questions
            self.logStr += self.labels[group] + '\n'
            self.logStr += 'Сложность: %d\n' % self.value[group]
            # check rb/chb
            if self.tp[group] == 'rb':
                self.minNum += 1
                correctThis = '--'
                for rb in self.bgrs[group].buttons():
                    # adding variants
                    self.logStr += '\t' + rb.text() + '\n'
                    if rb.isChecked():
                        if rb.text() == self.correct[group]:
                            correctThis = rb.text()
                            counter += self.value[group]
            elif self.tp[group] == 'chb':
                if self.correct[group][0] != 'none':
                    self.minNum += len(self.correct[group])
                correctThis = []
                chbCor = []
                for rb in self.bgrs[group].buttons():
                    # adding variants
                    self.logStr += '\t' + rb.text() + '\n'
                    if rb.isChecked():
                        # marked checkboxes
                        chbCor.append(rb.text())
                if len(chbCor) == 0:
                    chbCor.append('none')
                chbCor.sort()
                self.correct[group].sort()
                if self.correct[group] == chbCor:
                    counter += self.value[group]
                correctThis = chbCor

            self.logStr += 'Правильный ответ: %s' % self.listToString(
                self.correct[group]) + '\n'
            self.logStr += 'Ответ пользователя: %s' % self.listToString(
                correctThis) + '\n'
            if self.listToString(
                    self.correct[group]) == self.listToString(correctThis):
                self.logStr += 'TRUE\n'
            else:
                self.logStr += 'FALSE\n'
            self.logStr += '\n'
        # And this is the result! Rounded to 2 decimal points
        self.result = float(counter / sum(self.value) * 100)
        message = "Your result is " + "%.2f" % self.result + "%"
        self.ui.statusbar.setStyleSheet('color: navy; font-weight: bold;')
        self.ui.statusbar.showMessage(message)
        # creating log file
        self.log()

    def listToString(self, getlist):
        if type(getlist).__name__ == 'list':
            string = ''
            for i in getlist:
                string += i + '; '
            string = string[:-2] + '.'
            return string
        else:
            return getlist

    def updater(self, val):
        val = self.timeSeconds
        if val == 0:
            self.timer.stop()
            self.check()
            self.ui.scrollArea.setEnabled(False)
            self.ui.pushButton.setEnabled(False)
        self.ui.label.setText(self.intToTime(val))
        self.timeSeconds -= 1

    def intToTime(self, num):
        h = 0
        m = 0
        if num >= 3600:
            h = num // 3600
            num = num % 3600
        if num >= 60:
            m = num // 60
            num = num % 60
        s = num
        str1 = "%d." % h
        if m < 10:
            str1 += "0%d:" % m
        else:
            str1 += "%d:" % m
        if s < 10:
            str1 += "0%d" % s
        else:
            str1 += "%d" % s
        return str1  # returns time as a string

    def log(self):
        logFileName = self.name1 + '_' + self.group1 + '_%.2f' % self.result + '_' + str(
            self.timeConstant - self.timeRes) + '_%.2f' % (
                self.triggeredNum / self.minNum * 100) + '_' + str(
                    int(round(time.time() * 1000))) + '.txt'
        file = open(logFileName, 'w', encoding='utf-8')
        file.write("Тренажер: %s\n" % self.title)
        file.write("Имя: %s\nГруппа: %s\n" % (self.name1, self.group1))
        file.write("Дата и время записи: ")
        file.write(time.strftime("%Y-%m-%d %H:%M:%S"))
        file.write('\n\n')
        file.write(self.logStr)
        file.write('\n')
        file.write("Результат: %.2f" % self.result + " %\n")
        file.write('Выполнено за %d с\n' % (self.timeConstant - self.timeRes))
        # Nubmer of iteractions in percent relative to minimal number of interactions.
        # Minimal number of iteractions equals the quantity of radio buttons
        # multiplied by the quantity of correct variants in questions with check boxes
        # see line 140 and 150-151.
        file.write('Коэффициент интеракций: %.2f' %
                   (self.triggeredNum / self.minNum * 100) + ' %')
        # makes log file read only
        os.chmod(os.path.abspath(logFileName), stat.S_IREAD)
        file.close()
        self.triggeredNum = 0
        self.logStr = ''
Ejemplo n.º 41
0
class VKwindow(QWidget):

    def __init__(self, vkapi):
        super().__init__()
        self.vk = vkapi
        self.initUI()

    def initUI(self):
        self.player = QMediaPlayer()
        self.playlist = QMediaPlaylist()
        vbox = QVBoxLayout()
        hbox = QHBoxLayout()
        self.setGeometry(300, 300, 290, 150)
        self.slider = QSlider(Qt.Horizontal)
        self.playBtn = QPushButton('►')
        self.nextBtn = QPushButton('>')
        self.prevBtn = QPushButton('<')

        self.nextBtn.clicked.connect(self.nextSong)
        self.prevBtn.clicked.connect(self.prevSong)

        self.playBtn.clicked.connect(self.playSong)
        self.setWindowTitle('VK music')
        self.list = QListWidget(self)
        self.list.currentItemChanged.connect(self.selectSong)

        for track in self.vk.method('audio.get').get('items'):
            self.list.addItem(SongWidgetItem(track))
            self.playlist.addMedia(QMediaContent(QUrl(track['url'])))

        hbox.addWidget(self.prevBtn)
        hbox.addWidget(self.playBtn)
        hbox.addWidget(self.nextBtn)
        hbox.addWidget(self.slider)

        self.player.setPlaylist(self.playlist)
        self.player.positionChanged.connect(self.setPosition)
        vbox.addWidget(self.list)
        vbox.addLayout(hbox)
        self.setLayout(vbox)
        self.show()

    def selectSong(self, curr, prev):
        self.currentTrack = curr
        print(curr.getArtist())

    def playSong(self):
        print(self.currentTrack.getArtist())
        print(self.list.currentRow())
        if self.player.state() == QMediaPlayer.PlayingState and self.list.currentRow() == self.playlist.currentIndex():
            self.player.pause()
            return
        elif self.player.state() == QMediaPlayer.PausedState:
            self.player.play()
            return
        self.playlist.setCurrentIndex(self.list.currentRow())
        self.slider.setTickInterval(self.player.duration())
        self.player.play()

    def setPosition(self, pos):
        print(pos)
        self.slider.setTickPosition(pos)

    def nextSong(self):
        tmp = self.list.currentRow()
        size = self.list.count()
        tmp = (tmp + 1) % size
        self.list.setCurrentRow(tmp)
        self.playlist.setCurrentIndex(tmp)
        self.player.play()

    def prevSong(self):
        tmp = self.list.currentRow()
        size = self.list.count()
        tmp = (tmp - 1) % size
        self.list.setCurrentRow(tmp)
        self.playlist.setCurrentIndex(tmp)
        self.player.play()
Ejemplo n.º 42
-1
class Player(QWidget):

    fullScreenChanged = pyqtSignal(bool)

    def __init__(self, playlist, parent=None):
        super(Player, self).__init__(parent)

        self.colorDialog = None
        self.trackInfo = ""
        self.statusInfo = ""
        self.duration = 0

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

        self.player.durationChanged.connect(self.durationChanged)
        self.player.positionChanged.connect(self.positionChanged)
        self.player.metaDataChanged.connect(self.metaDataChanged)
        self.playlist.currentIndexChanged.connect(self.playlistPositionChanged)
        self.player.mediaStatusChanged.connect(self.statusChanged)
        self.player.bufferStatusChanged.connect(self.bufferingProgress)
        self.player.videoAvailableChanged.connect(self.videoAvailableChanged)
        self.player.error.connect(self.displayErrorMessage)

        self.videoWidget = VideoWidget()
        self.player.setVideoOutput(self.videoWidget)

        self.playlistModel = PlaylistModel()
        self.playlistModel.setPlaylist(self.playlist)

        self.playlistView = QListView()
        self.playlistView.setModel(self.playlistModel)
        self.playlistView.setCurrentIndex(
                self.playlistModel.index(self.playlist.currentIndex(), 0))

        self.playlistView.activated.connect(self.jump)

        self.slider = QSlider(Qt.Horizontal)
        self.slider.setRange(0, self.player.duration() / 1000)

        self.labelDuration = QLabel()
        self.slider.sliderMoved.connect(self.seek)

        self.labelHistogram = QLabel()
        self.labelHistogram.setText("Histogram:")
        self.histogram = HistogramWidget()
        histogramLayout = QHBoxLayout()
        histogramLayout.addWidget(self.labelHistogram)
        histogramLayout.addWidget(self.histogram, 1)

        self.probe = QVideoProbe()
        self.probe.videoFrameProbed.connect(self.histogram.processFrame)
        self.probe.setSource(self.player)

        openButton = QPushButton("Open", clicked=self.open)

        controls = PlayerControls()
        controls.setState(self.player.state())
        controls.setVolume(self.player.volume())
        controls.setMuted(controls.isMuted())

        controls.play.connect(self.player.play)
        controls.pause.connect(self.player.pause)
        controls.stop.connect(self.player.stop)
        controls.next.connect(self.playlist.next)
        controls.previous.connect(self.previousClicked)
        controls.changeVolume.connect(self.player.setVolume)
        controls.changeMuting.connect(self.player.setMuted)
        controls.changeRate.connect(self.player.setPlaybackRate)
        controls.stop.connect(self.videoWidget.update)

        self.player.stateChanged.connect(controls.setState)
        self.player.volumeChanged.connect(controls.setVolume)
        self.player.mutedChanged.connect(controls.setMuted)

        self.fullScreenButton = QPushButton("FullScreen")
        self.fullScreenButton.setCheckable(True)

        self.colorButton = QPushButton("Color Options...")
        self.colorButton.setEnabled(False)
        self.colorButton.clicked.connect(self.showColorDialog)

        displayLayout = QHBoxLayout()
        displayLayout.addWidget(self.videoWidget, 2)
        displayLayout.addWidget(self.playlistView)

        controlLayout = QHBoxLayout()
        controlLayout.setContentsMargins(0, 0, 0, 0)
        controlLayout.addWidget(openButton)
        controlLayout.addStretch(1)
        controlLayout.addWidget(controls)
        controlLayout.addStretch(1)
        controlLayout.addWidget(self.fullScreenButton)
        controlLayout.addWidget(self.colorButton)

        layout = QVBoxLayout()
        layout.addLayout(displayLayout)
        hLayout = QHBoxLayout()
        hLayout.addWidget(self.slider)
        hLayout.addWidget(self.labelDuration)
        layout.addLayout(hLayout)
        layout.addLayout(controlLayout)
        layout.addLayout(histogramLayout)

        self.setLayout(layout)

        if not self.player.isAvailable():
            QMessageBox.warning(self, "Service not available",
                    "The QMediaPlayer object does not have a valid service.\n"
                    "Please check the media service plugins are installed.")

            controls.setEnabled(False)
            self.playlistView.setEnabled(False)
            openButton.setEnabled(False)
            self.colorButton.setEnabled(False)
            self.fullScreenButton.setEnabled(False)

        self.metaDataChanged()

        self.addToPlaylist(playlist)

    def open(self):
        fileNames, _ = QFileDialog.getOpenFileNames(self, "Open Files")
        self.addToPlaylist(fileNames)

    def addToPlaylist(self, fileNames):
        for name in fileNames:
            fileInfo = QFileInfo(name)
            if fileInfo.exists():
                url = QUrl.fromLocalFile(fileInfo.absoluteFilePath())
                if fileInfo.suffix().lower() == 'm3u':
                    self.playlist.load(url)
                else:
                    self.playlist.addMedia(QMediaContent(url))
            else:
                url = QUrl(name)
                if url.isValid():
                    self.playlist.addMedia(QMediaContent(url))

    def durationChanged(self, duration):
        duration /= 1000

        self.duration = duration
        self.slider.setMaximum(duration)

    def positionChanged(self, progress):
        progress /= 1000

        if not self.slider.isSliderDown():
            self.slider.setValue(progress)

        self.updateDurationInfo(progress)

    def metaDataChanged(self):
        if self.player.isMetaDataAvailable():
            self.setTrackInfo("%s - %s" % (
                    self.player.metaData(QMediaMetaData.AlbumArtist),
                    self.player.metaData(QMediaMetaData.Title)))

    def previousClicked(self):
        # Go to the previous track if we are within the first 5 seconds of
        # playback.  Otherwise, seek to the beginning.
        if self.player.position() <= 5000:
            self.playlist.previous()
        else:
            self.player.setPosition(0)

    def jump(self, index):
        if index.isValid():
            self.playlist.setCurrentIndex(index.row())
            self.player.play()

    def playlistPositionChanged(self, position):
        self.playlistView.setCurrentIndex(
                self.playlistModel.index(position, 0))

    def seek(self, seconds):
        self.player.setPosition(seconds * 1000)

    def statusChanged(self, status):
        self.handleCursor(status)

        if status == QMediaPlayer.LoadingMedia:
            self.setStatusInfo("Loading...")
        elif status == QMediaPlayer.StalledMedia:
            self.setStatusInfo("Media Stalled")
        elif status == QMediaPlayer.EndOfMedia:
            QApplication.alert(self)
        elif status == QMediaPlayer.InvalidMedia:
            self.displayErrorMessage()
        else:
            self.setStatusInfo("")

    def handleCursor(self, status):
        if status in (QMediaPlayer.LoadingMedia, QMediaPlayer.BufferingMedia, QMediaPlayer.StalledMedia):
            self.setCursor(Qt.BusyCursor)
        else:
            self.unsetCursor()

    def bufferingProgress(self, progress):
        self.setStatusInfo("Buffering %d%" % progress)

    def videoAvailableChanged(self, available):
        if available:
            self.fullScreenButton.clicked.connect(
                    self.videoWidget.setFullScreen)
            self.videoWidget.fullScreenChanged.connect(
                    self.fullScreenButton.setChecked)

            if self.fullScreenButton.isChecked():
                self.videoWidget.setFullScreen(True)
        else:
            self.fullScreenButton.clicked.disconnect(
                    self.videoWidget.setFullScreen)
            self.videoWidget.fullScreenChanged.disconnect(
                    self.fullScreenButton.setChecked)

            self.videoWidget.setFullScreen(False)

        self.colorButton.setEnabled(available)

    def setTrackInfo(self, info):
        self.trackInfo = info

        if self.statusInfo != "":
            self.setWindowTitle("%s | %s" % (self.trackInfo, self.statusInfo))
        else:
            self.setWindowTitle(self.trackInfo)

    def setStatusInfo(self, info):
        self.statusInfo = info

        if self.statusInfo != "":
            self.setWindowTitle("%s | %s" % (self.trackInfo, self.statusInfo))
        else:
            self.setWindowTitle(self.trackInfo)

    def displayErrorMessage(self):
        self.setStatusInfo(self.player.errorString())

    def updateDurationInfo(self, currentInfo):
        duration = self.duration
        if currentInfo or duration:
            currentTime = QTime((currentInfo/3600)%60, (currentInfo/60)%60,
                    currentInfo%60, (currentInfo*1000)%1000)
            totalTime = QTime((duration/3600)%60, (duration/60)%60,
                    duration%60, (duration*1000)%1000);

            format = 'hh:mm:ss' if duration > 3600 else 'mm:ss'
            tStr = currentTime.toString(format) + " / " + totalTime.toString(format)
        else:
            tStr = ""

        self.labelDuration.setText(tStr)

    def showColorDialog(self):
        if self.colorDialog is None:
            brightnessSlider = QSlider(Qt.Horizontal)
            brightnessSlider.setRange(-100, 100)
            brightnessSlider.setValue(self.videoWidget.brightness())
            brightnessSlider.sliderMoved.connect(
                    self.videoWidget.setBrightness)
            self.videoWidget.brightnessChanged.connect(
                    brightnessSlider.setValue)

            contrastSlider = QSlider(Qt.Horizontal)
            contrastSlider.setRange(-100, 100)
            contrastSlider.setValue(self.videoWidget.contrast())
            contrastSlider.sliderMoved.connect(self.videoWidget.setContrast)
            self.videoWidget.contrastChanged.connect(contrastSlider.setValue)

            hueSlider = QSlider(Qt.Horizontal)
            hueSlider.setRange(-100, 100)
            hueSlider.setValue(self.videoWidget.hue())
            hueSlider.sliderMoved.connect(self.videoWidget.setHue)
            self.videoWidget.hueChanged.connect(hueSlider.setValue)

            saturationSlider = QSlider(Qt.Horizontal)
            saturationSlider.setRange(-100, 100)
            saturationSlider.setValue(self.videoWidget.saturation())
            saturationSlider.sliderMoved.connect(
                    self.videoWidget.setSaturation)
            self.videoWidget.saturationChanged.connect(
                    saturationSlider.setValue)

            layout = QFormLayout()
            layout.addRow("Brightness", brightnessSlider)
            layout.addRow("Contrast", contrastSlider)
            layout.addRow("Hue", hueSlider)
            layout.addRow("Saturation", saturationSlider)

            button = QPushButton("Close")
            layout.addRow(button)

            self.colorDialog = QDialog(self)
            self.colorDialog.setWindowTitle("Color Options")
            self.colorDialog.setLayout(layout)

            button.clicked.connect(self.colorDialog.close)

        self.colorDialog.show()