Ejemplo n.º 1
0
class Player(QGraphicsVideoItem):
    def __init__(self, parent=None):
        super().__init__()
        self.parent = parent

        self.player = QMediaPlayer()
        self.player.setVideoOutput(self)

    def playerPlayOrOpen(self, arg=None):
        if type(arg) == list and len(arg) > 1:
            content = QMediaContent(QUrl.fromLocalFile(arg[1]))
            self.player.setMedia(content)
            self.play()

    def addVideo(self, video):
        content = QMediaContent(QUrl.fromLocalFile(video))
        self.player.setMedia(content)
        self.play()

    def sliderChanged(self, pos):
        self.player.setPosition(pos)

    def mouseDoubleClickEvent(self, event):
        if not self.parent.isFullScreen():
            self.parent.showFullScreen()
        else:
            self.parent.showNormal()

    def play(self):
        self.player.play()

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

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

    def setMuted(self, mute):
        self.player.setMuted(mute)

    def mutedState(self):
        if self.player.isMuted():
            self.setMuted(False)
        else:
            self.setMuted(True)

    def isMuted(self):
        return self.player.isMuted()

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

    def volume(self):
        return self.player.volume()
Ejemplo n.º 2
0
class Player(QGraphicsVideoItem):
    def __init__(self, parent=None):
        super().__init__()
        self.parent = parent

        self.player = QMediaPlayer()
        self.player.setVideoOutput(self)

    def playerPlayOrOpen(self, arg=None):
        if type(arg) == list and len(arg) > 1:
            content = QMediaContent(QUrl.fromLocalFile(arg[1]))
            self.player.setMedia(content)
            self.play()

    def addVideo(self, video):
        content = QMediaContent(QUrl.fromLocalFile(video))
        self.player.setMedia(content)
        self.play()

    def sliderChanged(self, pos):
        self.player.setPosition(pos)

    def mouseDoubleClickEvent(self, event):
        if not self.parent.isFullScreen():
            self.parent.showFullScreen()
        else:
            self.parent.showNormal()

    def play(self):
        self.player.play()

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

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

    def setMuted(self, mute):
        self.player.setMuted(mute)

    def mutedState(self):
        if self.player.isMuted():
            self.setMuted(False)
        else:
            self.setMuted(True)

    def isMuted(self):
        return  self.player.isMuted()

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

    def volume(self):
        return self.player.volume()
Ejemplo n.º 3
0
class Reproductor(Genesis, QMainWindow):

    """ Instalar MatroskaSplitter y LAVFilters(Codecs), para que pueda reproducir videos y audio

    LAVFilters
    https://github.com/Nevcairiel/LAVFilters/releases
    
    MatroskaSplitter
    https://haali.su/mkv/  
    """
    
    def __init__(self, *args, **kwargs):
        super(Reproductor, self).__init__()

        self.transcurso = 0
        
        # Centramos la ventana principal
        self.centrar()

        # Inicializamos el modulo QMediaPlayer
        self.media = QMediaPlayer()
        self.media.setVolume(5)
        self.reproducir.setEnabled(False)

        # Setup the playlist.
        self.lista_repro = QMediaPlaylist()
        self.media.setPlaylist(self.lista_repro)

        self.modelo = ListaModelo(self.lista_repro)
        self.lista.setModel(self.modelo)

        self.lista_repro.currentIndexChanged.connect(self.cambio_lista_repro)

        modelo_seleccion = self.lista.selectionModel()
        modelo_seleccion.selectionChanged.connect(self.seleccion_lista_repro)


# **********  Inicializamos el modulo QVideoWidget *******
        self.video = QVideoWidget()

        # Agregamos el modulo QVideoWidget al grid donde se mostrara el video
        self.reproductor.addWidget(self.video)

        # Tambien lo agregamos al modulo QMediaPlayer
        self.media.setVideoOutput(self.video)

        # Conectamos el boton de reproducir con su metodo correspondiente
        self.reproducir.clicked.connect(self.play_video)

        # Conectamos el Skider del tiempo con su metodo correspondiente
        self.tiempo.sliderMoved.connect(self.posicion_establecida)
    

# ******  Conectamos los estados del modulo QMediaPlayer con sus correspondientes metodos  *****
        self.media.stateChanged.connect(self.cambios_video)
        self.media.positionChanged.connect(self.posicion_video)
        self.media.durationChanged.connect(self.duracion_video)
        self.total_duracion = 0

        self.cargar.clicked.connect(self.abrir_archivo)
        #self.marco.origen.connect(self.arrastrar_soltar)

        self.parar.pressed.connect(self.media.stop)
        self.atras.pressed.connect(self.lista_repro.previous)
        self.adelante.pressed.connect(self.lista_repro.next)
        self.volumen.valueChanged.connect(self.media.setVolume)
        self.logo_volumen.clicked.connect(self.silenciar)
        self.lista.doubleClicked.connect(self.play_video)
        self.video.keyPressEvent = self.keyPressEvent

#         ****** Boton de menu ******
        self.lista.setMinimumSize(QSize(0, 0))
        self.lista_visible = True
        self.menu.clicked.connect(self.boton_menu)

        self.setAcceptDrops(True)

        self.primera_reproduccion = True
        self.show()

# ---------------- Inicio de Metodos --------------------------- #

    # Detectamos una tecla presionada
    def keyPressEvent(self, event):
        if event.key() == Qt.Key_F11 or event.key() == Qt.Key_Escape and self.video.isFullScreen():
            self.fullscreen_change()
        elif event.key() == Qt.Key_Space:
            self.play_video()

    #Pantalla completa
    def fullscreen_change(self):
        if self.video.isFullScreen():
            self.video.setFullScreen(False)
            self.lista.setMinimumSize(QSize(300, 16777215))
        else:
            self.video.setFullScreen(True)


    # Ocultar y mostrar la lista de reproduccion
    def boton_menu(self):
        if self.lista_visible:
            self.lista.setVisible(False)
            size_policy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
            self.marco.setSizePolicy(size_policy)
            self.lista_visible = False
        else:
            self.lista.setVisible(True)
            self.lista_visible = True

    # Metodos para arrastrar y soltar en la lista de reproduccion
    def dragEnterEvent(self, e):
        if e.mimeData().hasUrls():
            e.acceptProposedAction()

    # Metodos para arrastrar y soltar en la lista de reproduccion
    def dropEvent(self, e):
        for url in e.mimeData().urls():
            self.lista_repro.addMedia(QMediaContent(url))
        
        self.lista_repro.setPlaybackMode(QMediaPlaylist.Loop)

        self.media.setPlaylist(self.lista_repro)
        self.reproducir.setEnabled(True)
        self.reproductor.removeWidget(self.logo)

        self.media.play()

        self.modelo.layoutChanged.emit()

        """

        # If not playing, seeking to first of newly added + play.
        if self.media.state() != QMediaPlayer.PlayingState:
            #i = self.lista_repro.mediaCount() - len(e.mimeData().urls())
            #print(i)
            #self.lista_repro.setCurrentIndex(i)            
            self.reproducir.setEnabled(True)
            self.reproductor.removeWidget(self.logo)
            #self.media.setPlaylist(playlist)
            self.media.play() """

    # Metodo para cargar el video en cuestion
    def abrir_archivo(self):
        archivo, _ = QFileDialog.getOpenFileName(self, '   Abrir Archivo !!!', 'C:/Users/Duque/Videos', 'Solo Video (*.mp4 *.mov *.flv *.mkv *.ts *.mts *.avi);; Solo Audio (*.mp3 *.flac *.m4a *.wav)')

        if archivo != '':
            self.reproductor.removeWidget(self.logo)
            self.primera_reproduccion = False
            self.lista_repro.addMedia(QMediaContent(QUrl.fromLocalFile(archivo)))
            self.reproducir.setEnabled(True)

        self.modelo.layoutChanged.emit()

    # Metodo para el cambio en la lista de reproduccion
    def cambio_lista_repro(self, i):
        if i > -1:
            ix = self.modelo.index(i)
            self.lista.setCurrentIndex(ix)

    # Metodo para la seleccion en la lista de reproduccion
    def seleccion_lista_repro(self, ix):
        i = ix.indexes()[0].row()
        self.lista_repro.setCurrentIndex(i)

    # Metodo para silenciar el audio o video
    def silenciar(self):
        if self.media.isMuted():
            self.media.setMuted(False)
            icon = QIcon()
            icon.addPixmap(QPixmap(":/img/altavoz3.png"), QIcon.Normal, QIcon.Off)
            self.logo_volumen.setIcon(icon)
            self.logo_volumen.setToolTip(' Silenciar ')
        else:
            self.media.setMuted(True)
            icon = QIcon()
            icon.addPixmap(QPixmap(":/img/altavoz4.png"), QIcon.Normal, QIcon.Off)
            self.logo_volumen.setIcon(icon)
            self.logo_volumen.setToolTip(' Restablecer Sonido ')



    @pyqtSlot(str)
    def arrastrar_soltar(self, archivo):
        if archivo != '':
            self.media.setMedia(QMediaContent(QUrl.fromLocalFile(archivo)))
            self.reproducir.setEnabled(True)
            self.lista_repro.addMedia(QMediaContent(QUrl.fromLocalFile(archivo)))
            self.modelo.layoutChanged.emit()

    # Metodo para reproducir el video en cuestion
    def play_video(self):
        if self.primera_reproduccion:
            self.reproductor.removeWidget(self.logo)
            self.primera_reproduccion = False
        if self.media.state() == QMediaPlayer.PlayingState:
            self.media.pause()
        else:
            self.media.play()

    # Metodo que detecta el estado de cambio del boton reproducir de play a pausa y viceversa
    def cambios_video(self, state):
        if self.media.state() == QMediaPlayer.PlayingState:
            icon = QIcon()
            icon.addPixmap(QPixmap(":/img/pausa.png"), QIcon.Normal, QIcon.Off)
            self.reproducir.setIcon(icon)
            self.reproducir.setToolTip(' Pausar Video o Audio ')
            QToolTip.setFont(QFont('Cascadia Code PL', 18))   
        else:
            icon = QIcon()
            icon.addPixmap(QPixmap(":/img/play.svg"), QIcon.Normal, QIcon.Off)
            self.reproducir.setIcon(icon)
            self.reproducir.setToolTip(' Reproducir Video o Audio ')
            QToolTip.setFont(QFont('Cascadia Code PL', 18))


    def duracion_video(self, duracion):
        """
        # Detecta la duración del vídeo en el slider.
        """
        self.tiempo.setMaximum(duracion)
        self.total_duracion = duracion

    # Metodo que detecta la posiscion del video en el slider
    def posicion_video(self, posicion):

        if posicion >= 0:
            reproduccion = f'{detalle_tiempo(posicion)} || {detalle_tiempo(self.total_duracion)}'
            self.datos.setText(reproduccion)

        self.tiempo.blockSignals(True)
        self.tiempo.setValue(posicion)
        self.tiempo.blockSignals(False)


    # Metodo que detecta la posiscion establecida del modulo QMediaPlayer   
    def posicion_establecida(self, position):
        self.media.setPosition(position)

    def errores(self):
        self.reproducir.setEnabled(False)
        # self.lbl.setText("Error: " + self.media.errorString())

    # Metodo para centrar la ventana principal
    def centrar(self):
        ventana = self.frameGeometry()
        centro = QDesktopWidget().availableGeometry().center()
        # print(centro)
        ventana.moveCenter(centro)
        self.move(ventana.topLeft())
Ejemplo n.º 4
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.º 5
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.º 6
0
class Demo(QWidget):
    def __init__(self):
        super(Demo, self).__init__()

        self.time_label = QLabel(self)
        self.volume_slider = QSlider(self)
        self.progress_slider = QSlider(self)
        self.sound_btn = QPushButton(self)
        self.previous_btn = QPushButton(self)
        self.play_pause_btn = QPushButton(self)
        self.next_btn = QPushButton(self)
        self.mode_btn = QPushButton(self)
        self.list_btn = QPushButton(self)
        self.list_widget = QListWidget(self)

        self.h1_layout = QHBoxLayout()
        self.h2_layout = QHBoxLayout()
        self.all_v_layout = QVBoxLayout()

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

        self.widget_init()
        self.layout_init()
        self.signal_init()

    def widget_init(self):
        self.time_label.setText('--/--')
        self.volume_slider.setRange(0, 100)
        self.volume_slider.setValue(100)
        self.volume_slider.setOrientation(Qt.Horizontal)
        self.progress_slider.setEnabled(False)
        self.progress_slider.setOrientation(Qt.Horizontal)
        self.sound_btn.setIcon(QIcon('images/sound_on.png'))
        self.previous_btn.setIcon(QIcon('images/previous.png'))
        self.play_pause_btn.setIcon(QIcon('images/play.png'))
        self.next_btn.setIcon(QIcon('images/next.png'))
        self.mode_btn.setIcon(QIcon('images/list_loop.png'))
        self.list_btn.setIcon(QIcon('images/show.png'))

        self.player.setPlaylist(self.playlist)
        self.media_list = ['/Users/louis/Downloads/music1.mp3',
                           '/Users/louis/Downloads/music2.mp4',
                           '/Users/louis/Downloads/music3.mp3']
        for m in self.media_list:
            self.playlist.addMedia(QMediaContent(QUrl.fromLocalFile(m)))
        self.playlist.setPlaybackMode(QMediaPlaylist.Sequential)

        self.list_widget.addItems([m.split('/')[-1] for m in self.media_list])

    def layout_init(self):
        self.h1_layout.addWidget(self.progress_slider)
        self.h1_layout.addWidget(self.time_label)
        self.h2_layout.addWidget(self.volume_slider)
        self.h2_layout.addWidget(self.sound_btn)
        self.h2_layout.addWidget(self.previous_btn)
        self.h2_layout.addWidget(self.play_pause_btn)
        self.h2_layout.addWidget(self.next_btn)
        self.h2_layout.addWidget(self.mode_btn)
        self.h2_layout.addWidget(self.list_btn)

        self.all_v_layout.addLayout(self.h1_layout)
        self.all_v_layout.addLayout(self.h2_layout)
        self.all_v_layout.addWidget(self.list_widget)
        self.all_v_layout.setSizeConstraint(QVBoxLayout.SetFixedSize)

        self.setLayout(self.all_v_layout)

    def signal_init(self):
        self.sound_btn.clicked.connect(lambda: self.btn_func(self.sound_btn))
        self.previous_btn.clicked.connect(lambda: self.btn_func(self.previous_btn))
        self.play_pause_btn.clicked.connect(lambda: self.btn_func(self.play_pause_btn))
        self.next_btn.clicked.connect(lambda: self.btn_func(self.next_btn))
        self.mode_btn.clicked.connect(lambda: self.btn_func(self.mode_btn))
        self.list_btn.clicked.connect(lambda: self.btn_func(self.list_btn))
        self.volume_slider.valueChanged.connect(self.volume_slider_func)
        self.list_widget.doubleClicked.connect(self.list_play_func)
        self.player.durationChanged.connect(self.get_duration_func)
        self.player.positionChanged.connect(self.get_position_func)
        self.progress_slider.sliderMoved.connect(self.update_position_func)

    def btn_func(self, btn):
        if btn == self.sound_btn:              
            if self.player.isMuted():
                self.player.setMuted(False)
                self.sound_btn.setIcon(QIcon('images/sound_on'))
            else:
                self.player.setMuted(True)
                self.sound_btn.setIcon(QIcon('images/sound_off'))

        elif btn == self.previous_btn:          
            if self.playlist.currentIndex() == 0:
                self.playlist.setCurrentIndex(self.playlist.mediaCount() - 1)
            else:
                self.playlist.previous()

        elif btn == self.play_pause_btn:      
            if self.player.state() == 1:
                self.player.pause()
                self.play_pause_btn.setIcon(QIcon('images/play.png'))
            else:
                self.player.play()
                self.play_pause_btn.setIcon(QIcon('images/pause.png'))

        elif btn == self.next_btn:              
            if self.playlist.currentIndex() == self.playlist.mediaCount() - 1:
                self.playlist.setCurrentIndex(0)
            else:
                self.playlist.next()

        elif btn == self.mode_btn:             
            if self.playlist.playbackMode() == 2:
                self.playlist.setPlaybackMode(QMediaPlaylist.Loop)
                self.mode_btn.setIcon(QIcon('images/item_loop.png'))

            elif self.playlist.playbackMode() == 3:
                self.playlist.setPlaybackMode(QMediaPlaylist.Random)
                self.mode_btn.setIcon(QIcon('images/random.png'))

            elif self.playlist.playbackMode() == 4:
                self.playlist.setPlaybackMode(QMediaPlaylist.Sequential)
                self.mode_btn.setIcon(QIcon('images/list_loop.png'))

        elif btn == self.list_btn:             
            if self.list_widget.isHidden():
                self.list_widget.show()
                self.list_btn.setIcon(QIcon('images/show.png'))
            else:
                self.list_widget.hide()
                self.list_btn.setIcon(QIcon('images/hide.png'))

    def volume_slider_func(self, value):
        self.player.setVolume(value)
        if value == 0:
            self.sound_btn.setIcon(QIcon('images/sound_off.png'))
        else:
            self.sound_btn.setIcon(QIcon('images/sound_on.png'))

    def list_play_func(self):
        self.playlist.setCurrentIndex(self.list_widget.currentRow())
        self.player.play()
        self.play_pause_btn.setIcon(QIcon('images/pause.png'))

    def get_duration_func(self, d):
        self.progress_slider.setRange(0, d)
        self.progress_slider.setEnabled(True)
        self.get_time_func(d)

    def get_time_func(self, d):
        seconds = int(d / 1000)
        minutes = int(seconds / 60)
        seconds -= minutes * 60
        if minutes == 0 and seconds == 0:
            self.time_label.setText('--/--')
            self.play_pause_btn.setIcon(QIcon('images/play.png'))
        else:
            self.time_label.setText('{}:{}'.format(minutes, seconds))

    def get_position_func(self, p):
        self.progress_slider.setValue(p)

    def update_position_func(self, v):
        self.player.setPosition(v)
        d = self.progress_slider.maximum() - v
        self.get_time_func(d)
Ejemplo n.º 7
0
class Control:
    """A class that handles the logic behind the program by manipulating the GUI classes
    and calling their methods in response to received signals."""

    MAGIC = b"\x01\xff"

    def __init__(self, screens: list) -> None:
        self.player = QMediaPlayer()
        self.player.setAudioRole(QAudio.MusicRole)
        self.playlist = QMediaPlaylist()
        self.player.setPlaylist(self.playlist)
        self.mainWindow = MainWindow(self, screens)
        self.mainArea = self.mainWindow.centralWidget().upperBox.mainArea
        self.songList = self.mainWindow.centralWidget().upperBox.songList
        self.mediaControlArea = self.mainWindow.centralWidget(
        ).mediaControlArea
        self.mainWindow.show()
        self.library = None
        self.currentSong = None
        self.playing = False
        self.random = False
        self.repeat = 0
        self.volume = 50

        self.volumeChange(self.volume)
        self.mediaControlArea.volumeControl.setValue(self.volume)

        self.mainTimer = QTimer()
        self.mainTimer.setInterval(100)
        self.mainTimer.timeout.connect(self.updateSongProgress)
        self.mainTimer.start()

        self.libraryUpdateTimer = QTimer()
        self.libraryUpdateTimer.setInterval(15_000)
        self.libraryUpdateTimer.timeout.connect(self.updateLibrary)
        self.libraryUpdateTimer.start()

        self._connection = None
        self.connections()

        self.displayedType = None
        self.displayedName = None
        self.types = None
        self.songListWidth = None
        values = self.load()
        if values:
            self.mainWindow.setGeometry(*values)
            self.volumeChange(self.volume)
            self.mediaControlArea.volumeControl.setValue(self.volume)

        self.setUpTimer = QTimer()
        self.setUpTimer.setInterval(20)
        self.setUpTimer.setSingleShot(True)
        self.setUpTimer.timeout.connect(self.setAreas)
        self.setUpTimer.start()

    def connections(self):
        self.player.currentMediaChanged.connect(self.updateCurrentSong)
        self.player.durationChanged.connect(self.updateSongProgressRange)
        self.player.stateChanged.connect(self.playerStatusChanged)
        self.mediaControlArea.previousButton.click.connect(
            self.playlist.previous)
        self.mediaControlArea.repeatButton.click.connect(
            self.repeatButtonClick)
        self.mediaControlArea.stopButton.click.connect(self.stopButtonClick)
        self.mediaControlArea.playButton.click.connect(self.playButtonClick)
        self.mediaControlArea.randomButton.click.connect(
            self.randomButtonClick)
        self.mediaControlArea.nextButton.click.connect(self.playlist.next)
        self.mediaControlArea.muteButton.click.connect(self.mute)
        self.mediaControlArea.songProgress.sliderMoved.connect(
            self.songProgressMove)
        self.mediaControlArea.volumeControl.sliderMoved.connect(
            self.volumeChange)

    def setAreas(self) -> None:
        """Called after the GUI is created to provide user with a feedback
        that the program is running in case a larger amount of songs will be added
        when the Library class is initialized."""
        # TODO add a tooltip that will notify the user larger amount of songs is being loaded
        #  (freezes the program as the execution moves to the Library class.)
        self.library = library.Library()
        self.types = {
            "artist": self.library.getSongsForArtist,
            "album": self.library.getSongsForAlbum,
            "playlist": self.library.getSongsForPlaylist
        }
        self.mainArea.setAreas(self.library)
        self.setUpTimer.deleteLater()
        self.setUpTimer = None
        self.getSongs(self.displayedType, self.displayedName)
        if self.songListWidth is not None:
            songListGeometry = self.songList.geometry()
            self.songList.preferredWidth = songListGeometry.width(
            ) - self.songListWidth
            self.mainWindow.centralWidget().upperBox.line.resizeWidgets(
                songListGeometry.width() - self.songListWidth)

    def updateLibrary(self) -> None:
        self.library.update()
        self.mainArea.updateView(self.library)

    def updateCurrentSong(self) -> None:
        """Update all areas that may display information about the currently
        playing song - SongList, Now Playing tab, BottomBox"""
        media = self.player.currentMedia()
        self.currentSong = media.request().url().toLocalFile().replace(
            "/", "\\")
        if self.currentSong in self.library.library:
            self.songList.updateActiveSong(self.currentSong)
            self.mainArea.updateActiveSong(self.playlist.currentIndex())
            songEntry = self.library.library[self.currentSong]
            self.mediaControlArea.updateSongInfo(
                f"{songEntry[ARTIST]} - {songEntry[NAME]}")

    def updateSongProgressRange(self) -> None:
        """Updates the range of the slider that represents the song position."""
        self.mediaControlArea.updateSongProgressRange(self.player.duration())

    def playerStatusChanged(self) -> None:
        """Used to properly update the player look after the current playlist has finished."""
        index = self.playlist.currentIndex()
        if index == -1:
            self.stopButtonClick()

    def getSongs(self, isType: str, name: str) -> None:
        """Retrieves the songs for a given artist, album or playlist based on type
        and passes the resulting list to the SongList class."""
        if isType is None:
            isType = self.displayedType
        if name is None:
            name = self.displayedName
        orderBy = self.songList.buttonOrderBy.text()
        reverse = True if self.songList.buttonOrderReverse.text() == chr(
            0x25bc) else False
        listForType = self.types[isType](name, orderBy, reverse)
        playlist = None
        if isType == "playlist":
            playlist = name
        if len(listForType) == 0:
            artists = self.library.artists
            if len(artists):
                listForType = self.library.getSongsForArtist(artists[0])
        self.songList.updateSongList(listForType, self.library.library,
                                     self.currentSong, playlist, isType)
        self.displayedType = isType
        self.displayedName = name

    def playSongList(self, song: str = None) -> None:
        """Called when user double-clicks on an artist/album/playlist widget or a song
        in right-hand side panel."""
        self.playlist.clear()
        index = 0
        loopIndex = 0
        for songPath in self.songList.garbageProtector:
            if song == songPath:
                index = loopIndex
            self.playlist.addMedia(QMediaContent(QUrl.fromLocalFile(songPath)))
            loopIndex += 1
        if self.playlist.isEmpty():
            return
        self.player.play()
        if index > 0:
            self.playlist.setCurrentIndex(index)
        self.playing = True
        self.mediaControlArea.playButton.updatePictures(
            bottom.pausePixmap, bottom.pauseHoverPixmap, False)
        self.mainArea.setNowPlayingArea(self.library)
        self.mainArea.updateActiveSong(self.playlist.currentIndex())

    def playSongWidget(self,
                       songPath: str,
                       afterCurrent: bool = False) -> None:
        if afterCurrent:
            index = self.playlist.currentIndex() + 1
            self.playlist.insertMedia(
                index, QMediaContent(QUrl.fromLocalFile(songPath)))
        else:
            self.playlist.addMedia(QMediaContent(QUrl.fromLocalFile(songPath)))
        self.mainArea.setNowPlayingArea(self.library)
        self.mainArea.updateActiveSong(self.playlist.currentIndex())
        self.playing = True

    def removeFromNowPlaying(self, widget) -> None:
        if self.playlist.mediaCount() > 1:
            for row in range(self.mainArea.nowPlayingLayout.rowCount()):
                for column in range(
                        self.mainArea.nowPlayingLayout.columnCount()):
                    if self.mainArea.nowPlayingLayout.itemAtPosition(
                            row, column).widget() is widget:
                        self.playlist.removeMedia(row - 1)
                        break
                else:
                    continue
                break
        else:
            self.stopButtonClick()
            self.playlist.clear()
        self.mainArea.setNowPlayingArea(self.library)
        if self.playing:
            self.mainArea.updateActiveSong(self.playlist.currentIndex())

    def playMediaWidget(self, isType: str, target: str, startOver: bool,
                        afterCurrent: bool) -> None:
        """Called from MediaWidget - plays all songs for MediaWidget's type and name."""
        if startOver:
            self.playlist.clear()
        if afterCurrent:
            index = self.playlist.currentIndex() + 1
            for songPath in self.types[isType](target):
                self.playlist.insertMedia(
                    index, QMediaContent(QUrl.fromLocalFile(songPath)))
                index += 1
        else:
            for songPath in self.types[isType](target):
                self.playlist.addMedia(
                    QMediaContent(QUrl.fromLocalFile(songPath)))
        if startOver:
            self.player.play()
            self.playing = True
            self.mediaControlArea.playButton.updatePictures(
                bottom.pausePixmap, bottom.pauseHoverPixmap, False)
        self.mainArea.setNowPlayingArea(self.library)
        self.mainArea.updateActiveSong(self.playlist.currentIndex())

    def playFromNowPlaying(self, song: str) -> None:
        """Called when user double-clicks on a song in the Now Playing tab."""
        for n in range(self.playlist.mediaCount()):
            media = self.playlist.media(n)
            if song == media.request().url().toLocalFile().replace("/", "\\"):
                self.playlist.setCurrentIndex(n)
                if not self.playing:
                    self.player.play()
                    self.playing = True
                return

    def createPlaylist(self, playlistName: str) -> None:
        self.library.createPlaylist(playlistName)
        self.mainArea.setMainAreaPlaylists(self.library)

    def addToExistingPlaylist(self, playlist: str, songOrWidget: str,
                              isType: str) -> None:
        if isType in self.types:
            for song in self.types[isType](songOrWidget):
                self.library.addToPlaylist(playlist, song)
        else:
            self.library.addToPlaylist(playlist, songOrWidget)
        self.library.update()

    def removeFromPlaylist(self, playlist: str, song: str) -> None:
        self.library.deleteFromPlaylist(playlist, song)
        self.mainArea.setMainAreaPlaylists(self.library)
        self.library.update()
        self.getSongs("playlist", playlist)

    def renamePlaylist(self, playlistName: str, newPlaylistName: str) -> None:
        self.library.renamePlaylist(playlistName, newPlaylistName)
        self.mainArea.setMainAreaPlaylists(self.library)
        self.library.update()

    def deletePlaylist(self, playlistName: str) -> None:
        self.library.deletePlaylist(playlistName)
        self.mainArea.setMainAreaPlaylists(self.library)
        self.library.update()

    def addWatchedFolder(self, folder: str) -> None:
        """Adds a folder to the Library class. all mp3 files within the folder
        and its sub-folders will be added to the library and accessible to the player."""
        self.library.addFolder(folder.replace("/", "\\"))
        self.mainArea.updateView(self.library)

    def removeWatchedFolder(self, folder: str) -> None:
        """Removes folder from the library, updates view and stops playback if
        the current song was in the now-removed folder."""
        self.library.deleteFolder(folder)
        self.mainArea.updateView(self.library)
        if self.currentSong not in self.library.library:
            self.songList.updateSongList([], [], "", "")
            self.player.stop()
            self.playlist.clear()
            self.mediaControlArea.updateSongInfo("")
            self.songList.nowPlayingSong = None
            self.mainArea.nowPlayingSong = None
            self.playing = False
            self.mediaControlArea.updatePlayButton(self.playing, False)

    def playButtonClick(self, passMove: bool = True) -> None:
        if not self.playing:
            if self.playlist.isEmpty():
                self.playSongList()
                return
            self.playing = True
            self.player.play()
            self.mainArea.updateActiveSong(self.playlist.currentIndex())
            self.songList.updateActiveSong(self.currentSong)
        else:
            self.playing = False
            self.player.pause()
        self.mediaControlArea.updatePlayButton(self.playing, passMove)

    def repeatButtonClick(self) -> None:
        if self.repeat == 0:
            self.repeat = 1
            self.playlist.setPlaybackMode(QMediaPlaylist.Loop)
        elif self.repeat == 1:
            self.repeat = 2
            self.playlist.setPlaybackMode(QMediaPlaylist.CurrentItemInLoop)
        elif self.repeat == 2:
            self.repeat = 0
            self.playlist.setPlaybackMode(QMediaPlaylist.Sequential)
        self.mediaControlArea.updateRepeatButton(self.repeat)

    def randomButtonClick(self) -> None:
        if not self.random:
            self.random = True
            self.playlist.setPlaybackMode(QMediaPlaylist.Random)
        else:
            self.random = False
            self.playlist.setPlaybackMode(QMediaPlaylist.Sequential)
        self.mediaControlArea.updateRandomButton(self.random)

    def stopButtonClick(self) -> None:
        self.playing = False
        self.player.stop()
        if self.songList.nowPlayingSong is not None:
            self.songList.nowPlayingSong.clear()
        if self.mainArea.nowPlayingSong is not None:
            self.mainArea.nowPlayingSong.clear()
        self.mediaControlArea.updatePlayButton(self.playing, False)

    def mute(self) -> None:
        if not self.player.isMuted():
            self.player.setMuted(True)
            self.mediaControlArea.showMute()
        else:
            self.player.setMuted(False)
            self.volumeChange(self.volume)

    def volumeChange(self, volume: int) -> None:
        logVolume = QAudio.convertVolume(volume / 100,
                                         QAudio.LogarithmicVolumeScale,
                                         QAudio.LinearVolumeScale) * 100
        self.player.setVolume(logVolume)
        self.volume = volume
        self.mediaControlArea.updateVolumeBar(volume)

    def songProgressMove(self, position: int) -> None:
        self.player.setPosition(position)

    def updateSongProgress(self) -> None:
        position = self.player.position()
        if 0 <= position < 2_000_000_000:
            if self.player.state() > 0:
                self.mediaControlArea.updateSongProgress(position)
                if self.playing:
                    self.songList.activeSongPixmap()
                    self.mainArea.activeSongPixmap()
            else:
                self.mediaControlArea.updateSongProgress(0)

    def disconnect(self):
        self.player.currentMediaChanged.disconnect()
        self.player.durationChanged.disconnect()
        self.player.stateChanged.disconnect()
        self.mediaControlArea.previousButton.click.disconnect()
        self.mediaControlArea.repeatButton.click.disconnect()
        self.mediaControlArea.stopButton.click.disconnect()
        self.mediaControlArea.playButton.click.disconnect()
        self.mediaControlArea.randomButton.click.disconnect()
        self.mediaControlArea.nextButton.click.disconnect()
        self.mediaControlArea.muteButton.click.disconnect()
        self.mediaControlArea.songProgress.sliderMoved.disconnect()
        self.mediaControlArea.volumeControl.sliderMoved.disconnect()

    def close(self) -> None:
        self.disconnect()
        self.player.stop()
        self.mainTimer.stop()
        self.save()

    def save(self) -> None:
        """Called on exit, saves current view, geometry and volume."""
        with gzip.open(r"musicplayer\mpdata", "wb") as fh:
            fh.write(self.MAGIC)
            toBeWritten = struct.pack(f"<h{len(self.displayedType.encode())}s",
                                      len(self.displayedType.encode()),
                                      self.displayedType.encode())
            fh.write(toBeWritten)
            fh.write(self.MAGIC)
            toBeWritten = struct.pack(f"<h{len(self.displayedName.encode())}s",
                                      len(self.displayedName.encode()),
                                      self.displayedName.encode())
            fh.write(toBeWritten)
            fh.write(self.MAGIC)
            geo = self.mainWindow.geometry()
            toBeWritten = struct.pack("<4h", geo.x(), geo.y(), geo.width(),
                                      geo.height())
            fh.write(toBeWritten)
            toBeWritten = struct.pack("<h", self.volume)
            fh.write(toBeWritten)
            toBeWritten = struct.pack("<h", self.songList.width())
            fh.write(toBeWritten)

    def load(self) -> [bool, tuple]:
        """Called on startup, loads view, geometry and volume saved on previous run."""
        try:
            with gzip.open(r"musicplayer\mpdata", "rb") as fh:
                if not fh.read(2) == self.MAGIC:
                    return False
                length = fh.read(2)
                length = struct.unpack("<h", length)[0]
                displayedType = fh.read(length)
                displayedType = struct.unpack(f"<{length}s",
                                              displayedType)[0].decode("utf8")
                if displayedType in ["artist", "album", "playlist"]:
                    self.displayedType = displayedType
                if not fh.read(2) == self.MAGIC:
                    return False
                length = fh.read(2)
                length = struct.unpack("<h", length)[0]
                displayedName = fh.read(length)
                displayedName = struct.unpack(f"<{length}s",
                                              displayedName)[0].decode("utf8")
                if not fh.read(2) == self.MAGIC:
                    return False
                self.displayedName = displayedName
                variables = []
                for n in range(6):
                    var = fh.read(2)
                    var = struct.unpack("<h", var)[0]
                    variables.append(var)
                x, y, width, height, volume, songListWidth = variables
                self.volume = volume
                self.songListWidth = songListWidth
                return x, y, width, height
        except Exception:
            return False
Ejemplo n.º 8
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()
Ejemplo n.º 9
0
class MainWindow(QMainWindow, Ui_MainWindow):
    def __init__(self, *args, **kwargs):
        super(MainWindow, self).__init__(*args, **kwargs)
        self.setupUi(self)

        self.player = QMediaPlayer()

        self.player.error.connect(self.erroralert)
        self.player.play()
        self.player.stateChanged.connect(self.Set_Icons)
        # self.player.volumeChanged.connect(self.prev_volume)
        # Connect control buttons/slides for media player.
        self.playButton.pressed.connect(self.play_pause)
        self.stopButton.pressed.connect(self.player.stop)
        self.showButton.pressed.connect(self.playlist_toggle)
        self.equalizerButton.pressed.connect(self.ShowEqualizer)
        self.volumeButton.pressed.connect(self.mute)

        self.volumeSlider.valueChanged.connect(self.volumeChanged)
        self.currentVolume = self.volumeSlider.value()
        self.timeSlider.valueChanged.connect(self.player.setPosition)

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

        self.model = PlaylistModel(self.playlist)
        self.listWidget.setModel(self.model)
        self.playlist.currentIndexChanged.connect(
            self.playlist_position_changed)
        selection_model = self.listWidget.selectionModel()
        selection_model.selectionChanged.connect(
            self.playlist_selection_changed)

        self.player.durationChanged.connect(self.update_duration)
        self.player.positionChanged.connect(self.update_position)

        self.actionOpen_File.triggered.connect(self.open_file)
        self.files = []
        self.setAcceptDrops(True)

        self.graphWidget.setBackground((60, 60, 60))
        self.graphWidget.GetViewBox().setMenuEnabled(False)
        self.graphWidget.GetViewBox().setMouseEnabled(x=False, y=False)
        self.graphWidget.setPlotEQ((42, 130, 218))

        self.Visualizer = FFTAnalyser(self.player)
        self.Visualizer.calculated_visual.connect(self.draw)
        self.Visualizer.start()
        self.Equalizer = QWidget()
        self.visdata = np.array([])
        self.show()

    def draw(self, visdata):
        self.visdata = np.array(visdata)
        self.graphWidget.UpdatePlotEQ(self.visdata)

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

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

    def Set_Icons(self, state):
        if state == QMediaPlayer.StoppedState:
            self.stopButton.setIcon(
                qta.icon('fa5s.stop-circle',
                         active='fa5s.stop-circle',
                         color='white',
                         color_active='grey'))
            self.playButton.setIcon(qta.icon('fa5s.play-circle',
                                             color='white'))
            self.playButton.setToolTip('Play')
        elif state == QMediaPlayer.PlayingState:
            self.playButton.setIcon(
                qta.icon('fa5s.pause-circle', color='white'))
            self.playButton.setToolTip('Pause')
        elif state == QMediaPlayer.PausedState:
            self.playButton.setIcon(qta.icon('fa5s.play-circle',
                                             color='white'))
            self.playButton.setToolTip('Play')

    def playlist_toggle(self):
        if self.listWidget.isHidden():
            self.listWidget.setHidden(False)
            self.listWidget.setProperty("showDropIndicator", True)
            self.showButton.setIcon(qta.icon('fa5s.eye-slash', color='white'))
            self.showButton.setToolTip('Hide Playlist')
        else:
            self.listWidget.setHidden(True)
            self.listWidget.setProperty("showDropIndicator", False)
            self.showButton.setIcon(qta.icon('fa5s.list-ul', color='white'))
            self.showButton.setToolTip('Show Playlist')

    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):
        options = QFileDialog.Options()
        options |= QFileDialog.DontUseNativeDialog
        path, _ = QFileDialog.getOpenFileName(self,
                                              "Open file",
                                              "",
                                              "Music Files (*.mp3 *.wav)",
                                              options=options)

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

        self.model.layoutChanged.emit()

    # def contextMenuEvent(self, event):
    # contextMenu = QMenu(self)
    # graph = contextMenu.addAction("Show Graph")

    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))

        self.timeSlider.blockSignals(True)
        self.timeSlider.setValue(position)
        self.timeSlider.blockSignals(False)

    def playlist_selection_changed(self, ix):
        i = ix.indexes()[0].row()
        self.playlist.setCurrentIndex(i)

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

    def erroralert(self, *args):
        print(args)

    def ShowEqualizer(self):
        if self.player.currentMedia().canonicalUrl().path() != "":
            self.Equalizer = WindowingWidget(
                self.player.currentMedia().canonicalUrl().path())
            self.Equalizer.SendPath.connect(self.AddPathToPlaylist)
            self.Equalizer.show()

    def AddPathToPlaylist(self, path):
        if path:
            self.playlist.addMedia(QMediaContent(QUrl.fromLocalFile(path)))
            self.files.append(path)

        self.model.layoutChanged.emit()

    def volumeChanged(self):
        self.currentVolume = self.volumeSlider.value()
        self.player.setVolume(self.volumeSlider.value())

    def mute(self):
        if self.player.isMuted():
            self.player.setMuted(False)
            self.volumeButton.setIcon(qta.icon('fa5s.volume-up',
                                               color='white'))
            self.volumeButton.setToolTip('Mute')
            self.volumeSlider.setEnabled(True)
        else:
            self.player.setMuted(True)
            self.volumeButton.setIcon(
                qta.icon('fa5s.volume-mute', color='white'))
            self.volumeButton.setToolTip('Unmute')
            self.volumeSlider.setEnabled(False)

    def closeEvent(self, event):
        self.Visualizer.terminate()
        if self.Equalizer.isVisible():
            self.Equalizer.close()
Ejemplo n.º 10
0
class Player(QGraphicsVideoItem):

    isSubtitle = pyqtSignal(bool)
    subtitlePos = pyqtSignal(int)

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

        self.player = QMediaPlayer()
        self.player.setVolume(int(settings().value("Player/volume") or 100))
        self.player.setVideoOutput(self)

        self.timer = QTimer(self)
        self.timer.timeout.connect(self.timerPos)

        self.player.currentMediaChanged.connect(self.signalStart)
        self.player.currentMediaChanged.connect(
            self.parent.subtitleitem.subtitleControl)
        self.player.currentMediaChanged.connect(self.videoConfigure)
        """self.player.mediaStatusChanged.connect(self.metadata)

    def metadata(self, data):
        if data and self.player.isMetaDataAvailable():
            print(self.player.metaData("VideoCodec"))"""

    def videoConfigure(self, media):
        video_name = os.path.basename(media.canonicalUrl().toLocalFile())
        videos = settings().value("Player/video_names") or []
        videos_time = settings().value("Player/videos_time") or []
        try:
            self.player.setPosition(int(videos_time[videos.index(video_name)]))
        except ValueError:
            pass

    def timerStart(self):
        self.timer.start(200)

    def signalStart(self, content):
        srt = content.canonicalUrl().toLocalFile().split(".")
        srt.pop(-1)
        srt.append("srt")
        srt = ".".join(srt)
        if QFile.exists(srt):
            self.isSubtitle.emit(True)
            self.timer.start(100)
        else:
            self.isSubtitle.emit(False)
            self.timer.stop()

    def timerPos(self):
        self.subtitlePos.emit(self.player.position())

    def playerPlayOrOpen(self, arg=None):
        if type(arg) == list and len(arg) > 1:
            content = QMediaContent(QUrl.fromLocalFile(arg[1]))
            self.player.setMedia(content)
            self.play()

    def addVideo(self, video):
        content = QMediaContent(QUrl.fromLocalFile(video))
        self.player.setMedia(content)
        self.play()

    def addYoutubeVideo(self, video):
        dm = DownloadManager(self)

        content = QMediaContent(dm.addUrl(video))
        self.player.setMedia(content)
        self.play()

    def sliderChanged(self, pos):
        self.player.setPosition(pos)

    def play(self):
        self.player.play()

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

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

    def setMuted(self, mute):
        self.player.setMuted(mute)

    def mutedState(self):
        if self.player.isMuted():
            self.setMuted(False)
        else:
            self.setMuted(True)

    def isMuted(self):
        return self.player.isMuted()

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

    def volume(self):
        return self.player.volume()
Ejemplo n.º 11
0
class VideoWindow(QMainWindow):
    def __init__(self, parent=None):
        super(VideoWindow, self).__init__(parent)
        self.first = True

        # -추가 : 양팡관련
        self.YangPang_play = False
        self.YangPang_first = 0

        global player
        global channel_ls

        # 제목 표시줄
        self.setWindowTitle(
            "PyQt Video Player Widget Example - pythonprogramminglanguage.com")

        # 비디오 파일 재생 위젯 생성
        self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.VideoSurface)

        # 비디오 출력 프레임 부분 위젯 생성
        self.videoWidget = QVideoWidget()

        # 플레이버튼 생성
        self.playButton = QPushButton()
        self.playButton.setEnabled(False)
        self.playButton.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay))
        self.playButton.clicked.connect(self.play)

        # 플레이용 수평 슬라이드 바 생성
        self.positionSlider = QSlider(Qt.Horizontal)

        # 0부터 0까지 칸 수 만큼 슬라이드 할 수 있는 바 생성
        self.positionSlider.setRange(0, 0)
        self.positionSlider.sliderMoved.connect(self.setPosition)

        # - 추가 : 사운드 이미지 라벨 생성
        self.soundImage = QPushButton()
        self.soundImage.setIcon(self.style().standardIcon(
            QStyle.SP_MediaVolume))
        self.soundImage.clicked.connect(self.sound)

        # - 추가 : 사운드용 수평 슬라이드 바 생성
        self.soundpositionSlider = QSlider(Qt.Horizontal)
        self.soundpositionSlider.setSizePolicy(QSizePolicy.Preferred,
                                               QSizePolicy.Maximum)

        # - 추가 : 0부터 100까지 칸 수 만큼 슬라이드 할 수 있는 바 생성
        self.soundpositionSlider.setRange(0, 100)
        self.soundpositionSlider.setValue(100)
        self.soundpositionSlider.sliderMoved.connect(self.setsoundPosition)

        # - 추가 : 링크기능
        self.textLink = QLineEdit()
        self.buttonLink = QPushButton()
        self.textLink.setObjectName("link")
        self.buttonLink.setText("연결")
        self.buttonLink.clicked.connect(self.connect_video)
        self.buttonLink.setSizePolicy(QSizePolicy.Preferred,
                                      QSizePolicy.Maximum)

        # 에러 Label 생성
        self.errorLabel = QLabel()

        # sizepolicy 정리
        # http://mitk.org/images/5/5e/BugSquashingSeminars%2414-04-30-bugsquashing-Qt-Size-Policy.pdf
        # https://stackoverflow.com/questions/4553304/understanding-form-layout-mechanisms-in-qt
        self.errorLabel.setSizePolicy(QSizePolicy.Preferred,
                                      QSizePolicy.Maximum)

        # 메뉴의 open 생성
        openAction = QAction(QIcon('open.png'), '&Open', self)
        openAction.setShortcut('Ctrl+O')
        openAction.setStatusTip('Open movie')
        openAction.triggered.connect(self.openFile)

        # 메뉴의 exit 생성
        exitAction = QAction(QIcon('exit.png'), '&Exit', self)
        exitAction.setShortcut('Ctrl+Q')
        exitAction.setStatusTip('Exit application')
        exitAction.triggered.connect(self.exitCall)

        # - 추가 : 메뉴의 channel add 생성
        channelAction = QAction(QIcon('exit.png'), '&Channel', self)
        channelAction.setStatusTip('Youtube channel set')
        channelAction.triggered.connect(opensetwin)

        # 메뉴바 및 메뉴 생성
        menuBar = self.menuBar()
        fileMenu = menuBar.addMenu('&File')

        # 메뉴 목록 추가
        fileMenu.addAction(openAction)
        fileMenu.addAction(exitAction)
        # - 추가
        fileMenu.addAction(channelAction)

        # centralwidget 부분 추가
        wid = QWidget(self)
        self.setCentralWidget(wid)

        # -추가 : 양팡관련
        self.YB = QPushButton()
        self.YB.setText("양팡 Start")
        self.YB.clicked.connect(self.YangPang)

        # -추가 : 채널관련
        self.CL = QPushButton()
        self.CL.setText("채널 Start")
        self.CL.clicked.connect(self.ChannelVideo)

        # 레이아웃을 생성하고 위에서 만들었던 Widget 수평으로 순서대로 추가
        controlLayout = QHBoxLayout()
        controlLayout.addWidget(self.playButton)
        controlLayout.addWidget(self.positionSlider)
        controlLayout.addWidget(self.soundImage)
        controlLayout.addWidget(self.soundpositionSlider)

        # 링크 부분 레이아웃 생성
        linkLayout = QHBoxLayout()
        linkLayout.addWidget(self.textLink)
        linkLayout.addWidget(self.buttonLink)

        # controlLayout 바깥으로 여백 추가 (left, right, up, down)
        controlLayout.setContentsMargins(0, 0, 0, 0)

        # 레이아웃을 생성하고 이 래이아웃들을 수직 순서대로 추가
        layout = QVBoxLayout()
        layout.addWidget(self.videoWidget)
        layout.addLayout(controlLayout)
        layout.addLayout(linkLayout)

        # -추가 : 양팡관련
        layout.addWidget(self.YB)

        # -추가 : 채널관련
        layout.addWidget(self.CL)

        layout.addWidget(self.errorLabel)

        # CentralWidget에 layout 넣기
        wid.setLayout(layout)

        # 미디어 위젯에 비디오를 출력 시킴
        self.mediaPlayer.setVideoOutput(self.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)

        # - 추가 : 영상 1/3 나누어서 5초 앞 / 시작 or 정지 / 5초 뒤 투명한 버튼 생성
        hide_layout = QHBoxLayout()
        self.before = QPushButton()
        self.state_change = QPushButton()
        self.after = QPushButton()
        self.before.setEnabled(False)
        self.state_change.setEnabled(False)
        self.after.setEnabled(False)
        self.before.clicked.connect(self.before_f)
        self.state_change.clicked.connect(self.play)
        self.after.clicked.connect(self.after_f)
        self.before.setShortcut('left')
        self.state_change.setShortcut('space')
        self.after.setShortcut('right')
        hide_layout.addWidget(self.before)
        hide_layout.addWidget(self.state_change)
        hide_layout.addWidget(self.after)
        self.before.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
        self.state_change.setSizePolicy(QSizePolicy.Preferred,
                                        QSizePolicy.Preferred)
        self.after.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
        self.videoWidget.setLayout(hide_layout)

    # 파일 불러오기
    def openFile(self):
        # QFileDialog.getOpenFileName(self, "제목 표시줄", QDir.homePath())
        # 이 함수를 통해 filename엔 파일의 전체 경로와 어떤 종류로 가져 왔는지 변수로 줌(ex. All Files (*))
        fileName, _ = QFileDialog.getOpenFileName(self, "Open Movie",
                                                  QDir.homePath())
        # -추가 : 양팡관련
        self.YangPang_play = False
        self.YangPang_first = 0
        # 위에서 받아온 경로의 파일을 미디어위젯에 대입
        if fileName != '':
            self.mediaPlayer.setMedia(
                QMediaContent(QUrl.fromLocalFile(fileName)))
            self.playButton.setEnabled(True)
            self.check_url = False
            self.best = None

    # 윈도우 종료 함수
    def exitCall(self):
        sys.exit(app.exec_())

    # - 추가 : 링크로 연결 (유튜브 주소만 호환)
    def connect_video(self):
        # -추가 : 양팡관련
        if not self.YangPang_play:
            self.textValueB = self.textLink.text()
            self.YangPang_first = 0
        url = self.textValueB
        if self.textLink.text() != "":
            self.YangPang_play = False

        play_link = pafy.new(url)
        self.best = play_link.getbest()
        self.mediaPlayer.setMedia(QMediaContent(QUrl(self.best.url)))
        self.playButton.setEnabled(True)
        self.check_url = True
        self.play()

    # 플레이 버튼 함수
    def play(self):
        # 현재 미디어 위젯의 플레이 상태가 재생중일 때이거나 다른 경우
        # PlayingState는 Q미디어플레이어.play() 인듯 = 1
        if self.mediaPlayer.state() == QMediaPlayer.PlayingState:
            self.mediaPlayer.pause()
        else:
            self.mediaPlayer.play()

    # - 추가 : 사운드 버튼 함수
    def sound(self):
        if self.mediaPlayer.isMuted():
            self.mediaPlayer.setMuted(False)
            self.soundImage.setIcon(self.style().standardIcon(
                QStyle.SP_MediaVolume))
        else:
            self.mediaPlayer.setMuted(True)
            self.soundImage.setIcon(self.style().standardIcon(
                QStyle.SP_MediaVolumeMuted))

    # 플레이 버튼 모양 변경
    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))

        # 양팡 및 채널 관련
        if self.mediaPlayer.state() == QMediaPlayer.StoppedState:
            if self.YangPang_play:
                if self.YangPang_first == 1:
                    self.YangPang()
                if self.YangPang_first == 2:
                    self.ChannelVideo()

    # 영상의 진행 정도에 따른 슬라이드 바 위치 변경
    def positionChanged(self, position):
        self.positionSlider.setValue(position)
        self.position = position

    # 영상의 길이만큼 슬라이드 바의 최대값 설정
    def durationChanged(self, duration):
        self.positionSlider.setRange(0, duration)

        # - 추가 : 슬라이드 이동 간격 설정
        self.mediaPlayer.setNotifyInterval(1)

        # - 추가 : 자동으로 영상크기만큼 윈도우 크기 조절
        if self.mediaPlayer.metaData("Resolution") != None:
            if not self.check_url:
                player.resize(self.mediaPlayer.metaData("Resolution"))
        else:
            if self.best != None:
                x, y = parse("{}x{}", self.best.resolution)
                player.resize(int(x), int(y))

        # - 추가 : 영상 추가시 버튼 활성화
        self.before.setEnabled(True)
        self.state_change.setEnabled(True)
        self.after.setEnabled(True)

    # - 추가 : 5초 앞
    def before_f(self):
        self.mediaPlayer.setPosition(self.position - 5000)

    # - 추가 : 5초 뒤
    def after_f(self):
        self.mediaPlayer.setPosition(self.position + 5000)

    # 영상 슬라이드 바 위치에 따른 화면 변경
    def setPosition(self, position):
        self.mediaPlayer.setPosition(position)

    # 에러 출력 함수
    def handleError(self):
        self.playButton.setEnabled(False)
        self.before.setEnabled(False)
        self.state_change.setEnabled(False)
        self.after.setEnabled(False)
        self.errorLabel.setText("Error: " + self.mediaPlayer.errorString())

    # - 추가 : 사운드 슬라이드 바 위치에 따른 소리 크기 변경
    def setsoundPosition(self, position):
        self.mediaPlayer.setVolume(position)

    # - 추가 : 양팡 유튜브 영상 재생
    def YangPang(self):
        # if not self.YangPang_play:
        if self.YangPang_first == 1:
            web_url = self.textValueB

            with urllib.request.urlopen(web_url) as response:
                html = response.read()
                soup = BeautifulSoup(html, 'html.parser')
                yp_find = soup.find_all("a")

            self.yp_find_list = list()
            for info in yp_find:
                if parse("/watch?v={}", info["href"]) != None:
                    if str(info.find("span", {"class": "stat attribution"
                                              })).count('양팡 YangPang') > 0:
                        self.yp_find_list.append(info["href"])
                        break

        if self.YangPang_first != 1:
            web_url = "https://www.youtube.com/channel/UCMVC92EOs9yDJG5JS-CMesQ/videos"
            self.YangPang_first = 1

            with urllib.request.urlopen(web_url) as response:
                html = response.read()
                soup = BeautifulSoup(html, 'html.parser')
                yp_find = soup.find_all("a")

            self.yp_find_list = list()
            for info in yp_find:
                if parse("/watch?v={}", info["href"]) != None:
                    self.yp_find_list.append(info["href"])

        self.YangPang_play = True
        cnt = len(self.yp_find_list) - 1

        self.textValueB = "https://www.youtube.com/" + str(
            self.yp_find_list[random.randint(0, cnt)])
        self.setWindowTitle("양팡플레이어")
        self.connect_video()

    def ChannelVideo(self):
        if self.YangPang_first == 2:
            web_url = self.textValueB

            with urllib.request.urlopen(web_url) as response:
                html = response.read()
                soup = BeautifulSoup(html, 'html.parser')
                yp_find = soup.find_all("a")

            self.yp_find_list = list()
            for info in yp_find:
                if parse("/watch?v={}", info["href"]) != None:
                    if str(info.find("span", {"class": "stat attribution"
                                              })).count(self.name) > 0:
                        self.yp_find_list.append(info["href"])
                        break

            k = random.randint(0, 1)
            if k == 0:
                self.YangPang_first = 0

        if self.YangPang_first != 2:
            web_url = channel_ls[random.randint(0, len(channel_ls) - 1)]
            self.YangPang_first = 2

            with urllib.request.urlopen(web_url) as response:
                html = response.read()
                soup = BeautifulSoup(html, 'html.parser')
                yp_find = soup.find_all("a")
                self.name_ls = soup.find_all("img")

            for info in self.name_ls:
                if info["alt"] != None:
                    self.name = info["alt"]
                    break

            self.yp_find_list = list()
            for info in yp_find:
                if parse("/watch?v={}", info["href"]) != None:
                    self.yp_find_list.append(info["href"])

        self.YangPang_play = True
        cnt = len(self.yp_find_list) - 1

        self.textValueB = "https://www.youtube.com/" + str(
            self.yp_find_list[random.randint(0, cnt)])
        self.setWindowTitle("랜덤플레이어")
        self.connect_video()
Ejemplo n.º 12
0
class Player(QGraphicsVideoItem):

    isSubtitle = pyqtSignal(bool)
    subtitlePos = pyqtSignal(int)
    def __init__(self, parent=None):
        super().__init__()
        self.parent = parent

        self.player = QMediaPlayer()
        self.player.setVolume(int(settings().value("Player/volume") or 100))
        self.player.setVideoOutput(self)

        self.timer = QTimer(self)
        self.timer.timeout.connect(self.timerPos)

        self.player.currentMediaChanged.connect(self.signalStart)
        self.player.currentMediaChanged.connect(self.parent.subtitleitem.subtitleControl)
        self.player.currentMediaChanged.connect(self.videoConfigure)
        """self.player.mediaStatusChanged.connect(self.metadata)

    def metadata(self, data):
        if data and self.player.isMetaDataAvailable():
            print(self.player.metaData("VideoCodec"))"""

    def videoConfigure(self, media):
        video_name = os.path.basename(media.canonicalUrl().toLocalFile())
        videos = settings().value("Player/video_names") or []
        videos_time = settings().value("Player/videos_time") or []
        try:
            self.player.setPosition(int(videos_time[videos.index(video_name)]))
        except ValueError:
            pass

    def timerStart(self):
        self.timer.start(200)

    def signalStart(self, content):
        srt = content.canonicalUrl().toLocalFile().split(".")
        srt.pop(-1)
        srt.append("srt")
        srt = ".".join(srt)
        if QFile.exists(srt):
            self.isSubtitle.emit(True)
            self.timer.start(100)
        else:
            self.isSubtitle.emit(False)
            self.timer.stop()

    def timerPos(self):
        self.subtitlePos.emit(self.player.position())

    def playerPlayOrOpen(self, arg=None):
        if type(arg) == list and len(arg) > 1:
            content = QMediaContent(QUrl.fromLocalFile(arg[1]))
            self.player.setMedia(content)
            self.play()

    def addVideo(self, video):
        content = QMediaContent(QUrl.fromLocalFile(video))
        self.player.setMedia(content)
        self.play()

    def addYoutubeVideo(self, video):
        dm = DownloadManager(self)

        content = QMediaContent(dm.addUrl(video))
        self.player.setMedia(content)
        self.play()

    def sliderChanged(self, pos):
        self.player.setPosition(pos)

    def play(self):
        self.player.play()

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

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

    def setMuted(self, mute):
        self.player.setMuted(mute)

    def mutedState(self):
        if self.player.isMuted():
            self.setMuted(False)
        else:
            self.setMuted(True)

    def isMuted(self):
        return  self.player.isMuted()

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

    def volume(self):
        return self.player.volume()
Ejemplo n.º 13
0
class Window(QWidget, Ui_Window):
    def __init__(self):
        super().__init__()
        self.setupUi(self)

        self.status = False

        self.player = QMediaPlayer()
        self.player.setNotifyInterval(100)
        self.open_button.clicked.connect(self.open_dialog)

        self.play_pause_button.clicked.connect(self.play_pause)
        self.stop_button.clicked.connect(self.stop)

        self.player.durationChanged.connect(self.track_duration)
        self.player.positionChanged.connect(self.track_position)

        self.player.mediaStatusChanged.connect(self.track_status)

        self.position_slider.sliderPressed.connect(
            self.change_track_position_block)
        self.position_slider.sliderReleased.connect(
            self.change_track_position_unblock)

        self.volume_slider.valueChanged.connect(self.player.setVolume)
        self.mute_button.clicked.connect(self.mute)

        self.playback_spinbox.valueChanged.connect(self.change_playback)

    def play_pause(self):
        if self.status:
            self.play_pause_button.setText('Play')
            self.player.pause()
            self.status = False
        else:
            self.play_pause_button.setText('Pause')
            self.stop_button.setEnabled(True)
            self.player.play()
            self.status = True

    def stop(self):
        if self.status:
            self.play_pause_button.setText('Play')
        self.stop_button.setEnabled(False)
        self.player.stop()
        self.status = False

    def track_duration(self, duration):
        self.track_duration_label.setText(ms_to_time(duration))
        self.position_slider.setMaximum(duration)

    def track_position(self, position):
        self.track_position_label.setText(ms_to_time(position))
        self.position_slider.setValue(position)

    def change_track_position_block(self):
        self.player.positionChanged.disconnect(self.track_position)
        self.position_slider.valueChanged.connect(
            self.change_track_position_label)

    def change_track_position_label(self, value):
        self.track_position_label.setText(ms_to_time(value))

    def change_track_position_unblock(self):
        self.player.setPosition(self.position_slider.value())
        self.position_slider.valueChanged.disconnect(
            self.change_track_position_label)
        self.player.positionChanged.connect(self.track_position)

    def track_status(self, status):
        if status == 7:
            self.stop()
            self.player.setPosition(0)

    def change_playback(self, value):
        self.player.positionChanged.disconnect(self.track_position)
        position = self.player.position()
        self.player.stop()
        self.player.setPlaybackRate(value)
        self.player.play()
        self.player.setPosition(position)
        self.player.positionChanged.connect(self.track_position)

    def mute(self):
        if self.player.isMuted():
            self.player.setMuted(False)
            self.volume_slider.setEnabled(True)
            self.mute_button.setText('🔊')
        else:
            self.volume_slider.setEnabled(False)
            self.player.setMuted(True)
            self.mute_button.setText('🔈')

    def open_dialog(self):
        track = QFileDialog.getOpenFileName(
            self, dialog, '', 'Music (*.flac *.ogg *.mp3 *.wav *.webm)')[0]
        if track:
            self.play_pause_button.setEnabled(True)
            self.position_slider.setEnabled(True)
            self.volume_slider.setEnabled(True)
            self.mute_button.setEnabled(True)
            self.playback_spinbox.setEnabled(True)
            self.player.setMedia(QMediaContent(QUrl.fromLocalFile(track)))
            self.stop()
Ejemplo n.º 14
0
class VidCutter(QWidget):
    def __init__(self, parent):
        super(VidCutter, self).__init__(parent)
        self.novideoWidget = QWidget(self, autoFillBackground=True)
        self.parent = parent
        self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.VideoSurface)
        self.videoWidget = VideoWidget(self)
        self.videoService = VideoService(self)

        QFontDatabase.addApplicationFont(
            MainWindow.get_path('fonts/DroidSansMono.ttf'))
        QFontDatabase.addApplicationFont(
            MainWindow.get_path('fonts/OpenSans.ttf'))

        fontSize = 12 if sys.platform == 'darwin' else 10
        appFont = QFont('Open Sans', fontSize, 300)
        qApp.setFont(appFont)

        self.clipTimes = []
        self.inCut = False
        self.movieFilename = ''
        self.movieLoaded = False
        self.timeformat = 'hh:mm:ss'
        self.finalFilename = ''
        self.totalRuntime = 0

        self.initIcons()
        self.initActions()

        self.toolbar = QToolBar(floatable=False,
                                movable=False,
                                iconSize=QSize(40, 36))
        self.toolbar.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)
        self.toolbar.setStyleSheet('''QToolBar { spacing:10px; }
            QToolBar QToolButton { border:1px solid transparent; min-width:95px; font-size:11pt; font-weight:400;
                border-radius:5px; padding:1px 2px; color:#444; }
            QToolBar QToolButton:hover { border:1px inset #6A4572; color:#6A4572; background-color:rgba(255, 255, 255, 0.85); }
            QToolBar QToolButton:pressed { border:1px inset #6A4572; color:#6A4572; background-color:rgba(255, 255, 255, 0.25); }
            QToolBar QToolButton:disabled { color:#999; }''')
        self.initToolbar()

        self.appMenu, self.cliplistMenu = QMenu(), QMenu()
        self.initMenus()

        self.seekSlider = VideoSlider(parent=self,
                                      sliderMoved=self.setPosition)

        self.initNoVideo()

        self.cliplist = QListWidget(
            sizePolicy=QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Expanding),
            contextMenuPolicy=Qt.CustomContextMenu,
            uniformItemSizes=True,
            iconSize=QSize(100, 700),
            dragDropMode=QAbstractItemView.InternalMove,
            alternatingRowColors=True,
            customContextMenuRequested=self.itemMenu,
            dragEnabled=True)
        self.cliplist.setStyleSheet(
            'QListView { border-radius:0; border:none; border-left:1px solid #B9B9B9; '
            +
            'border-right:1px solid #B9B9B9; } QListView::item { padding:10px 0; }'
        )
        self.cliplist.setFixedWidth(185)
        self.cliplist.model().rowsMoved.connect(self.syncClipList)

        listHeader = QLabel(pixmap=QPixmap(
            MainWindow.get_path('images/clipindex.png'), 'PNG'),
                            alignment=Qt.AlignCenter)
        listHeader.setStyleSheet(
            '''padding:5px; padding-top:8px; border:1px solid #b9b9b9;
                                    background-color:qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #FFF,
                                    stop: 0.5 #EAEAEA, stop: 0.6 #EAEAEA stop:1 #FFF);'''
        )

        self.runtimeLabel = QLabel('<div align="right">00:00:00</div>',
                                   textFormat=Qt.RichText)
        self.runtimeLabel.setStyleSheet(
            '''font-family:Droid Sans Mono; font-size:10pt; color:#FFF;
                                           background:rgb(106, 69, 114) url(:images/runtime.png)
                                           no-repeat left center; padding:2px; padding-right:8px;
                                           border:1px solid #B9B9B9;''')

        self.clipindexLayout = QVBoxLayout(spacing=0)
        self.clipindexLayout.setContentsMargins(0, 0, 0, 0)
        self.clipindexLayout.addWidget(listHeader)
        self.clipindexLayout.addWidget(self.cliplist)
        self.clipindexLayout.addWidget(self.runtimeLabel)

        self.videoLayout = QHBoxLayout()
        self.videoLayout.setContentsMargins(0, 0, 0, 0)
        self.videoLayout.addWidget(self.novideoWidget)
        self.videoLayout.addLayout(self.clipindexLayout)

        self.timeCounter = QLabel('00:00:00 / 00:00:00',
                                  autoFillBackground=True,
                                  alignment=Qt.AlignCenter,
                                  sizePolicy=QSizePolicy(
                                      QSizePolicy.Expanding,
                                      QSizePolicy.Fixed))
        self.timeCounter.setStyleSheet(
            'color:#FFF; background:#000; font-family:Droid Sans Mono; font-size:10.5pt; padding:4px;'
        )

        videoplayerLayout = QVBoxLayout(spacing=0)
        videoplayerLayout.setContentsMargins(0, 0, 0, 0)
        videoplayerLayout.addWidget(self.videoWidget)
        videoplayerLayout.addWidget(self.timeCounter)

        self.videoplayerWidget = QWidget(self, visible=False)
        self.videoplayerWidget.setLayout(videoplayerLayout)

        self.muteButton = QPushButton(icon=self.unmuteIcon,
                                      flat=True,
                                      toolTip='Mute',
                                      statusTip='Toggle audio mute',
                                      iconSize=QSize(16, 16),
                                      cursor=Qt.PointingHandCursor,
                                      clicked=self.muteAudio)

        self.volumeSlider = QSlider(Qt.Horizontal,
                                    toolTip='Volume',
                                    statusTip='Adjust volume level',
                                    cursor=Qt.PointingHandCursor,
                                    value=50,
                                    minimum=0,
                                    maximum=100,
                                    sliderMoved=self.setVolume)

        self.menuButton = QPushButton(
            icon=self.menuIcon,
            flat=True,
            toolTip='Menu',
            statusTip='Media + application information',
            iconSize=QSize(24, 24),
            cursor=Qt.PointingHandCursor)
        self.menuButton.setMenu(self.appMenu)

        toolbarLayout = QHBoxLayout()
        toolbarLayout.addWidget(self.toolbar)
        toolbarLayout.setContentsMargins(2, 2, 2, 2)

        toolbarGroup = QGroupBox()
        toolbarGroup.setFlat(False)
        toolbarGroup.setCursor(Qt.PointingHandCursor)
        toolbarGroup.setLayout(toolbarLayout)

        toolbarGroup.setStyleSheet(
            '''QGroupBox { background-color:rgba(0, 0, 0, 0.1);
            border:1px inset #888; border-radius:5px; }''')

        controlsLayout = QHBoxLayout(spacing=0)
        controlsLayout.addStretch(1)
        controlsLayout.addWidget(toolbarGroup)
        controlsLayout.addStretch(1)
        controlsLayout.addWidget(self.muteButton)
        controlsLayout.addWidget(self.volumeSlider)
        controlsLayout.addSpacing(1)
        controlsLayout.addWidget(self.menuButton)

        layout = QVBoxLayout()
        layout.setContentsMargins(10, 10, 10, 4)
        layout.addLayout(self.videoLayout)
        layout.addWidget(self.seekSlider)
        layout.addSpacing(5)
        layout.addLayout(controlsLayout)
        layout.addSpacing(2)

        self.setLayout(layout)

        self.mediaPlayer.setVideoOutput(self.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 initNoVideo(self) -> None:
        novideoImage = QLabel(
            alignment=Qt.AlignCenter,
            autoFillBackground=False,
            pixmap=QPixmap(MainWindow.get_path('images/novideo.png'), 'PNG'),
            sizePolicy=QSizePolicy(QSizePolicy.Expanding,
                                   QSizePolicy.MinimumExpanding))
        novideoImage.setBackgroundRole(QPalette.Dark)
        novideoImage.setContentsMargins(0, 20, 0, 20)
        self.novideoLabel = QLabel(alignment=Qt.AlignCenter,
                                   autoFillBackground=True,
                                   sizePolicy=QSizePolicy(
                                       QSizePolicy.Expanding,
                                       QSizePolicy.Minimum))
        self.novideoLabel.setBackgroundRole(QPalette.Dark)
        self.novideoLabel.setContentsMargins(0, 20, 15, 60)
        novideoLayout = QVBoxLayout(spacing=0)
        novideoLayout.addWidget(novideoImage)
        novideoLayout.addWidget(self.novideoLabel, alignment=Qt.AlignTop)
        self.novideoMovie = QMovie(
            MainWindow.get_path('images/novideotext.gif'))
        self.novideoMovie.frameChanged.connect(self.setNoVideoText)
        self.novideoMovie.start()
        self.novideoWidget.setBackgroundRole(QPalette.Dark)
        self.novideoWidget.setLayout(novideoLayout)

    def initIcons(self) -> None:
        self.appIcon = QIcon(MainWindow.get_path('images/vidcutter.png'))
        self.openIcon = icon('fa.film',
                             color='#444',
                             color_active='#6A4572',
                             scale_factor=0.9)
        self.playIcon = icon('fa.play-circle-o',
                             color='#444',
                             color_active='#6A4572',
                             scale_factor=1.1)
        self.pauseIcon = icon('fa.pause-circle-o',
                              color='#444',
                              color_active='#6A4572',
                              scale_factor=1.1)
        self.cutStartIcon = icon('fa.scissors',
                                 scale_factor=1.15,
                                 color='#444',
                                 color_active='#6A4572')
        endicon_normal = icon('fa.scissors', scale_factor=1.15,
                              color='#444').pixmap(QSize(36, 36)).toImage()
        endicon_active = icon('fa.scissors',
                              scale_factor=1.15,
                              color='#6A4572').pixmap(QSize(36, 36)).toImage()
        self.cutEndIcon = QIcon()
        self.cutEndIcon.addPixmap(
            QPixmap.fromImage(
                endicon_normal.mirrored(horizontal=True, vertical=False)),
            QIcon.Normal, QIcon.Off)
        self.cutEndIcon.addPixmap(
            QPixmap.fromImage(
                endicon_active.mirrored(horizontal=True, vertical=False)),
            QIcon.Active, QIcon.Off)
        self.saveIcon = icon('fa.video-camera',
                             color='#6A4572',
                             color_active='#6A4572')
        self.muteIcon = QIcon(MainWindow.get_path('images/muted.png'))
        self.unmuteIcon = QIcon(MainWindow.get_path('images/unmuted.png'))
        self.upIcon = icon('ei.caret-up', color='#444')
        self.downIcon = icon('ei.caret-down', color='#444')
        self.removeIcon = icon('ei.remove', color='#B41D1D')
        self.removeAllIcon = icon('ei.trash', color='#B41D1D')
        self.successIcon = QIcon(MainWindow.get_path('images/success.png'))
        self.menuIcon = icon('fa.cog', color='#444', scale_factor=1.15)
        self.completePlayIcon = icon('fa.play', color='#444')
        self.completeOpenIcon = icon('fa.folder-open', color='#444')
        self.completeRestartIcon = icon('fa.retweet', color='#444')
        self.completeExitIcon = icon('fa.sign-out', color='#444')
        self.mediaInfoIcon = icon('fa.info-circle', color='#444')
        self.updateCheckIcon = icon('fa.cloud-download', color='#444')

    def initActions(self) -> None:
        self.openAction = QAction(self.openIcon,
                                  'Open',
                                  self,
                                  statusTip='Open media file',
                                  triggered=self.openMedia)
        self.playAction = QAction(self.playIcon,
                                  'Play',
                                  self,
                                  statusTip='Play media file',
                                  triggered=self.playMedia,
                                  enabled=False)
        self.cutStartAction = QAction(self.cutStartIcon,
                                      ' Start',
                                      self,
                                      toolTip='Start',
                                      statusTip='Set clip start marker',
                                      triggered=self.setCutStart,
                                      enabled=False)
        self.cutEndAction = QAction(self.cutEndIcon,
                                    ' End',
                                    self,
                                    toolTip='End',
                                    statusTip='Set clip end marker',
                                    triggered=self.setCutEnd,
                                    enabled=False)
        self.saveAction = QAction(self.saveIcon,
                                  'Save',
                                  self,
                                  statusTip='Save clips to a new video file',
                                  triggered=self.cutVideo,
                                  enabled=False)
        self.moveItemUpAction = QAction(
            self.upIcon,
            'Move up',
            self,
            statusTip='Move clip position up in list',
            triggered=self.moveItemUp,
            enabled=False)
        self.moveItemDownAction = QAction(
            self.downIcon,
            'Move down',
            self,
            statusTip='Move clip position down in list',
            triggered=self.moveItemDown,
            enabled=False)
        self.removeItemAction = QAction(
            self.removeIcon,
            'Remove clip',
            self,
            statusTip='Remove selected clip from list',
            triggered=self.removeItem,
            enabled=False)
        self.removeAllAction = QAction(self.removeAllIcon,
                                       'Clear list',
                                       self,
                                       statusTip='Clear all clips from list',
                                       triggered=self.clearList,
                                       enabled=False)
        self.mediaInfoAction = QAction(
            self.mediaInfoIcon,
            'Media information',
            self,
            statusTip='View current media file information',
            triggered=self.mediaInfo,
            enabled=False)
        self.updateCheckAction = QAction(
            self.updateCheckIcon,
            'Check for updates...',
            self,
            statusTip='Check for application updates',
            triggered=self.updateCheck)
        self.aboutQtAction = QAction('About Qt',
                                     self,
                                     statusTip='About Qt',
                                     triggered=qApp.aboutQt)
        self.aboutAction = QAction('About %s' % qApp.applicationName(),
                                   self,
                                   statusTip='Credits and licensing',
                                   triggered=self.aboutInfo)

    def initToolbar(self) -> None:
        self.toolbar.addAction(self.openAction)
        self.toolbar.addAction(self.playAction)
        self.toolbar.addAction(self.cutStartAction)
        self.toolbar.addAction(self.cutEndAction)
        self.toolbar.addAction(self.saveAction)

    def initMenus(self) -> None:
        self.appMenu.addAction(self.mediaInfoAction)
        self.appMenu.addAction(self.updateCheckAction)
        self.appMenu.addSeparator()
        self.appMenu.addAction(self.aboutQtAction)
        self.appMenu.addAction(self.aboutAction)

        self.cliplistMenu.addAction(self.moveItemUpAction)
        self.cliplistMenu.addAction(self.moveItemDownAction)
        self.cliplistMenu.addSeparator()
        self.cliplistMenu.addAction(self.removeItemAction)
        self.cliplistMenu.addAction(self.removeAllAction)

    @staticmethod
    def getSpacer() -> QWidget:
        spacer = QWidget()
        spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred)
        return spacer

    def setRunningTime(self, runtime: str) -> None:
        self.runtimeLabel.setText('<div align="right">%s</div>' % runtime)

    @pyqtSlot(int)
    def setNoVideoText(self) -> None:
        self.novideoLabel.setPixmap(self.novideoMovie.currentPixmap())

    def itemMenu(self, pos: QPoint) -> None:
        globalPos = self.cliplist.mapToGlobal(pos)
        self.moveItemUpAction.setEnabled(False)
        self.moveItemDownAction.setEnabled(False)
        self.removeItemAction.setEnabled(False)
        self.removeAllAction.setEnabled(False)
        index = self.cliplist.currentRow()
        if index != -1:
            if not self.inCut:
                if index > 0:
                    self.moveItemUpAction.setEnabled(True)
                if index < self.cliplist.count() - 1:
                    self.moveItemDownAction.setEnabled(True)
            if self.cliplist.count() > 0:
                self.removeItemAction.setEnabled(True)
        if self.cliplist.count() > 0:
            self.removeAllAction.setEnabled(True)
        self.cliplistMenu.exec_(globalPos)

    def moveItemUp(self) -> None:
        index = self.cliplist.currentRow()
        tmpItem = self.clipTimes[index]
        del self.clipTimes[index]
        self.clipTimes.insert(index - 1, tmpItem)
        self.renderTimes()

    def moveItemDown(self) -> None:
        index = self.cliplist.currentRow()
        tmpItem = self.clipTimes[index]
        del self.clipTimes[index]
        self.clipTimes.insert(index + 1, tmpItem)
        self.renderTimes()

    def removeItem(self) -> None:
        index = self.cliplist.currentRow()
        del self.clipTimes[index]
        if self.inCut and index == self.cliplist.count() - 1:
            self.inCut = False
            self.initMediaControls()
        self.renderTimes()

    def clearList(self) -> None:
        self.clipTimes.clear()
        self.cliplist.clear()
        self.inCut = False
        self.renderTimes()
        self.initMediaControls()

    def mediaInfo(self) -> None:
        if self.mediaPlayer.isMetaDataAvailable():
            content = '<table cellpadding="4">'
            for key in self.mediaPlayer.availableMetaData():
                val = self.mediaPlayer.metaData(key)
                if type(val) is QSize:
                    val = '%s x %s' % (val.width(), val.height())
                content += '<tr><td align="right"><b>%s:</b></td><td>%s</td></tr>\n' % (
                    key, val)
            content += '</table>'
            mbox = QMessageBox(windowTitle='Media Information',
                               windowIcon=self.parent.windowIcon(),
                               textFormat=Qt.RichText)
            mbox.setText('<b>%s</b>' % os.path.basename(
                self.mediaPlayer.currentMedia().canonicalUrl().toLocalFile()))
            mbox.setInformativeText(content)
            mbox.exec_()
        else:
            QMessageBox.critical(
                self.parent, 'MEDIA ERROR',
                '<h3>Could not probe media file.</h3>' +
                '<p>An error occurred while analyzing the media file for its metadata details.'
                +
                '<br/><br/><b>This DOES NOT mean there is a problem with the file and you should '
                + 'be able to continue using it.</b></p>')

    def aboutInfo(self) -> None:
        about_html = '''<style>
    a { color:#441d4e; text-decoration:none; font-weight:bold; }
    a:hover { text-decoration:underline; }
</style>
<div style="min-width:650px;">
<p style="font-size:26pt; font-weight:bold; color:#6A4572;">%s</p>
<p>
    <span style="font-size:13pt;"><b>Version: %s</b></span>
    <span style="font-size:10pt;position:relative;left:5px;">( %s )</span>
</p>
<p style="font-size:13px;">
    Copyright &copy; 2016 <a href="mailto:[email protected]">Pete Alexandrou</a>
    <br/>
    Website: <a href="%s">%s</a>
</p>
<p style="font-size:13px;">
    Thanks to the folks behind the <b>Qt</b>, <b>PyQt</b> and <b>FFmpeg</b>
    projects for all their hard and much appreciated work.
</p>
<p style="font-size:11px;">
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
    as published by the Free Software Foundation; either version 2
    of the License, or (at your option) any later version.
</p>
<p style="font-size:11px;">
    This software uses libraries from the <a href="https://www.ffmpeg.org">FFmpeg</a> project under the
    <a href="https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html">LGPLv2.1</a>
</p></div>''' % (qApp.applicationName(), qApp.applicationVersion(),
                 platform.architecture()[0], qApp.organizationDomain(),
                 qApp.organizationDomain())
        QMessageBox.about(self.parent, 'About %s' % qApp.applicationName(),
                          about_html)

    def openMedia(self) -> None:
        filename, _ = QFileDialog.getOpenFileName(self.parent,
                                                  caption='Select video',
                                                  directory=QDir.homePath())
        if filename != '':
            self.loadFile(filename)

    def loadFile(self, filename: str) -> None:
        self.movieFilename = filename
        if not os.path.exists(filename):
            return
        self.mediaPlayer.setMedia(QMediaContent(QUrl.fromLocalFile(filename)))
        self.initMediaControls(True)
        self.cliplist.clear()
        self.clipTimes = []
        self.parent.setWindowTitle(
            '%s - %s' % (qApp.applicationName(), os.path.basename(filename)))
        if not self.movieLoaded:
            self.videoLayout.replaceWidget(self.novideoWidget,
                                           self.videoplayerWidget)
            self.novideoMovie.stop()
            self.novideoMovie.deleteLater()
            self.novideoWidget.deleteLater()
            self.videoplayerWidget.show()
            self.videoWidget.show()
            self.movieLoaded = True
        if self.mediaPlayer.isVideoAvailable():
            self.mediaPlayer.setPosition(1)
        self.mediaPlayer.play()
        self.mediaPlayer.pause()

    def playMedia(self) -> None:
        if self.mediaPlayer.state() == QMediaPlayer.PlayingState:
            self.mediaPlayer.pause()
            self.playAction.setText('Play')
        else:
            self.mediaPlayer.play()
            self.playAction.setText('Pause')

    def initMediaControls(self, flag: bool = True) -> None:
        self.playAction.setEnabled(flag)
        self.saveAction.setEnabled(False)
        self.cutStartAction.setEnabled(flag)
        self.cutEndAction.setEnabled(False)
        self.mediaInfoAction.setEnabled(flag)
        if flag:
            self.seekSlider.setRestrictValue(0)

    def setPosition(self, position: int) -> None:
        self.mediaPlayer.setPosition(position)

    def positionChanged(self, progress: int) -> None:
        self.seekSlider.setValue(progress)
        currentTime = self.deltaToQTime(progress)
        totalTime = self.deltaToQTime(self.mediaPlayer.duration())
        self.timeCounter.setText('%s / %s' % (currentTime.toString(
            self.timeformat), totalTime.toString(self.timeformat)))

    @pyqtSlot()
    def mediaStateChanged(self) -> None:
        if self.mediaPlayer.state() == QMediaPlayer.PlayingState:
            self.playAction.setIcon(self.pauseIcon)
        else:
            self.playAction.setIcon(self.playIcon)

    def durationChanged(self, duration: int) -> None:
        self.seekSlider.setRange(0, duration)

    def muteAudio(self) -> None:
        if self.mediaPlayer.isMuted():
            self.muteButton.setIcon(self.unmuteIcon)
            self.muteButton.setToolTip('Mute')
        else:
            self.muteButton.setIcon(self.muteIcon)
            self.muteButton.setToolTip('Unmute')
        self.mediaPlayer.setMuted(not self.mediaPlayer.isMuted())

    def setVolume(self, volume: int) -> None:
        self.mediaPlayer.setVolume(volume)

    def toggleFullscreen(self) -> None:
        self.videoWidget.setFullScreen(not self.videoWidget.isFullScreen())

    def setCutStart(self) -> None:
        self.clipTimes.append([
            self.deltaToQTime(self.mediaPlayer.position()), '',
            self.captureImage()
        ])
        self.cutStartAction.setDisabled(True)
        self.cutEndAction.setEnabled(True)
        self.seekSlider.setRestrictValue(self.seekSlider.value(), True)
        self.inCut = True
        self.renderTimes()

    def setCutEnd(self) -> None:
        item = self.clipTimes[len(self.clipTimes) - 1]
        selected = self.deltaToQTime(self.mediaPlayer.position())
        if selected.__lt__(item[0]):
            QMessageBox.critical(
                self.parent, 'Invalid END Time',
                'The clip end time must come AFTER it\'s start time. Please try again.'
            )
            return
        item[1] = selected
        self.cutStartAction.setEnabled(True)
        self.cutEndAction.setDisabled(True)
        self.seekSlider.setRestrictValue(0, False)
        self.inCut = False
        self.renderTimes()

    @pyqtSlot(QModelIndex, int, int, QModelIndex, int)
    def syncClipList(self, parent: QModelIndex, start: int, end: int,
                     destination: QModelIndex, row: int) -> None:
        if start < row:
            index = row - 1
        else:
            index = row
        clip = self.clipTimes.pop(start)
        self.clipTimes.insert(index, clip)

    def renderTimes(self) -> None:
        self.cliplist.clear()
        if len(self.clipTimes) > 4:
            self.cliplist.setFixedWidth(200)
        else:
            self.cliplist.setFixedWidth(185)
        self.totalRuntime = 0
        for item in self.clipTimes:
            endItem = ''
            if type(item[1]) is QTime:
                endItem = item[1].toString(self.timeformat)
                self.totalRuntime += item[0].msecsTo(item[1])
            listitem = QListWidgetItem()
            listitem.setTextAlignment(Qt.AlignVCenter)
            if type(item[2]) is QPixmap:
                listitem.setIcon(QIcon(item[2]))
            self.cliplist.addItem(listitem)
            marker = QLabel(
                '''<style>b { font-size:7pt; } p { margin:2px 5px; }</style>
                            <p><b>START</b><br/>%s<br/><b>END</b><br/>%s</p>'''
                % (item[0].toString(self.timeformat), endItem))
            marker.setStyleSheet('border:none;')
            self.cliplist.setItemWidget(listitem, marker)
            listitem.setFlags(Qt.ItemIsSelectable | Qt.ItemIsDragEnabled
                              | Qt.ItemIsEnabled)
        if len(self.clipTimes) and not self.inCut:
            self.saveAction.setEnabled(True)
        if self.inCut or len(self.clipTimes) == 0 or not type(
                self.clipTimes[0][1]) is QTime:
            self.saveAction.setEnabled(False)
        self.setRunningTime(
            self.deltaToQTime(self.totalRuntime).toString(self.timeformat))

    @staticmethod
    def deltaToQTime(millisecs: int) -> QTime:
        secs = millisecs / 1000
        return QTime((secs / 3600) % 60, (secs / 60) % 60, secs % 60,
                     (secs * 1000) % 1000)

    def captureImage(self) -> QPixmap:
        frametime = self.deltaToQTime(self.mediaPlayer.position()).toString(
            self.timeformat)
        inputfile = self.mediaPlayer.currentMedia().canonicalUrl().toLocalFile(
        )
        imagecap = self.videoService.capture(inputfile, frametime)
        if type(imagecap) is QPixmap:
            return imagecap

    def cutVideo(self) -> bool:
        clips = len(self.clipTimes)
        filename, filelist = '', []
        source = self.mediaPlayer.currentMedia().canonicalUrl().toLocalFile()
        _, sourceext = os.path.splitext(source)
        if clips > 0:
            self.finalFilename, _ = QFileDialog.getSaveFileName(
                self.parent, 'Save video', source,
                'Video files (*%s)' % sourceext)
            if self.finalFilename == '':
                return False
            qApp.setOverrideCursor(Qt.BusyCursor)
            self.saveAction.setDisabled(True)
            self.showProgress(clips)
            file, ext = os.path.splitext(self.finalFilename)
            index = 1
            self.progress.setLabelText('Cutting media files...')
            qApp.processEvents()
            for clip in self.clipTimes:
                duration = self.deltaToQTime(clip[0].msecsTo(
                    clip[1])).toString(self.timeformat)
                filename = '%s_%s%s' % (file, '{0:0>2}'.format(index), ext)
                filelist.append(filename)
                self.videoService.cut(source, filename,
                                      clip[0].toString(self.timeformat),
                                      duration)
                index += 1
            if len(filelist) > 1:
                self.joinVideos(filelist, self.finalFilename)
            else:
                QFile.remove(self.finalFilename)
                QFile.rename(filename, self.finalFilename)
            self.progress.setLabelText('Complete...')
            self.progress.setValue(100)
            qApp.processEvents()
            self.progress.close()
            self.progress.deleteLater()
            qApp.restoreOverrideCursor()
            self.complete()
            return True
        return False

    def joinVideos(self, joinlist: list, filename: str) -> None:
        listfile = os.path.normpath(
            os.path.join(os.path.dirname(joinlist[0]), '.vidcutter.list'))
        fobj = open(listfile, 'w')
        for file in joinlist:
            fobj.write('file \'%s\'\n' % file.replace("'", "\\'"))
        fobj.close()
        self.videoService.join(listfile, filename)
        QFile.remove(listfile)
        for file in joinlist:
            if os.path.isfile(file):
                QFile.remove(file)

    def updateCheck(self) -> None:
        self.updater = Updater()
        self.updater.updateAvailable.connect(self.updateHandler)
        self.updater.start()

    def updateHandler(self, updateExists: bool, version: str = None):
        if updateExists:
            if Updater.notify_update(self, version) == QMessageBox.AcceptRole:
                self.updater.install_update(self)
        else:
            Updater.notify_no_update(self)

    def showProgress(self,
                     steps: int,
                     label: str = 'Analyzing media...') -> None:
        self.progress = QProgressDialog(label,
                                        None,
                                        0,
                                        steps,
                                        self.parent,
                                        windowModality=Qt.ApplicationModal,
                                        windowIcon=self.parent.windowIcon(),
                                        minimumDuration=0,
                                        minimumWidth=500)
        self.progress.show()
        for i in range(steps):
            self.progress.setValue(i)
            qApp.processEvents()
            time.sleep(1)

    def complete(self) -> None:
        info = QFileInfo(self.finalFilename)
        mbox = QMessageBox(windowTitle='VIDEO PROCESSING COMPLETE',
                           minimumWidth=500,
                           textFormat=Qt.RichText)
        mbox.setText(
            '''
    <style>
        table.info { margin:6px; padding:4px 15px; }
        td.label { font-weight:bold; font-size:10.5pt; text-align:right; }
        td.value { font-size:10.5pt; }
    </style>
    <table class="info" cellpadding="4" cellspacing="0">
        <tr>
            <td class="label"><b>File:</b></td>
            <td class="value" nowrap>%s</td>
        </tr>
        <tr>
            <td class="label"><b>Size:</b></td>
            <td class="value">%s</td>
        </tr>
        <tr>
            <td class="label"><b>Length:</b></td>
            <td class="value">%s</td>
        </tr>
    </table><br/>''' %
            (QDir.toNativeSeparators(
                self.finalFilename), self.sizeof_fmt(int(info.size())),
             self.deltaToQTime(self.totalRuntime).toString(self.timeformat)))
        play = mbox.addButton('Play', QMessageBox.AcceptRole)
        play.setIcon(self.completePlayIcon)
        play.clicked.connect(self.openResult)
        fileman = mbox.addButton('Open', QMessageBox.AcceptRole)
        fileman.setIcon(self.completeOpenIcon)
        fileman.clicked.connect(self.openFolder)
        end = mbox.addButton('Exit', QMessageBox.AcceptRole)
        end.setIcon(self.completeExitIcon)
        end.clicked.connect(self.close)
        new = mbox.addButton('Restart', QMessageBox.AcceptRole)
        new.setIcon(self.completeRestartIcon)
        new.clicked.connect(self.parent.restart)
        mbox.setDefaultButton(new)
        mbox.setEscapeButton(new)
        mbox.adjustSize()
        mbox.exec_()

    def sizeof_fmt(self, num: float, suffix: chr = 'B') -> str:
        for unit in ['', 'K', 'M', 'G', 'T', 'P', 'E', 'Z']:
            if abs(num) < 1024.0:
                return "%3.1f%s%s" % (num, unit, suffix)
            num /= 1024.0
        return "%.1f%s%s" % (num, 'Y', suffix)

    @pyqtSlot()
    def openFolder(self) -> None:
        self.openResult(pathonly=True)

    @pyqtSlot(bool)
    def openResult(self, pathonly: bool = False) -> None:
        self.parent.restart()
        if len(self.finalFilename) and os.path.exists(self.finalFilename):
            target = self.finalFilename if not pathonly else os.path.dirname(
                self.finalFilename)
            QDesktopServices.openUrl(QUrl.fromLocalFile(target))

    @pyqtSlot()
    def startNew(self) -> None:
        qApp.restoreOverrideCursor()
        self.clearList()
        self.seekSlider.setValue(0)
        self.seekSlider.setRange(0, 0)
        self.mediaPlayer.setMedia(QMediaContent())
        self.initNoVideo()
        self.videoLayout.replaceWidget(self.videoplayerWidget,
                                       self.novideoWidget)
        self.initMediaControls(False)
        self.parent.setWindowTitle('%s' % qApp.applicationName())

    def wheelEvent(self, event: QWheelEvent) -> None:
        if self.mediaPlayer.isVideoAvailable(
        ) or self.mediaPlayer.isAudioAvailable():
            if event.angleDelta().y() > 0:
                newval = self.seekSlider.value() - 1000
            else:
                newval = self.seekSlider.value() + 1000
            self.seekSlider.setValue(newval)
            self.seekSlider.setSliderPosition(newval)
            self.mediaPlayer.setPosition(newval)
        event.accept()

    def keyPressEvent(self, event: QKeyEvent) -> None:
        if self.mediaPlayer.isVideoAvailable(
        ) or self.mediaPlayer.isAudioAvailable():
            addtime = 0
            if event.key() == Qt.Key_Left:
                addtime = -1000
            elif event.key() == Qt.Key_PageUp or event.key() == Qt.Key_Up:
                addtime = -10000
            elif event.key() == Qt.Key_Right:
                addtime = 1000
            elif event.key() == Qt.Key_PageDown or event.key() == Qt.Key_Down:
                addtime = 10000
            elif event.key() == Qt.Key_Enter:
                self.toggleFullscreen()
            elif event.key(
            ) == Qt.Key_Escape and self.videoWidget.isFullScreen():
                self.videoWidget.setFullScreen(False)
            if addtime != 0:
                newval = self.seekSlider.value() + addtime
                self.seekSlider.setValue(newval)
                self.seekSlider.setSliderPosition(newval)
                self.mediaPlayer.setPosition(newval)
        event.accept()

    def mousePressEvent(self, event: QMouseEvent) -> None:
        if event.button() == Qt.BackButton and self.cutStartAction.isEnabled():
            self.setCutStart()
            event.accept()
        elif event.button(
        ) == Qt.ForwardButton and self.cutEndAction.isEnabled():
            self.setCutEnd()
            event.accept()
        else:
            super(VidCutter, self).mousePressEvent(event)

    @pyqtSlot(QMediaPlayer.Error)
    def handleError(self, error: QMediaPlayer.Error) -> None:
        qApp.restoreOverrideCursor()
        self.startNew()
        if error == QMediaPlayer.ResourceError:
            QMessageBox.critical(
                self.parent, 'INVALID MEDIA',
                'Invalid media file detected at:<br/><br/><b>%s</b><br/><br/>%s'
                % (self.movieFilename, self.mediaPlayer.errorString()))
        else:
            QMessageBox.critical(self.parent, 'ERROR NOTIFICATION',
                                 self.mediaPlayer.errorString())

    def closeEvent(self, event: QCloseEvent) -> None:
        self.parent.closeEvent(event)
Ejemplo n.º 15
0
class PlayerSound(QWidget):
    '''
    represente le lecteur de musique, permettant de mettre pause/play, changer de musique, etc.

    :param board: le tableau de bord du lecteur
    :type board: model.Board
    '''
    def __init__(self, board, parent=None):
        QWidget.__init__(self, parent)

        # hauteur du lecteur
        heightWindow = 125
        self.setMinimumHeight(heightWindow)
        self.setMaximumHeight(heightWindow)

        # images des bouttons
        self.iconPlay = QIcon(QPixmap("assets/play.png"))
        self.iconPause = QIcon(QPixmap("assets/pause.png"))
        iconNext = QIcon(QPixmap("assets/next.png"))
        iconPrecedent = QIcon(QPixmap("assets/precedent.png"))
        iconShuffle = QIcon(QPixmap("assets/shuffle.png"))
        iconReplay = QIcon(QPixmap("assets/replay.png"))
        self.iconSoundOn = QIcon(QPixmap("assets/soundOn.png"))
        self.iconSoundOff = QIcon(QPixmap("assets/soundOff.png"))
        iconConfig = QIcon(QPixmap("assets/config.png"))
        # taille des bouttons
        iconSize = QSize(50, 50)

        self.board = board
        self.isPlaying = False

        # lecteur Qt et musique en cours
        currentSong = self.board.getCurrentSong()
        self.player = QMediaPlayer()
        nameSong = ""
        nameAuthor = ""
        if currentSong:
            nameSong = currentSong.getName()
            nameAuthor = currentSong.getAuthor()
        self.songName = QLabel(nameSong)
        self.songAuthor = QLabel(nameAuthor)
        self.songName.setWordWrap(True)
        self.songName.setFixedWidth(310)
        self.songName.setProperty("class", "songName")
        self.songAuthor.setProperty("class", "author")
        self.player.mediaStatusChanged.connect(self.mediaFinished)
        self.player.positionChanged.connect(self.changeSliderPosition)

        # bouttons au dessus de la barre de progression de la lecture de la musique
        bShuffle = QPushButton()
        bShuffle.setToolTip("Melanger la liste d'attente")
        bShuffle.setFixedSize(iconSize)
        bShuffle.setIcon(iconShuffle)
        bShuffle.setIconSize(iconSize)
        bShuffle.clicked.connect(self.shuffle)
        bPrecedent = QPushButton()
        bPrecedent.setFixedSize(iconSize)
        bPrecedent.setIcon(iconPrecedent)
        bPrecedent.setIconSize(iconSize)
        bPrecedent.clicked.connect(self.precedentSong)
        self.bPlay = QPushButton()
        self.bPlay.setFixedSize(iconSize)
        self.bPlay.setIcon(self.iconPlay)
        self.bPlay.setIconSize(iconSize)
        self.bPlay.clicked.connect(self.play)
        bNext = QPushButton()
        bNext.setFixedSize(iconSize)
        bNext.setIcon(iconNext)
        bNext.setIconSize(iconSize)
        bNext.clicked.connect(self.nextSong)
        bReplay = QPushButton()
        bReplay.setToolTip("Rejouer")
        bReplay.setFixedSize(iconSize)
        bReplay.setIcon(iconReplay)
        bReplay.setIconSize(iconSize)
        bReplay.clicked.connect(self.replay)

        # barre de progression de la lecture de la musique en cours
        self.sliderSong = QSlider(Qt.Horizontal)
        self.sliderSong.setMinimumWidth(600)
        self.sliderSong.setMaximumWidth(600)
        self.labCurrentDuration = QLabel("0:00")
        self.labCurrentDuration.setProperty("class", "duration")
        self.volumeSlider = QSlider(Qt.Horizontal)
        self.labMaxDuration = QLabel("0:00")
        self.labMaxDuration.setProperty("class", "duration")

        # controles sur le son de la musique
        self.bMute = QPushButton()
        self.bMute.setIcon(self.iconSoundOn)
        self.bMute.setFixedSize(iconSize)
        self.bMute.setIconSize(iconSize)
        self.bMute.clicked.connect(self.mute)
        self.labelVolume = QLabel("100")
        self.labelVolume.setAlignment(Qt.AlignCenter)
        self.volumeSlider.setFixedWidth(250)
        self.volumeSlider.setValue(100)
        self.volumeSlider.valueChanged.connect(self.changeVolume)

        # boutton pour ouvrir la fenetre de parametres
        bParams = QPushButton()
        bParams.setToolTip("Parametres")
        bParams.setFixedSize(iconSize)
        bParams.setIcon(iconConfig)
        bParams.setIconSize(iconSize)
        bParams.clicked.connect(self.openParams)

        # position elements

        leftInfoSong = QVBoxLayout()
        leftInfoSong.addWidget(self.songName)
        leftInfoSong.addWidget(self.songAuthor)

        centerPlayer = QVBoxLayout()
        buttonsPlayer = QHBoxLayout()
        buttonsPlayer.addStretch()
        buttonsPlayer.addWidget(bShuffle)
        buttonsPlayer.addSpacing(8)
        buttonsPlayer.addWidget(bPrecedent)
        buttonsPlayer.addSpacing(8)
        buttonsPlayer.addWidget(self.bPlay)
        buttonsPlayer.addSpacing(8)
        buttonsPlayer.addWidget(bNext)
        buttonsPlayer.addSpacing(8)
        buttonsPlayer.addWidget(bReplay)
        buttonsPlayer.addStretch()
        centerPlayer.addLayout(buttonsPlayer)
        sliderWithTime = QHBoxLayout()
        sliderWithTime.addWidget(self.labCurrentDuration)
        sliderWithTime.addWidget(self.sliderSong)
        sliderWithTime.addWidget(self.labMaxDuration)
        centerPlayer.addLayout(sliderWithTime)

        rightVolumeParam = QVBoxLayout()
        sliderAndMuteLayout = QHBoxLayout()
        sliderAndMuteLayout.addWidget(self.bMute)
        sliderAndMuteLayout.addWidget(self.volumeSlider)
        rightVolumeParam.addLayout(sliderAndMuteLayout)
        otherButtonsZone = QHBoxLayout()
        otherButtonsZone.addStretch()
        otherButtonsZone.addWidget(bParams)
        otherButtonsZone.addStretch()
        rightVolumeParam.addLayout(otherButtonsZone)

        # positionnement global
        layout = QHBoxLayout()
        self.setLayout(layout)
        layout.addLayout(leftInfoSong)
        layout.addStretch()
        layout.addLayout(centerPlayer)
        layout.addStretch()
        layout.addLayout(rightVolumeParam)

    def mediaFinished(self, status):
        if status == QMediaPlayer.EndOfMedia:
            self.nextSong()

    def shuffle(self):
        self.board.shuffle(5)

    def replay(self):
        self.player.setPosition(0)
        self.sliderSong.setValue(0)
        self.update()

    def play(self):
        state = self.player.state()
        currentSong = self.board.getCurrentSong()
        if currentSong:
            if state == QMediaPlayer.PausedState or state == QMediaPlayer.StoppedState:
                if state == QMediaPlayer.StoppedState:
                    self.setSongInPlayer()
                self.player.play()
                self.bPlay.setIcon(self.iconPause)
                self.isPlaying = True
            else:
                self.player.pause()
                self.bPlay.setIcon(self.iconPlay)
                self.isPlaying = False

    def mute(self):
        isMuted = self.player.isMuted()
        self.player.setMuted(not isMuted)
        if isMuted:
            self.bMute.setIcon(self.iconSoundOn)
        else:
            self.bMute.setIcon(self.iconSoundOff)

    def nextSong(self):
        self.board.nextSong()
        self.player.stop()
        self.setSongInPlayer()
        if self.isPlaying:
            self.play()

    def precedentSong(self):
        state = self.player.state()
        stateStop = QMediaPlayer.StoppedState
        statePause = QMediaPlayer.PausedState
        playerStoped = state == stateStop or state == statePause
        if not playerStoped:
            self.player.stop()
        self.board.precedentSong()
        self.setSongInPlayer()
        if not playerStoped:
            self.player.play()

    def setSongInPlayer(self):
        ''' set la musique courante dans le lecteur Qt '''
        song = self.board.getCurrentSong()
        url = QUrl.fromLocalFile(song.getFullFilename())
        self.player.setMedia(QMediaContent(url))
        # set du temps maximum pour la barre de progression
        self.sliderSong.setMaximum(song.getDuration())
        self.labMaxDuration.setText(getStrDuration(song.getDuration()))

    def changeSliderPosition(self, position):
        self.sliderSong.setValue(position)
        self.update()

    def changeVolume(self):
        valueVolume = self.volumeSlider.value()
        self.player.setVolume(valueVolume)

    def openParams(self):
        w = QMainWindow(self)
        w.setCentralWidget(ConfigWindow(self.board, w))
        w.setGeometry(650, 500, 600, 150)
        w.setStyleSheet(open("src/gui/styleSheet/styleParam.qss", "r").read())
        w.setWindowTitle("Parametres")
        w.show()

    def update(self):
        song = self.board.getCurrentSong()
        if song:
            self.songName.setText(song.getName())
            self.songAuthor.setText(song.getAuthor())
        else:
            self.songName.setText("")
            self.songAuthor.setText("")
            self.player.stop()
            self.bPlay.setIcon(self.iconPlay)
            self.isPlaying = False
        self.labCurrentDuration.setText(getStrDuration(self.player.position()))
Ejemplo n.º 16
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.º 17
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] =="vut":
            self.projectfile = projectfile
        else:
            self.projectfile = projectfile +'.vut'
        self.videofile = None
        self.GPXfile = None
        self.GPXList = None
        self.fps = None
        self.RealFps = None
        self.DB = None
        self.DEM = None
        self.Image = None
        self.HFilmSize = None
        self.VFilmSize = None
        self.FocalLenght = None
        self.GPXMode = 2
        self.Course = 0
        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)
        self.toolButton_4.clicked.connect(self.Setup3DParameterer)

        if os.name == 'nt':
            self.toolButton_4.setEnabled(False)

    def Setup3DParameterer(self):
        treDOptions = Setup3D(QgsProject)
        a = treDOptions.exec_()
        if a == 1:
            self.DEM = treDOptions.DEM
            self.Image = treDOptions.Image
            self.HFilmSize = treDOptions.HFilmSize
            self.VFilmSize = treDOptions.VFilmSize
            self.FocalLenght = treDOptions.FocalLenght
            self.GPXMode = treDOptions.GPXMODE
            if self.GPXMode == 1:
                self.HeadingOffset = treDOptions.HeadingOffset
                self.PitchOffset = treDOptions.PitchOffset
                self.RollOffset = treDOptions.RollOffset

    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.checkBox.isChecked():
            PixelConversion = str(1)
        else:
            PixelConversion = str(0)

        if self.DB == None:
            outputFile.write('Video UAV Tracker Project v0.2 DO NOT MODIFY'+
                             '\nVideo file location = ' +self.videofile+
                             '\nVideo start at msecond: '+
                              str(self.player.position())+
                              ' #fps = '+str(self.RealFps)+' '+str(self.VideoWidth)+' '+str(self.VideoHeight)+' '+PixelConversion+
                              '\nDB = None'+
                              '\n3D = ' + str(self.DEM) + ',' + str(self.Image) + ',' + str(self.HFilmSize) + ',' + str(self.VFilmSize) + ',' + str(self.FocalLenght) +','+str(self.Course)+
                              '\n'+'Latitude # Longitude # Ele # Speed (m/s) # Course # Time  \n')
        else:
            outputFile.write('Video UAV Tracker Project v0.2 DO NOT MODIFY'+
                             '\nVideo file location = ' +self.videofile+
                             '\nVideo start at msecond: '+
                              str(self.player.position())+
                              ' #fps = '+str(self.RealFps)+' '+str(self.VideoWidth)+' '+str(self.VideoHeight)+' '+PixelConversion+
                              '\nDB = '+str(self.DB.dataProvider().dataSourceUri().split('|')[0])+
                              '\n3D = '+str(self.DEM)+','+str(self.Image)+','+str(self.HFilmSize)+','+str(self.VFilmSize)+','+str(self.FocalLenght)+','+str(self.Course)+
                              '\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
                if self.Course == 1:
                    Course = float(x[1][4])
                    Pitch = float(x[1][5])
                    Roll = float(x[1][6])
                else:
                    Course = GeodesicCalcolus['azi2']
                    if Course < 0:
                        Course += 360
                    Pitch = 0
                    Roll = 0
                if self.GPXMode == 1:      # correct value with fixed offset
                    Course = Course + self.HeadingOffset
                    if Course > 360:
                        Course = Course -360
                    elif Course < 0:
                        Course += 360
                    Pitch = Pitch + self.PitchOffset
                    if Pitch < -180:
                        Pitch = 360 - abs(Pitch)
                    elif Pitch > 180:
                        Pitch = -(360-Pitch)
                    Roll = Roll + self.RollOffset
                    if Roll < -180:
                        Roll = 360 - abs(Roll)
                    elif Roll > 180:
                        Roll = -(360-Roll)

                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
                if self.Course == 1:
                    Course = float(x[1][4])
                    Pitch = float(x[1][5])
                    Roll = float(x[1][6])
                else:
                    Course = GeodesicCalcolus['azi2']
                    if Course < 0:
                        Course += 360
                    Pitch = 0
                    Roll = 0
                if self.GPXMode == 1:      # correct value with fixed offset
                    Course = Course + self.HeadingOffset
                    if Course > 360:
                        Course = Course -360
                    elif Course < 0:
                        Course += 360
                    Pitch = Pitch + self.PitchOffset
                    if Pitch < -180:
                        Pitch = 360 - abs(Pitch)
                    elif Pitch > 180:
                        Pitch = -(360-Pitch)
                    Roll = Roll + self.RollOffset
                    if Roll < -180:
                        Roll = 360 - abs(Roll)
                    elif Roll > 180:
                        Roll = -(360-Roll)

                Ele = x[1][2]
                Time = x[1][3]
                Counter = Counter + 1  
            outputFile.write(str(ActualLatitude)+' '+str(ActualLongitude)+
                             ' '+str(Ele)+' '+str(Speed)+' '+str(Course)+
                             ' '+str(Pitch)+' '+str(Roll)+' '+str(Time)+'\n')
        outputFile.close() 
        self.Main.LoadProjFromNew(self.projectfile)
        self.close()
         
    def SelectVideoGPX(self):
        if os.name == 'nt':
            ffmpeg = os.path.dirname(__file__)+'/FFMPEG/ffprobe.exe'
            versione = 'ffprobe.exe'
        else:
            ffmpeg = os.path.dirname(__file__)+'/FFMPEG/./ffprobe'
            versione = 'ffprobe'
        if os.path.exists(ffmpeg):
            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.Course = 0
                    self.ParseGpx(self.GPXfile)
                    self.LoadVideo(self.videofile)
                    self.replayPosition_label.setText( "-:- / -:-")
        else:
            ret = QMessageBox.warning(self, "Warning", 'missing ffprobe binaries, please download it from https://github.com/sagost/Video_UAV_Tracker-3D/tree/master/Video_UAV_Tracker/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,'Course':0,'Pitch':0,'Roll':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:-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:
                                        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:
                                            Error = 1
                                            FormatoErrore = str(x)
                elif x.find('<course>')==0:
                    dict['Course'] = float(x[8:-9])
                    self.Course = 1
                elif x.find('<yaw>') == 0:
                    dict['Course'] = float(x[5:-6])
                    self.Course = 1
                elif x.find('<pitch>') == 0:
                    dict['Pitch'] = float(x[7:-8])
                elif x.find('<roll>') == 0:
                    dict['Roll'] = float(x[6:-7])


            if dict['Time'] != Timestamp:
                if self.Course == 1:
                    Point = [dict['Lat'], dict['Lon'], dict['Ele'], dict['Time'],dict['Course'],dict['Pitch'],dict['Roll']]
                else:
                    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):
        
        filepath2 = '"'+filepath+'"'
        if os.name == 'nt':
            ffmpeg = '"'+os.path.dirname(__file__)[0:-18]+'/Video_UAV_Tracker/FFMPEG/ffprobe.exe'+'"'
        else:
            ffmpeg = os.path.dirname(__file__)+'/FFMPEG/./ffprobe'

        p = os.popen(ffmpeg +  ' -v error -show_format -show_streams '+filepath2)
        lines = p.readlines()
        for l in lines:
            l = l.strip()
            if str(l).startswith("width"):
                self.VideoWidth = str(l).split('=')[1]
            elif str(l).startswith("height"):
                self.VideoHeight = str(l).split('=')[1]
            elif str(l).startswith("r_frame_rate"):
               if str(l).split('=')[1] != '0/0'
                    fps = float(str(l).split('=')[1].split('/')[0] ) / float(str(l).split('=')[1].split('/')[1] )
                    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+round(self.fps))
    
    def BackwardFrame(self):
        position = self.player.position()
        self.player.setPosition(position-round(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.º 18
0
class MediaPlayer(QWidget):

    # 初始化
    def __init__(self):
        super(MediaPlayer, self).__init__()
        self.setWindowTitle('播放器')
        # 先注册一个媒体播放器
        self.player = QMediaPlayer(self)
        # 注册其他控件
        self.volume_slider = QSlider(self)
        self.volume_save = 0
        self.player.setVolume(36)
        # 进度条
        self.progress_slider = QSlider(self)
        self.time_stamp = QLabel(self)
        # 按钮(PushButton)有,播放(暂停) 上一首,下一首 ,播放模式
        self.preview_btn = QPushButton(self)
        # 播放按钮要切换播放与暂停
        self.play_pause_btn = QPushButton(self)
        self.next_btn = QPushButton(self)
        self.play_mode = QPushButton()
        self.get_music = QPushButton('云音乐')
        self.sound_btn = QPushButton(self)

        # 播放列表
        self.mediaList = QMediaPlaylist(self)
        self.play_list = QListWidget(self)

        self.songs_list = []
        self.songs_formats = ['mp3', 'm4a', 'flac', 'wav', 'ogg']

        # 布局注册
        self.h1_layout = QHBoxLayout()
        self.h2_layout = QHBoxLayout()
        self.all_v_layout = QVBoxLayout()

        self.widget_init()
        self.layout_init()
        self.signal_init()
        self.center()

    '''控件初始化'''
    def widget_init(self):

        self.time_stamp.setText('--/--')
        self.volume_slider.setRange(0, 100)
        self.volume_slider.setValue(36)
        self.volume_slider.setOrientation(Qt.Horizontal)
        self.progress_slider.setEnabled(False)
        self.progress_slider.setOrientation(Qt.Horizontal)
        self.sound_btn.setIcon(QIcon('../icon_font/sound_on.png'))
        self.next_btn.setIcon(QIcon(r'..\icon\next.png'))
        self.play_pause_btn.setIcon(QIcon(r'..\icon\play.png'))
        self.preview_btn.setIcon(QIcon(r'..\icon\prev.png'))
        self.play_mode.setIcon(QIcon('../icon_font/list_down.png'))
        self.sound_btn.setIcon(QIcon(r'..\icon_font\sound_on.png'))

        self.player.setPlaylist(self.mediaList)
        self.mediaList.setPlaybackMode(QMediaPlaylist.Sequential)


    # 布局初始化
    def layout_init(self):
        self.h1_layout.addWidget(self.progress_slider)  # 5
        self.h1_layout.addWidget(self.time_stamp)
        self.h2_layout.addWidget(self.preview_btn)
        self.h2_layout.addWidget(self.play_pause_btn)
        self.h2_layout.addWidget(self.next_btn)
        self.h2_layout.addWidget(self.sound_btn)
        self.h2_layout.addWidget(self.volume_slider)
        self.h2_layout.addWidget(self.play_mode)
        self.h2_layout.addWidget(self.get_music)

        self.all_v_layout.addLayout(self.h1_layout)
        self.all_v_layout.addWidget(self.play_list)
        self.all_v_layout.addLayout(self.h2_layout)

        self.all_v_layout.setSizeConstraint(QVBoxLayout.SetFixedSize)  # 6

        self.setLayout(self.all_v_layout)

    # 创建信号函数,连接槽函数
    def signal_init(self):
        #
        self.preview_btn.clicked.connect(lambda: self.slot_func(self.preview_btn))
        self.play_pause_btn.clicked.connect(lambda: self.slot_func(self.play_pause_btn))
        self.next_btn.clicked.connect(lambda: self.slot_func(self.next_btn))
        self.play_mode.clicked.connect(lambda: self.slot_func(self.play_mode))
        self.sound_btn.clicked.connect(lambda: self.slot_func(self.sound_btn))
        # 获取云音乐函数
        self.get_music.clicked.connect(self.get_music_func)
        # 播放器音量控制
        self.volume_slider.valueChanged.connect(self.volume_slider_func)
        self.play_list.doubleClicked.connect(self.play_list_func)
        self.player.durationChanged.connect(self.get_progress_func)
        self.player.positionChanged.connect(self.get_position_func)
        self.progress_slider.sliderMoved.connect(self.update_position_func)

    # 建立槽函数
    def slot_func(self, btn):

        if btn == self.play_pause_btn:
            if self.player.state() == 1:
                self.player.pause()
                self.play_pause_btn.setIcon(QIcon(r'G:\python3\PyQt_Study\icon\play.png'))
            else:
                self.player.play()
                self.play_pause_btn.setIcon(QIcon(r'G:\python3\PyQt_Study\icon\pause.png'))
        #下一首
        elif btn == self.next_btn:
            # 如果点击下一个按钮时为最后一首歌
            if self.mediaList.currentIndex() == self.mediaList.mediaCount() - 1:
                self.mediaList.setCurrentIndex(0)
                self.play_list.setCurrentRow(0)
            else:
                # print(self.player.state())
                if self.player.state() == 1:
                    self.play_list.setCurrentRow(self.mediaList.currentIndex() + 1)
                    self.mediaList.next()
                    self.play_pause_btn.setIcon(QIcon(r'G:\python3\PyQt_Study\icon\pause.png'))
        # 上一首
        elif btn == self.preview_btn:
            if self.mediaList.currentIndex() == 0:
                self.mediaList.setCurrentIndex(self.mediaList.mediaCount() -1)
            else:
                if self.player.state() == 1:
                    self.mediaList.previous()
                    self.play_pause_btn.setIcon(QIcon(r'G:\python3\PyQt_Study\icon\pause.png'))
        # 播放模式
        elif btn == self.play_mode:
            # 根据播放模式切换
            if self.mediaList.playbackMode() == 2:
                self.mediaList.setPlaybackMode(QMediaPlaylist.Loop)
                self.play_mode.setIcon(QIcon(r'G:\python3\PyQt_Study\icon_font\loop.png'))

            elif self.mediaList.playbackMode() == 3:
                self.mediaList.setPlaybackMode(QMediaPlaylist.Random)
                self.play_mode.setIcon(QIcon(r'..\icon_font\random.png'))

            elif self.mediaList.playbackMode() == 4:
                self.mediaList.setPlaybackMode(QMediaPlaylist.Sequential)
                self.play_mode.setIcon(QIcon(r'..\icon_font\list_loop.png'))
        # 声音按钮控制
        elif btn == self.sound_btn:
            if self.player.isMuted():
                # self.sound_btn.setIcon('')
                print("1", self.player.isMuted())
                self.volume_slider.setValue(self.volume_save)
                self.player.setMuted(False)
                self.sound_btn.setIcon(QIcon(r'G:\python3\PyQt_Study\icon_font\sound_on.png'))
            else:
                print("2", self.player.isMuted())
                self.player.setMuted(True)
                self.volume_save = self.volume_slider.value()
                self.volume_slider.setValue(0)
                self.sound_btn.setIcon(QIcon(r'G:\python3\PyQt_Study\icon_font\sound_off.png'))

    # 窗口居中
    def center(self):

        qr = self.frameGeometry()  # 获得主窗口的一个矩形特定几何图形。这包含了窗口的框架。
        cp = QDesktopWidget().availableGeometry().center()  # 算出相对于显示器的绝对值。
        # 并且从这个绝对值中,我们获得了屏幕中心点。
        qr.moveCenter(cp)  # 矩形已经设置好了它的宽和高。现在我们把矩形的中心设置到屏幕的中间去。
        # 矩形的大小并不会改变。
        self.move(qr.topLeft())  # 移动了应用窗口的左上方的点到qr矩形的左上方的点,因此居中显示在我们的屏幕上。

    # 获取音乐槽函数
    def get_music_func(self):
        self.mediaList.clear()
        url = 'http://47.108.93.231:8000/cloudMusic'
        response = request.urlopen(url).read()
        # print(json.loads(response), type(json.loads(response)))
        # 读取数据库信息
        # print(json.loads(response))
        msg = json.loads(response)['msg']
        for song in msg:
            if song['url'].split('.')[-1] in self.songs_formats:
                # self.songs_list.append([song, song['url']])
                self.mediaList.addMedia(QMediaContent(QUrl(song['url'])))
                self.play_list.addItem(song['name'])
        self.play_list.setCurrentRow(0)
        # print(self.mediaList.mediaCount())
        if self.songs_list:
            self.cur_playing_song = self.songs_list[self.play_list.currentRow()][-1]

    def volume_slider_func(self, val):
        self.player.setVolume(val)
        # if val == 0:
        #     self.sound_btn.setICon(QIcon(r'G:\python3\PyQt_Study\icon\sound.png'))
        # else:
        #     self.sound_btn.setIcon(QIcon(r'G:\python3\PyQt_Study\icon\sound.png'))

    # 播放列表双击函数
    def play_list_func(self):
        self.mediaList.setCurrentIndex(self.play_list.currentRow())
        self.player.play()
        self.play_pause_btn.setIcon(QIcon(r'G:\python3\PyQt_Study\icon\pause.png'))


    def get_progress_func(self, d):
        # 连接的函数,传入参数的d为毫秒。所以做一个时间变换
        self.progress_slider.setRange(0, d)
        self.progress_slider.setEnabled(True)
        self.get_time_func(d)

    # 时间控制函数,每次调用改变滑条位置,以及时间减少
    def get_time_func(self, d):

        seconds = int(d / 1000)
        minutes = int(seconds / 60)
        seconds -= minutes * 60
        # print("%s分" %minutes, "%s秒" %seconds)
        if minutes == 0 and seconds == 0:
            self.time_stamp.setText("--/--")
            self.play_pause_btn.setIcon(QIcon(r'G:\python3\PyQt_Study\icon\play.png'))

        else:
            self.time_stamp.setText("{}:{}".format(minutes, seconds))


    def get_position_func(self, p):
        self.progress_slider.setValue(p)
        self.get_time_func(self.progress_slider.maximum() - self.progress_slider.value())

    # 当且仅当用户手动改变滑条位置时
    def update_position_func(self, v):
        self.player.setPosition(v)
        d = self.progress_slider.maximum() - v
        self.get_time_func(d)
Ejemplo n.º 19
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.º 20
0
class MusicPlayer(QWidget):
    def __init__(self, parent=None):
        QWidget.__init__(self, parent)
        self.options = self.parent().options

        self.ffmpeg = self.options['paths']['ffmpeg_bin']
        self.thumbnails = self.options['paths']['thumbnails']
        self.thumb_width = self.options['thumbnail']['width']
        self.thumb_height = self.options['thumbnail']['height']

        self.jumping = False
        self.blocked = False
        self.durations = {}
        self.playback_value = 0

        self.text = ["None", "Repeat", "Random"]
        self.playlist_list = []
        self.values = [
            QMediaPlaylist.Loop, QMediaPlaylist.CurrentItemInLoop,
            QMediaPlaylist.Random
        ]

        # Thumbnail widget
        self.image_label = QLabel()

        # Control widgets
        self.playButton = QToolButton(clicked=self.play)
        self.playButton.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay))

        self.stopButton = QToolButton(clicked=self.stop)
        self.stopButton.setIcon(self.style().standardIcon(QStyle.SP_MediaStop))
        self.stopButton.setEnabled(False)

        self.playbackButton = QToolButton(clicked=self.playback_mode)
        self.playbackButton.setText(self.text[0])

        self.nextButton = QToolButton(clicked=self.next_song)
        self.nextButton.setIcon(self.style().standardIcon(
            QStyle.SP_MediaSkipForward))

        self.previousButton = QToolButton(clicked=self.previous_song)
        self.previousButton.setIcon(self.style().standardIcon(
            QStyle.SP_MediaSkipBackward))

        self.muteButton = QToolButton(clicked=self.mute_clicked)
        self.muteButton.setIcon(self.style().standardIcon(
            QStyle.SP_MediaVolume))

        self.volumeSlider = QSlider(Qt.Horizontal,
                                    sliderMoved=self.change_volume)
        self.volumeSlider.setRange(0, 100)
        self.volumeSlider.setPageStep(1)
        self.volumeSlider.setValue(50)

        # Player and playlist setup

        self.player = QMediaPlayer()
        self.player.setVolume(50)
        self.player.stateChanged.connect(self.waveform)

        self.playlist = QMediaPlaylist()
        self.playlist.setPlaybackMode(self.values[0])
        self.playlist.setCurrentIndex(1)

        self.player.setPlaylist(self.playlist)

        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.playlistView.setContextMenuPolicy(Qt.CustomContextMenu)
        self.playlistView.customContextMenuRequested.connect(
            self.list_view_menu)
        self.playlist.currentIndexChanged.connect(
            lambda position: self.change_thumbnail(position))

        song_search = QLineEdit()
        song_search.textChanged.connect(self.search)
        song_search.setClearButtonEnabled(True)

        # Playlist
        self.playlist_name = QComboBox()
        self.playlist_name.currentTextChanged.connect(self.switch_playlist)
        self.refresh_lists()

        self.up_button = QToolButton(clicked=self.move_up)
        self.up_button.setIcon(self.style().standardIcon(QStyle.SP_ArrowUp))
        self.down_button = QToolButton(clicked=self.move_down)
        self.down_button.setIcon(self.style().standardIcon(
            QStyle.SP_ArrowDown))

        # Sound wave widget

        self.wave_graphic = WaveGraphic(self)
        #self.wave_graphic.hide()

        # Testing slider again
        self.slider = QSlider(Qt.Horizontal)
        self.slider.setRange(0, self.player.duration() / 1000)
        self.slider.sliderMoved.connect(self.seek)
        self.player.durationChanged.connect(self.durationChanged)
        self.player.positionChanged.connect(self.positionChanged)

        # Shortcuts
        QShortcut(QKeySequence(Qt.CTRL + Qt.Key_F), self, song_search.setFocus)

        # Layouts setup

        playlist_layout = QHBoxLayout()
        playlist_layout.addWidget(self.playlist_name)
        playlist_layout.addWidget(self.up_button)
        playlist_layout.addWidget(self.down_button)

        control_layout = QHBoxLayout()
        control_layout.setContentsMargins(0, 0, 0, 0)
        control_layout.addWidget(self.stopButton)
        control_layout.addWidget(self.previousButton)
        control_layout.addWidget(self.playButton)
        control_layout.addWidget(self.nextButton)
        control_layout.addWidget(self.muteButton)
        control_layout.addWidget(self.volumeSlider)
        control_layout.addWidget(self.playbackButton)

        display_layout = QVBoxLayout()
        display_layout.addWidget(song_search)
        display_layout.addWidget(self.playlistView)
        display_layout.addLayout(playlist_layout)

        music_layout = QVBoxLayout()
        music_layout.addWidget(self.image_label)
        music_layout.addWidget(self.slider)
        music_layout.addLayout(control_layout)

        main_layout = QHBoxLayout()
        main_layout.addLayout(music_layout)
        main_layout.addLayout(display_layout)

        main_2_layout = QVBoxLayout()
        main_2_layout.addLayout(main_layout)
        main_2_layout.addWidget(self.wave_graphic)

        self.setLayout(main_2_layout)

    def waveform(self, status):
        if status == QMediaPlayer.PlayingState:
            self.wave_graphic.start()
        elif status == QMediaPlayer.PausedState:
            self.wave_graphic.pause()
        else:
            self.wave_graphic.stop()

    def list_view_menu(self, point):
        menu = QMenu("Menu", self)
        recommend_action = QAction('&Recommend Songs', self)
        menu.addAction(recommend_action)

        # TODO: [FEATURE] add rename song
        recommend_action.triggered.connect(
            lambda: self.parent().call_download_manager(self.get_links()))

        rename_action = QAction('&Rename', self)
        menu.addAction(rename_action)

        # TODO: [FEATURE] add rename song
        rename_action.triggered.connect(lambda: print("rename"))

        # Show the context menu.
        menu.exec_(self.playlistView.mapToGlobal(point))

    def get_links(self):
        title = self.playlistView.selectedIndexes()[0].data()
        link = getYoutubeURLFromSearch(title)
        if len(link) > 1:
            return youtube_recommendations(link)

    def move_up(self):
        index = self.playlistView.currentIndex().row()
        if index - 1 >= 0:
            item, above = self.playlist.media(index), self.playlist.media(
                index - 1)
            self.playlist.removeMedia(index)
            self.playlist.removeMedia(index - 1)
            self.playlist.insertMedia(index - 1, item)
            self.playlist.insertMedia(index, above)
            self.blocked = True
            self.playlistView.setCurrentIndex(
                self.playlistModel.index(index - 1, 0))
            self.blocked = False
            self.stop()

    def move_down(self):
        index = self.playlistView.currentIndex().row()
        if index + 1 <= self.playlistModel.rowCount():
            item, below = self.playlist.media(index), self.playlist.media(
                index + 1)
            self.playlist.removeMedia(index + 1)
            self.playlist.removeMedia(index)
            self.playlist.insertMedia(index, below)
            self.playlist.insertMedia(index + 1, item)
            self.blocked = True
            self.playlistView.setCurrentIndex(
                self.playlistModel.index(index + 1, 0))
            self.blocked = False
            self.stop()

    def search(self, part_of_song):
        for index in range(self.playlistModel.rowCount()):
            item = self.playlistModel.data(self.playlistModel.index(
                index, 0)).lower()
            self.playlistView.setRowHidden(index,
                                           part_of_song.lower() not in item)

    def change_thumbnail(self, position=0):

        self.playlistView.setCurrentIndex(self.playlistModel.index(
            position, 0))

        song = self.playlistView.selectedIndexes()[0].data()
        if self.wave_graphic.is_song_cached(song):
            self.wave_graphic.load_waves(song)
        else:
            wc_ = WaveConverter(song, self.wave_graphic.set_wav)
            wc_.convert()

        if self.playlistView.currentIndex().data() is None or self.blocked:
            return

        max_ratio = 0
        img = None

        for item in listdir(self.thumbnails):
            if item.endswith('.jpg'):
                ratio = similar(
                    item,
                    self.playlistView.currentIndex().data().replace(
                        '.mp3', '.jpg'))
                if ratio > max_ratio:
                    max_ratio = ratio
                    img = item

        if img:
            p = QPixmap(self.thumbnails + img)
            self.image_label.setPixmap(
                p.scaled(self.thumb_width, self.thumb_height,
                         Qt.KeepAspectRatio))

    def switch_playlist(self, current_text):
        self.playlist.clear()
        if current_text == "No Playlist":
            self.refresh()
        else:
            if read_playlist(current_text):
                songs = read_playlist(current_text).split('\n')
                for song in songs:
                    self.playlist.addMedia(
                        QMediaContent(QUrl.fromLocalFile(song)))

    def refresh(self):
        # Change it so it will go to same song.
        if self.playlist_name.currentText() != "No Playlist":
            return

        paths = fetch_options()['paths']['music_path'].split(';')

        current_songs = [
            self.playlistModel.data(self.playlistModel.index(row, 0))
            for row in range(self.playlistModel.rowCount())
        ]

        for path in paths:
            if not path:
                continue
            for item in listdir(path):
                if isfile(join(path, item)) and item.endswith(".mp3") and (
                        item not in current_songs):
                    self.playlist.addMedia(
                        QMediaContent(QUrl.fromLocalFile(join(path, item))))

    def refresh_lists(self):
        path = fetch_options()['paths']['playlist']
        self.playlist_name.clear()
        self.playlist_list = ["No Playlist"]
        self.playlist_name.addItem("No Playlist")
        for item in listdir(path):
            if isfile(join(path, item)) and item.endswith(".lst"):
                self.playlist_list.append(item.split('.')[0])
                self.playlist_name.addItem(item.split('.')[0])

    def playback_mode(self):
        # Normal -> Loop -> Random
        def up_value(value, max_value=3):
            if value + 1 == max_value:
                return 0
            return value + 1

        self.playback_value = up_value(self.playback_value)
        self.playlist.setPlaybackMode(self.values[self.playback_value])
        self.playbackButton.setText(self.text[self.playback_value])

    def jump(self, index):
        if index.isValid() and not self.blocked:
            self.playlist.setCurrentIndex(index.row())
            self.jumping = True
            self.play()

    def play(self):
        if self.blocked:
            return
        if self.player.state() != QMediaPlayer.PlayingState or self.jumping:
            self.player.play()
            self.playButton.setIcon(self.style().standardIcon(
                QStyle.SP_MediaPause))
            self.jumping = False
        else:
            self.player.pause()
            self.playButton.setIcon(self.style().standardIcon(
                QStyle.SP_MediaPlay))
        self.stopButton.setEnabled(True)

    def change_volume(self, value):
        self.player.setVolume(value)

    def stop(self):
        if self.player.state() != QMediaPlayer.StoppedState:
            self.player.stop()
        self.playButton.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay))
        self.stopButton.setEnabled(False)

    def next_song(self):
        self.playlist.next()
        self.playlistView.setCurrentIndex(
            self.playlistModel.index(self.playlist.currentIndex(), 0))

    def previous_song(self):
        self.playlist.previous()
        self.playlistView.setCurrentIndex(
            self.playlistModel.index(self.playlist.currentIndex(), 0))

    def mute_clicked(self):
        self.player.setMuted(not self.player.isMuted())
        self.muteButton.setIcon(self.style().standardIcon(
            QStyle.SP_MediaVolume if not self.player.isMuted() else QStyle.
            SP_MediaVolumeMuted))

    def durationChanged(self, duration):
        duration /= 1000
        self.slider.setMaximum(duration)

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

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

    def seek(self, seconds):
        self.player.setPosition(seconds * 1000)
Ejemplo n.º 21
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:]
Ejemplo n.º 22
0
class QmyMainWindow(QMainWindow):
    def __init__(self, parent=None):
        super().__init__(parent)  #调用父类构造函数,创建窗体
        self.ui = Ui_MainWindow()  #创建UI对象
        self.ui.setupUi(self)  #构造UI界面

        ##      self.setWindowTitle("Demo10_1,音乐播放器")
        self.player = QMediaPlayer(self)
        self.playlist = QMediaPlaylist(self)
        self.player.setPlaylist(self.playlist)
        self.playlist.setPlaybackMode(QMediaPlaylist.Loop)  #循环模式

        self.__duration = ""  #文件总时间长度
        self.__curPos = ""  #当前播放到位置

        self.player.stateChanged.connect(self.do_stateChanged)

        self.player.positionChanged.connect(self.do_positionChanged)

        self.player.durationChanged.connect(self.do_durationChanged)

        self.playlist.currentIndexChanged.connect(self.do_currentChanged)

##  ==============自定义功能函数============

##  ===============event 处理函数==========

    def closeEvent(self, event):  ##窗体关闭时
        ##  窗口关闭时不能自动停止播放,需手动停止
        if (self.player.state() == QMediaPlayer.PlayingState):
            self.player.stop()

##  ==========由connectSlotsByName() 自动连接的槽函数==================
#  播放列表管理

    @pyqtSlot()  ##添加文件
    def on_btnAdd_clicked(self):
        ##      curPath=os.getcwd()     #获取系统当前目录
        ##      curPath=QDir.homePath()
        curPath = QDir.currentPath()
        dlgTitle = "选择音频文件"
        filt = "音频文件(*.mp3 *.wav *.wma);;所有文件(*.*)"
        fileList, flt = QFileDialog.getOpenFileNames(self, dlgTitle, curPath,
                                                     filt)
        count = len(fileList)
        if count < 1:
            return

        filename = fileList[0]
        fileInfo = QFileInfo(filename)  #文件信息
        QDir.setCurrent(fileInfo.absolutePath())  #重设当前路径

        for i in range(count):
            filename = fileList[i]
            fileInfo.setFile(filename)
            song = QMediaContent(QUrl.fromLocalFile(filename))
            self.playlist.addMedia(song)  #添加播放媒体
            ##         basename=os.path.basename(filename)    #文件名和后缀
            basename = fileInfo.baseName()
            self.ui.listWidget.addItem(basename)  #添加到界面文件列表

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

    @pyqtSlot()  ##移除一个文件
    def on_btnRemove_clicked(self):
        pos = self.ui.listWidget.currentRow()
        item = self.ui.listWidget.takeItem(pos)  #python会自动删除

        if (self.playlist.currentIndex() == pos):  #是当前播放的曲目
            nextPos = 0
            if pos >= 1:
                nextPos = pos - 1

            self.playlist.removeMedia(pos)  #从播放列表里移除
            if self.ui.listWidget.count() > 0:  #剩余个数
                self.playlist.setCurrentIndex(nextPos)
                self.do_currentChanged(nextPos)  #当前曲目变化
            else:
                self.player.stop()
                self.ui.LabCurMedia.setText("无曲目")
        else:
            self.playlist.removeMedia(pos)

    @pyqtSlot()  ##清空播放列表
    def on_btnClear_clicked(self):
        self.playlist.clear()  #清空播放列表
        self.ui.listWidget.clear()
        self.player.stop()  #停止播放

    ##   @pyqtSlot()    ##双击时切换播放文件
    def on_listWidget_doubleClicked(self, index):
        rowNo = index.row()  #行号
        self.playlist.setCurrentIndex(rowNo)
        self.player.play()

#  播放控制

    @pyqtSlot()  ##播放
    def on_btnPlay_clicked(self):
        if (self.playlist.currentIndex() < 0):
            self.playlist.setCurrentIndex(0)
        self.player.play()

    @pyqtSlot()  ##暂停
    def on_btnPause_clicked(self):
        self.player.pause()

    @pyqtSlot()  ##停止
    def on_btnStop_clicked(self):
        self.player.stop()

    @pyqtSlot()  ##上一曲目
    def on_btnPrevious_clicked(self):
        self.playlist.previous()

    @pyqtSlot()  ##下一曲目
    def on_btnNext_clicked(self):
        self.playlist.next()

    @pyqtSlot()  ##静音控制
    def on_btnSound_clicked(self):
        mute = self.player.isMuted()
        self.player.setMuted(not mute)
        if mute:
            self.ui.btnSound.setIcon(QIcon(":/icons/images/volumn.bmp"))
        else:
            self.ui.btnSound.setIcon(QIcon(":/icons/images/mute.bmp"))

    @pyqtSlot(int)  ##调节音量
    def on_sliderVolumn_valueChanged(self, value):
        self.player.setVolume(value)

    @pyqtSlot(int)  ##文件进度调控
    def on_sliderPosition_valueChanged(self, value):
        self.player.setPosition(value)

##  =============自定义槽函数===============================

    def do_stateChanged(self, state):  ##播放器状态变化
        self.ui.btnPlay.setEnabled(state != QMediaPlayer.PlayingState)
        self.ui.btnPause.setEnabled(state == QMediaPlayer.PlayingState)
        self.ui.btnStop.setEnabled(state == QMediaPlayer.PlayingState)

    def do_positionChanged(self, position):  ##当前文件播放位置变化,更新进度显示
        if (self.ui.sliderPosition.isSliderDown()):  #在拖动滑块调整进度
            return
        self.ui.sliderPosition.setSliderPosition(position)
        secs = position / 1000  #秒
        mins = secs / 60  #分钟
        secs = secs % 60  #余数秒
        self.__curPos = "%d:%d" % (mins, secs)
        self.ui.LabRatio.setText(self.__curPos + "/" + self.__duration)

    def do_durationChanged(self, duration):  ##文件时长变化
        self.ui.sliderPosition.setMaximum(duration)

        secs = duration / 1000  #秒
        mins = secs / 60  #分钟
        secs = secs % 60  #余数秒
        self.__duration = "%d:%d" % (mins, secs)
        self.ui.LabRatio.setText(self.__curPos + "/" + self.__duration)

    def do_currentChanged(self, position):  ##playlist当前曲目变化
        self.ui.listWidget.setCurrentRow(position)
        item = self.ui.listWidget.currentItem()  #QListWidgetItem
        if (item != None):
            self.ui.LabCurMedia.setText(item.text())
Ejemplo n.º 23
0
class VidCutter(QWidget):
    def __init__(self, parent):
        super(VidCutter, self).__init__(parent)
        self.parent = parent
        self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.VideoSurface)
        self.videoWidget = VideoWidget()
        self.videoService = VideoService(self)

        QFontDatabase.addApplicationFont(
            os.path.join(self.getAppPath(), 'fonts', 'DroidSansMono.ttf'))
        QFontDatabase.addApplicationFont(
            os.path.join(self.getAppPath(), 'fonts', 'HelveticaNeue.ttf'))
        qApp.setFont(QFont('Helvetica Neue', 10))

        self.clipTimes = []
        self.inCut = False
        self.movieFilename = ''
        self.movieLoaded = False
        self.timeformat = 'hh:mm:ss'
        self.finalFilename = ''
        self.totalRuntime = 0

        self.initIcons()
        self.initActions()

        self.toolbar = QToolBar(
            floatable=False,
            movable=False,
            iconSize=QSize(28, 28),
            toolButtonStyle=Qt.ToolButtonTextUnderIcon,
            styleSheet=
            'QToolBar QToolButton { min-width:82px; margin-left:10px; margin-right:10px; font-size:14px; }'
        )
        self.initToolbar()

        self.aboutMenu, self.cliplistMenu = QMenu(), QMenu()
        self.initMenus()

        self.seekSlider = VideoSlider(parent=self,
                                      sliderMoved=self.setPosition)
        self.seekSlider.installEventFilter(self)

        self.initNoVideo()

        self.cliplist = QListWidget(
            sizePolicy=QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Expanding),
            contextMenuPolicy=Qt.CustomContextMenu,
            uniformItemSizes=True,
            iconSize=QSize(100, 700),
            dragDropMode=QAbstractItemView.InternalMove,
            alternatingRowColors=True,
            customContextMenuRequested=self.itemMenu,
            styleSheet='QListView::item { margin:10px 5px; }')
        self.cliplist.setFixedWidth(185)
        self.cliplist.model().rowsMoved.connect(self.syncClipList)

        listHeader = QLabel(pixmap=QPixmap(
            os.path.join(self.getAppPath(), 'images', 'clipindex.png'), 'PNG'),
                            alignment=Qt.AlignCenter)
        listHeader.setStyleSheet(
            '''padding:5px; padding-top:8px; border:1px solid #b9b9b9; border-bottom:none;
                                    background-color:qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #FFF,
                                    stop: 0.5 #EAEAEA, stop: 0.6 #EAEAEA stop:1 #FFF);'''
        )

        self.runtimeLabel = QLabel('<div align="right">00:00:00</div>',
                                   textFormat=Qt.RichText)
        self.runtimeLabel.setStyleSheet(
            '''font-family:Droid Sans Mono; font-size:10pt; color:#FFF;
                                           background:rgb(106, 69, 114) url(:images/runtime.png)
                                           no-repeat left center; padding:2px; padding-right:8px;
                                           border:1px solid #b9b9b9; border-top:none;'''
        )

        self.clipindexLayout = QVBoxLayout(spacing=0)
        self.clipindexLayout.setContentsMargins(0, 0, 0, 0)
        self.clipindexLayout.addWidget(listHeader)
        self.clipindexLayout.addWidget(self.cliplist)
        self.clipindexLayout.addWidget(self.runtimeLabel)

        self.videoLayout = QHBoxLayout()
        self.videoLayout.setContentsMargins(0, 0, 0, 0)
        self.videoLayout.addWidget(self.novideoWidget)
        self.videoLayout.addLayout(self.clipindexLayout)

        self.timeCounter = QLabel('00:00:00 / 00:00:00',
                                  autoFillBackground=True,
                                  alignment=Qt.AlignCenter,
                                  sizePolicy=QSizePolicy(
                                      QSizePolicy.Expanding,
                                      QSizePolicy.Fixed))
        self.timeCounter.setStyleSheet(
            'color:#FFF; background:#000; font-family:Droid Sans Mono; font-size:10.5pt; padding:4px;'
        )

        videoplayerLayout = QVBoxLayout(spacing=0)
        videoplayerLayout.setContentsMargins(0, 0, 0, 0)
        videoplayerLayout.addWidget(self.videoWidget)
        videoplayerLayout.addWidget(self.timeCounter)

        self.videoplayerWidget = QWidget(self, visible=False)
        self.videoplayerWidget.setLayout(videoplayerLayout)

        self.menuButton = QPushButton(icon=self.aboutIcon,
                                      flat=True,
                                      toolTip='About',
                                      statusTip='About',
                                      iconSize=QSize(24, 24),
                                      cursor=Qt.PointingHandCursor)
        self.menuButton.setMenu(self.aboutMenu)

        self.muteButton = QPushButton(icon=self.unmuteIcon,
                                      flat=True,
                                      toolTip='Mute',
                                      statusTip='Toggle audio mute',
                                      cursor=Qt.PointingHandCursor,
                                      clicked=self.muteAudio)

        self.volumeSlider = QSlider(Qt.Horizontal,
                                    toolTip='Volume',
                                    statusTip='Adjust volume level',
                                    cursor=Qt.PointingHandCursor,
                                    value=50,
                                    sizePolicy=QSizePolicy(
                                        QSizePolicy.Fixed,
                                        QSizePolicy.Minimum),
                                    minimum=0,
                                    maximum=100,
                                    sliderMoved=self.setVolume)
        self.volumeSlider.setStyleSheet(
            '''QSlider::groove:horizontal { height:40px; }
                                           QSlider::sub-page:horizontal { border:1px outset #6A4572; background:#6A4572; margin:2px; }
                                           QSlider::handle:horizontal { image: url(:images/knob.png) no-repeat top left; width:20px; }'''
        )

        self.saveAction = QPushButton(
            self.parent,
            icon=self.saveIcon,
            text='Save Video',
            flat=True,
            toolTip='Save Video',
            clicked=self.cutVideo,
            cursor=Qt.PointingHandCursor,
            iconSize=QSize(30, 30),
            statusTip='Save video clips merged as a new video file',
            enabled=False)
        self.saveAction.setStyleSheet(
            '''QPushButton { color:#FFF; padding:8px; font-size:12pt;
                                            border:1px inset #481953; border-radius:4px;
                                            background-color:rgb(106, 69, 114); }
                                         QPushButton:!enabled { background-color:rgba(0, 0, 0, 0.1);
                                            color:rgba(0, 0, 0, 0.3); border:1px inset #CDCDCD; }
                                         QPushButton:hover { background-color:rgba(255, 255, 255, 0.8); color:#444; }
                                         QPushButton:pressed { background-color:rgba(218, 218, 219, 0.8); color:#444; }'''
        )

        controlsLayout = QHBoxLayout()
        controlsLayout.addStretch(1)
        controlsLayout.addWidget(self.toolbar)
        controlsLayout.addSpacerItem(QSpacerItem(20, 1))
        controlsLayout.addWidget(self.saveAction)
        controlsLayout.addStretch(1)
        controlsLayout.addWidget(self.muteButton)
        controlsLayout.addWidget(self.volumeSlider)
        controlsLayout.addSpacing(1)
        controlsLayout.addWidget(self.menuButton)

        layout = QVBoxLayout()
        layout.setContentsMargins(10, 10, 10, 4)
        layout.addLayout(self.videoLayout)
        layout.addWidget(self.seekSlider)
        layout.addLayout(controlsLayout)

        self.setLayout(layout)

        self.mediaPlayer.setVideoOutput(self.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 initNoVideo(self) -> None:
        novideoImage = QLabel(alignment=Qt.AlignCenter,
                              autoFillBackground=False,
                              pixmap=QPixmap(
                                  os.path.join(self.getAppPath(), 'images',
                                               'novideo.png'), 'PNG'),
                              sizePolicy=QSizePolicy(
                                  QSizePolicy.Expanding,
                                  QSizePolicy.MinimumExpanding))
        novideoImage.setBackgroundRole(QPalette.Dark)
        novideoImage.setContentsMargins(0, 20, 0, 20)
        self.novideoLabel = QLabel(alignment=Qt.AlignCenter,
                                   autoFillBackground=True,
                                   sizePolicy=QSizePolicy(
                                       QSizePolicy.Expanding,
                                       QSizePolicy.Minimum))
        self.novideoLabel.setBackgroundRole(QPalette.Dark)
        self.novideoLabel.setContentsMargins(0, 20, 15, 60)
        novideoLayout = QVBoxLayout(spacing=0)
        novideoLayout.addWidget(novideoImage)
        novideoLayout.addWidget(self.novideoLabel, alignment=Qt.AlignTop)
        self.novideoMovie = QMovie(
            os.path.join(self.getAppPath(), 'images', 'novideotext.gif'))
        self.novideoMovie.frameChanged.connect(self.setNoVideoText)
        self.novideoMovie.start()
        self.novideoWidget = QWidget(self, autoFillBackground=True)
        self.novideoWidget.setBackgroundRole(QPalette.Dark)
        self.novideoWidget.setLayout(novideoLayout)

    def initIcons(self) -> None:
        self.appIcon = QIcon(
            os.path.join(self.getAppPath(), 'images', 'vidcutter.png'))
        self.openIcon = QIcon(
            os.path.join(self.getAppPath(), 'images', 'addmedia.png'))
        self.playIcon = QIcon(
            os.path.join(self.getAppPath(), 'images', 'play.png'))
        self.pauseIcon = QIcon(
            os.path.join(self.getAppPath(), 'images', 'pause.png'))
        self.cutStartIcon = QIcon(
            os.path.join(self.getAppPath(), 'images', 'cut-start.png'))
        self.cutEndIcon = QIcon(
            os.path.join(self.getAppPath(), 'images', 'cut-end.png'))
        self.saveIcon = QIcon(
            os.path.join(self.getAppPath(), 'images', 'save.png'))
        self.muteIcon = QIcon(
            os.path.join(self.getAppPath(), 'images', 'muted.png'))
        self.unmuteIcon = QIcon(
            os.path.join(self.getAppPath(), 'images', 'unmuted.png'))
        self.upIcon = QIcon(os.path.join(self.getAppPath(), 'images',
                                         'up.png'))
        self.downIcon = QIcon(
            os.path.join(self.getAppPath(), 'images', 'down.png'))
        self.removeIcon = QIcon(
            os.path.join(self.getAppPath(), 'images', 'remove.png'))
        self.removeAllIcon = QIcon(
            os.path.join(self.getAppPath(), 'images', 'remove-all.png'))
        self.successIcon = QIcon(
            os.path.join(self.getAppPath(), 'images', 'success.png'))
        self.aboutIcon = QIcon(
            os.path.join(self.getAppPath(), 'images', 'about.png'))
        self.completePlayIcon = QIcon(
            os.path.join(self.getAppPath(), 'images', 'complete-play.png'))
        self.completeOpenIcon = QIcon(
            os.path.join(self.getAppPath(), 'images', 'complete-open.png'))
        self.completeRestartIcon = QIcon(
            os.path.join(self.getAppPath(), 'images', 'complete-restart.png'))
        self.completeExitIcon = QIcon(
            os.path.join(self.getAppPath(), 'images', 'complete-exit.png'))

    def initActions(self) -> None:
        self.openAction = QAction(self.openIcon,
                                  'Add Media',
                                  self,
                                  statusTip='Select media source',
                                  triggered=self.openFile)
        self.playAction = QAction(self.playIcon,
                                  'Play Video',
                                  self,
                                  statusTip='Play selected media',
                                  triggered=self.playVideo,
                                  enabled=False)
        self.cutStartAction = QAction(self.cutStartIcon,
                                      'Set Start',
                                      self,
                                      toolTip='Set Start',
                                      statusTip='Set start marker',
                                      triggered=self.cutStart,
                                      enabled=False)
        self.cutEndAction = QAction(self.cutEndIcon,
                                    'Set End',
                                    self,
                                    statusTip='Set end marker',
                                    triggered=self.cutEnd,
                                    enabled=False)
        self.moveItemUpAction = QAction(
            self.upIcon,
            'Move Up',
            self,
            statusTip='Move clip position up in list',
            triggered=self.moveItemUp,
            enabled=False)
        self.moveItemDownAction = QAction(
            self.downIcon,
            'Move Down',
            self,
            statusTip='Move clip position down in list',
            triggered=self.moveItemDown,
            enabled=False)
        self.removeItemAction = QAction(
            self.removeIcon,
            'Remove clip',
            self,
            statusTip='Remove selected clip from list',
            triggered=self.removeItem,
            enabled=False)
        self.removeAllAction = QAction(self.removeAllIcon,
                                       'Clear list',
                                       self,
                                       statusTip='Clear all clips from list',
                                       triggered=self.clearList,
                                       enabled=False)
        self.aboutAction = QAction('About %s' % qApp.applicationName(),
                                   self,
                                   statusTip='Credits and acknowledgements',
                                   triggered=self.aboutInfo)
        self.aboutQtAction = QAction('About Qt',
                                     self,
                                     statusTip='About Qt',
                                     triggered=qApp.aboutQt)
        self.mediaInfoAction = QAction(
            'Media Information',
            self,
            statusTip='Media information from loaded video file',
            triggered=self.mediaInfo,
            enabled=False)

    def initToolbar(self) -> None:
        self.toolbar.addAction(self.openAction)
        self.toolbar.addAction(self.playAction)
        self.toolbar.addSeparator()
        self.toolbar.addAction(self.cutStartAction)
        self.toolbar.addAction(self.cutEndAction)
        self.toolbar.addSeparator()

    def initMenus(self) -> None:
        self.aboutMenu.addAction(self.mediaInfoAction)
        self.aboutMenu.addSeparator()
        self.aboutMenu.addAction(self.aboutQtAction)
        self.aboutMenu.addAction(self.aboutAction)
        self.cliplistMenu.addAction(self.moveItemUpAction)
        self.cliplistMenu.addAction(self.moveItemDownAction)
        self.cliplistMenu.addSeparator()
        self.cliplistMenu.addAction(self.removeItemAction)
        self.cliplistMenu.addAction(self.removeAllAction)

    def setRunningTime(self, runtime: str) -> None:
        self.runtimeLabel.setText('<div align="right">%s</div>' % runtime)

    @pyqtSlot(int)
    def setNoVideoText(self, frame: int) -> None:
        self.novideoLabel.setPixmap(self.novideoMovie.currentPixmap())

    def itemMenu(self, pos: QPoint) -> None:
        globalPos = self.cliplist.mapToGlobal(pos)
        self.moveItemUpAction.setEnabled(False)
        self.moveItemDownAction.setEnabled(False)
        self.removeItemAction.setEnabled(False)
        self.removeAllAction.setEnabled(False)
        index = self.cliplist.currentRow()
        if index != -1:
            if not self.inCut:
                if index > 0:
                    self.moveItemUpAction.setEnabled(True)
                if index < self.cliplist.count() - 1:
                    self.moveItemDownAction.setEnabled(True)
            if self.cliplist.count() > 0:
                self.removeItemAction.setEnabled(True)
        if self.cliplist.count() > 0:
            self.removeAllAction.setEnabled(True)
        self.cliplistMenu.exec_(globalPos)

    def moveItemUp(self) -> None:
        index = self.cliplist.currentRow()
        tmpItem = self.clipTimes[index]
        del self.clipTimes[index]
        self.clipTimes.insert(index - 1, tmpItem)
        self.renderTimes()

    def moveItemDown(self) -> None:
        index = self.cliplist.currentRow()
        tmpItem = self.clipTimes[index]
        del self.clipTimes[index]
        self.clipTimes.insert(index + 1, tmpItem)
        self.renderTimes()

    def removeItem(self) -> None:
        index = self.cliplist.currentRow()
        del self.clipTimes[index]
        if self.inCut and index == self.cliplist.count() - 1:
            self.inCut = False
            self.initMediaControls()
        self.renderTimes()

    def clearList(self) -> None:
        self.clipTimes.clear()
        self.cliplist.clear()
        self.inCut = False
        self.renderTimes()
        self.initMediaControls()

    def mediaInfo(self) -> None:
        if self.mediaPlayer.isMetaDataAvailable():
            content = '<table cellpadding="4">'
            for key in self.mediaPlayer.availableMetaData():
                val = self.mediaPlayer.metaData(key)
                if type(val) is QSize:
                    val = '%s x %s' % (val.width(), val.height())
                content += '<tr><td align="right"><b>%s:</b></td><td>%s</td></tr>\n' % (
                    key, val)
            content += '</table>'
            mbox = QMessageBox(windowTitle='Media Information',
                               windowIcon=self.parent.windowIcon(),
                               textFormat=Qt.RichText)
            mbox.setText('<b>%s</b>' % os.path.basename(
                self.mediaPlayer.currentMedia().canonicalUrl().toLocalFile()))
            mbox.setInformativeText(content)
            mbox.exec_()
        else:
            QMessageBox.critical(
                self.parent, 'Could not retrieve media information',
                '''There was a problem in tring to retrieve media information.
                                    This DOES NOT mean there is a problem with the file and you should
                                    be able to continue using it.''')

    def aboutInfo(self) -> None:
        about_html = '''<style>
    a { color:#441d4e; text-decoration:none; font-weight:bold; }
    a:hover { text-decoration:underline; }
</style>
<p style="font-size:26pt; font-weight:bold;">%s</p>
<p>
    <span style="font-size:13pt;"><b>Version: %s</b></span>
    <span style="font-size:10pt;position:relative;left:5px;">( %s )</span>
</p>
<p style="font-size:13px;">
    Copyright &copy; 2016 <a href="mailto:[email protected]">Pete Alexandrou</a>
    <br/>
    Website: <a href="%s">%s</a>
</p>
<p style="font-size:13px;">
    Thanks to the folks behind the <b>Qt</b>, <b>PyQt</b> and <b>FFmpeg</b>
    projects for all their hard and much appreciated work.
</p>
<p style="font-size:11px;">
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
    as published by the Free Software Foundation; either version 2
    of the License, or (at your option) any later version.
</p>
<p style="font-size:11px;">
    This software uses libraries from the <a href="https://www.ffmpeg.org">FFmpeg</a> project under the
    <a href="https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html">LGPLv2.1</a>
</p>''' % (qApp.applicationName(), qApp.applicationVersion(),
           platform.architecture()[0], qApp.organizationDomain(),
           qApp.organizationDomain())
        QMessageBox.about(self.parent, 'About %s' % qApp.applicationName(),
                          about_html)

    def openFile(self) -> None:
        filename, _ = QFileDialog.getOpenFileName(self.parent,
                                                  caption='Select video',
                                                  directory=QDir.homePath())
        if filename != '':
            self.loadFile(filename)

    def loadFile(self, filename: str) -> None:
        self.movieFilename = filename
        if not os.path.exists(filename):
            return
        self.mediaPlayer.setMedia(QMediaContent(QUrl.fromLocalFile(filename)))
        self.initMediaControls(True)
        self.cliplist.clear()
        self.clipTimes = []
        self.parent.setWindowTitle(
            '%s - %s' % (qApp.applicationName(), os.path.basename(filename)))
        if not self.movieLoaded:
            self.videoLayout.replaceWidget(self.novideoWidget,
                                           self.videoplayerWidget)
            self.novideoMovie.stop()
            self.novideoMovie.deleteLater()
            self.novideoWidget.deleteLater()
            self.videoplayerWidget.show()
            self.videoWidget.show()
            self.movieLoaded = True
        if self.mediaPlayer.isVideoAvailable():
            self.mediaPlayer.setPosition(1)
        self.mediaPlayer.play()
        self.mediaPlayer.pause()

    def playVideo(self) -> None:
        if self.mediaPlayer.state() == QMediaPlayer.PlayingState:
            self.mediaPlayer.pause()
            self.playAction.setText('Play Video')
        else:
            self.mediaPlayer.play()
            self.playAction.setText('Pause Video')

    def initMediaControls(self, flag: bool = True) -> None:
        self.playAction.setEnabled(flag)
        self.saveAction.setEnabled(False)
        self.cutStartAction.setEnabled(flag)
        self.cutEndAction.setEnabled(False)
        self.mediaInfoAction.setEnabled(flag)
        if flag:
            self.seekSlider.setRestrictValue(0)

    def setPosition(self, position: int) -> None:
        self.mediaPlayer.setPosition(position)

    def positionChanged(self, progress: int) -> None:
        self.seekSlider.setValue(progress)
        currentTime = self.deltaToQTime(progress)
        totalTime = self.deltaToQTime(self.mediaPlayer.duration())
        self.timeCounter.setText('%s / %s' % (currentTime.toString(
            self.timeformat), totalTime.toString(self.timeformat)))

    @pyqtSlot()
    def mediaStateChanged(self) -> None:
        if self.mediaPlayer.state() == QMediaPlayer.PlayingState:
            self.playAction.setIcon(self.pauseIcon)
        else:
            self.playAction.setIcon(self.playIcon)

    def durationChanged(self, duration: int) -> None:
        self.seekSlider.setRange(0, duration)

    def muteAudio(self, muted: bool) -> None:
        if self.mediaPlayer.isMuted():
            self.mediaPlayer.setMuted(not self.mediaPlayer.isMuted())
            self.muteButton.setIcon(self.unmuteIcon)
            self.muteButton.setToolTip('Mute')
        else:
            self.mediaPlayer.setMuted(not self.mediaPlayer.isMuted())
            self.muteButton.setIcon(self.muteIcon)
            self.muteButton.setToolTip('Unmute')

    def setVolume(self, volume: int) -> None:
        self.mediaPlayer.setVolume(volume)

    def toggleFullscreen(self) -> None:
        self.videoWidget.setFullScreen(not self.videoWidget.isFullScreen())

    def cutStart(self) -> None:
        self.clipTimes.append([
            self.deltaToQTime(self.mediaPlayer.position()), '',
            self.captureImage()
        ])
        self.cutStartAction.setDisabled(True)
        self.cutEndAction.setEnabled(True)
        self.seekSlider.setRestrictValue(self.seekSlider.value() + 1000)
        self.mediaPlayer.setPosition(self.seekSlider.restrictValue)
        self.inCut = True
        self.renderTimes()

    def cutEnd(self) -> None:
        item = self.clipTimes[len(self.clipTimes) - 1]
        selected = self.deltaToQTime(self.mediaPlayer.position())
        if selected.__lt__(item[0]):
            QMessageBox.critical(
                self.parent, 'Invalid END Time',
                'The clip end time must come AFTER it\'s start time. Please try again.'
            )
            return
        item[1] = selected
        self.cutStartAction.setEnabled(True)
        self.cutEndAction.setDisabled(True)
        self.seekSlider.setRestrictValue(0)
        self.inCut = False
        self.renderTimes()

    @pyqtSlot(QModelIndex, int, int, QModelIndex, int)
    def syncClipList(self, parent: QModelIndex, start: int, end: int,
                     destination: QModelIndex, row: int) -> None:
        if start < row:
            index = row - 1
        else:
            index = row
        clip = self.clipTimes.pop(start)
        self.clipTimes.insert(index, clip)

    def renderTimes(self) -> None:
        self.cliplist.clear()
        self.seekSlider.setCutMode(self.inCut)
        if len(self.clipTimes) > 4:
            self.cliplist.setFixedWidth(200)
        else:
            self.cliplist.setFixedWidth(185)
        self.totalRuntime = 0
        for item in self.clipTimes:
            endItem = ''
            if type(item[1]) is QTime:
                endItem = item[1].toString(self.timeformat)
                self.totalRuntime += item[0].msecsTo(item[1])
            listitem = QListWidgetItem()
            listitem.setTextAlignment(Qt.AlignVCenter)
            if type(item[2]) is QPixmap:
                listitem.setIcon(QIcon(item[2]))
            self.cliplist.addItem(listitem)
            marker = QLabel(
                '''<style>b { font-size:8pt; } p { margin:5px; }</style>
                            <p><b>START</b><br/>%s</p><p><b>END</b><br/>%s</p>'''
                % (item[0].toString(self.timeformat), endItem))
            self.cliplist.setItemWidget(listitem, marker)
            listitem.setFlags(Qt.ItemIsSelectable | Qt.ItemIsDragEnabled
                              | Qt.ItemIsEnabled)
        if len(self.clipTimes) and not self.inCut:
            self.saveAction.setEnabled(True)
        if self.inCut or len(self.clipTimes) == 0 or not type(
                self.clipTimes[0][1]) is QTime:
            self.saveAction.setEnabled(False)
        self.setRunningTime(
            self.deltaToQTime(self.totalRuntime).toString(self.timeformat))

    @staticmethod
    def deltaToQTime(millisecs: int) -> QTime:
        secs = millisecs / 1000
        return QTime((secs / 3600) % 60, (secs / 60) % 60, secs % 60,
                     (secs * 1000) % 1000)

    def captureImage(self) -> None:
        frametime = self.deltaToQTime(
            self.mediaPlayer.position()).addSecs(1).toString(self.timeformat)
        inputfile = self.mediaPlayer.currentMedia().canonicalUrl().toLocalFile(
        )
        imagecap = self.videoService.capture(inputfile, frametime)
        if type(imagecap) is QPixmap:
            return imagecap

    def cutVideo(self) -> bool:
        self.setCursor(Qt.BusyCursor)
        clips = len(self.clipTimes)
        filename, filelist = '', []
        source = self.mediaPlayer.currentMedia().canonicalUrl().toLocalFile()
        _, sourceext = os.path.splitext(source)
        if clips > 0:
            self.finalFilename, _ = QFileDialog.getSaveFileName(
                self.parent, 'Save video', source,
                'Video files (*%s)' % sourceext)
            if self.finalFilename != '':
                self.saveAction.setDisabled(True)
                self.showProgress(clips)
                file, ext = os.path.splitext(self.finalFilename)
                index = 1
                self.progress.setLabelText('Cutting video clips...')
                qApp.processEvents()
                for clip in self.clipTimes:
                    duration = self.deltaToQTime(clip[0].msecsTo(
                        clip[1])).toString(self.timeformat)
                    filename = '%s_%s%s' % (file, '{0:0>2}'.format(index), ext)
                    filelist.append(filename)
                    self.videoService.cut(source, filename,
                                          clip[0].toString(self.timeformat),
                                          duration)
                    index += 1
                if len(filelist) > 1:
                    self.joinVideos(filelist, self.finalFilename)
                else:
                    QFile.remove(self.finalFilename)
                    QFile.rename(filename, self.finalFilename)
                self.unsetCursor()
                self.progress.setLabelText('Complete...')
                qApp.processEvents()
                self.saveAction.setEnabled(True)
                self.progress.close()
                self.progress.deleteLater()
                self.complete()
                self.saveAction.setEnabled(True)
            self.unsetCursor()
            self.saveAction.setDisabled(True)
            return True
        self.unsetCursor()
        self.saveAction.setDisabled(True)
        return False

    def joinVideos(self, joinlist: list, filename: str) -> None:
        listfile = os.path.normpath(
            os.path.join(os.path.dirname(joinlist[0]), '.vidcutter.list'))
        fobj = open(listfile, 'w')
        for file in joinlist:
            fobj.write('file \'%s\'\n' % file.replace("'", "\\'"))
        fobj.close()
        self.videoService.join(listfile, filename)
        try:
            QFile.remove(listfile)
            for file in joinlist:
                if os.path.isfile(file):
                    QFile.remove(file)
        except:
            pass

    def showProgress(self,
                     steps: int,
                     label: str = 'Processing video...') -> None:
        self.progress = QProgressDialog(label,
                                        None,
                                        0,
                                        steps,
                                        self.parent,
                                        windowModality=Qt.ApplicationModal,
                                        windowIcon=self.parent.windowIcon(),
                                        minimumDuration=0,
                                        minimumWidth=500)
        self.progress.show()
        for i in range(steps):
            self.progress.setValue(i)
            qApp.processEvents()
            time.sleep(1)

    def complete(self) -> None:
        info = QFileInfo(self.finalFilename)
        mbox = QMessageBox(windowTitle='Success',
                           windowIcon=self.parent.windowIcon(),
                           minimumWidth=500,
                           iconPixmap=self.successIcon.pixmap(48, 49),
                           textFormat=Qt.RichText)
        mbox.setText(
            '''
<style>
    table.info { margin:8px; padding:4px 15px; }
    td.label { font-weight:bold; font-size:9pt; text-align:right; background-color:#444; color:#FFF; }
    td.value { background-color:#FFF !important; font-size:10pt; }
</style>
<p>Your video was successfully created.</p>
<p align="center">
    <table class="info" cellpadding="6" cellspacing="0">
        <tr>
            <td class="label"><b>Filename</b></td>
            <td class="value" nowrap>%s</td>
        </tr>
        <tr>
            <td class="label"><b>Size</b></td>
            <td class="value">%s</td>
        </tr>
        <tr>
            <td class="label"><b>Runtime</b></td>
            <td class="value">%s</td>
        </tr>
    </table>
</p>
<p>How would you like to proceed?</p>''' %
            (QDir.toNativeSeparators(
                self.finalFilename), self.sizeof_fmt(int(info.size())),
             self.deltaToQTime(self.totalRuntime).toString(self.timeformat)))
        play = mbox.addButton('Play', QMessageBox.AcceptRole)
        play.setIcon(self.completePlayIcon)
        play.clicked.connect(self.openResult)
        fileman = mbox.addButton('Open', QMessageBox.AcceptRole)
        fileman.setIcon(self.completeOpenIcon)
        fileman.clicked.connect(self.openFolder)
        end = mbox.addButton('Exit', QMessageBox.AcceptRole)
        end.setIcon(self.completeExitIcon)
        end.clicked.connect(self.close)
        new = mbox.addButton('Restart', QMessageBox.AcceptRole)
        new.setIcon(self.completeRestartIcon)
        new.clicked.connect(self.startNew)
        mbox.setDefaultButton(new)
        mbox.setEscapeButton(new)
        mbox.exec_()

    def sizeof_fmt(self, num: float, suffix: chr = 'B') -> str:
        for unit in ['', 'K', 'M', 'G', 'T', 'P', 'E', 'Z']:
            if abs(num) < 1024.0:
                return "%3.1f%s%s" % (num, unit, suffix)
            num /= 1024.0
        return "%.1f%s%s" % (num, 'Y', suffix)

    @pyqtSlot()
    def openFolder(self) -> None:
        self.openResult(pathonly=True)

    @pyqtSlot(bool)
    def openResult(self, pathonly: bool = False) -> None:
        self.startNew()
        if len(self.finalFilename) and os.path.exists(self.finalFilename):
            target = self.finalFilename if not pathonly else os.path.dirname(
                self.finalFilename)
            QDesktopServices.openUrl(QUrl.fromLocalFile(target))

    @pyqtSlot()
    def startNew(self) -> None:
        self.unsetCursor()
        self.clearList()
        self.seekSlider.setValue(0)
        self.seekSlider.setRange(0, 0)
        self.mediaPlayer.setMedia(QMediaContent())
        self.initNoVideo()
        self.videoLayout.replaceWidget(self.videoplayerWidget,
                                       self.novideoWidget)
        self.initMediaControls(False)
        self.parent.setWindowTitle('%s' % qApp.applicationName())

    def wheelEvent(self, event: QWheelEvent) -> None:
        if self.mediaPlayer.isVideoAvailable(
        ) or self.mediaPlayer.isAudioAvailable():
            if event.angleDelta().y() > 0:
                newval = self.seekSlider.value() - 1000
            else:
                newval = self.seekSlider.value() + 1000
            self.seekSlider.setValue(newval)
            self.seekSlider.setSliderPosition(newval)
            self.mediaPlayer.setPosition(newval)
        event.accept()

    def keyPressEvent(self, event: QKeyEvent) -> None:
        if self.mediaPlayer.isVideoAvailable(
        ) or self.mediaPlayer.isAudioAvailable():
            addtime = 0
            if event.key() == Qt.Key_Left:
                addtime = -1000
            elif event.key() == Qt.Key_PageUp or event.key() == Qt.Key_Up:
                addtime = -10000
            elif event.key() == Qt.Key_Right:
                addtime = 1000
            elif event.key() == Qt.Key_PageDown or event.key() == Qt.Key_Down:
                addtime = 10000
            elif event.key() == Qt.Key_Enter:
                self.toggleFullscreen()
            elif event.key(
            ) == Qt.Key_Escape and self.videoWidget.isFullScreen():
                self.videoWidget.setFullScreen(False)
            if addtime != 0:
                newval = self.seekSlider.value() + addtime
                self.seekSlider.setValue(newval)
                self.seekSlider.setSliderPosition(newval)
                self.mediaPlayer.setPosition(newval)
        event.accept()

    def mousePressEvent(self, event: QMouseEvent) -> None:
        if event.button() == Qt.BackButton and self.cutStartAction.isEnabled():
            self.cutStart()
            event.accept()
        elif event.button(
        ) == Qt.ForwardButton and self.cutEndAction.isEnabled():
            self.cutEnd()
            event.accept()
        else:
            super(VidCutter, self).mousePressEvent(event)

    def eventFilter(self, obj: QObject, event: QEvent) -> bool:
        if event.type() == QEvent.MouseButtonRelease and isinstance(
                obj, VideoSlider):
            if obj.objectName() == 'VideoSlider' and (
                    self.mediaPlayer.isVideoAvailable()
                    or self.mediaPlayer.isAudioAvailable()):
                obj.setValue(
                    QStyle.sliderValueFromPosition(obj.minimum(),
                                                   obj.maximum(), event.x(),
                                                   obj.width()))
                self.mediaPlayer.setPosition(obj.sliderPosition())
        return QWidget.eventFilter(self, obj, event)

    @pyqtSlot(QMediaPlayer.Error)
    def handleError(self, error: QMediaPlayer.Error) -> None:
        self.unsetCursor()
        self.startNew()
        if error == QMediaPlayer.ResourceError:
            QMessageBox.critical(
                self.parent, 'Error',
                'Invalid media file detected at:<br/><br/><b>%s</b><br/><br/>%s'
                % (self.movieFilename, self.mediaPlayer.errorString()))
        else:
            QMessageBox.critical(self.parent, 'Error',
                                 self.mediaPlayer.errorString())

    def getAppPath(self) -> str:
        return ':'

    def closeEvent(self, event: QCloseEvent) -> None:
        self.parent.closeEvent(event)
Ejemplo n.º 24
0
class QgsFmvPlayer(QMainWindow, Ui_PlayerWindow):
    """ Video Player Class """
    def __init__(self,
                 iface,
                 path,
                 parent=None,
                 meta_reader=None,
                 pass_time=None,
                 initialPt=None,
                 isStreaming=False):
        """ Constructor """
        super(QgsFmvPlayer, self).__init__(parent)
        self.setupUi(self)
        self.parent = parent
        self.iface = iface
        self.fileName = path
        self.initialPt = initialPt
        self.meta_reader = meta_reader
        self.isStreaming = isStreaming
        self.createingMosaic = False
        self.currentInfo = 0.0
        self.data = None

        # Create Draw Toolbar
        self.DrawToolBar.addAction(self.actionMagnifying_glass)
        self.DrawToolBar.addSeparator()

        # Draw Polygon QToolButton
        self.toolBtn_DPolygon.setDefaultAction(self.actionDraw_Polygon)
        self.DrawToolBar.addWidget(self.toolBtn_DPolygon)

        # Draw Point QToolButton
        self.toolBtn_DPoint.setDefaultAction(self.actionDraw_Pinpoint)
        self.DrawToolBar.addWidget(self.toolBtn_DPoint)

        # Draw Point QToolButton
        self.toolBtn_DLine.setDefaultAction(self.actionDraw_Line)
        self.DrawToolBar.addWidget(self.toolBtn_DLine)

        self.DrawToolBar.addAction(self.actionRuler)
        self.DrawToolBar.addSeparator()

        #         # Censure QToolButton
        #         self.toolBtn_Cesure.setDefaultAction(self.actionCensure)
        #         self.DrawToolBar.addWidget(self.toolBtn_Cesure)
        #         self.DrawToolBar.addSeparator()
        #
        #         # Object Tracking
        #         self.DrawToolBar.addAction(self.actionObject_Tracking)
        self.toolBtn_Cesure.setVisible(False)
        # Hide Color Button
        self.btn_Color.hide()

        self.RecGIF = QMovie(":/imgFMV/images/record.gif")

        self.videoWidget.customContextMenuRequested[QPoint].connect(
            self.contextMenuRequested)

        self.menubarwidget.customContextMenuRequested[QPoint].connect(
            self.contextMenuBarRequested)

        self.duration = 0
        self.playerMuted = False
        self.HasFileAudio = False

        self.player = QMediaPlayer(None, QMediaPlayer.VideoSurface)
        self.pass_time = pass_time
        self.player.setNotifyInterval(700)  # Metadata Callback Interval
        self.playlist = QMediaPlaylist()

        self.player.setVideoOutput(
            self.videoWidget.videoSurface())  # Abstract 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.LoadingMedia
        self.playFile(path)

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

        self.volumeSlider.setValue(self.player.volume())
        self.volumeSlider.enterEvent = self.showVolumeTip

        self.metadataDlg = QgsFmvMetadata(parent=self, player=self)
        self.addDockWidget(Qt.RightDockWidgetArea, self.metadataDlg)
        self.metadataDlg.setMinimumWidth(500)
        self.metadataDlg.hide()

        self.converter = Converter()
        self.BitratePlot = CreatePlotsBitrate()

    def HasAudio(self, videoPath):
        """ Check if video have Metadata or not """
        try:
            p = _spawn([
                '-i', videoPath, '-show_streams', '-select_streams', 'a',
                '-preset', 'ultrafast', '-loglevel', 'error'
            ],
                       t="probe")

            stdout_data, _ = p.communicate()

            if stdout_data == b'':
                qgsu.showUserAndLogMessage(
                    QCoreApplication.translate(
                        "QgsFmvPlayer", "This video doesn't have Audio ! "))
                self.actionAudio.setEnabled(False)
                self.actionSave_Audio.setEnabled(False)
                return False

            return True
        except Exception as e:
            qgsu.showUserAndLogMessage(
                QCoreApplication.translate("QgsFmvPlayer",
                                           "Audio check Failed! : "), str(e))
            self.actionAudio.setEnabled(False)
            self.actionSave_Audio.setEnabled(False)

    def get_metadata_from_buffer(self, currentTime):
        """ Metadata CallBack """
        try:

            # There is no way to spawn a thread and call after join() without blocking the video UI thread.
            # callBackMetadata can be as fast as possible, it will always create a small video lag every time meta are read.
            # To get rid of this, we fill a buffer (BufferedMetaReader) in the QManager with some Metadata in advance,
            # and hope they'll be ready to read here in a totaly non-blocking
            # way (increase the buffer size if needed in QManager).

            stdout_data = self.meta_reader.get(currentTime)
            # qgsu.showUserAndLogMessage(
            #    "", "stdout_data: " + str(stdout_data) + " currentTime: " + str(currentTime), onlyLog=True)
            if stdout_data == 'NOT_READY':
                self.metadataDlg.menuSave.setEnabled(False)
                qgsu.showUserAndLogMessage(
                    "",
                    "Buffer value read but is not ready, increase buffer size. : ",
                    onlyLog=True)
                return

            #Values need to be read, pause the video a short while
            elif stdout_data == 'BUFFERING':
                qgsu.showUserAndLogMessage("Buffering metadata...",
                                           "",
                                           duration=4,
                                           level=QGis.Info)
                self.player.pause()
                QTimer.singleShot(2500, lambda: self.player.play())
                return

            elif stdout_data == b'' or len(stdout_data) == 0:
                self.metadataDlg.menuSave.setEnabled(False)
                qgsu.showUserAndLogMessage(
                    "",
                    "Buffer returned empty metadata, check pass_time. : ",
                    onlyLog=True)
                return

            self.packetStreamParser(stdout_data)

        except Exception as inst:
            qgsu.showUserAndLogMessage(
                QCoreApplication.translate("QgsFmvPlayer",
                                           "Metadata Buffer Failed! : "),
                str(inst))

    def packetStreamParser(self, stdout_data):
        ''' Common packet process'''
        for packet in StreamParser(stdout_data):
            try:
                if isinstance(packet, UnknownElement):
                    qgsu.showUserAndLogMessage(
                        "Error interpreting klv data, metadata cannot be read.",
                        "the parser did not recognize KLV data",
                        level=QGis.Warning,
                        onlyLog=True)
                    continue
                data = packet.MetadataList()
                self.data = data
                if self.metadataDlg.isVisible(
                ):  # Only add metada to table if this QDockWidget is visible (speed plugin)
                    self.metadataDlg.menuSave.setEnabled(True)
                    self.addMetadata(data)

                UpdateLayers(packet, parent=self, mosaic=self.createingMosaic)
                QApplication.processEvents()
                return
            except Exception:
                None
#                     qgsu.showUserAndLogMessage(QCoreApplication.translate(
#                         "QgsFmvPlayer", "Meta update failed! "), " Packet:" + str(packet) + ", error:" + str(inst), level=QGis.Warning)

    def callBackMetadata(self, currentTime, nextTime):
        """ Metadata CallBack """
        try:
            port = int(self.fileName.split(':')[2])
            t = callBackMetadataThread(cmds=[
                '-i',
                self.fileName.replace(str(port), str(
                    port + 1)), '-ss', currentTime, '-to', nextTime, '-map',
                'data-re', '-preset', 'ultrafast', '-f', 'data', '-'
            ])
            t.start()
            t.join(1)
            if t.is_alive():
                t.p.terminate()
                t.join()

            qgsu.showUserAndLogMessage("",
                                       "callBackMetadataThread self.stdout: " +
                                       str(t.stdout),
                                       onlyLog=True)

            if t.stdout == b'':
                return

            self.packetStreamParser(t.stdout)

        except Exception as e:
            qgsu.showUserAndLogMessage(
                QCoreApplication.translate("QgsFmvPlayer",
                                           "Metadata Callback Failed! : "),
                str(e))

    def GetPacketData(self):
        ''' Return Current Packet data '''
        return self.data

    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 Exception:
            None

    def saveInfoToJson(self):
        """ Save video Info to json """
        out_json, _ = askForFiles(self,
                                  QCoreApplication.translate(
                                      "QgsFmvPlayer", "Save Json"),
                                  isSave=True,
                                  exts="json")

        if not out_json:
            return

        taskSaveInfoToJson = QgsTask.fromFunction(
            'Save Video Info to Json Task',
            self.converter.probeToJson,
            fname=self.fileName,
            output=out_json,
            on_finished=self.finishedTask,
            flags=QgsTask.CanCancel)

        QgsApplication.taskManager().addTask(taskSaveInfoToJson)
        return

    def showVideoInfo(self):
        ''' Show default probe info '''

        taskSaveInfoToJson = QgsTask.fromFunction(
            'Show Video Info Task',
            self.converter.probeShow,
            fname=self.fileName,
            on_finished=self.finishedTask,
            flags=QgsTask.CanCancel)

        QgsApplication.taskManager().addTask(taskSaveInfoToJson)
        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.ColorDialog.exec_()
        QApplication.processEvents()
        self.ColorDialog.contrastSlider.setValue(80)
        self.ColorDialog.contrastSlider.triggerAction(
            QAbstractSlider.SliderMove)
        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, _ = os.path.splitext(os.path.basename(self.fileName))
        qgsu.createFolderByName(homefmv, root)
        self.createingMosaic = value
        # Create Group
        CreateGroupByName()
        return

    def contextMenuBarRequested(self, point):
        ''' Context Menu Menu Bar '''
        menu = QMenu('ToolBars')
        toolbars = self.findChildren(QToolBar)
        for toolbar in toolbars:
            action = menu.addAction(toolbar.windowTitle())
            action.setCheckable(True)
            action.setChecked(toolbar.isVisible())
            action.setObjectName(toolbar.windowTitle())
            action.triggered.connect(lambda _: self.ToggleQToolBar())
        menu.exec_(self.mapToGlobal(point))
        return

    def ToggleQToolBar(self):
        ''' Toggle ToolBar '''
        toolbars = self.findChildren(QToolBar)
        for toolbar in toolbars:
            if self.sender().objectName() == toolbar.windowTitle():
                toolbar.toggleViewAction().trigger()

    def contextMenuRequested(self, point):
        ''' Context Menu Video '''
        menu = QMenu('Video')

        #         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+Shift+U")
        actionMute.triggered.connect(self.setMuted)

        menu.addSeparator()
        actionAllFrames = menu.addAction(
            QCoreApplication.translate("QgsFmvPlayer", "Extract All Frames"))
        actionAllFrames.setShortcut("Ctrl+Shift+A")
        actionAllFrames.triggered.connect(self.ExtractAllFrames)

        actionCurrentFrames = menu.addAction(
            QCoreApplication.translate("QgsFmvPlayer",
                                       "Extract Current Frame"))
        actionCurrentFrames.setShortcut("Ctrl+Shift+Q")
        actionCurrentFrames.triggered.connect(self.ExtractCurrentFrame)

        menu.addSeparator()
        actionShowMetadata = menu.addAction(
            QCoreApplication.translate("QgsFmvPlayer", "Show Metadata"))
        actionShowMetadata.setShortcut("Ctrl+Shift+M")
        actionShowMetadata.triggered.connect(self.OpenQgsFmvMetadata)

        menu.exec_(self.mapToGlobal(point))

    # Start Snnipet FILTERS
    def grayFilter(self, value):
        ''' Gray Video Filter '''
        self.UncheckFilters(self.sender(), value)
        self.videoWidget.SetGray(value)
        self.videoWidget.UpdateSurface()
        return

    def MirrorHorizontalFilter(self, value):
        ''' Mirror Horizontal Video Filter '''
        self.UncheckFilters(self.sender(), value)
        self.videoWidget.SetMirrorH(value)
        self.videoWidget.UpdateSurface()
        return

    def edgeFilter(self, value):
        ''' Edge Detection Video Filter '''
        self.UncheckFilters(self.sender(), value)
        self.videoWidget.SetEdgeDetection(value)
        self.videoWidget.UpdateSurface()
        return

    def invertColorFilter(self, value):
        ''' Invert Color Video Filter '''
        self.UncheckFilters(self.sender(), value)
        self.videoWidget.SetInvertColor(value)
        self.videoWidget.UpdateSurface()
        return

    def autoContrastFilter(self, value):
        ''' Auto Contrast Video Filter '''
        self.UncheckFilters(self.sender(), value)
        self.videoWidget.SetAutoContrastFilter(value)
        self.videoWidget.UpdateSurface()
        return

    def monoFilter(self, value):
        ''' Filter Mono Video '''
        self.UncheckFilters(self.sender(), value)
        self.videoWidget.SetMonoFilter(value)
        self.videoWidget.UpdateSurface()
        return

    def magnifier(self, value):
        ''' Magnifier Glass Utils '''
        self.UncheckUtils(self.sender(), value)
        self.videoWidget.SetMagnifier(value)
        self.videoWidget.UpdateSurface()
        return

    def pointDrawer(self, value):
        ''' Draw Point '''
        self.UncheckUtils(self.sender(), value)
        self.videoWidget.SetPointDrawer(value)
        self.videoWidget.UpdateSurface()

    def lineDrawer(self, value):
        ''' Draw Line '''
        self.UncheckUtils(self.sender(), value)
        self.videoWidget.SetLineDrawer(value)
        self.videoWidget.UpdateSurface()

    def polygonDrawer(self, value):
        ''' Draw Polygon '''
        self.UncheckUtils(self.sender(), value)
        self.videoWidget.SetPolygonDrawer(value)
        self.videoWidget.UpdateSurface()

    def ojectTracking(self, value):
        ''' Object Tracking '''
        self.UncheckUtils(self.sender(), value)
        self.videoWidget.SetObjectTracking(value)
        self.videoWidget.UpdateSurface()

    def VideoRuler(self, value):
        ''' Video Ruler '''
        self.UncheckUtils(self.sender(), value)
        self.videoWidget.SetRuler(value)
        if value:
            self.player.pause()
            self.btn_play.setIcon(QIcon(":/imgFMV/images/play-arrow.png"))
        else:
            self.videoWidget.ResetDrawRuler()
            self.player.play()
            self.btn_play.setIcon(QIcon(":/imgFMV/images/pause.png"))

        self.videoWidget.UpdateSurface()

    def VideoCensure(self, value):
        ''' Censure Video Parts'''
        self.UncheckUtils(self.sender(), value)
        self.videoWidget.SetCensure(value)
        self.videoWidget.UpdateSurface()
        return

    def UncheckUtils(self, sender, value):
        ''' Uncheck Utils Video '''
        self.actionMagnifying_glass.setChecked(False)
        self.actionDraw_Pinpoint.setChecked(False)
        self.actionDraw_Line.setChecked(False)
        self.actionDraw_Polygon.setChecked(False)
        self.actionObject_Tracking.setChecked(False)
        self.actionRuler.setChecked(False)
        self.actionCensure.setChecked(False)

        self.videoWidget.RestoreDrawer()

        sender.setChecked(value)
        return

    def UncheckFilters(self, sender, value):
        ''' Uncheck Filters Video '''
        self.actionGray.setChecked(False)
        self.actionInvert_Color.setChecked(False)
        self.actionMono_Filter.setChecked(False)
        self.actionCanny_edge_detection.setChecked(False)
        self.actionAuto_Contrast_Filter.setChecked(False)
        self.actionMirroredH.setChecked(False)

        self.videoWidget.RestoreFilters()

        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'''
        # Prevent Error in a Video Utils.Disable Magnifier
        if self.actionMagnifying_glass.isChecked():
            self.actionMagnifying_glass.trigger()
        # Stop Video
        self.fakeStop()
        return

    def volume(self):
        ''' Volume Slider '''
        return self.volumeSlider.value()

    def setVolume(self, volume):
        ''' Tooltip and set Volume value and icon '''
        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
            currentTimeInfo = _seconds_to_time_frac(currentInfo)
            # Get Metadata from buffer
            if not self.isStreaming:
                self.get_metadata_from_buffer(currentTimeInfo)
            else:
                qgsu.showUserAndLogMessage("", "Streaming on ", onlyLog=True)
                nextTime = currentInfo + self.pass_time / 1000
                nextTimeInfo = _seconds_to_time_frac(nextTime)
                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 is QMediaPlayer.LoadingMedia or status is QMediaPlayer.StalledMedia or status is QMediaPlayer.InvalidMedia:
            self.videoAvailableChanged(False)
        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()
            #             if "udp://" in videoPath:
            #                 host, port = videoPath.split("://")[1].split(":")
            #                 receiver = UDPClient(host, int(port), type="udp")
            #                 receiver.show()
            #                 self.close()
            #                 return
            #             if "tcp://" in videoPath:
            #                 host, port = videoPath.split("://")[1].split(":")
            #                 receiver = UDPClient(host, port, type="tcp")
            #                 receiver.show()
            #                 self.close()
            #                 return
            self.fileName = videoPath
            self.playlist = QMediaPlaylist()
            if self.isStreaming:
                url = QUrl(videoPath)
            else:
                url = QUrl.fromLocalFile(videoPath)
            qgsu.showUserAndLogMessage("", "Added: " + str(url), onlyLog=True)
            self.playlist.addMedia(QMediaContent(url))
            self.player.setPlaylist(self.playlist)

            self.setWindowTitle(
                QCoreApplication.translate("QgsFmvPlayer", 'Playing : ') +
                os.path.basename(os.path.normpath(videoPath)))

            CreateVideoLayers()
            self.clearMetadata()

            self.HasFileAudio = True
            if not self.HasAudio(videoPath):
                self.actionAudio.setEnabled(False)
                self.actionSave_Audio.setEnabled(False)
                self.HasFileAudio = False

            # Recenter map on video initial point
            if self.initialPt:
                rect = QgsRectangle(self.initialPt[1], self.initialPt[0],
                                    self.initialPt[1], self.initialPt[0])
                self.iface.mapCanvas().setExtent(rect)
                self.iface.mapCanvas().refresh()

            self.playClicked(True)

        except Exception as e:
            qgsu.showUserAndLogMessage(QCoreApplication.translate(
                "QgsFmvPlayer", 'Open Video File : '),
                                       str(e),
                                       level=QGis.Warning)

    def ReciconUpdate(self, _):
        ''' Record Button Icon Effect '''
        self.btn_Rec.setIcon(QIcon(self.RecGIF.currentPixmap()))

    def StopRecordAnimation(self):
        '''Stop record gif animation'''
        self.RecGIF.frameChanged.disconnect(self.ReciconUpdate)
        self.RecGIF.stop()
        self.btn_Rec.setIcon(QIcon(":/imgFMV/images/record.png"))

    # TODO: Make in other thread
    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, _ = askForFiles(self,
                                 QCoreApplication.translate(
                                     "QgsFmvPlayer", "Save video record"),
                                 isSave=True,
                                 exts=file_extension[1:])

            if not out:
                self.StopRecordAnimation()
                return

            p = _spawn([
                '-i', self.fileName, '-ss', self.startRecord, '-to',
                self.endRecord, '-preset', 'ultrafast', '-c', 'copy', out
            ])
            p.communicate()
            qgsu.showUserAndLogMessage(
                QCoreApplication.translate("QgsFmvPlayer",
                                           "Save file succesfully!"))

            self.StopRecordAnimation()
        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 fakeStop(self):
        '''self.player.stop() make a black screen and not reproduce it again'''
        self.player.pause()
        self.StartMedia()
        self.btn_play.setIcon(QIcon(":/imgFMV/images/play-arrow.png"))

    def playClicked(self, _):
        ''' Stop and Play video '''
        if self.playerState in (QMediaPlayer.StoppedState,
                                QMediaPlayer.PausedState):
            self.btn_play.setIcon(QIcon(":/imgFMV/images/pause.png"))
            # Uncheck Ruler
            self.videoWidget.ResetDrawRuler()
            self.actionRuler.setChecked(False)
            self.videoWidget.SetRuler(False)
            # Play Video
            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 '''
        out, _ = askForFiles(self,
                             QCoreApplication.translate(
                                 "QgsFmvPlayer", "Save Video as..."),
                             isSave=True,
                             exts=[
                                 "mp4", "ogg", "avi", "mkv", "webm", "flv",
                                 "mov", "mpg", "mp3"
                             ])

        if not out:
            return

        # TODO : Make Correct format Conversion and embebed metadata
        info = self.converter.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
                }
            }

        taskConvertVideo = QgsTask.fromFunction('Converting Video Task',
                                                self.converter.convert,
                                                infile=self.fileName,
                                                outfile=out,
                                                options=options,
                                                twopass=False,
                                                on_finished=self.finishedTask,
                                                flags=QgsTask.CanCancel)

        QgsApplication.taskManager().addTask(taskConvertVideo)

    def CreateBitratePlot(self):
        ''' Create video Plot Bitrate Thread '''
        sender = self.sender().objectName()

        if sender == "actionAudio":
            taskactionAudio = QgsTask.fromFunction(
                'Show Audio Bitrate',
                self.BitratePlot.CreatePlot,
                fileName=self.fileName,
                output=None,
                t='audio',
                on_finished=self.finishedTask,
                flags=QgsTask.CanCancel)

            QgsApplication.taskManager().addTask(taskactionAudio)

        elif sender == "actionVideo":
            taskactionVideo = QgsTask.fromFunction(
                'Show Video Bitrate',
                self.BitratePlot.CreatePlot,
                fileName=self.fileName,
                output=None,
                t='video',
                on_finished=self.finishedTask,
                flags=QgsTask.CanCancel)

            QgsApplication.taskManager().addTask(taskactionVideo)

        elif sender == "actionSave_Audio":
            fileaudio, _ = askForFiles(self,
                                       QCoreApplication.translate(
                                           "QgsFmvPlayer",
                                           "Save Audio Bitrate Plot"),
                                       isSave=True,
                                       exts=[
                                           "png", "pdf", "pgf", "eps", "ps",
                                           "raw", "rgba", "svg", "svgz"
                                       ])

            if not fileaudio:
                return

            taskactionSave_Audio = QgsTask.fromFunction(
                'Save Action Audio Bitrate',
                self.BitratePlot.CreatePlot,
                fileName=self.fileName,
                output=fileaudio,
                t='audio',
                on_finished=self.finishedTask,
                flags=QgsTask.CanCancel)

            QgsApplication.taskManager().addTask(taskactionSave_Audio)

        elif sender == "actionSave_Video":
            filevideo, _ = askForFiles(self,
                                       QCoreApplication.translate(
                                           "QgsFmvPlayer",
                                           "Save Video Bitrate Plot"),
                                       isSave=True,
                                       exts=[
                                           "png", "pdf", "pgf", "eps", "ps",
                                           "raw", "rgba", "svg", "svgz"
                                       ])

            if not filevideo:
                return

            taskactionSave_Video = QgsTask.fromFunction(
                'Save Action Video Bitrate',
                self.BitratePlot.CreatePlot,
                fileName=self.fileName,
                output=filevideo,
                t='video',
                on_finished=self.finishedTask,
                flags=QgsTask.CanCancel)

            QgsApplication.taskManager().addTask(taskactionSave_Video)

    def finishedTask(self, e, result=None):
        """ Common finish task function """
        if e is None:
            if result is None:
                qgsu.showUserAndLogMessage(QCoreApplication.translate(
                    "QgsFmvPlayer", 'Completed with no exception and no result '\
                    '(probably manually canceled by the user)'), level=QGis.Warning)
            else:
                if "Georeferencing" in result['task']:
                    return
                qgsu.showUserAndLogMessage(
                    QCoreApplication.translate(
                        "QgsFmvPlayer", "Succesfully " + result['task'] + "!"))
                if "Bitrate" in result['task']:
                    self.matplot = ShowPlot(self.BitratePlot.bitrate_data,
                                            self.BitratePlot.frame_count,
                                            self.fileName,
                                            self.BitratePlot.output)
                if result['task'] == 'Show Video Info Task':
                    self.showVideoInfoDialog(self.converter.bytes_value)
        else:
            qgsu.showUserAndLogMessage(QCoreApplication.translate(
                "QgsFmvPlayer", "Failed " + result['task'] + "!"),
                                       level=QGis.Warning)
            raise e

    def ExtractAllFrames(self):
        """ Extract All Video Frames Task """
        directory = askForFolder(
            self,
            QCoreApplication.translate("QgsFmvPlayer", "Save all Frames"),
            options=QFileDialog.DontResolveSymlinks | QFileDialog.ShowDirsOnly)

        if directory:
            taskExtractAllFrames = QgsTask.fromFunction(
                'Save All Frames Task',
                self.SaveAllFrames,
                fileName=self.fileName,
                directory=directory,
                on_finished=self.finishedTask,
                flags=QgsTask.CanCancel)

            QgsApplication.taskManager().addTask(taskExtractAllFrames)
        return

    def SaveAllFrames(self, task, fileName, directory):
        vidcap = cv2.VideoCapture(fileName)
        length = int(vidcap.get(cv2.CAP_PROP_FRAME_COUNT))
        count = 0
        while not task.isCanceled():
            _, image = vidcap.read()
            cv2.imwrite(directory + "\\frame_%d.jpg" % count,
                        image)  # save frame as JPEG file
            task.setProgress(count * 100 / length)
            count += 1
        vidcap.release()
        cv2.destroyAllWindows()
        if task.isCanceled():
            return None
        return {'task': task.description()}

    def ExtractCurrentFrame(self):
        """ Extract Current Frame Task """
        image = self.videoWidget.GetCurrentFrame()
        output, _ = askForFiles(self,
                                QCoreApplication.translate(
                                    "QgsFmvPlayer", "Save Current Frame"),
                                isSave=True,
                                exts=["png", "jpg", "bmp", "tiff"])

        if not output:
            return

        taskCurrentFrame = QgsTask.fromFunction('Save Current Frame Task',
                                                self.SaveCapture,
                                                image=image,
                                                output=output,
                                                on_finished=self.finishedTask,
                                                flags=QgsTask.CanCancel)

        QgsApplication.taskManager().addTask(taskCurrentFrame)
        return

    def SaveCapture(self, task, image, output):
        ''' Save Current Frame '''
        image.save(output)
        if task.isCanceled():
            return None
        return {'task': task.description()}

    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 showVideoInfoDialog(self, outjson):
        """ Show Video Information Dialog """
        view = QTreeView()
        model = QJsonModel()
        view.setModel(model)
        model.loadJsonFromConsole(outjson)

        self.VideoInfoDialog = QDialog(self)
        self.VideoInfoDialog.setWindowTitle(
            QCoreApplication.translate("QgsFmvPlayer", "Video Information : ")
            + self.fileName)
        self.VideoInfoDialog.setWindowIcon(
            QIcon(":/imgFMV/images/video-info.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, _):
        """ Close Event """
        self.stop()
        self.parent._PlayerDlg = None
        self.parent.ToggleActiveFromTitle()
        RemoveVideoLayers()
        RemoveGroupByName()
        ResetData()

        try:
            self.metadataDlg.hide()
        except Exception:
            None
        try:
            self.matplot.close()
        except Exception:
            None
        # Restore Filters State
        self.videoWidget.RestoreFilters()
Ejemplo n.º 25
0
class Player(QWidget):
    """Sub-class of QWidget"""
    def __init__(self, parent=None, *args, **kwargs):
        """Initialize class attributes"""
        super(Player, self).__init__(parent, *args, **kwargs)
        self.init_ui()

    def init_ui(self):
        """Create local components"""
        # loop
        self.loop = False
        # time label text
        self.time_text = '{:0>2d}:{:0>2d}:{:0>2d}/{:0>2d}:{:0>2d}:{:0>2d}'
        self.hours = self.minutes = self.seconds = 0
        # create media player object
        self.mediaPlayer = QMediaPlayer(self, QMediaPlayer.VideoSurface)
        # create videowidget object
        self.videoWidget = QVideoWidget()

        # create open button
        self.btn_size = QSize(16, 16)
        openButton = Button("Open")
        openButton.setToolTip("Open Media File")
        openButton.setStatusTip("Open Media File")
        openButton.setFixedHeight(24)
        openButton.setIconSize(self.btn_size)
        openButton.setIcon(
            QIcon.fromTheme("document-open", QIcon("Icons/Open.bmp")))
        # openButton.setStyleSheet("background-color: #B0C4DE")
        openButton.clicked.connect(self.abrir)

        # create play button
        self.playButton = Button()
        self.playButton.setEnabled(False)
        self.playButton.setFixedHeight(24)
        self.playButton.setIconSize(self.btn_size)
        self.playButton.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay))
        # self.playButton.setStyleSheet("background-color: #B0C4DE")
        self.playButton.clicked.connect(self.play)

        # create slider
        self.positionSlider = PositionSlider(self.mediaPlayer, Qt.Horizontal)
        self.positionSlider.setRange(0, 0)
        self.positionSlider.setObjectName("positionSlider")

        # create status bar
        self.statusBar = QStatusBar()
        self.statusBar.setFont(QFont("Noto sans", 8))
        self.statusBar.setFixedHeight(14)
        self.statusBar.setStyleSheet('color:#ffffff')

        # create duration time label
        self.durationLabel = QLabel()
        self.durationLabel.setStyleSheet(
            'background-color:rgba(255, 255, 255, 0)')
        self.durationLabel.setText('00:00:00/00:00:00')

        # create hbox layout
        controlLayoutWidget = QWidget(self)
        controlLayout = QHBoxLayout(controlLayoutWidget)
        controlLayoutWidget.setLayout(controlLayout)
        controlLayout.setContentsMargins(2, 2, 2, 2)
        # set widgets to the hbox layout
        controlLayout.addWidget(openButton)
        controlLayout.addWidget(self.playButton)
        controlLayout.addWidget(self.positionSlider)
        controlLayout.addWidget(self.durationLabel)
        # change hbox color
        controlLayoutWidget.setStyleSheet(
            'background-color:rgba(255, 255, 255, 50)')
        controlLayoutWidget.setWindowOpacity(0.1)

        # create vbox layout
        self.layout = QVBoxLayout()
        self.layout.setSpacing(0)
        # set widgets to vbox layout
        self.layout.addWidget(self.videoWidget)
        self.layout.addWidget(controlLayoutWidget)
        self.sub_controls()
        self.layout.addWidget(self.statusBar)

        self.setLayout(self.layout)

        self.mediaPlayer.setVideoOutput(self.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)
        self.statusBar.showMessage('{:->33s}{:-<33s}'.format("Have Fun", ""))
        self.key_bindings()

    def key_bindings(self):
        # bind Keys to methods
        self.onplaypause = self.create_shortcut(Qt.Key_Space, self.videoWidget,
                                                self.play)  # Space key for

        self.on_fscreen = self.create_shortcut(
            Qt.Key_F, self.videoWidget,
            self.toggle_fullscreen)  # F key for fullscreen on

        self.onforward = self.create_shortcut(
            Qt.Key_Right, self.videoWidget,
            self.forward)  # Right key for forward

        self.redvolume = self.create_shortcut(
            Qt.Key_Down, self.videoWidget,
            self.red_volume)  # Down key reduce volume

        self.incvolume = self.create_shortcut(
            Qt.Key_Up, self.videoWidget,
            self.inc_volume)  # Up key increase volume

        self.onsetloop = self.create_shortcut(
            "L",
            self.videoWidget,  # L key for repeat on,
            (lambda self=self: self.repeat.toggle() or self.play_again()))

        self.onrewind = self.create_shortcut(
            Qt.Key_Left, self.videoWidget, self.rewind)  # Left key for rewind

        self.volmute = self.create_shortcut(Qt.Key_M, self.videoWidget,
                                            self.mute)  # M for mute and unmute

        self.onopen = self.create_shortcut('Ctrl+O', self.videoWidget,
                                           self.abrir)  # Ctrl+O for open

        self.onstop = self.create_shortcut(Qt.Key_S, self.videoWidget,
                                           self.stop_media)  # S key for stop

    def create_shortcut(self, sequence, widget, obj):
        """generate key shortcuts"""
        return QShortcut(QKeySequence(sequence),
                         widget,
                         obj,
                         context=Qt.ApplicationShortcut)

    def sub_controls(self):
        """Repeat, volume, and mute controls"""
        # repeat button
        self.repeat = Button()
        self.repeat.setCheckable(True)
        self.repeat.toggle()
        self.repeat.setIconSize(self.btn_size)
        self.repeat.setFixedHeight(24)
        self.repeat.setFixedWidth(26)
        self.repeat.setToolTip("repeat")
        self.repeat.setStatusTip("repeat")

        # Icons to correspond with button state
        icon = QIcon()
        icon.addPixmap(QPixmap(os.path.join(FOLDER, "Icons/repeat(1).png")),
                       QIcon.Normal, QIcon.On)
        icon.addPixmap(QPixmap(os.path.join(FOLDER, "Icons/repeat(2).png")),
                       QIcon.Active)
        self.repeat.setIcon(icon)
        # self.repeat.setStyleSheet("background-color: #B0C4DE; margin: 0px 0px 0px 2px;")
        self.repeat.clicked.connect(self.play_again)

        # stop button
        self.stop = Button()
        self.stop.setIconSize(self.btn_size)
        self.stop.setFixedHeight(24)
        self.stop.setFixedWidth(26)
        self.stop.setToolTip("Stop playing media")
        self.stop.setStatusTip("Stop playing media")
        self.stop.setIcon(self.style().standardIcon(QStyle.SP_MediaStop))
        # self.stop.setStyleSheet("background-color: #B0C4DE; margin: 0px 0px 0px 2px;")
        self.stop.clicked.connect(self.stop_media)

        # volume slider
        self.volumeSlider = VolumeSlider(self.mediaPlayer, Qt.Horizontal)
        self.volumeSlider.setRange(0, 100)
        self.volumeSlider.setFixedWidth(200)
        self.mediaPlayer.setVolume(50)
        self.volumeSlider.sliderMoved.connect(self.set_volume)

        # volume button
        self.volume = Button(self)
        self.volume.setIconSize(self.btn_size)
        self.volume.setFixedHeight(24)
        self.volume.setFixedWidth(26)
        self.volume.setToolTip("Mute or Unmute")
        self.volume.setStatusTip("Mute or Unmute")
        self.volume.setIcon(self.style().standardIcon(QStyle.SP_MediaVolume))
        # self.volume.setStyleSheet("background-color: #B0C4DE; margin: 0px 0px 0px 2px;")
        self.volume.clicked.connect(self.mute)

        # create control widget
        subControlWidget = QWidget(self)
        subControlWidget.setStyleSheet(
            'background-color:rgba(255, 255, 255, 30)')
        # create Horizontal Layout
        subControlLayout = QHBoxLayout(subControlWidget)
        subControlLayout.setContentsMargins(0, 0, 0, 0)
        subControlLayout.addWidget(self.repeat, 0, Qt.AlignLeft)
        subControlLayout.addWidget(self.stop, 1, Qt.AlignLeft)
        # sub layout for volume control
        self.sub_layout = QHBoxLayout()
        self.sub_layout.addWidget(self.volume)
        self.sub_layout.addWidget(self.volumeSlider)
        subControlLayout.addLayout(self.sub_layout)
        subControlLayout.setContentsMargins(2, 2, 2, 2)

        self.layout.addWidget(subControlWidget)

    def abrir(self, event=None, url=None):
        """" Equivalent to open for most GUIs"""
        fileName = None
        if self.videoWidget.isFullScreen():
            self.toggle_fullscreen()
        if not url:
            fileName, _ = QFileDialog.getOpenFileName(self, "Select media")
            if fileName:
                self.mediaPlayer.setMedia(
                    QMediaContent(QUrl.fromLocalFile(fileName)))
        else:
            self.mediaPlayer.setMedia(QMediaContent(QUrl(url)))
        if url or fileName:
            self.volumeSlider.setValue(self.mediaPlayer.volume())
            self.playButton.setEnabled(True)
            self.statusBar.showMessage((fileName or url))
            if not self.loop:
                self.play()

    def play(self):
        """Start media player"""
        if self.playButton.isEnabled():
            if self.mediaPlayer.state() == QMediaPlayer.PlayingState:
                self.mediaPlayer.pause()
            else:
                self.mediaPlayer.play()

    def mediaStateChanged(self, state):
        """Callback for media player state change"""
        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))
        if state == QMediaPlayer.StoppedState and self.loop:
            self.play()

    def positionChanged(self, position):
        """Callback for media player position change"""
        if self.mediaPlayer.state() == QMediaPlayer.StoppedState:
            position = 0
        self.positionSlider.setValue(position)
        hours, position = position // 3600000, position % 3600000
        minutes, position = position // 60000, position % 60000
        seconds = position // 1000
        self.durationLabel.setText(
            self.time_text.format(hours, minutes, seconds, self.hours,
                                  self.minutes, self.seconds))

    def durationChanged(self, duration):
        """Callback for media player duration of media change"""
        self.positionSlider.setRange(0, duration)
        self.hours, duration = duration // 3600000, duration % 3600000
        self.minutes, duration = duration // 60000, duration % 60000
        self.seconds = duration // 1000
        self.durationLabel.setText(
            self.time_text.format(0, 0, 0, self.hours, self.minutes,
                                  self.seconds))

    def setPosition(self, position):
        """set media player play position"""
        self.mediaPlayer.setPosition(position)

    def handleError(self):
        """Callback for multiplayer errors"""
        self.playButton.setEnabled(False)
        self.statusBar.showMessage("Error: " + self.mediaPlayer.errorString())

    def play_again(self):
        """Set repeat on or off"""
        self.loop = not self.loop

    def stop_media(self):
        """Callback for stop button"""
        if self.loop:
            self.loop = False
            self.repeat.toggle()
        self.mediaPlayer.stop()

    def toggle_fullscreen(self):
        """Toggle in or out of fullscreen mode"""
        self.videoWidget.setWindowFlags(Qt.FramelessWindowHint
                                        | Qt.WindowStaysOnTopHint)
        if self.videoWidget.isFullScreen():
            self.videoWidget.setFullScreen(False)
            self.videoWidget.setWindowState(Qt.WindowNoState)
            self.videoWidget.setParent(self)
            self.layout.insertWidget(0, self.videoWidget)
            self.videoWidget.showNormal()
            self.show()
        else:
            self.videoWidget.setFullScreen(True)
            self.hide()

    def rewind(self, lapse=2500):
        """Rewind the current media file by 1 second"""
        new_position = self.mediaPlayer.position() - lapse
        self.setPosition(new_position)

    def forward(self, lapse=2500):
        """Forward media file by 1 second"""
        new_position = self.mediaPlayer.position() + lapse
        self.setPosition(new_position)

    def set_volume(self, vol=0):
        """Set media player volume volume"""
        if vol:
            self.mediaPlayer.setVolume(vol)

    def red_volume(self, vol=1):
        """Reduce volume by a factor of 0.01"""
        volume = self.mediaPlayer.volume()
        if volume >= 0:
            new_volume = volume - 1
            self.volumeSlider.setValue(new_volume)
            self.set_volume(new_volume)

    def inc_volume(self, vol=1):
        """Increase volume by a factor of 0.01"""
        volume = self.mediaPlayer.volume()
        if self.mediaPlayer.isMuted():
            self.mediaPlayer.setMuted(False)
            self.volume.setIcon(self.style().standardIcon(
                QStyle.SP_MediaVolume))
        if volume <= 100:
            new_volume = volume + 1
            self.volumeSlider.setValue(new_volume)
            self.set_volume(new_volume)

    def mute(self):
        """Mute media player"""
        if self.mediaPlayer.isMuted():
            self.mediaPlayer.setMuted(False)
            self.volume.setIcon(self.style().standardIcon(
                QStyle.SP_MediaVolume))
        else:
            self.mediaPlayer.setMuted(True)
            self.volume.setIcon(self.style().standardIcon(
                QStyle.SP_MediaVolumeMuted))
Ejemplo n.º 26
0
class QmyMainWindow(QMainWindow):
    def __init__(self, parent=None):
        super().__init__(parent)  #调用父类构造函数,创建窗体
        self.ui = Ui_MainWindow()  #创建UI对象
        self.ui.setupUi(self)  #构造UI界面

        self.player = QMediaPlayer(self)  #创建视频播放器
        self.player.setNotifyInterval(1000)  #信息更新周期, ms

        scene = QGraphicsScene(self)
        self.ui.graphicsView.setScene(scene)

        self.videoItem = QGraphicsVideoItem()  #视频显示画面
        self.videoItem.setSize(QSizeF(320, 220))
        self.videoItem.setFlag(QGraphicsItem.ItemIsMovable)
        self.videoItem.setFlag(QGraphicsItem.ItemIsSelectable)
        self.videoItem.setFlag(QGraphicsItem.ItemIsFocusable)

        scene.addItem(self.videoItem)
        self.player.setVideoOutput(self.videoItem)  #设置视频显示图形项

        self.textItem = QGraphicsTextItem("面朝大海,春暖花开")  #弹幕文字
        font = self.textItem.font()
        font.setPointSize(20)
        self.textItem.setFont(font)
        self.textItem.setDefaultTextColor(Qt.red)
        self.textItem.setPos(100, 220)
        self.textItem.setFlag(QGraphicsItem.ItemIsMovable)
        self.textItem.setFlag(QGraphicsItem.ItemIsSelectable)
        self.textItem.setFlag(QGraphicsItem.ItemIsFocusable)
        scene.addItem(self.textItem)

        self.ui.btnText.setCheckable(True)  #弹幕文字按钮
        self.ui.btnText.setChecked(True)

        self.__duration = ""
        self.__curPos = ""
        self.player.stateChanged.connect(self.do_stateChanged)
        self.player.positionChanged.connect(self.do_positionChanged)
        self.player.durationChanged.connect(self.do_durationChanged)

##  ==============自定义功能函数========================

##  ==============event处理函数==========================

    def closeEvent(self, event):  #窗体关闭时
        # 窗口关闭时不能自动停止播放,需手动停止
        if (self.player.state() == QMediaPlayer.PlayingState):
            self.player.stop()

##  ==========由connectSlotsByName()自动连接的槽函数============

    @pyqtSlot()  ##打开文件
    def on_btnOpen_clicked(self):
        curPath = QDir.currentPath()  #获取系统当前目录
        ##      curPath=os.getcwd()
        title = "选择视频文件"
        filt = "视频文件(*.wmv *.avi);;所有文件(*.*)"
        fileName, flt = QFileDialog.getOpenFileName(self, title, curPath, filt)

        if (fileName == ""):
            return

        fileInfo = QFileInfo(fileName)
        baseName = fileInfo.fileName()
        ##      baseName=os.path.basename(fileName)
        self.ui.LabCurMedia.setText(baseName)
        curPath = fileInfo.absolutePath()
        QDir.setCurrent(curPath)  #重设当前目录

        media = QMediaContent(QUrl.fromLocalFile(fileName))

        self.player.setMedia(media)  #设置播放文件
        self.player.play()

    @pyqtSlot()  ##播放
    def on_btnPlay_clicked(self):
        self.player.play()

    @pyqtSlot()  ##暂停
    def on_btnPause_clicked(self):
        self.player.pause()

    @pyqtSlot()  ##停止
    def on_btnStop_clicked(self):
        self.player.stop()

    @pyqtSlot()  ##全屏
    def on_btnFullScreen_clicked(self):
        self.videoWidget.setFullScreen(True)

    @pyqtSlot()  ##静音按钮
    def on_btnSound_clicked(self):
        mute = self.player.isMuted()
        self.player.setMuted(not mute)
        if mute:
            self.ui.btnSound.setIcon(QIcon(":/icons/images/volumn.bmp"))
        else:
            self.ui.btnSound.setIcon(QIcon(":/icons/images/mute.bmp"))

    @pyqtSlot(int)  ##音量调节
    def on_sliderVolumn_valueChanged(self, value):
        self.player.setVolume(value)

    @pyqtSlot(int)  ##播放进度调节
    def on_sliderPosition_valueChanged(self, value):
        self.player.setPosition(value)

    @pyqtSlot()  ##放大
    def on_btnZoomIn_clicked(self):
        sc = self.videoItem.scale()
        self.videoItem.setScale(sc + 0.1)

    @pyqtSlot()  ##缩小
    def on_btnZoomOut_clicked(self):
        sc = self.videoItem.scale()
        self.videoItem.setScale(sc - 0.1)

    @pyqtSlot(bool)  ##弹幕
    def on_btnText_clicked(self, checked):
        self.textItem.setVisible(checked)

##  =============自定义槽函数===============================

    def do_stateChanged(self, state):
        isPlaying = (state == QMediaPlayer.PlayingState)

        self.ui.btnPlay.setEnabled(not isPlaying)
        self.ui.btnPause.setEnabled(isPlaying)
        self.ui.btnStop.setEnabled(isPlaying)

    def do_durationChanged(self, duration):
        self.ui.sliderPosition.setMaximum(duration)

        secs = duration / 1000  #秒
        mins = secs / 60  #分钟
        secs = secs % 60  #余数秒
        self.__duration = "%d:%d" % (mins, secs)
        self.ui.LabRatio.setText(self.__curPos + "/" + self.__duration)

    def do_positionChanged(self, position):
        if (self.ui.sliderPosition.isSliderDown()):
            return  #如果正在拖动滑条,退出

        self.ui.sliderPosition.setSliderPosition(position)

        secs = position / 1000  #秒
        mins = secs / 60  #分钟
        secs = secs % 60  #余数秒
        self.__curPos = "%d:%d" % (mins, secs)
        self.ui.LabRatio.setText(self.__curPos + "/" + self.__duration)
Ejemplo n.º 27
0
class QmyMainWindow(QMainWindow):
    def __init__(self, parent=None):
        super().__init__(parent)  #调用父类构造函数,创建窗体
        self.ui = Ui_MainWindow()  #创建UI对象
        self.ui.setupUi(self)  #构造UI界面

        self.player = QMediaPlayer(self)  #创建视频播放器
        self.player.setNotifyInterval(1000)  #信息更新周期, ms
        self.player.setVideoOutput(self.ui.videoWidget)  #视频显示组件

        self.ui.videoWidget.installEventFilter(self)  #事件过滤器

        self.__duration = ""
        self.__curPos = ""

        self.player.stateChanged.connect(self.do_stateChanged)
        self.player.positionChanged.connect(self.do_positionChanged)
        self.player.durationChanged.connect(self.do_durationChanged)

##  ==============自定义功能函数========================

##  ==============event处理函数==========================

    def closeEvent(self, event):  #窗体关闭时
        # 窗口关闭时不能自动停止播放,需手动停止
        if (self.player.state() == QMediaPlayer.PlayingState):
            self.player.stop()

    def eventFilter(self, watched, event):  ##事件过滤器
        if (watched != self.ui.videoWidget):
            return super().eventFilter(watched, event)

        #鼠标左键按下时,暂停或继续播放
        if event.type() == QEvent.MouseButtonPress:
            if event.button() == Qt.LeftButton:
                if self.player.state() == QMediaPlayer.PlayingState:
                    self.player.pause()
                else:
                    self.player.play()

        #全屏状态时,按ESC键退出全屏
        if event.type() == QEvent.KeyPress:
            if event.key() == Qt.Key_Escape:
                if self.ui.videoWidget.isFullScreen():
                    self.ui.videoWidget.setFullScreen(False)

        return super().eventFilter(watched, event)

##  ==========由connectSlotsByName()自动连接的槽函数============

    @pyqtSlot()  ##打开文件
    def on_btnOpen_clicked(self):
        ##      curPath=os.getcwd()  #获取系统当前目录
        curPath = QDir.currentPath()  #获取系统当前目录
        title = "选择视频文件"
        filt = "视频文件(*.wmv *.avi);;所有文件(*.*)"
        fileName, flt = QFileDialog.getOpenFileName(self, title, curPath, filt)
        if (fileName == ""):
            return

        fileInfo = QFileInfo(fileName)
        baseName = fileInfo.fileName()
        ##      baseName=os.path.basename(fileName)
        self.ui.LabCurMedia.setText(baseName)

        curPath = fileInfo.absolutePath()
        QDir.setCurrent(curPath)  #重设当前目录

        media = QMediaContent(QUrl.fromLocalFile(fileName))
        self.player.setMedia(media)  #设置播放文件
        self.player.play()

    @pyqtSlot()  ##播放
    def on_btnPlay_clicked(self):
        self.player.play()

    @pyqtSlot()  ##暂停
    def on_btnPause_clicked(self):
        self.player.pause()

    @pyqtSlot()  ##停止
    def on_btnStop_clicked(self):
        self.player.stop()

    @pyqtSlot()  ##全屏
    def on_btnFullScreen_clicked(self):
        self.ui.videoWidget.setFullScreen(True)

    @pyqtSlot()  ##静音按钮
    def on_btnSound_clicked(self):
        mute = self.player.isMuted()
        self.player.setMuted(not mute)
        if mute:
            self.ui.btnSound.setIcon(QIcon(":/icons/images/volumn.bmp"))
        else:
            self.ui.btnSound.setIcon(QIcon(":/icons/images/mute.bmp"))

    @pyqtSlot(int)  ##音量调节
    def on_sliderVolumn_valueChanged(self, value):
        self.player.setVolume(value)

    @pyqtSlot(int)  ##播放进度调节
    def on_sliderPosition_valueChanged(self, value):
        self.player.setPosition(value)

##  =============自定义槽函数===============================

    def do_stateChanged(self, state):  ##状态变化
        isPlaying = (state == QMediaPlayer.PlayingState)

        self.ui.btnPlay.setEnabled(not isPlaying)
        self.ui.btnPause.setEnabled(isPlaying)
        self.ui.btnStop.setEnabled(isPlaying)

    def do_durationChanged(self, duration):  ##文件长度变化
        self.ui.sliderPosition.setMaximum(duration)

        secs = duration / 1000  #秒
        mins = secs / 60  #分钟
        secs = secs % 60  #余数秒
        self.__duration = "%d:%d" % (mins, secs)
        self.ui.LabRatio.setText(self.__curPos + "/" + self.__duration)

    def do_positionChanged(self, position):  ##当前播放位置变化
        if (self.ui.sliderPosition.isSliderDown()):
            return  #如果正在拖动滑条,退出

        self.ui.sliderPosition.setSliderPosition(position)
        secs = position / 1000  #秒
        mins = secs / 60  #分钟
        secs = secs % 60  #余数秒
        self.__curPos = "%d:%d" % (mins, secs)
        self.ui.LabRatio.setText(self.__curPos + "/" + self.__duration)
Ejemplo n.º 28
0
class QGisMap(QtWidgets.QWidget, Ui_Form):
    
    def __init__(self,projectfile,MainWidget):
        QtWidgets.QMainWindow.__init__(self)
        if os.name == 'nt':
            ffmpeg = os.path.dirname(__file__)[0:-18]+'/Video_UAV_Tracker/FFMPEG/ffmpeg.exe'
            versione = 'ffmpeg.exe'
        else:
            ffmpeg = os.path.dirname(__file__)+'/FFMPEG/./ffmpeg'
            versione = 'ffmpeg'
        if os.path.exists(ffmpeg) == True:
            self.setupUi(self)
            self.setWindowFlags(Qt.WindowStaysOnTopHint)
            self.Main = MainWidget
            self.projectfile = projectfile
            with open(self.projectfile,'r') as File:
                    for line in File:
                        if line[0:19] == 'Video file location':
                            self.videoFile = line.split('=')[-1][1:-1]
                        elif line[0:23] == 'Video start at msecond:':
                            self.fps = (1 / (float(line.split()[7]))) * 1000
                            self.StartMsecond = int(line.split()[4])
                        elif line[0:4] == 'DB =':
                            DB = line.split('=')[-1][1:-1]
                            if DB == 'None':
                                self.DB = None
                            else:
                                self.DB = DB
                            break            
            self.pushButton_3.setCheckable(True)
            self.EnableMapTool = False
            self.ExtractTool = 0
            self.dockWidget_4.hide()
            self.GPXList = []
            self.positionMarker=PositionMarker(self.Main.iface.mapCanvas())               
            self.muteButton.setIcon(
                        self.style().standardIcon(QStyle.SP_MediaVolume))
            self.playButton.setIcon(
                        self.style().standardIcon(QStyle.SP_MediaPause))
            self.player = QMediaPlayer()
            self.player.setVideoOutput(self.video_frame)  
            self.playButton.clicked.connect(self.PlayPause)
            self.muteButton.clicked.connect(self.MuteUnmute)
            self.toolButton_11.clicked.connect(self.SkipBackward)
            self.toolButton_12.clicked.connect(self.SkipForward)
            self.SkipBacktoolButton_8.clicked.connect(self.BackwardFrame)
            self.SkipFortoolButton_9.clicked.connect(self.ForwardFrame)
            self.toolButton_4.clicked.connect(self.ExtractToolbar)
            self.toolButton_5.clicked.connect(self.close)   
            self.pushButtonCut_2.clicked.connect(self.ExtractCommand)
            self.pushButtonCutA_6.clicked.connect(self.ExtractFromA)
            self.pushButtonCutB_6.clicked.connect(self.ExtractToB)
            self.pushButton_5.clicked.connect(self.CancelVertex)  
            self.progressBar.hide()     
            self.Main.pushButton_2.hide()
            self.Main.pushButton_8.hide()
            self.Main.groupBox.show()
            self.Main.groupBox_4.hide()
            self.ExtractA = False
            self.ExtractB = False
            self.ExtractedDirectory = None 
            self.pushButtonCut_2.setEnabled(False)
            self.toolButton_6.setEnabled(False)
            self.LoadGPXVideoFromPrj(self.projectfile)  
        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 LoadGPXVideoFromPrj(self,VideoGisPrj):
        
        self.Polyline = []
        with open(VideoGisPrj,'r') as File:
            Counter = 0
            for line in File:
                if Counter < 5:
                    pass
                else:
                    line = line.split()
                    lat = float(line[0])
                    lon = float(line[1])
                    ele = float(line[2])
                    speed = float(line[3])
                    course = float(line[4])
                    time = line[5]
                    Point = [lat,lon,ele,speed,course,time]
                    qgsPoint = QgsPoint(lon,lat)
                    self.Polyline.append(qgsPoint)
                    self.GPXList.append(Point)
                Counter = Counter + 1
        self.GpsLayer = QgsVectorLayer("LineString?crs=epsg:4326", self.videoFile.split('.')[-2].split('/')[-1], "memory")
        self.pr = self.GpsLayer.dataProvider()
        feat = QgsFeature()
        feat.setGeometry(QgsGeometry.fromPolyline(self.Polyline))
        self.pr.addFeatures([feat])
        self.GpsLayer.updateExtents()
        if self.DB != None:
            try:
                self.DBLayer = QgsVectorLayer(self.DB,self.DB.split('.')[-2].split('/')[-1],'ogr')
                QgsProject.instance().addMapLayers([self.DBLayer,self.GpsLayer]) 
                self.AddPointMapTool = AddPointTool(self.Main.iface.mapCanvas(),self.DBLayer,self)
                self.toolButton_6.clicked.connect(self.AddPointTool)   
                self.toolButton_6.setEnabled(True)
            except:
                ret = QMessageBox.warning(self, "Warning", str(self.DB)+' is not a valid shapefile.', QMessageBox.Ok)
                return
        else:
            QgsProject.instance().addMapLayers([self.GpsLayer])    
        self.duration = len(self.GPXList)
        self.ExtractToB = self.duration
        self.horizontalSlider.setSingleStep(1000)
        self.horizontalSlider.setMinimum(0)
        self.horizontalSlider.setMaximum(len(self.GPXList)*1000)
        url = QUrl.fromLocalFile(str(self.videoFile))
        mc = QMediaContent(url)
        self.player.setMedia(mc)
        self.player.setPosition(self.StartMsecond)
        self.player.play()
        self.horizontalSlider.sliderMoved.connect(self.setPosition)
        self.player.stateChanged.connect(self.mediaStateChanged)
        self.player.positionChanged.connect(self.positionChanged)
        self.pushButton_3.clicked.connect(self.MapTool)
        self.skiptracktool = SkipTrackTool( self.Main.iface.mapCanvas(),self.GpsLayer , self)

    def AddPointTool(self):
        self.Main.iface.mapCanvas().setMapTool(self.AddPointMapTool) 
             
    def MapTool(self):
        if self.EnableMapTool == False:
            self.Main.iface.mapCanvas().setMapTool(self.skiptracktool)
            self.pushButton_3.setChecked(True)
            self.EnableMapTool = True
        else:
            self.Main.iface.mapCanvas().unsetMapTool(self.skiptracktool)
            self.pushButton_3.setChecked(False)
            self.EnableMapTool = False
                           
    def closeEvent(self, *args, **kwargs):
        try:
            self.player.stop()
            self.Main.iface.mapCanvas().scene().removeItem(self.positionMarker)
            self.CancelVertex()
            self.Main.pushButton_2.show()
            #self.Main.horizontalSpacer_2.show()
            self.Main.groupBox.hide()
            self.Main.pushButton_8.show()
            self.Main.groupBox_4.show()
            self.dockWidget_2.close()
        except:
            pass
        return QtWidgets.QWidget.closeEvent(self, *args, **kwargs)                      
    def mediaStateChanged(self, state):
        if self.player.state() == QMediaPlayer.PlayingState:
            self.playButton.setIcon(
                    self.style().standardIcon(QStyle.SP_MediaPause))
        else:
            self.playButton.setIcon(
                    self.style().standardIcon(QStyle.SP_MediaPlay))
    
    def setPosition(self, position):
        self.player.setPosition(position+self.StartMsecond)   
    
    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):
        if progress < self.StartMsecond:
            self.player.setPosition(self.StartMsecond)
            progress = self.StartMsecond
        AssociatedGps = round((progress - self.StartMsecond )/1000)
        self.DisplayPoint(AssociatedGps)
        totalTime = self.secTotime(self.duration)
        actualTime = self.secTotime((progress - self.StartMsecond )/1000)
        self.replayPosition_label.setText(actualTime + ' / '+totalTime)
        if not self.horizontalSlider.isSliderDown():
            self.horizontalSlider.setValue(progress - self.StartMsecond ) 

    def DisplayPoint(self,Point):
        if Point >= len(self.GPXList):
            Point = len(self.GPXList) - 1
        gpx = self.GPXList[Point]
        lat = round(gpx[0],7)
        lon = round(gpx[1],7)
        ele = gpx[2]
        speed = gpx[3]
        course = gpx[4]
        time = gpx[5]
        Point = QgsPointXY()
        Point.set(lon, lat)
        canvas = self.Main.iface.mapCanvas()
        crsSrc = QgsCoordinateReferenceSystem(4326)    # .gpx is in WGS 84
        crsDest = QgsProject.instance().crs()
        xform = QgsCoordinateTransform(crsSrc, crsDest)
        self.positionMarker.setHasPosition(True)
        self.Point = xform.transform(Point)
        self.positionMarker.newCoords(self.Point)
        self.positionMarker.angle = float(course)
        extent = canvas.extent() 
        boundaryExtent=QgsRectangle(extent)
        boundaryExtent.scale(0.7)
        if not boundaryExtent.contains(QgsRectangle(Point, self.Point)):
            extentCenter= self.Point
            newExtent=QgsRectangle(
                        extentCenter.x()-extent.width()/2,
                        extentCenter.y()-extent.height()/2,
                        extentCenter.x()+extent.width()/2,
                        extentCenter.y()+extent.height()/2
                        )
            self.Main.iface.mapCanvas().setExtent(newExtent)
            self.Main.iface.mapCanvas().refresh() 
        self.Main.label_14.setText('GPS Time: '+str(time))
        self.Main.label_15.setText('Course: '+"%.2f" % (course))
        self.Main.label_16.setText('Ele: '+"%.2f" %(ele))
        self.Main.label_17.setText('Speed m/s: '+"%.2f" %(speed))
        self.Main.label_19.setText('Lat : '+str(lat))
        self.Main.label_18.setText('Lon : '+str(lon))
                  
    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 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 PlayPause(self):
        if self.player.state() == QMediaPlayer.PlayingState:
            self.player.pause()
        else:
            self.player.play()
            
    def findNearestPointInRecording(self, x,y):
        ClickPt = QgsPoint(x,y)
        Low =  ClickPt.distanceSquared(self.Polyline[0])
        NearPoint = 0
        Counter = 0
        for Point in self.Polyline:
            dist = ClickPt.distanceSquared(Point)
            if dist < Low:
                Low = dist
                NearPoint = Counter
                Counter = Counter + 1
            else:
                Counter = Counter + 1
        self.setPosition(NearPoint*1000)
        
    def ExtractSingleFrameOnTime(self, pos, outputfile):
        if os.name == 'nt':
            ffmpeg = ('"'+os.path.dirname(__file__)[0:-18]+'/Video_UAV_Tracker/FFMPEG/ffmpeg.exe'+'"')
            os.popen(str(ffmpeg)+' -ss '+str(pos/1000)+' -i '+str('"' +self.videoFile+ '"')+ ' -t 1 '+str('"'+outputfile+'"'))
        else:
            ffmpeg = os.path.dirname(__file__)+'/FFMPEG/./ffmpeg'
            os.system(str(ffmpeg)+' -ss '+str(pos/1000)+' -i '+str(self.videoFile)+' -t 1 '+str(outputfile))
                 
    def AddPoint(self,x,y):
        self.Main.iface.mapCanvas().unsetMapTool(self.AddPointMapTool)
        Point = QgsPointXY(x,y)
        pos = self.player.position()
        if self.player.state() == QMediaPlayer.PlayingState:
            self.player.pause()
        a = self.DBLayer.name()
        last_desc = '///'
        LayerName =str(a)
        last_desc2 = LayerName + ' Point N '
        directory = str(self.DB.split('.')[0])+'_Image/'
        if not os.path.exists(directory):
            os.makedirs(directory)
        fc = int(self.DBLayer.featureCount())
        self.ExtractSingleFrameOnTime(pos,directory+LayerName+'_'+str(fc)+'_.jpg')
        fields = self.DBLayer.fields()
        attributes = []
        lat,lon = Point.y(), Point.x()
        for field in fields:
            a = str(field.name())
            b = str(field.typeName())
            if a == 'id':
                fcnr = fc
                attributes.append(fcnr)  
            elif a == 'Lon(WGS84)':
                attributes.append(str(lon))                       
            elif a == 'Lat(WGS84)':
                attributes.append(str(lat))               
            elif a == 'Image link':
                attributes.append(str(directory+LayerName+'_'+str(fc)+'_.jpg'))                   
            else:                    
                if b == 'String':      
                    (a,ok) = QInputDialog.getText(
                                                  self.Main.iface.mainWindow(), 
                                                  "Attributes",
                                                  a + ' = String',
                                                  QLineEdit.Normal)
                    attributes.append(a)               
                elif b == 'Real':                    
                    (a,ok) = QInputDialog.getDouble(
                                                    self.Main.iface.mainWindow(), 
                                                    "Attributes",
                                                    a + ' = Real', decimals = 10)
                    attributes.append(a)
                elif b == 'Integer64':                    
                    (a,ok) = QInputDialog.getInt(
                                                 self.Main.iface.mainWindow(), 
                                                 "Attributes",
                                                 a + ' = Integer')
                    attributes.append(a)                    
        feature = QgsFeature()
        feature.setGeometry(QgsGeometry.fromPoint(Point))
        feature.setAttributes(attributes)
        self.DBLayer.startEditing()
        self.DBLayer.addFeature(feature)
        self.DBLayer.commitChanges()    
        self.DBLayer.triggerRepaint()

    def ExtractCommand(self):
        if self.ExtractToB <= self.ExtractFromA:
            ret = QMessageBox.warning(self, "Warning", '"To B" point must be after "from A" point', QMessageBox.Ok)
            self.CancelVertex()
        else:
            if os.name == 'nt':
                ffmpeg = '"'+os.path.dirname(__file__)[0:-18]+'/Video_UAV_Tracker/FFMPEG/ffmpeg.exe'+'"'
            else:
                ffmpeg = os.path.dirname(__file__)+'/FFMPEG/./ffmpeg'
            Directory,_ = QFileDialog.getSaveFileName(caption= 'Save georeferenced images')
            if Directory:
                self.progressBar.show()
                self.progressBar.setValue(0)
                start = self.ExtractFromA
                if self.comboBox_6.currentText() == 'seconds':           
                    finish = self.ExtractToB - self.ExtractFromA
                    fps = self.doubleSpinBox_2.value()
                    if fps < 1.0:
                        fps = 1.0 / fps
                    elif fps > 1:
                        fps = 1.0 / fps
                        
                    if os.name == 'nt':
                        os.popen(str(ffmpeg+ ' -ss ' + str(start) + ' -i '+ str('"'+self.videoFile+'"')+ ' -t ' + str(finish) + ' -vf fps=' + str(fps) + ' ' + '"'+Directory + '_%d.png'+'"'))
                    else:
                        os.system(ffmpeg+' -ss '+ str(start) + ' -i '+ str(self.videoFile) + ' -t ' + str(finish) + ' -vf fps=' + str(fps) + ' ' + Directory + '_%d.png')
                else:
                    txtGPSFile = open(Directory + 'UTM_Coordinates.txt', 'w')
                    txtGPSFile.close()
                    txtGPSFile = open(Directory+ 'UTM_Coordinates.txt', 'a')
                    txtGPSFile.write('filename # East UTM # North UTM # Ele '+ '\n')
                    finish = self.ExtractToB
                    meters = self.doubleSpinBox_2.value()
                    Timerange = range(start, finish + 1)
                    RemainToUseMeterTotal = 0
                    if os.name == 'nt':
                        os.popen(ffmpeg+' -ss '+ str(start) + ' -i '+ str('"'+self.videoFile+'"') + ' -frames:v 1 ' + '"'+Directory + '_sec_' + str(start)+'.00.png'+'"')
                    else:
                        os.system(ffmpeg+' -ss '+ str(start) + ' -i '+ str(self.videoFile) + ' -frames:v 1 ' + Directory + '_sec_' + str(start)+'.00.png')
                    lonUTM, latUTM,quotainutile = self.transform_wgs84_to_utm(float(self.GPXList[start][1]) , float(self.GPXList[start][0]))
                    ele = float(self.GPXList[start][2])
                    txtGPSFile.write(str(Directory.split('/')[-1]) + '_sec_' + str(start)+'.00.png,'+' '+ str(lonUTM) + ', '+ str(latUTM) + ', ' + str(ele) + '\n')
                    for i in Timerange:
                        progessBarValue = ((i-start) * 100) // len(Timerange)
                        self.progressBar.setValue(int(progessBarValue))
                        latitude1,longitude1 = float(self.GPXList[i][0]) ,float(self.GPXList[i][1])
                        latitude2,longitude2 = float(self.GPXList[i+1][0]) ,float(self.GPXList[i+1][1])
                        ele1 = float(self.GPXList[i][2])
                        ele2 = float(self.GPXList[i+1][2])
                        Calculus = Geodesic.WGS84.Inverse(latitude1, longitude1, latitude2, longitude2)
                        DistanceBetweenPoint = Calculus['s12']    
                        Azimuth =   Calculus['azi2']                 
                        SpeedMeterSecond = DistanceBetweenPoint             #GPS refresh rate is actually 1, change parameter for different rates
                       # Time = 1                                            
                        if RemainToUseMeterTotal == 0:
                            if DistanceBetweenPoint >= meters:
                                decimalSecondToAdd = meters / DistanceBetweenPoint
                                RemainToUseMeter = DistanceBetweenPoint - meters
                                if os.name == 'nt':
                                    os.popen(ffmpeg+ ' -ss '+ str(i + decimalSecondToAdd) +
                                             ' -i '+ str('"'+self.videoFile+'"') + ' -frames:v 1 ' +'"'+ Directory + '_sec_' + str(i) + str(decimalSecondToAdd)[1:4] +'.png'+'"')
                                else:
                                    os.system(ffmpeg+ ' -ss '+ str(i + decimalSecondToAdd) +
                                              ' -i '+ str(self.videoFile) + ' -frames:v 1 ' + Directory + '_sec_' + str(i) + str(decimalSecondToAdd)[1:4] +'.png')
                                    
                                
                                
                                
                                
                                CalculusDirect = Geodesic.WGS84.Direct(latitude1, longitude1, Azimuth,decimalSecondToAdd* SpeedMeterSecond) 
                                X,Y,quotainutile = self.transform_wgs84_to_utm(CalculusDirect['lon2'],CalculusDirect['lat2'] )  
                                Z = ele1 + decimalSecondToAdd*(ele2 - ele1)
                                txtGPSFile.write(str(Directory.split('/')[-1]) + '_sec_'  + str(i) + str(decimalSecondToAdd)[1:4]+'.png,' + ' ' + str(X) + ', ' + str(Y) + ', ' + str(Z) + '\n')
                                while RemainToUseMeter > meters:
                                    decimalSecondToAddMore = meters / SpeedMeterSecond
                                    RemainToUseMeter = RemainToUseMeter - meters
                                    decimalSecondToAdd = decimalSecondToAdd + decimalSecondToAddMore
                                    if os.name == 'nt':
                                        os.popen(ffmpeg+ ' -ss '+ str(i + decimalSecondToAdd) +
                                                 ' -i '+ str('"'+self.videoFile+'"') + ' -frames:v 1 ' +'"'+ Directory + '_sec_' + str(i) + str(decimalSecondToAdd)[1:4] +'.png'+'"')
                                    else:
                                        os.system(ffmpeg+ ' -ss '+ str(i + decimalSecondToAdd) +
                                                  ' -i '+ str(self.videoFile) + ' -frames:v 1 ' + Directory + '_sec_' + str(i) + str(decimalSecondToAdd)[1:4] +'.png')
                                    
                                    CalculusDirect = Geodesic.WGS84.Direct(latitude1, longitude1, Azimuth,decimalSecondToAdd* SpeedMeterSecond) 
                                    X,Y,quotainutile = self.transform_wgs84_to_utm(CalculusDirect['lon2'],CalculusDirect['lat2'] )  
                                    Z = ele1 + decimalSecondToAdd*(ele2 - ele1)
                                    txtGPSFile.write(str(Directory.split('/')[-1]) + '_sec_'  + str(i) + str(decimalSecondToAdd)[1:4]+'.png,' + ' ' + str(X) + ', ' + str(Y) + ', ' + str(Z) + '\n')
                                if RemainToUseMeter == meters:
                                    decimalSecondToAddMore = meters / SpeedMeterSecond
                                    RemainToUseMeter = RemainToUseMeter - meters
                                    decimalSecondToAdd = decimalSecondToAdd + decimalSecondToAddMore
                                    if os.name == 'nt':
                                        os.popen(ffmpeg+ ' -ss '+ str(i + decimalSecondToAdd) +
                                                 ' -i '+ str('"'+self.videoFile+'"') + ' -frames:v 1 ' +'"'+ Directory + '_sec_' + str(i) + str(decimalSecondToAdd)[1:4] +'.png'+'"')
                                    else:
                                        os.system(ffmpeg+ ' -ss '+ str(i + decimalSecondToAdd) +
                                                  ' -i '+ str(self.videoFile) + ' -frames:v 1 ' + Directory + '_sec_' + str(i) + str(decimalSecondToAdd)[1:4] +'.png')
                                    
                                    CalculusDirect = Geodesic.WGS84.Direct(latitude1, longitude1, Azimuth,decimalSecondToAdd* SpeedMeterSecond) 
                                    X,Y,quotainutile = self.transform_wgs84_to_utm(CalculusDirect['lon2'],CalculusDirect['lat2'] )  
                                    Z = ele1 + decimalSecondToAdd*(ele2 - ele1)
                                    txtGPSFile.write(str(Directory.split('/')[-1]) + '_sec_'  + str(i) + str(decimalSecondToAdd)[1:4]+'.png,' + ' ' +str(X) + ', ' + str(Y) + ', ' + str(Z) + '\n')
                                    RemainToUseMeterTotal = 0  
                                elif RemainToUseMeter < meters:
                                    RemainToUseMeterTotal = RemainToUseMeter
                                    pass
                            else:
                                RemainToUseMeterTotal = meters - DistanceBetweenPoint       
                        elif RemainToUseMeterTotal > 0:
                            if DistanceBetweenPoint >= (meters - RemainToUseMeterTotal) :
                                decimalSecondToAdd = (meters - RemainToUseMeterTotal) / DistanceBetweenPoint
                                RemainToUseMeter = DistanceBetweenPoint - (meters - RemainToUseMeterTotal)
                                if os.name == 'nt':
                                    os.popen(ffmpeg+ ' -ss '+ str(i + decimalSecondToAdd) +
                                             ' -i '+ str('"'+self.videoFile+'"') + ' -frames:v 1 ' +'"'+ Directory + '_sec_' + str(i) + str(decimalSecondToAdd)[1:4] +'.png'+'"')
                                else:
                                    os.system(ffmpeg+ ' -ss '+ str(i + decimalSecondToAdd) +
                                              ' -i '+ str(self.videoFile) + ' -frames:v 1 ' + Directory + '_sec_' + str(i) + str(decimalSecondToAdd)[1:4] +'.png')
                                    
                                CalculusDirect = Geodesic.WGS84.Direct(latitude1, longitude1, Azimuth,decimalSecondToAdd* SpeedMeterSecond) 
                                X,Y,quotainutile = self.transform_wgs84_to_utm(CalculusDirect['lon2'],CalculusDirect['lat2'] )  
                                Z = ele1 + decimalSecondToAdd*(ele2 - ele1)
                                txtGPSFile.write(str(Directory.split('/')[-1]) + '_sec_'  + str(i) + str(decimalSecondToAdd)[1:4]+'.png,' + ' ' + str(X) + ', ' + str(Y) + ', ' + str(Z) + '\n')
                                while RemainToUseMeter > meters:
                                    decimalSecondToAddMore = meters / SpeedMeterSecond
                                    RemainToUseMeter = RemainToUseMeter - meters
                                    decimalSecondToAdd = decimalSecondToAdd + decimalSecondToAddMore
                                    if os.name == 'nt':
                                        os.popen(ffmpeg+ ' -ss '+ str(i + decimalSecondToAdd) +
                                                 ' -i '+ str('"'+self.videoFile+'"') + ' -frames:v 1 ' +'"'+ Directory + '_sec_' + str(i) + str(decimalSecondToAdd)[1:4] +'.png'+'"')
                                    else:
                                        os.system(ffmpeg+ ' -ss '+ str(i + decimalSecondToAdd) +
                                                  ' -i '+ str(self.videoFile) + ' -frames:v 1 ' + Directory + '_sec_' + str(i) + str(decimalSecondToAdd)[1:4] +'.png')
                
                                    CalculusDirect = Geodesic.WGS84.Direct(latitude1, longitude1, Azimuth,decimalSecondToAdd* SpeedMeterSecond) 
                                    X,Y,quotainutile = self.transform_wgs84_to_utm(CalculusDirect['lon2'],CalculusDirect['lat2'] )  
                                    Z = ele1 + decimalSecondToAdd*(ele2 - ele1)
                                    txtGPSFile.write(str(Directory.split('/')[-1]) + '_sec_'  + str(i) + str(decimalSecondToAdd)[1:4]+'.png,' + ' ' + str(X) + ', ' + str(Y) + ', ' + str(Z) + '\n')
                                if RemainToUseMeter == meters:
                                    decimalSecondToAddMore = meters / SpeedMeterSecond
                                    RemainToUseMeter = RemainToUseMeter - meters
                                    decimalSecondToAdd = decimalSecondToAdd + decimalSecondToAddMore
                                    if os.name == 'nt':
                                        os.popen(ffmpeg+ ' -ss '+ str(i + decimalSecondToAdd) +
                                                 ' -i '+ str('"'+self.videoFile+'"') + ' -frames:v 1 ' +'"'+ Directory + '_sec_' + str(i) + str(decimalSecondToAdd)[1:4] +'.png'+'"')
                                    else:
                                        os.system(ffmpeg+ ' -ss '+ str(i + decimalSecondToAdd) +
                                                  ' -i '+ str(self.videoFile) + ' -frames:v 1 ' + Directory + '_sec_' + str(i) + str(decimalSecondToAdd)[1:4] +'.png')
                                    
                                    CalculusDirect = Geodesic.WGS84.Direct(latitude1, longitude1, Azimuth,decimalSecondToAdd* SpeedMeterSecond) 
                                    X,Y,quotainutile = self.transform_wgs84_to_utm(CalculusDirect['lon2'],CalculusDirect['lat2'] )  
                                    Z = ele1 + decimalSecondToAdd*(ele2 - ele1)
                                    txtGPSFile.write(str(Directory.split('/')[-1]) + '_sec_'  + str(i) + str(decimalSecondToAdd)[1:4]+'.png,' + ' ' + str(X) + ', ' + str(Y) + ', ' + str(Z) + '\n')
                                    RemainToUseMeterTotal = 0
                                elif RemainToUseMeter < meters:
                                    RemainToUseMeterTotal = RemainToUseMeter
                            else:
                                RemainToUseMeterTotal = (meters - DistanceBetweenPoint) + RemainToUseMeterTotal
                    txtGPSFile.close()            
            self.progressBar.hide()
            
    def ExtractFromA(self):
        
        if self.ExtractA == True:
            self.Main.iface.mapCanvas().scene().removeItem(self.ExtractAVertex)
        self.ExtractA = False
        self.ExtractFromA = round((self.player.position()- self.StartMsecond )/1000)
        canvas = self.Main.iface.mapCanvas()
        crsSrc = QgsCoordinateReferenceSystem(4326)    # .gpx is in WGS 84
        crsDest = QgsProject.instance().crs()
        xform = QgsCoordinateTransform(crsSrc, crsDest)
        latitude,longitude = self.Polyline[self.ExtractFromA].y(), self.Polyline[self.ExtractFromA].x()
        self.ExtractAVertex = QgsVertexMarker(canvas)
        self.ExtractAVertex.setCenter(xform.transform(QgsPointXY(longitude, latitude)))
        self.ExtractAVertex.setColor(QColor(0,255,0))
        self.ExtractAVertex.setIconSize(10)
        self.ExtractAVertex.setIconType(QgsVertexMarker.ICON_X)
        self.ExtractAVertex.setPenWidth(10)
        self.ExtractA = True
        if self.ExtractB == True:
            self.pushButtonCut_2.setEnabled(True)
        else:
            self.pushButtonCut_2.setEnabled(False)
            
    def ExtractToB(self):
        if self.ExtractB == True:
            self.Main.iface.mapCanvas().scene().removeItem(self.ExtractBVertex)
        self.ExtractB = False    
        self.ExtractToB = round((self.player.position()- self.StartMsecond )/1000)  
        if self.ExtractA == True:
            if self.ExtractToB > self.ExtractFromA:
                canvas = self.Main.iface.mapCanvas()
                crsSrc = QgsCoordinateReferenceSystem(4326)    # .gpx is in WGS 84
                crsDest = QgsProject.instance().crs()
                xform = QgsCoordinateTransform(crsSrc, crsDest)   
                latitude,longitude = self.Polyline[self.ExtractToB].y(), self.Polyline[self.ExtractToB].x()
                self.ExtractBVertex = QgsVertexMarker(canvas)
                self.ExtractBVertex.setCenter(xform.transform(QgsPointXY(longitude, latitude)))
                self.ExtractBVertex.setColor(QColor(255,0,0))
                self.ExtractBVertex.setIconSize(10)
                self.ExtractBVertex.setIconType(QgsVertexMarker.ICON_X)
                self.ExtractBVertex.setPenWidth(10)
                self.ExtractB = True
                self.pushButtonCut_2.setEnabled(True)
            else:
                self.pushButtonCut_2.setEnabled(False)
                           
    def CancelVertex(self): 
        if self.ExtractA == True:
            self.Main.iface.mapCanvas().scene().removeItem(self.ExtractAVertex)
            self.ExtractA = False
        if self.ExtractB == True:
            self.Main.iface.mapCanvas().scene().removeItem(self.ExtractBVertex)
            self.ExtractB = False
        self.pushButtonCut_2.setEnabled(False)
                  
    def ExtractToolbar(self):
        if self.ExtractTool == 0:
            self.dockWidget_4.show()
            self.ExtractTool = 1
        else:
            self.dockWidget_4.hide()
            self.ExtractTool = 0
            
    def transform_wgs84_to_utm(self, lon, lat): 
           
        def get_utm_zone(longitude):
            return (int(1+(longitude+180.0)/6.0))

        def is_northern(latitude):
            """
            Determines if given latitude is a northern for UTM
            """
            if (latitude < 0.0):
                return 0
            else:
                return 1
        utm_coordinate_system = osr.SpatialReference()
        utm_coordinate_system.SetWellKnownGeogCS("WGS84") # Set geographic coordinate system to handle lat/lon  
        utm_coordinate_system.SetUTM(get_utm_zone(lon), is_northern(lat))
        wgs84_coordinate_system = utm_coordinate_system.CloneGeogCS() # Clone ONLY the geographic coordinate system 
        wgs84_to_utm_transform = osr.CoordinateTransformation(wgs84_coordinate_system, utm_coordinate_system) # (<from>, <to>)
        return wgs84_to_utm_transform.TransformPoint(lon, lat, 0) # returns easting, northing, altitude 
Ejemplo n.º 29
0
class DPlayerCore(QWidget):
    def __init__(self):
        """Initialize player and load playlist if any."""
        super().__init__()

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

        self.shuffling = False
        self.repeatingPlaylist = False
        self.repeatingSong = False

        self.musicOrder = []
        self.loadPlaylist(QUrl(
            'file://{}/lastListened.m3u'.format(os.getcwd())))

        self.lyricsApi = 'http://api.musixmatch.com/ws/1.1/'
        self.lyricsApiKey = '4b364f0652e471aa50813a22cdf830ea'
        self.lastFMapi = 'http://ws.audioscrobbler.com/2.0/'
        self.lastFMapikey = '052c43a00a4fc294bb3c9e0c38bdf710'
        self.lastFMsecret = '14c66392fa9c6c142a41ccc2b0674e19'
        self.username = None
        self.password = None
        self.network = None
        self.error = 'Something went wrong! Try again later.'

    def play(self):
        """Start the player."""
        self.player.play()

    def pause(self):
        """Pause the player."""
        self.player.pause()

    def stop(self):
        """Stop the player."""
        self.player.stop()

    def previous(self):
        """Play previous song."""
        self.playlist.previous()

    def next(self):
        """Play next song."""
        self.playlist.next()

    def mute(self):
        """Mute the player."""
        self.player.setMuted(True)

    def unmute(self):
        """Unmute the player."""
        self.player.setMuted(False)

    def setVolume(self, value):
        """Set player's volume to value."""
        self.player.setVolume(value)

    def add(self, fileNames):
        """Add fileNames to the playlist."""
        for name in fileNames:
            url = QUrl.fromLocalFile(QFileInfo(name).absoluteFilePath())
            self.playlist.addMedia(QMediaContent(url))
            self.musicOrder.append([name])

        self.added(len(fileNames))

    def added(self, added):
        """Saves music info in musicOrder."""
        for name, index in zip(
                self.musicOrder[self.playlist.mediaCount() - added:],
                range(self.playlist.mediaCount() - added,
                      len(self.musicOrder))):
            name = name[0]
            artist = self.getArtist(name)[0]
            title = self.getTitle(name)[0]
            album = self.getAlbum(name)[0]
            seconds = self.getDuration(name)
            duration = QTime(0, seconds // 60, seconds % 60)
            duration = duration.toString('mm:ss')
            self.musicOrder[index].extend(
                [artist, title, album, duration])

    def remove(self, songIndexes):
        """Remove songIndexes from the playlist."""
        for index in songIndexes:
            self.songChanged = True
            del self.musicOrder[index]
            self.playlist.removeMedia(index)
        self.songChanged = False

    def savePlaylist(self, path):
        """Save playlist to path."""
        if path.toString()[len(path.toString()) - 4:] != '.m3u':
            path = QUrl('{}.m3u'.format(path.toString()))
        self.playlist.save(path, 'm3u')

    def loadPlaylist(self, path):
        """Load playlist form path."""
        count = self.playlist.mediaCount()
        self.playlist.load(path)

        for index in range(count, self.playlist.mediaCount()):
            self.musicOrder.append(
                [self.playlist.media(index).canonicalUrl().path()])

        self.added(self.playlist.mediaCount() - count)

    def clearPlaylist(self):
        """Delete all songs in the playlist."""
        self.playlist.clear()
        self.musicOrder = []

    def shuffle(self, value):
        """Shuffle playlist if value = True."""
        self.shuffling = value

        if self.repeatingSong:
            return
        if self.shuffling:
            self.playlist.setPlaybackMode(QMediaPlaylist.Random)
        elif self.repeatingPlaylist:
            self.playlist.setPlaybackMode(QMediaPlaylist.Loop)
        else:
            self.playlist.setPlaybackMode(QMediaPlaylist.Sequential)

    def repeatPlaylist(self, value):
        """Repeat playlist after the last song is finished if value = True."""
        self.repeatingPlaylist = value

        if self.repeatingSong or self.shuffling:
            return
        if self.repeatingPlaylist:
            self.playlist.setPlaybackMode(QMediaPlaylist.Loop)
        else:
            self.playlist.setPlaybackMode(QMediaPlaylist.Sequential)

    def repeatSong(self, value):
        """Repeat current song if value = True."""
        self.repeatingSong = value

        if self.repeatingSong:
            self.playlist.setPlaybackMode(QMediaPlaylist.CurrentItemInLoop)
        elif self.shuffling:
            self.playlist.setPlaybackMode(QMediaPlaylist.Random)
        elif self.repeatingPlaylist:
            self.playlist.setPlaybackMode(QMediaPlaylist.Loop)
        else:
            self.playlist.setPlaybackMode(QMediaPlaylist.Sequential)

    def sort(self, column, order):
        """Sort playlist by column in order."""
        ordered = sorted(self.musicOrder, key=itemgetter(column + 1),
                         reverse=order)

        self.clearPlaylist()
        for song in ordered:
            url = QUrl.fromLocalFile(QFileInfo(song[0]).absoluteFilePath())
            self.playlist.addMedia(QMediaContent(url))

        self.musicOrder = ordered

    def findLyrics(self, index):
        """Returns lyrics for song at index."""
        if self.musicOrder[index][2] == 'Unknown':
            return 'Unknown song.'

        searchSong = '{}track.search?q_track={}'.format(
            self.lyricsApi, self.musicOrder[index][2].replace(' ', '%20'))
        if self.musicOrder[index][1] != 'Unknown':
            searchSong = '{}&q_artist={}'.format(
                searchSong, self.musicOrder[index][1].replace(' ', '%20'))
        searchSong = '{}&f_has_lyrics=1&apikey={}'.format(
            searchSong, self.lyricsApiKey)

        try:
            requestSong = requests.get(searchSong)
        except requests.ConnectionError:
            return self.error

        songJson = requestSong.json()
        if requestSong.status_code != 200 or \
                songJson['message']['header']['available'] == 0:
            return self.error

        songId = songJson[
            'message']['body']['track_list'][0]["track"]["track_id"]
        searchLyrics = '{}track.lyrics.get?track_id={}&apikey={}'.format(
            self.lyricsApi, songId, self.lyricsApiKey)

        try:
            requestLyrics = requests.get(searchLyrics)
        except requests.ConnectionError:
            return self.error

        if requestLyrics.status_code != 200 or \
                songJson['message']['header']['available'] == 0:
            return self.error
        return requestLyrics.json()[
            'message']['body']['lyrics']['lyrics_body'][:-58]  # spam and bacon

    def findInfo(self, index):
        """Returns info about artist and album for index if any."""
        info = []

        if self.musicOrder[index][1] != 'Unknown':
            artist = self.artistInfo(self.musicOrder[index][1])
            if artist != self.error:
                info += artist

        if self.musicOrder[index][1] != 'Unknown' and \
                self.musicOrder[index][3] != 'Unknown':
            album = self.albumInfo(self.musicOrder[index][1],
                                   self.musicOrder[index][3])
            if album != self.error:
                info += album

        if info:
            return info
        else:
            return ['Unknown artist and song!']

    def artistInfo(self, artist):
        """Returns info about artist if any."""
        try:
            response = requests.get(
                ('{}/?method=artist.getinfo&artist={}&api_key={}&'
                    'format=json&autocorrect=1').format(
                    self.lastFMapi, artist, self.lastFMapikey))
        except Exception:
            return self.error

        if response.status_code != 200:
            return self.error

        artist = 'Artist: {}'.format(response.json()['artist']['name'])
        bio = 'Bio: {}'.format(
            response.json()['artist']['bio']['summary'].replace('.', '.\n'))
        spam = bio.find('<a')
        bio = bio[:spam]

        return [artist, bio]

    def albumInfo(self, artist, album):
        """Returns info about album if any."""
        try:
            response = requests.get(
                ('{}/?method=album.getinfo&artist={}&album={}&api_key={}&'
                    'format=json&autocorrect=1').format(
                    self.lastFMapi, artist, album, self.lastFMapikey))
        except Exception:
            return self.error

        if response.status_code != 200 or \
                'album' not in response.json().keys():
            return self.error

        album = 'Album: {}'.format(response.json()['album']['name'])
        tracks = ['Tracks: ']
        t = response.json()['album']['tracks']['track']
        for track, index in zip(t, range(len(t))):
            tracks.append('{}. {}'.format(index + 1, track['name']))

        info = [album, '\n'.join(tracks)]

        if 'wiki' in response.json()['album'].keys():
            wiki = response.json()['album']['wiki']
            if 'published' in wiki.keys():
                info.append('Published: {}'.format(wiki['published']))
            if 'summary' in wiki.keys():
                summary = wiki['summary'].replace('.', '.\n')
                spam = summary.find('<a')
                info.append('Summary: {}'.format(summary[:spam]))
            if 'Musical style' in wiki.keys():
                info.append('Musical style: {}'.format(wiki['Musical style']))

        return info

    def login(self, username, password):
        """Creates lastFM network."""
        self.username = username
        self.password = pylast.md5(password)
        try:
            self.network = pylast.LastFMNetwork(api_key=self.lastFMapikey,
                                                api_secret=self.lastFMsecret,
                                                username=self.username,
                                                password_hash=self.password)
        except Exception:
            self.username = None
            self.password = None
            self.network = None
            return False
        return True

    def logout(self):
        """Destoys lastFM network and current user info."""
        self.username = None
        self.password = None
        self.network = None

    def loveTrack(self, index):
        """Love track at index in lastFM."""
        if self.network is None:
            return False

        track = self.network.get_track(self.musicOrder[index][1],
                                       self.musicOrder[index][2])
        try:
            track.love()
        except Exception:
            return False
        return True

    def unloveTrack(self, index):
        """Unlove track at index in lastFM."""
        if self.network is None:
            return False

        track = self.network.get_track(self.musicOrder[index][1],
                                       self.musicOrder[index][2])
        try:
            track.unlove()
        except Exception:
            return False
        return True

    def isMuted(self):
        """Returns True if player is muted."""
        return self.player.isMuted()

    def getArtist(self, song):
        """Returns the artist of song."""
        if song[-4:] == '.mp3':
            obj = EasyID3(song)
            if 'artist' in obj.keys():
                return obj['artist']
        elif 'TAG' in mediainfo(song).keys():
            obj = mediainfo(song)['TAG']
            if 'artist' in obj.keys():
                return [obj['artist']]
            elif 'ARTIST' in obj.keys():
                return [obj['ARTIST']]
            else:
                return ['Unknown']
        else:
            return ['Unknown']

    def getTitle(self, song):
        """Returns the title of song."""
        if song[-4:] == '.mp3':
            obj = EasyID3(song)
            if 'title' in obj.keys():
                return obj['title']
        elif 'TAG' in mediainfo(song).keys():
            obj = mediainfo(song)['TAG']
            if 'title' in obj.keys():
                return [obj['title']]
            elif 'TITLE' in obj.keys():
                return [obj['TITLE']]
            else:
                return ['Unknown']
        else:
            return ['Unknown']

    def getAlbum(self, song):
        """Returns the album of song."""
        if song[-4:] == '.mp3':
            obj = EasyID3(song)
            if 'album' in obj.keys():
                return obj['album']
        elif 'TAG' in mediainfo(song).keys():
            obj = mediainfo(song)['TAG']
            if 'album' in obj.keys():
                return [obj['album']]
            elif 'ALBUM' in obj.keys():
                return [obj['ALBUM']]
            else:
                return ['Unknown']
        else:
            return ['Unknown']

    def getDuration(self, song):
        """Returns the duration of song."""
        if song[-4:] == '.mp3':
            return MP3(song).info.length
        return int(float(mediainfo(song)['duration']))
Ejemplo n.º 30
0
class videoPlayer(QVideoWidget):
    def __init__(self, parent):

        super(QVideoWidget, self).__init__(parent)
        self.player = QMediaPlayer(self)
        self.player.setVolume(50)
        self.player.setVideoOutput(self)
        self.player.mediaStatusChanged.connect(self.mediaStatusChanged)

    def update(self, path):

        if path: path = QUrl.fromLocalFile(path)
        self.player.setMedia(QMediaContent(path))
        self.player.play()

    def rotate(self, path, sign):

        self.update(None)
        clip = VideoFileClip(path)
        clip.rotate(90 * sign)

        if path.endswith(('gif')):
            clip.write_gif(path)
        else:
            clip.write_videofile(path)

        clip.close()

    def pause(self):

        status = self.player.state()
        if status == QMediaPlayer.PlayingState: self.player.pause()
        elif status == QMediaPlayer.PausedState: self.player.play()

    def position(self, delta):

        self.player.setPosition(self.player.position() + delta)

    def volume(self, delta):

        if self.player.isAudioAvailable():

            self.player.setVolume(self.player.volume() + delta)

    def mute(self):

        if self.player.isAudioAvailable():

            self.player.setMuted(not self.player.isMuted())

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

    def mediaStatusChanged(self, status):

        if status == QMediaPlayer.EndOfMedia: self.player.play()

        elif status not in (2, 1):

            self.parent().setCurrentIndex(1)

    def wheelEvent(self, event):

        self.volume(event.angleDelta().y() // 12)
Ejemplo n.º 31
0
class Ui_MainWindow(QWidget):
    def __init__(self, feature=feature):
        super().__init__()
        self.feature = feature
        self.points_CAM1 = []
        self.points_CAM2 = []
        self.points_CAM3 = []
        self.numWarning = 0

    def setupUi(self, Form):
        Form.setObjectName("Form")
        Form.resize(1048, 375)
        self.verticalLayout_4 = QtWidgets.QVBoxLayout(Form)
        self.verticalLayout_4.setObjectName("verticalLayout_4")
        self.tabWidget = QtWidgets.QTabWidget(Form)
        self.tabWidget.setObjectName("tabWidget")
        self.tab = QtWidgets.QWidget()
        self.tab.setObjectName("tab")

        # View CAM 1
        self.gridLayout = QtWidgets.QGridLayout(self.tab)
        self.gridLayout.setHorizontalSpacing(20)
        self.gridLayout.setObjectName("gridLayout")
        self.verticalLayout_3 = QtWidgets.QVBoxLayout()
        self.verticalLayout_3.setSpacing(10)
        self.verticalLayout_3.setObjectName("verticalLayout_3")
        self.CAM1 = QtWidgets.QLabel(self.tab)
        self.CAM1.setMinimumSize(QtCore.QSize(320, 240))
        self.CAM1.setMaximumSize(QtCore.QSize(426, 400))
        self.CAM1.setFrameShape(QtWidgets.QFrame.Box)
        self.CAM1.setObjectName("CAM1")
        self.verticalLayout_3.addWidget(self.CAM1)
        self.horizontalLayout_6 = QtWidgets.QHBoxLayout()
        self.horizontalLayout_6.setObjectName("horizontalLayout_6")
        self.startCAM1 = QtWidgets.QPushButton(self.tab)
        self.startCAM1.setObjectName("startCAM1")
        self.horizontalLayout_6.addWidget(self.startCAM1)
        self.carProtectionCAM1 = QtWidgets.QPushButton(self.tab)
        self.carProtectionCAM1.setObjectName("carProtectionCAM1")
        self.horizontalLayout_6.addWidget(self.carProtectionCAM1)
        self.monitorAreaCAM1 = QtWidgets.QPushButton(self.tab)
        self.monitorAreaCAM1.setObjectName("monitorAreaCAM1")
        self.horizontalLayout_6.addWidget(self.monitorAreaCAM1)
        self.verticalLayout_3.addLayout(self.horizontalLayout_6)
        self.horizontalLayout_7 = QtWidgets.QHBoxLayout()
        self.horizontalLayout_7.setObjectName("horizontalLayout_7")
        self.stopCAM1 = QtWidgets.QPushButton(self.tab)
        self.stopCAM1.setEnabled(False)
        self.stopCAM1.setObjectName("stopCAM1")
        self.horizontalLayout_7.addWidget(self.stopCAM1)
        self.personSearchingCAM1 = QtWidgets.QPushButton(self.tab)
        self.personSearchingCAM1.setObjectName("personSearchingCAM1")
        self.horizontalLayout_7.addWidget(self.personSearchingCAM1)
        self.illegalCAM1 = QtWidgets.QPushButton(self.tab)
        self.illegalCAM1.setObjectName("illegalCAM1")
        self.horizontalLayout_7.addWidget(self.illegalCAM1)
        self.verticalLayout_3.addLayout(self.horizontalLayout_7)
        self.gridLayout.addLayout(self.verticalLayout_3, 0, 0, 1, 1)
        self.verticalLayout = QtWidgets.QVBoxLayout()
        self.verticalLayout.setSpacing(10)
        self.verticalLayout.setObjectName("verticalLayout")

        # View CAM 2
        self.CAM2 = QtWidgets.QLabel(self.tab)
        self.CAM2.setMinimumSize(QtCore.QSize(320, 240))
        self.CAM2.setMaximumSize(QtCore.QSize(426, 400))
        self.CAM2.setFrameShape(QtWidgets.QFrame.Box)
        self.CAM2.setObjectName("CAM2")
        self.verticalLayout.addWidget(self.CAM2)
        self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
        self.horizontalLayout_2.setObjectName("horizontalLayout_2")
        self.startCAM2 = QtWidgets.QPushButton(self.tab)
        self.startCAM2.setObjectName("startCAM2")
        self.horizontalLayout_2.addWidget(self.startCAM2)
        self.carProtectionCAM2 = QtWidgets.QPushButton(self.tab)
        self.carProtectionCAM2.setObjectName("carProtectionCAM2")
        self.horizontalLayout_2.addWidget(self.carProtectionCAM2)
        self.monitorAreaCAM2 = QtWidgets.QPushButton(self.tab)
        self.monitorAreaCAM2.setObjectName("monitorAreaCAM2")
        self.horizontalLayout_2.addWidget(self.monitorAreaCAM2)
        self.verticalLayout.addLayout(self.horizontalLayout_2)
        self.horizontalLayout_3 = QtWidgets.QHBoxLayout()
        self.horizontalLayout_3.setObjectName("horizontalLayout_3")
        self.stopCAM2 = QtWidgets.QPushButton(self.tab)
        self.stopCAM2.setEnabled(False)
        self.stopCAM2.setObjectName("stopCAM2")
        self.horizontalLayout_3.addWidget(self.stopCAM2)
        self.personSearchingCAM2 = QtWidgets.QPushButton(self.tab)
        self.personSearchingCAM2.setObjectName("personSearchingCAM2")
        self.horizontalLayout_3.addWidget(self.personSearchingCAM2)
        self.illegalCAM2 = QtWidgets.QPushButton(self.tab)
        self.illegalCAM2.setObjectName("illegalCAM2")
        self.horizontalLayout_3.addWidget(self.illegalCAM2)
        self.verticalLayout.addLayout(self.horizontalLayout_3)
        self.gridLayout.addLayout(self.verticalLayout, 0, 1, 1, 1)
        self.verticalLayout_2 = QtWidgets.QVBoxLayout()
        self.verticalLayout_2.setSpacing(10)
        self.verticalLayout_2.setObjectName("verticalLayout_2")

        # View CAM 3
        self.CAM3 = QtWidgets.QLabel(self.tab)
        self.CAM3.setMinimumSize(QtCore.QSize(320, 240))
        self.CAM3.setMaximumSize(QtCore.QSize(426, 400))
        self.CAM3.setFrameShape(QtWidgets.QFrame.Box)
        self.CAM3.setObjectName("CAM3")
        self.verticalLayout_2.addWidget(self.CAM3)
        self.horizontalLayout_4 = QtWidgets.QHBoxLayout()
        self.horizontalLayout_4.setObjectName("horizontalLayout_4")
        self.startCAM3 = QtWidgets.QPushButton(self.tab)
        self.startCAM3.setObjectName("startCAM3")
        self.horizontalLayout_4.addWidget(self.startCAM3)
        self.carProtectionCAM3 = QtWidgets.QPushButton(self.tab)
        self.carProtectionCAM3.setObjectName("carProtectionCAM3")
        self.horizontalLayout_4.addWidget(self.carProtectionCAM3)
        self.monitorAreaCAM3 = QtWidgets.QPushButton(self.tab)
        self.monitorAreaCAM3.setObjectName("monitorAreaCAM3")
        self.horizontalLayout_4.addWidget(self.monitorAreaCAM3)
        self.verticalLayout_2.addLayout(self.horizontalLayout_4)
        self.horizontalLayout_5 = QtWidgets.QHBoxLayout()
        self.horizontalLayout_5.setObjectName("horizontalLayout_5")
        self.stopCAM3 = QtWidgets.QPushButton(self.tab)
        self.stopCAM3.setEnabled(False)
        self.stopCAM3.setObjectName("stopCAM3")
        self.horizontalLayout_5.addWidget(self.stopCAM3)
        self.personSearchingCAM3 = QtWidgets.QPushButton(self.tab)
        self.personSearchingCAM3.setObjectName("personSearchingCAM3")
        self.horizontalLayout_5.addWidget(self.personSearchingCAM3)
        self.illegalCAM3 = QtWidgets.QPushButton(self.tab)
        self.illegalCAM3.setObjectName("illegalCAM3")
        self.horizontalLayout_5.addWidget(self.illegalCAM3)
        self.verticalLayout_2.addLayout(self.horizontalLayout_5)
        self.gridLayout.addLayout(self.verticalLayout_2, 0, 2, 1, 1)
        self.tabWidget.addTab(self.tab, "")

        # Media Tab
        self.tab_2 = QtWidgets.QWidget()
        self.tab_2.setObjectName("tab_2")
        self.tabWidget.addTab(self.tab_2, "")

        self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.VideoSurface)
        videowidget = QVideoWidget()
        self.openBtn = QtWidgets.QPushButton('Open Video')
        self.playBtn = QtWidgets.QPushButton()
        self.playBtn.setEnabled(False)
        self.playBtn.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay))
        self.stopBtn = QtWidgets.QPushButton()
        self.stopBtn.setIcon(self.style().standardIcon(QStyle.SP_MediaStop))
        self.slowBtn = QtWidgets.QPushButton()
        self.slowBtn.setIcon(self.style().standardIcon(
            QStyle.SP_MediaSeekBackward))
        self.fastBtn = QtWidgets.QPushButton()
        self.fastBtn.setIcon(self.style().standardIcon(
            QStyle.SP_MediaSeekForward))
        self.volumeBtn = QtWidgets.QPushButton()
        self.volumeBtn.setIcon(self.style().standardIcon(
            QStyle.SP_MediaVolume))
        self.fullscreenBtn = QPushButton("Full Screen")
        self.slider = QSlider(Qt.Horizontal)
        self.slider.setRange(0, 0)
        self.volume_slider = QSlider(Qt.Horizontal)
        self.volume_slider.setRange(0, 100)
        self.volume_slider.setValue(100)
        self.label_2_1 = QLabel()
        self.label_2_1.setSizePolicy(QSizePolicy.Preferred,
                                     QSizePolicy.Maximum)
        self.label_2_2 = QLabel()
        hboxLayout_2_1 = QHBoxLayout()
        hboxLayout_2_2 = QHBoxLayout()
        hboxLayout_2_3 = QHBoxLayout()
        hboxLayout_2_1.addWidget(self.slider)
        hboxLayout_2_2.addWidget(self.openBtn)
        hboxLayout_2_2.addWidget(self.stopBtn)
        hboxLayout_2_2.addWidget(self.slowBtn)
        hboxLayout_2_2.addWidget(self.playBtn)
        hboxLayout_2_2.addWidget(self.fastBtn)
        hboxLayout_2_2.addWidget(self.volumeBtn)
        hboxLayout_2_2.addWidget(self.volume_slider)
        hboxLayout_2_2.addStretch(1)
        hboxLayout_2_2.addWidget(self.fullscreenBtn)
        hboxLayout_2_3.addWidget(videowidget)
        vboxLayout_2_1 = QVBoxLayout()
        vboxLayout_2_1.addLayout(hboxLayout_2_3)
        vboxLayout_2_1.addLayout(hboxLayout_2_1)
        vboxLayout_2_1.addLayout(hboxLayout_2_2)
        vboxLayout_2_1.addWidget(self.label_2_1)
        self.tab_2.setLayout(vboxLayout_2_1)

        # Setting CAM 1
        self.tab_3 = QtWidgets.QWidget()
        self.tab_3.setObjectName("tab_3")
        self.gridLayout_2 = QtWidgets.QGridLayout(self.tab_3)
        self.gridLayout_2.setHorizontalSpacing(20)
        self.gridLayout_2.setObjectName("gridLayout_2")
        self.verticalLayout_5 = QtWidgets.QVBoxLayout()
        self.verticalLayout_5.setSpacing(10)
        self.verticalLayout_5.setObjectName("verticalLayout_5")
        self.CAM1_draw = QtWidgets.QLabel(self.tab_3)
        self.CAM1_draw.setMinimumSize(QtCore.QSize(320, 240))
        self.CAM1_draw.setMaximumSize(QtCore.QSize(426, 400))
        self.CAM1_draw.setFrameShape(QtWidgets.QFrame.Box)
        self.CAM1_draw.setObjectName("CAM1_draw")
        self.verticalLayout_5.addWidget(self.CAM1_draw)
        self.horizontalLayout_8 = QtWidgets.QHBoxLayout()
        self.horizontalLayout_8.setObjectName("horizontalLayout_8")
        self.drawCAM1 = QtWidgets.QPushButton(self.tab_3)
        self.drawCAM1.setObjectName("drawCAM1")
        self.horizontalLayout_8.addWidget(self.drawCAM1)
        self.removeCAM1 = QtWidgets.QPushButton(self.tab_3)
        self.removeCAM1.setObjectName("removeCAM1")
        self.horizontalLayout_8.addWidget(self.removeCAM1)
        self.verticalLayout_5.addLayout(self.horizontalLayout_8)
        self.gridLayout_2.addLayout(self.verticalLayout_5, 0, 0, 1, 1)
        self.verticalLayout_6 = QtWidgets.QVBoxLayout()
        self.verticalLayout_6.setSpacing(10)
        self.verticalLayout_6.setObjectName("verticalLayout_6")

        # Setting CAM 2
        self.CAM2_draw = QtWidgets.QLabel(self.tab_3)
        self.CAM2_draw.setMinimumSize(QtCore.QSize(320, 240))
        self.CAM2_draw.setMaximumSize(QtCore.QSize(426, 400))
        self.CAM2_draw.setFrameShape(QtWidgets.QFrame.Box)
        self.CAM2_draw.setObjectName("CAM2_draw")
        self.verticalLayout_6.addWidget(self.CAM2_draw)
        self.horizontalLayout_10 = QtWidgets.QHBoxLayout()
        self.horizontalLayout_10.setObjectName("horizontalLayout_10")
        self.drawCAM2 = QtWidgets.QPushButton(self.tab_3)
        self.drawCAM2.setObjectName("drawCAM2")
        self.horizontalLayout_10.addWidget(self.drawCAM2)
        self.removeCAM2 = QtWidgets.QPushButton(self.tab_3)
        self.removeCAM2.setObjectName("removeCAM2")
        self.horizontalLayout_10.addWidget(self.removeCAM2)
        self.verticalLayout_6.addLayout(self.horizontalLayout_10)
        self.gridLayout_2.addLayout(self.verticalLayout_6, 0, 1, 1, 1)
        self.verticalLayout_7 = QtWidgets.QVBoxLayout()
        self.verticalLayout_7.setSpacing(10)
        self.verticalLayout_7.setObjectName("verticalLayout_7")

        # Setting CAM 3
        self.CAM3_draw = QtWidgets.QLabel(self.tab_3)
        self.CAM3_draw.setMinimumSize(QtCore.QSize(320, 240))
        self.CAM3_draw.setMaximumSize(QtCore.QSize(426, 400))
        self.CAM3_draw.setFrameShape(QtWidgets.QFrame.Box)
        self.CAM3_draw.setObjectName("CAM3_draw")
        self.verticalLayout_7.addWidget(self.CAM3_draw)
        self.horizontalLayout_12 = QtWidgets.QHBoxLayout()
        self.horizontalLayout_12.setObjectName("horizontalLayout_12")
        self.drawCAM3 = QtWidgets.QPushButton(self.tab_3)
        self.drawCAM3.setObjectName("drawCAM3")
        self.horizontalLayout_12.addWidget(self.drawCAM3)
        self.removeCAM3 = QtWidgets.QPushButton(self.tab_3)
        self.removeCAM3.setObjectName("removeCAM3")
        self.horizontalLayout_12.addWidget(self.removeCAM3)
        self.verticalLayout_7.addLayout(self.horizontalLayout_12)
        self.gridLayout_2.addLayout(self.verticalLayout_7, 0, 2, 1, 1)
        self.tabWidget.addTab(self.tab_3, "")
        self.verticalLayout_4.addWidget(self.tabWidget)

        # Setup Connect
        # Setup enable
        self.removeCAM1.setEnabled(False)
        self.removeCAM2.setEnabled(False)
        self.removeCAM3.setEnabled(False)
        # Setup choosing feature
        self.carProtectionCAM1.setVisible(self.feature['car1'])
        self.carProtectionCAM2.setVisible(self.feature['car2'])
        self.carProtectionCAM3.setVisible(self.feature['car3'])

        self.illegalCAM1.setVisible(self.feature['illegal1'])
        self.illegalCAM2.setVisible(self.feature['illegal2'])
        self.illegalCAM3.setVisible(self.feature['illegal3'])

        self.monitorAreaCAM1.setVisible(self.feature['mpa1'])
        self.monitorAreaCAM1.toggle()
        self.monitorAreaCAM1.setCheckable(True)
        self.monitorAreaCAM2.setVisible(self.feature['mpa2'])
        self.monitorAreaCAM3.setVisible(self.feature['mpa3'])

        self.personSearchingCAM1.setVisible(self.feature['person1'])
        self.personSearchingCAM2.setVisible(self.feature['person2'])
        self.personSearchingCAM3.setVisible(self.feature['person3'])
        # setup media player
        self.mediaPlayer.setVideoOutput(videowidget)
        self.openBtn.clicked.connect(self.open_file)
        self.playBtn.clicked.connect(self.play_video)
        self.stopBtn.clicked.connect(self.stop_video)
        self.fastBtn.clicked.connect(self.fast)
        self.slowBtn.clicked.connect(self.slow)
        self.volumeBtn.clicked.connect(self.mute)
        self.fullscreenBtn.clicked.connect(self.fullscreen)
        self.volume_slider.sliderMoved.connect(self.set_volume)
        self.slider.sliderMoved.connect(self.set_position)

        self.mediaPlayer.stateChanged.connect(self.mediastate_changed)
        self.mediaPlayer.positionChanged.connect(self.position_changed)
        self.mediaPlayer.durationChanged.connect(self.duration_changed)

        # setup image processing
        #  create a timer
        self.timer = QTimer()
        self.timer2 = QTimer()
        self.timer3 = QTimer()
        # set timer timeout callback function
        self.timer.timeout.connect(self.viewCam1)
        self.startCAM1.clicked.connect(self.start_view1)
        self.stopCAM1.clicked.connect(self.stop_view1)

        self.timer2.timeout.connect(self.viewCam2)
        self.startCAM2.clicked.connect(self.start_view2)
        self.stopCAM2.clicked.connect(self.stop_view2)

        self.timer3.timeout.connect(self.viewCam3)
        self.startCAM3.clicked.connect(self.start_view3)
        self.stopCAM3.clicked.connect(self.stop_view3)

        self.CAM1_draw.mousePressEvent = self.mouseEventCAM1
        self.CAM2_draw.mousePressEvent = self.mouseEventCAM2
        self.CAM3_draw.mousePressEvent = self.mouseEventCAM3

        self.drawCAM1.clicked.connect(self.startDrawAreaCAM1)
        self.removeCAM1.clicked.connect(self.removeAreaCAM1)

        self.drawCAM2.clicked.connect(self.startDrawAreaCAM2)
        self.removeCAM2.clicked.connect(self.removeAreaCAM2)

        self.drawCAM3.clicked.connect(self.startDrawAreaCAM3)
        self.removeCAM3.clicked.connect(self.removeAreaCAM3)

        self.retranslateUi(Form)
        self.tabWidget.setCurrentIndex(0)
        QtCore.QMetaObject.connectSlotsByName(Form)
# All function
# Function retranslateUI

    def retranslateUi(self, Form):
        _translate = QtCore.QCoreApplication.translate
        Form.setWindowTitle(_translate("Form", "Form"))
        self.CAM1.setText(_translate("Form", "IP CAM 1"))
        self.startCAM1.setText(_translate("Form", "Start"))
        self.carProtectionCAM1.setText(_translate("Form", "Car protection"))
        self.monitorAreaCAM1.setText(
            _translate("Form", "Monitor prohibited area"))
        self.stopCAM1.setText(_translate("Form", "Stop"))
        self.personSearchingCAM1.setText(_translate("Form",
                                                    "Person searching"))
        self.illegalCAM1.setText(_translate("Form", "Illegal access action"))
        self.CAM2.setText(_translate("Form", "IP CAM 2"))
        self.startCAM2.setText(_translate("Form", "Start"))
        self.carProtectionCAM2.setText(_translate("Form", "Car protection"))
        self.monitorAreaCAM2.setText(
            _translate("Form", "Monitor prohibited area"))
        self.stopCAM2.setText(_translate("Form", "Stop"))
        self.personSearchingCAM2.setText(_translate("Form",
                                                    "Person searching"))
        self.illegalCAM2.setText(_translate("Form", "Illegal access action"))
        self.CAM3.setText(_translate("Form", "IP CAM 3"))
        self.startCAM3.setText(_translate("Form", "Start"))
        self.carProtectionCAM3.setText(_translate("Form", "Car protection"))
        self.monitorAreaCAM3.setText(
            _translate("Form", "Monitor prohibited area"))
        self.stopCAM3.setText(_translate("Form", "Stop"))
        self.personSearchingCAM3.setText(_translate("Form",
                                                    "Person searching"))
        self.illegalCAM3.setText(_translate("Form", "Illegal access action"))
        self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab),
                                  _translate("Form", "3 IP CAMs"))
        self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_2),
                                  _translate("Form", "PLAY RECORD"))
        self.CAM1_draw.setText(_translate("Form", "TextLabel"))
        self.drawCAM1.setText(_translate("Form", "Draw"))
        self.removeCAM1.setText(_translate("Form", "Clear"))
        self.CAM2_draw.setText(_translate("Form", "TextLabel"))
        self.drawCAM2.setText(_translate("Form", "Draw"))
        self.removeCAM2.setText(_translate("Form", "Clear"))
        self.CAM3_draw.setText(_translate("Form", "TextLabel"))
        self.drawCAM3.setText(_translate("Form", "Draw"))
        self.removeCAM3.setText(_translate("Form", "Clear"))
        self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_3),
                                  _translate("Form", "SETTING"))
# Function for media player

    def open_file(self):
        filename, _ = QFileDialog.getOpenFileName(self, "Open Video")

        if filename != '':
            self.mediaPlayer.setMedia(
                QMediaContent(QUrl.fromLocalFile(filename)))
            self.playBtn.setEnabled(True)

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

    def stop_video(self):
        self.mediaPlayer.stop()

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

    def position_changed(self, position):
        self.slider.setValue(position)

    def duration_changed(self, duration):
        self.slider.setRange(0, duration)

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

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

    def mute(self):
        if not self.mediaPlayer.isMuted():
            self.mediaPlayer.setMuted(True)
            self.volumeBtn.setIcon(self.style().standardIcon(
                QStyle.SP_MediaVolumeMuted))
        else:
            self.mediaPlayer.setMuted(False)
            self.volumeBtn.setIcon(self.style().standardIcon(
                QStyle.SP_MediaVolume))

    def handle_errors(self):
        self.playBtn.setEnabled(False)
        self.label.setText("Error: " + self.mediaPlayer.errorString())

        self.startCAM1.clicked.connect(self.start)
        self.stopCAM1.clicked.connect(self.stop)

    def fullscreen(self):
        if self.windowState() & Qt.WindowFullScreen:
            QApplication.setOverrideCursor(Qt.ArrowCursor)
            self.showNormal()
            print("no Fullscreen")
        else:
            Form.showFullScreen()
            QApplication.setOverrideCursor(Qt.BlankCursor)
            print("Fullscreen entered")

    def fast(self):
        self.mediaPlayer.setPosition(self.mediaPlayer.position() + 10 * 60)

    def slow(self):
        self.mediaPlayer.setPosition(self.mediaPlayer.position() - 10 * 60)

# Function for image processing

    def image_to_QImage(self, image, label: QLabel):
        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
        image = cv2.resize(image, (label.width(), label.height()))
        height, width, channel = image.shape
        step = channel * width
        return QImage(image.data, width, height, step, QImage.Format_RGB888)

    def start_view1(self):
        self.stopCAM1.setEnabled(True)
        self.startCAM1.setEnabled(False)
        self.vs1 = VideoStream(src=IP_CAM_ADDRESS['CAM1'])
        self.flag_CAM1 = self.vs1.flag
        if self.vs1.flag:
            self.vs1.start()
            now = datetime.now()
            self.savePath1 = self.createDir('IP_CAM_1')
            self.startTime1 = str(now.day) + ' - ' + str(now.hour) + 'h' + str(
                now.minute) + ' - '
            fourcc = cv2.VideoWriter_fourcc(*'XVID')
            self.outVivdeo = cv2.VideoWriter(
                self.savePath1 + 'output.avi', fourcc, 30,
                (int(self.vs1.stream.get(3)), int(self.vs1.stream.get(4))))
            self.timer.start(20)
        else:
            self.startCAM1.setEnabled(True)
            self.stopCAM1.setEnabled(False)
            image = cv2.imread('no-connection.jpg')
            self.CAM1.setPixmap(
                QPixmap.fromImage(self.image_to_QImage(image, self.CAM1)))

    def viewCam1(self):
        image = self.vs1.read()
        self.outVivdeo.write(image)
        self.CAM1.setPixmap(
            QPixmap.fromImage(self.image_to_QImage(image, self.CAM1)))
        if self.feature['mpa1'] and self.monitorAreaCAM1.isChecked():
            image, self.numWarning = detectObject(image,
                                                  self.points_CAM1,
                                                  flag_Warning=1,
                                                  numWarning=self.numWarning)
        self.CAM1_draw.setPixmap(
            QPixmap.fromImage(
                self.image_to_QImage(
                    self.drawArea(image, self.points_CAM1, self.CAM1_draw),
                    self.CAM1_draw)))

    def stop_view1(self):
        self.startCAM1.setEnabled(True)
        self.stopCAM1.setEnabled(False)
        self.timer.stop()
        self.vs1.stop()
        image = cv2.imread('stopVideo.png')
        self.CAM1.setPixmap(
            QPixmap.fromImage(self.image_to_QImage(image, self.CAM1)))
        now = datetime.now()
        fileName = self.startTime1 + str(now.hour) + 'h' + str(
            now.minute) + '.avi'
        os.rename(self.savePath1 + 'output.avi', self.savePath1 + fileName)

    def start_view2(self):
        self.stopCAM2.setEnabled(True)
        self.startCAM2.setEnabled(False)
        self.vs2 = VideoStream(src=IP_CAM_ADDRESS['CAM2'])
        print('ok')
        if self.vs2.flag:
            self.vs2.start()
            now = datetime.now()
            self.savePath2 = self.createDir('IP_CAM_2')
            self.startTime2 = str(now.day) + ' - ' + str(now.hour) + 'h' + str(
                now.minute) + ' - '
            fourcc = cv2.VideoWriter_fourcc(*'XVID')
            self.outVivdeo2 = cv2.VideoWriter(
                self.savePath2 + 'output2.avi', fourcc, 30,
                (int(self.vs2.stream.get(3)), int(self.vs2.stream.get(4))))
            self.timer2.start(20)
        else:
            self.startCAM2.setEnabled(True)
            self.stopCAM2.setEnabled(False)
            image = cv2.imread('no-connection.jpg')
            self.CAM2.setPixmap(
                QPixmap.fromImage(self.image_to_QImage(image, self.CAM2)))

    def viewCam2(self):
        image = self.vs2.read()
        self.outVivdeo2.write(image)
        self.CAM2.setPixmap(
            QPixmap.fromImage(self.image_to_QImage(image, self.CAM2)))

    def stop_view2(self):
        self.startCAM2.setEnabled(True)
        self.stopCAM2.setEnabled(False)
        self.timer2.stop()
        self.vs2.stop()
        image = cv2.imread('stopVideo.png')
        self.CAM2.setPixmap(
            QPixmap.fromImage(self.image_to_QImage(image, self.CAM2)))
        now = datetime.now()
        fileName = self.startTime2 + str(now.hour) + 'h' + str(
            now.minute) + '.avi'
        os.rename(self.savePath2 + 'output2.avi', self.savePath2 + fileName)

    # def viewCam(self):
    #     # while True:
    #     ret, image = self.cap.read()
    #     self.outVivdeo.write(image)
    #     self.CAM1.setPixmap(QPixmap.fromImage(self.image_to_QImage(image, self.CAM1)))
    #     if self.feature['mpa1'] and self.monitorAreaCAM1.isChecked():
    #       image, self.numWarning = detectObject(image, self.points_CAM1, flag_Warning=1, numWarning=self.numWarning)
    #     self.CAM1_draw.setPixmap(QPixmap.fromImage(self.image_to_QImage(self.drawArea(image, self.points_CAM1, self.CAM1_draw), self.CAM1_draw)))

    # def start_view(self):
    #         self.stopCAM1.setEnabled(True)
    #         self.startCAM1.setEnabled(False)
    #         self.cap = cv2.VideoCapture(IP_CAM_ADDRESS['CAM1'])
    #         self.flag_CAM1 = self.cap.isOpened()
    #         if self.cap.isOpened():
    #             now = datetime.now()
    #             self.savePath1 = self.createDir('IP_CAM_1')
    #             self.startTime1 = str(now.day)+' - '+str(now.hour)+'h'+str(now.minute)+ ' - '
    #             fourcc = cv2.VideoWriter_fourcc(*'XVID')
    #             self.outVivdeo = cv2.VideoWriter(self.savePath1+'output.avi', fourcc, 30, (int(self.cap.get(3)), int(self.cap.get(4))))
    #             self.timer.start(0)
    #         else:
    #             self.startCAM1.setEnabled(True)
    #             self.stopCAM1.setEnabled(False)
    #             image = cv2.imread('no-connection.jpg')
    #             self.CAM1.setPixmap(QPixmap.fromImage(self.image_to_QImage(image, self.CAM1)))

    # def stop_view(self):
    #     self.startCAM1.setEnabled(True)
    #     self.stopCAM1.setEnabled(False)
    #     self.timer.stop()
    #     self.cap.release()
    #     self.outVivdeo.release()
    #     print("ok")
    #     image = cv2.imread('stopVideo.png')
    #     self.CAM1.setPixmap(QPixmap.fromImage(self.image_to_QImage(image, self.CAM1)))
    #     print('ok2')
    #     now = datetime.now()
    #     fileName = self.startTime1+str(now.hour)+'h'+str(now.minute)+'.avi'
    #     os.rename(self.savePath1+'output.avi', self.savePath1+fileName)

    # def viewCam2(self):
    #     ret, image = self.cap2.read()
    #     self.outVivdeo2.write(image)
    #     self.CAM2_draw.setPixmap(QPixmap.fromImage(self.image_to_QImage(self.drawArea(image, self.points_CAM2, self.CAM2_draw), self.CAM2_draw)))
    #     self.CAM2.setPixmap(QPixmap.fromImage(self.image_to_QImage(image, self.CAM2)))

    # def start_view2(self):
    #     if not self.timer2.isActive():
    #         self.stopCAM2.setEnabled(True)
    #         self.startCAM2.setEnabled(False)
    #         self.cap2 = cv2.VideoCapture(IP_CAM_ADDRESS['CAM2'])
    #         self.flag_CAM2 = self.cap2.isOpened()
    #         if self.cap2.isOpened():
    #             now = datetime.now()
    #             self.savePath2 = self.createDir('IP_CAM_2')
    #             self.startTime2 = str(now.day)+' - '+str(now.hour)+'h'+str(now.minute)+ ' - '
    #             # fourcc = cv2.VideoWriter_fourcc(*'mp4v')
    #             fourcc = cv2.VideoWriter_fourcc(*'XVID')
    #             self.outVivdeo2 = cv2.VideoWriter(self.savePath2+'output2.avi', fourcc, 30, (int(self.cap2.get(3)), int(self.cap2.get(4))))
    #             self.timer2.start(0)
    #         else:
    #             self.startCAM2.setEnabled(True)
    #             self.stopCAM2.setEnabled(False)
    #             image = cv2.imread('no-connection.jpg')
    #             self.CAM2.setPixmap(QPixmap.fromImage(self.image_to_QImage(image, self.CAM2)))

    # def stop_view2(self):
    #     self.startCAM2.setEnabled(True)
    #     self.stopCAM2.setEnabled(False)
    #     self.timer2.stop()
    #     self.outVivdeo2.release()
    #     image = cv2.imread('stopVideo.png')
    #     self.CAM2.setPixmap(QPixmap.fromImage(self.image_to_QImage(image, self.CAM2)))
    #     self.cap2.release()
    #     now = datetime.now()
    #     fileName = self.startTime2+str(now.hour)+'h'+str(now.minute)+'.avi'
    #     os.rename(self.savePath2+'output2.avi', self.savePath2+fileName)

    def viewCam3(self):
        ret, image = self.cap3.read()
        self.outVivdeo3.write(image)
        self.CAM3_draw.setPixmap(
            QPixmap.fromImage(
                self.image_to_QImage(
                    self.drawArea(image, self.points_CAM3, self.CAM3_draw),
                    self.CAM3_draw)))
        self.CAM3.setPixmap(
            QPixmap.fromImage(self.image_to_QImage(image, self.CAM3)))

    def start_view3(self):
        if not self.timer3.isActive():
            self.stopCAM3.setEnabled(True)
            self.startCAM3.setEnabled(False)
            self.cap3 = cv2.VideoCapture(IP_CAM_ADDRESS['CAM3'])
            self.flag_CAM3 = self.cap3.isOpened()
            if self.cap3.isOpened():
                now = datetime.now()
                self.savePath3 = self.createDir('IP_CAM_3')
                self.startTime3 = str(now.day) + ' - ' + str(
                    now.hour) + 'h' + str(now.minute) + ' - '
                # fourcc = cv2.VideoWriter_fourcc(*'mp4v')
                fourcc = cv2.VideoWriter_fourcc(*'XVID')
                self.outVivdeo3 = cv2.VideoWriter(
                    self.savePath3 + 'output3.avi', fourcc, 30,
                    (int(self.cap3.get(3)), int(self.cap3.get(4))))
                self.timer3.start(0)
            else:
                self.startCAM3.setEnabled(True)
                self.stopCAM3.setEnabled(False)
                image = cv2.imread('no-connection.jpg')
                self.CAM3.setPixmap(
                    QPixmap.fromImage(self.image_to_QImage(image, self.CAM3)))

    def stop_view3(self):
        self.startCAM3.setEnabled(True)
        self.stopCAM3.setEnabled(False)
        self.timer3.stop()
        self.outVivdeo3.release()
        image = cv2.imread('stopVideo.png')
        self.CAM3.setPixmap(
            QPixmap.fromImage(self.image_to_QImage(image, self.CAM3)))
        self.cap3.release()
        now = datetime.now()
        fileName = self.startTime3 + str(now.hour) + 'h' + str(
            now.minute) + '.avi'
        os.rename(self.savePath3 + 'output3.avi', self.savePath3 + fileName)

    def createDir(self, IP_CAM_Number: str):
        now = datetime.now()
        year = now.year
        month = MONTH[now.month]

        curPath = os.getcwd()
        if not path.exists(curPath + '/IVA'):
            os.mkdir(curPath + '/IVA')
        if not path.exists(curPath + '/IVA/' + IP_CAM_Number):
            os.mkdir(curPath + '/IVA/' + IP_CAM_Number)

        # check path exists
        if path.exists(curPath + '/IVA/' + IP_CAM_Number + '/' + str(year)):
            if path.exists(curPath + '/IVA/' + IP_CAM_Number + '/' +
                           str(year) + '/' + month):
                return curPath + '/IVA/' + IP_CAM_Number + '/' + str(
                    year) + '/' + month + '/'
            else:
                os.mkdir(curPath + '/IVA/' + IP_CAM_Number + '/' + str(year) +
                         '/' + month)
                return curPath + '/IVA/' + IP_CAM_Number + '/' + str(
                    year) + '/' + month + '/'
        else:
            os.mkdir(curPath + '/IVA/' + IP_CAM_Number + '/' + str(year))
            if path.exists(curPath + '/IVA/' + IP_CAM_Number + '/' +
                           str(year) + '/' + month):
                return curPath + '/IVA/' + IP_CAM_Number + '/' + str(
                    year) + '/' + month + '/'
            else:
                os.mkdir(curPath + '/IVA/' + IP_CAM_Number + '/' + str(year) +
                         '/' + month)
                return curPath + '/IVA/' + IP_CAM_Number + '/' + str(
                    year) + '/' + month + '/'

    # Create Mouse Event for draw protected area
    def mouseEventCAM1(self, event):
        if self.removeCAM1.isEnabled() and (
                not self.startCAM1.isEnabled()) and self.flag_CAM1 == True:
            # print(self.CAM1_draw.width(), self.CAM1_draw.height())
            x = event.pos().x()
            y = event.pos().y()
            print(x, y)
            x = round((x / self.CAM1_draw.width()), 10)
            y = round((y / self.CAM1_draw.height()), 10)
            self.points_CAM1.append([x, y])
            print("Position clicked is ({}, {})".format(
                int(x * self.CAM1_draw.width()),
                int(y * self.CAM1_draw.height())))
            # print(self.points_CAM1)

    def mouseEventCAM2(self, event):
        if self.removeCAM2.isEnabled() and (
                not self.startCAM2.isEnabled()) and self.flag_CAM2 == True:
            x = event.pos().x()
            y = event.pos().y()
            self.points_CAM2.append([x, y])
            print("Position clicked is ({}, {})".format(x, y))

    def mouseEventCAM3(self, event):
        if self.removeCAM3.isEnabled() and (
                not self.startCAM3.isEnabled()) and self.flag_CAM3 == True:
            x = event.pos().x()
            y = event.pos().y()
            self.points_CAM3.append([x, y])
            print("Position clicked is ({}, {})".format(x, y))

    def startDrawAreaCAM1(self):
        self.drawCAM1.setEnabled(False)
        self.removeCAM1.setEnabled(True)

    def removeAreaCAM1(self):
        while len(self.points_CAM1):
            self.points_CAM1.pop()
        self.drawCAM1.setEnabled(True)
        self.removeCAM1.setEnabled(False)

    def startDrawAreaCAM2(self):
        self.drawCAM2.setEnabled(False)
        self.removeCAM2.setEnabled(True)

    def removeAreaCAM2(self):
        while len(self.points_CAM2):
            self.points_CAM2.pop()
        self.drawCAM2.setEnabled(True)
        self.removeCAM2.setEnabled(False)

    def startDrawAreaCAM3(self):
        self.drawCAM3.setEnabled(False)
        self.removeCAM3.setEnabled(True)

    def removeAreaCAM3(self):
        while len(self.points_CAM3):
            self.points_CAM3.pop()
        self.drawCAM3.setEnabled(True)
        self.removeCAM3.setEnabled(False)

    def drawArea(self, image, points: list, qlabel: QtWidgets.QLabel):
        image_draw = image.copy()
        (width, height) = image.shape[:2]
        image_draw = cv2.resize(image_draw, (qlabel.width(), qlabel.height()))

        if len(points) > 1:
            point1 = []
            for point in points:
                x = int(point[0] * qlabel.width())
                y = int(point[1] * qlabel.height())
                point1.append((x, y))
            cv2.polylines(image_draw, np.array([point1]), 1, (255, 0, 0), 1)
            b, g, r = cv2.split(image_draw)
            cv2.fillPoly(b, np.array([point1]), (0, 255, 0))
            cv2.fillPoly(r, np.array([point1]), (0, 255, 0))
            image_draw = cv2.merge([b, g, r])
        return image_draw

# Function for IVA tasks

    def monitorProhibitedArea(self, frame, points: list, flag_Warning: int):
        pass
Ejemplo n.º 32
0
class MainWindow(QMainWindow):
    def __init__(self, app):
        super(MainWindow, self).__init__()
        self.app = app
        print('window created')
        self.setWindowIcon(QIcon('img/icon.png'))
        self.setWindowTitle('Kasino')
        self.setPalette(QPalette(Qt.darkGreen))
        self.setup_music()

        self.statusbar = QStatusBar(self)
        self.statusbar.setStyleSheet('background: white')
        self.setStatusBar(self.statusbar)
        self.statusbar.showMessage('Welcome to the Cassino game!')

        self.menubar = QMenuBar(self)
        self.optionsMenu = self.menubar.addMenu('Options')
        self.music_toggle = QAction()
        self.music_toggle.setText('Music')
        self.music_toggle.setShortcut('Ctrl+m')
        self.music_toggle.setCheckable(True)
        self.music_toggle.setChecked(True)
        self.optionsMenu.addAction(self.music_toggle)
        self.music_toggle.triggered.connect(self.toggle_music)

        self.speedGroup = QActionGroup(self)
        self.speedGroup.triggered.connect(self.set_speed)

        self.slow_speed = QAction('Slow', self.speedGroup)
        self.slow_speed.setCheckable(True)
        self.normal_speed = QAction('Normal', self.speedGroup)
        self.normal_speed.setCheckable(True)
        self.fast_speed = QAction('Fast', self.speedGroup)
        self.fast_speed.setCheckable(True)
        self.vfast_speed = QAction('Very Fast', self.speedGroup)
        self.vfast_speed.setCheckable(True)
        self.normal_speed.setChecked(True)

        self.speed_menu = self.optionsMenu.addMenu('Speed')
        self.speed_menu.addActions(self.speedGroup.actions())
        self.menubar.setMouseTracking(False)
        self.setMenuBar(self.menubar)

        self.play_widget = PlayWidget(self)
        self.main_menu = MainMenu(self)
        self.start_menu = StartMenu(self)
        self.widgets = QStackedWidget(self)
        self.widgets.addWidget(self.play_widget)
        self.widgets.addWidget(self.main_menu)
        self.widgets.addWidget(self.start_menu)
        self.widgets.setCurrentWidget(self.main_menu)

        self.setCentralWidget(self.widgets)
        self.setGeometry(25, 50, 1028, 720)

        self.main_menu.startbutton.clicked.connect(self.init_game)
        self.main_menu.loadbutton.clicked.connect(self.load_game)
        self.main_menu.quitbutton.clicked.connect(self.quit)
        self.play_widget.quit_button.clicked.connect(self.quit_to_menu)
        self.play_widget.save_button.clicked.connect(self.save_game)
        self.start_menu.startbutton.clicked.connect(self.start_game)

    def setup_music(self):
        self.music = QMediaPlayer()
        self.playlist = QMediaPlaylist()
        self.playlist.setPlaybackMode(QMediaPlaylist.Loop)
        file_name = "sound/bg.mp3"
        self.media = QMediaContent(QUrl.fromLocalFile(file_name))
        self.playlist.addMedia(self.media)
        self.music.setPlaylist(self.playlist)
        self.music.setVolume(20)
        self.music.play()

    def toggle_music(self):
        if self.music.isMuted():
            self.music.setMuted(False)
            self.statusbar.showMessage('Music on', 5000)
        else:
            self.music.setMuted(True)
            self.statusbar.showMessage('Music off', 5000)

    def set_speed(self, action):
        if action == self.slow_speed:
            self.play_widget.speed = 1
        elif action == self.normal_speed:
            self.play_widget.speed = 3
        elif action == self.fast_speed:
            self.play_widget.speed = 4
        else:
            self.play_widget.speed = 6

    def start_game(self):
        self.play_widget.init_game(
            self.start_menu.extract_info_and_init_game())
        self.widgets.setCurrentWidget(self.play_widget)
        self.statusbar.showMessage('Game launched', 2000)

    def load_game(self):
        path = QFileDialog.getOpenFileName(self, 'Open save file',
                                           QDir.currentPath() + '/sav')[0]
        if path != '':
            game, msg, count = load(path)
            self.play_widget.resume_from_save(game, msg, count)
            self.widgets.setCurrentWidget(self.play_widget)
            self.statusbar.showMessage('Loaded save file', 5000)

    def save_game(self):
        path = QFileDialog.getSaveFileName(self, 'Create save file',
                                           QDir.currentPath() + '/sav')[0]
        if path != '':
            save(path, self.play_widget.game, self.play_widget.export_log(),
                 self.play_widget.move_count)
            self.statusbar.showMessage('Game saved', 5000)

    def init_game(self):
        self.widgets.setCurrentWidget(self.start_menu)
        self.statusbar.showMessage('Starting new game')

    def quit_to_menu(self):
        #Reset playwidget
        self.widgets.removeWidget(self.play_widget)
        speed = self.play_widget.speed
        self.play_widget.setParent(None)
        self.play_widget = PlayWidget(self)
        self.play_widget.speed = speed
        self.widgets.addWidget(self.play_widget)
        self.play_widget.quit_button.clicked.connect(self.quit_to_menu)
        self.play_widget.save_button.clicked.connect(self.save_game)

        self.widgets.setCurrentWidget(self.main_menu)

    def closeEvent(self, *args,
                   **kwargs):  #for handling closing from 'x' button
        self.quit()

    def quit(self):
        print('Exited game. Thanks for playing!\n')
        self.app.exit()
Ejemplo n.º 33
0
class Ui_Form(QWidget):
    def __init__(self):
        super().__init__()
        self.points_CAM1 = []
        self.points_CAM2 = []
        self.points_CAM3 = []

    def setupUi(self, Form):
        Form.setObjectName("Form")
        self.tabWidget = QtWidgets.QTabWidget(Form)
        self.tabWidget.setObjectName("tabWidget")
        self.multiTab = QtWidgets.QWidget()
        self.multiTab.setObjectName("multiTab")
        # cam1
        self.cam_1 = QtWidgets.QWidget(self.multiTab)
        self.cam_1.setObjectName("cam_1")
        self.CAM1 = QtWidgets.QLabel(self.cam_1)
        self.CAM1.setFrameShape(QtWidgets.QFrame.Box)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred,
                                           QtWidgets.QSizePolicy.Preferred)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.CAM1.sizePolicy().hasHeightForWidth())
        self.CAM1.setSizePolicy(sizePolicy)
        self.CAM1.setMinimumSize(QtCore.QSize(320, 240))
        self.CAM1.setMaximumSize(QtCore.QSize(400, 320))
        self.CAM1.setSizeIncrement(QtCore.QSize(3, 2))
        self.CAM1.setScaledContents(True)
        self.CAM1.setObjectName("CAM1")
        self.startCAM1 = QtWidgets.QPushButton(self.cam_1)
        self.startCAM1.setObjectName("startCAM1")
        self.stopCAM1 = QtWidgets.QPushButton(self.cam_1)
        self.stopCAM1.setObjectName("stopCAM1")
        self.reIDBtn_1 = QtWidgets.QPushButton(self.cam_1)
        self.reIDBtn_1.setObjectName("reIDBtn_1")
        self.falldetectionBtn_1 = QtWidgets.QPushButton(self.cam_1)
        self.falldetectionBtn_1.setObjectName("falldetectionBtn_1")
        self.peoplecntBtn_1 = QtWidgets.QPushButton(self.cam_1)
        self.peoplecntBtn_1.setObjectName("peoplecntBtn_1")
        self.areaprotectionBtn_1 = QtWidgets.QPushButton(self.cam_1)
        self.areaprotectionBtn_1.setObjectName("areaprotectionBtn_1")

        layoutCam_1 = QGridLayout(self.cam_1)
        layoutCam_1.addWidget(self.CAM1, 0, 0, 7, 3)
        layoutCam_1.addWidget(self.startCAM1, 8, 0)
        layoutCam_1.addWidget(self.stopCAM1, 9, 0)
        layoutCam_1.addWidget(self.reIDBtn_1, 8, 1)
        layoutCam_1.addWidget(self.falldetectionBtn_1, 8, 2)
        layoutCam_1.addWidget(self.peoplecntBtn_1, 9, 1)
        layoutCam_1.addWidget(self.areaprotectionBtn_1, 9, 2)
        self.cam_1.setLayout(layoutCam_1)

        # Setting Multi_tab Cam 2
        self.cam_2 = QtWidgets.QWidget(self.multiTab)
        self.cam_2.setObjectName("cam_2")
        self.CAM2 = QtWidgets.QLabel(self.cam_2)
        self.CAM2.setFrameShape(QtWidgets.QFrame.Box)
        self.CAM2.setSizePolicy(sizePolicy)
        self.CAM2.setMinimumSize(QtCore.QSize(320, 240))
        self.CAM2.setMaximumSize(QtCore.QSize(400, 320))
        self.CAM2.setSizeIncrement(QtCore.QSize(3, 2))
        self.CAM2.setObjectName("CAM2")
        self.CAM2.setScaledContents(True)
        self.peoplecntBtn_2 = QtWidgets.QPushButton(self.cam_2)
        self.peoplecntBtn_2.setObjectName("peoplecntBtn_2")
        self.falldetectionBtn_2 = QtWidgets.QPushButton(self.cam_2)
        self.falldetectionBtn_2.setObjectName("falldetectionBtn_2")
        self.reIDBtn_2 = QtWidgets.QPushButton(self.cam_2)
        self.reIDBtn_2.setObjectName("reIDBtn_2")
        self.stop_CAM2 = QtWidgets.QPushButton(self.cam_2)
        self.stop_CAM2.setObjectName("stop_CAM2")
        self.start_CAM2 = QtWidgets.QPushButton(self.cam_2)
        self.start_CAM2.setObjectName("start_CAM2")
        self.areaprotectionBtn_2 = QtWidgets.QPushButton(self.cam_2)
        self.areaprotectionBtn_2.setObjectName("areaprotectionBtn_2")

        layoutCam_2 = QGridLayout(self.cam_2)
        layoutCam_2.addWidget(self.CAM2, 0, 0, 7, 3)
        layoutCam_2.addWidget(self.start_CAM2, 8, 0)
        layoutCam_2.addWidget(self.stop_CAM2, 9, 0)
        layoutCam_2.addWidget(self.reIDBtn_2, 8, 1)
        layoutCam_2.addWidget(self.falldetectionBtn_2, 8, 2)
        layoutCam_2.addWidget(self.peoplecntBtn_2, 9, 1)
        layoutCam_2.addWidget(self.areaprotectionBtn_2, 9, 2)
        self.cam_2.setLayout(layoutCam_2)

        # Setting Multi_tab Cam 3
        self.cam_3 = QtWidgets.QWidget(self.multiTab)
        self.cam_3.setObjectName("cam_3")
        self.CAM3 = QtWidgets.QLabel(self.cam_3)
        self.CAM3.setFrameShape(QtWidgets.QFrame.Box)
        self.CAM3.setSizePolicy(sizePolicy)
        self.CAM3.setMinimumSize(QtCore.QSize(320, 240))
        self.CAM3.setMaximumSize(QtCore.QSize(400, 320))
        self.CAM3.setSizeIncrement(QtCore.QSize(3, 2))
        self.CAM3.setObjectName("CAM3")
        self.CAM3.setScaledContents(True)
        self.peoplecntBtn_3 = QtWidgets.QPushButton(self.cam_3)
        self.peoplecntBtn_3.setObjectName("peoplecntBtn_3")
        self.falldetectionBtn_3 = QtWidgets.QPushButton(self.cam_3)
        self.falldetectionBtn_3.setObjectName("falldetectionBtn_3")
        self.reIDBtn_3 = QtWidgets.QPushButton(self.cam_3)
        self.reIDBtn_3.setObjectName("reIDBtn_3")
        self.stop_CAM3 = QtWidgets.QPushButton(self.cam_3)
        self.stop_CAM3.setObjectName("stop_CAM3")
        self.start_CAM3 = QtWidgets.QPushButton(self.cam_3)
        self.start_CAM3.setObjectName("start_CAM3")
        self.areaprotectionBtn_3 = QtWidgets.QPushButton(self.cam_3)
        self.areaprotectionBtn_3.setObjectName("areaprotectionBtn_3")

        layoutCam_3 = QGridLayout(self.cam_3)
        layoutCam_3.addWidget(self.CAM3, 0, 0, 7, 3)
        layoutCam_3.addWidget(self.start_CAM3, 8, 0)
        layoutCam_3.addWidget(self.stop_CAM3, 9, 0)
        layoutCam_3.addWidget(self.reIDBtn_3, 8, 1)
        layoutCam_3.addWidget(self.falldetectionBtn_3, 8, 2)
        layoutCam_3.addWidget(self.peoplecntBtn_3, 9, 1)
        layoutCam_3.addWidget(self.areaprotectionBtn_3, 9, 2)
        self.cam_3.setLayout(layoutCam_3)

        # Setting layout multi_tab
        layoutMultitab = QGridLayout(self.multiTab)
        layoutMultitab.addWidget(self.cam_1, 0, 0)
        layoutMultitab.addWidget(self.cam_2, 0, 1)
        layoutMultitab.addWidget(self.cam_3, 0, 2)
        self.multiTab.setLayout(layoutMultitab)
        self.tabWidget.addTab(self.multiTab, "")

        # Media Player

        self.playRec = QtWidgets.QWidget()
        self.playRec.setObjectName("playRec")
        self.tabWidget.addTab(self.playRec, "")
        self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.VideoSurface)
        videowidget = QVideoWidget()
        self.openBtn = QtWidgets.QPushButton('Open Video')
        self.playBtn = QtWidgets.QPushButton()
        self.playBtn.setEnabled(False)
        self.playBtn.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay))
        self.stopBtn = QtWidgets.QPushButton()
        self.stopBtn.setIcon(self.style().standardIcon(QStyle.SP_MediaStop))
        self.slowBtn = QtWidgets.QPushButton()
        self.slowBtn.setIcon(self.style().standardIcon(
            QStyle.SP_MediaSeekBackward))
        self.fastBtn = QtWidgets.QPushButton()
        self.fastBtn.setIcon(self.style().standardIcon(
            QStyle.SP_MediaSeekForward))
        self.volumeBtn = QtWidgets.QPushButton()
        self.volumeBtn.setIcon(self.style().standardIcon(
            QStyle.SP_MediaVolume))
        self.fullscreenBtn = QPushButton("Full Screen")
        self.slider = QSlider(Qt.Horizontal)
        self.slider.setRange(0, 0)
        self.volume_slider = QSlider(Qt.Horizontal)
        self.volume_slider.setRange(0, 100)
        self.volume_slider.setValue(100)
        self.label_2_1 = QLabel()
        self.label_2_1.setSizePolicy(QSizePolicy.Preferred,
                                     QSizePolicy.Maximum)
        self.label_2_2 = QLabel()
        hboxLayout_2_1 = QHBoxLayout()
        hboxLayout_2_2 = QHBoxLayout()
        hboxLayout_2_3 = QHBoxLayout()
        hboxLayout_2_1.addWidget(self.slider)
        hboxLayout_2_2.addWidget(self.openBtn)
        hboxLayout_2_2.addWidget(self.stopBtn)
        hboxLayout_2_2.addWidget(self.slowBtn)
        hboxLayout_2_2.addWidget(self.playBtn)
        hboxLayout_2_2.addWidget(self.fastBtn)
        hboxLayout_2_2.addWidget(self.volumeBtn)
        hboxLayout_2_2.addWidget(self.volume_slider)
        hboxLayout_2_2.addStretch(1)
        hboxLayout_2_2.addWidget(self.fullscreenBtn)
        hboxLayout_2_3.addWidget(videowidget)
        vboxLayout_2_1 = QVBoxLayout()
        vboxLayout_2_1.addLayout(hboxLayout_2_3)
        vboxLayout_2_1.addLayout(hboxLayout_2_1)
        vboxLayout_2_1.addLayout(hboxLayout_2_2)
        vboxLayout_2_1.addWidget(self.label_2_1)
        self.playRec.setLayout(vboxLayout_2_1)

        #Tab Setting
        self.setting = QtWidgets.QWidget()
        self.setting.setObjectName("setting")
        self.tabWidget.addTab(self.setting, "")
        # Cam 1
        self.camSetting_1 = QtWidgets.QWidget(self.setting)
        self.camSetting_1.setObjectName("camSetting_1")
        self.CAM1_Draw = QtWidgets.QLabel(self.camSetting_1)
        self.CAM1_Draw.setFrameShape(QtWidgets.QFrame.Box)
        self.CAM1_Draw.setSizePolicy(sizePolicy)
        self.CAM1_Draw.setMinimumSize(QtCore.QSize(320, 240))
        self.CAM1_Draw.setMaximumSize(QtCore.QSize(400, 320))
        self.CAM1_Draw.setSizeIncrement(QtCore.QSize(3, 2))
        self.CAM1_Draw.setObjectName("CAM1_Draw")
        self.draw_CAM1 = QtWidgets.QPushButton(self.camSetting_1)
        self.draw_CAM1.setObjectName("draw_CAM1")
        self.remove_CAM1 = QtWidgets.QPushButton(self.camSetting_1)
        self.remove_CAM1.setObjectName("remove_CAM1")

        layoutCamSetting_1 = QGridLayout()
        layoutCamSetting_1.addWidget(self.CAM1_Draw, 0, 0, 7, 4)
        layoutCamSetting_1.addWidget(self.draw_CAM1, 8, 1)
        layoutCamSetting_1.addWidget(self.remove_CAM1, 8, 2)
        self.camSetting_1.setLayout(layoutCamSetting_1)

        #camSetting 2
        self.camSetting_2 = QtWidgets.QWidget(self.setting)
        self.camSetting_2.setObjectName("camSetting_2")
        self.CAM2_Draw = QtWidgets.QLabel(self.camSetting_2)
        self.CAM2_Draw.setFrameShape(QtWidgets.QFrame.Box)
        self.CAM2_Draw.setSizePolicy(sizePolicy)
        self.CAM2_Draw.setMinimumSize(QtCore.QSize(320, 240))
        self.CAM2_Draw.setMaximumSize(QtCore.QSize(400, 320))
        self.CAM2_Draw.setSizeIncrement(QtCore.QSize(3, 2))
        self.CAM2_Draw.setObjectName("CAM2_Draw")
        self.draw_CAM2 = QtWidgets.QPushButton(self.camSetting_2)
        self.draw_CAM2.setObjectName("draw_CAM2")
        self.remove_CAM2 = QtWidgets.QPushButton(self.camSetting_2)
        self.remove_CAM2.setObjectName("remove_CAM2")

        layoutCamSetting_2 = QGridLayout()
        layoutCamSetting_2.addWidget(self.CAM2_Draw, 0, 0, 7, 4)
        layoutCamSetting_2.addWidget(self.draw_CAM2, 8, 1)
        layoutCamSetting_2.addWidget(self.remove_CAM2, 8, 2)
        self.camSetting_2.setLayout(layoutCamSetting_2)

        #camSeting 3
        self.camSetting_3 = QtWidgets.QWidget(self.setting)
        self.camSetting_3.setObjectName("camSetting_3")
        self.CAM3_Draw = QtWidgets.QLabel(self.camSetting_3)
        self.CAM3_Draw.setFrameShape(QtWidgets.QFrame.Box)
        self.CAM3_Draw.setSizePolicy(sizePolicy)
        self.CAM3_Draw.setMinimumSize(QtCore.QSize(320, 240))
        self.CAM3_Draw.setMaximumSize(QtCore.QSize(400, 320))
        self.CAM3_Draw.setSizeIncrement(QtCore.QSize(3, 2))
        self.CAM3_Draw.setObjectName("CAM3_Draw")
        self.draw_CAM3 = QtWidgets.QPushButton(self.camSetting_3)
        self.draw_CAM3.setObjectName("draw_CAM3")
        self.remove_CAM3 = QtWidgets.QPushButton(self.camSetting_3)
        self.remove_CAM3.setObjectName("remove_CAM3")

        layoutCamSetting_3 = QGridLayout()
        layoutCamSetting_3.addWidget(self.CAM3_Draw, 0, 0, 7, 4)
        layoutCamSetting_3.addWidget(self.draw_CAM3, 8, 1)
        layoutCamSetting_3.addWidget(self.remove_CAM3, 8, 2)
        self.camSetting_3.setLayout(layoutCamSetting_3)

        #layout Setting
        layoutSetting = QGridLayout()
        layoutSetting.addWidget(self.camSetting_1, 0, 0)
        layoutSetting.addWidget(self.camSetting_2, 0, 1)
        layoutSetting.addWidget(self.camSetting_3, 0, 2)

        self.setting.setLayout(layoutSetting)

        self.mediaPlayer.setVideoOutput(videowidget)
        self.openBtn.clicked.connect(self.open_file)
        self.playBtn.clicked.connect(self.play_video)
        self.stopBtn.clicked.connect(self.stop_video)
        self.fastBtn.clicked.connect(self.fast)
        self.slowBtn.clicked.connect(self.slow)
        self.volumeBtn.clicked.connect(self.mute)
        self.fullscreenBtn.clicked.connect(self.fullscreen)
        self.volume_slider.sliderMoved.connect(self.set_volume)
        self.slider.sliderMoved.connect(self.set_position)

        self.mediaPlayer.stateChanged.connect(self.mediastate_changed)
        self.mediaPlayer.positionChanged.connect(self.position_changed)
        self.mediaPlayer.durationChanged.connect(self.duration_changed)

        self.startCAM1.setEnabled(True)
        self.start_CAM2.setEnabled(True)
        self.start_CAM3.setEnabled(True)

        self.stopCAM1.setEnabled(False)
        self.stop_CAM2.setEnabled(False)
        self.stop_CAM3.setEnabled(False)

        #  create a timer
        self.timer = QTimer()
        self.timer2 = QTimer()
        self.timer3 = QTimer()
        # set timer timeout callback function
        self.timer.timeout.connect(self.viewCam)
        self.startCAM1.clicked.connect(self.start_view)
        self.stopCAM1.clicked.connect(self.stop_view)

        self.timer2.timeout.connect(self.viewCam2)
        self.start_CAM2.clicked.connect(self.start_view2)
        self.stop_CAM2.clicked.connect(self.stop_view2)

        self.timer3.timeout.connect(self.viewCam3)
        self.start_CAM3.clicked.connect(self.start_view3)
        self.stop_CAM3.clicked.connect(self.stop_view3)

        self.CAM1_Draw.mousePressEvent = self.mouseEventCAM1
        self.CAM2_Draw.mousePressEvent = self.mouseEventCAM2
        self.CAM3_Draw.mousePressEvent = self.mouseEventCAM3

        self.draw_CAM1.clicked.connect(self.startDrawAreaCAM1)
        self.remove_CAM1.clicked.connect(self.removeAreaCAM1)

        self.draw_CAM2.clicked.connect(self.startDrawAreaCAM2)
        self.remove_CAM2.clicked.connect(self.removeAreaCAM2)

        self.draw_CAM3.clicked.connect(self.startDrawAreaCAM3)
        self.remove_CAM3.clicked.connect(self.removeAreaCAM3)

        self.retranslateUi(Form)
        QtCore.QMetaObject.connectSlotsByName(Form)
        a = QVBoxLayout()
        a.addWidget(self.tabWidget)
        Form.setLayout(a)


# all function

    def retranslateUi(self, Form):
        _translate = QtCore.QCoreApplication.translate
        Form.setWindowTitle(_translate("Form", "Form"))
        self.CAM1.setText(_translate("Form", "Cam 1"))
        self.peoplecntBtn_1.setText(_translate("Form", "People Counting"))
        self.falldetectionBtn_1.setText(_translate("Form", "Fall Detection"))
        self.reIDBtn_1.setText(_translate("Form", "Person Re-ID"))
        self.stopCAM1.setText(_translate("Form", "Stop"))
        self.startCAM1.setText(_translate("Form", "Start"))
        self.areaprotectionBtn_1.setText(_translate("Form", "Area Protection"))

        self.CAM2.setText(_translate("Form", "cam 2"))
        self.peoplecntBtn_2.setText(_translate("Form", "People Counting"))
        self.falldetectionBtn_2.setText(_translate("Form", "Fall Detection"))
        self.reIDBtn_2.setText(_translate("Form", "Person Re-ID"))
        self.stop_CAM2.setText(_translate("Form", "Stop"))
        self.start_CAM2.setText(_translate("Form", "Start"))
        self.areaprotectionBtn_2.setText(_translate("Form", "Area Protection"))

        self.CAM3.setText(_translate("Form", "cam 3"))
        self.peoplecntBtn_3.setText(_translate("Form", "People Counting"))
        self.falldetectionBtn_3.setText(_translate("Form", "Fall Detection"))
        self.reIDBtn_3.setText(_translate("Form", "Person Re-ID"))
        self.stop_CAM3.setText(_translate("Form", "Stop"))
        self.start_CAM3.setText(_translate("Form", "Start"))
        self.areaprotectionBtn_3.setText(_translate("Form", "Area Protection"))

        self.CAM1_Draw.setText(_translate("Form", "cam 1"))
        self.draw_CAM1.setText(_translate("Form", "Draw"))
        self.remove_CAM1.setText(_translate("Form", "Clean"))

        self.CAM2_Draw.setText(_translate("Form", "cam 2"))
        self.draw_CAM2.setText(_translate("Form", "Draw"))
        self.remove_CAM2.setText(_translate("Form", "Clean"))

        self.CAM3_Draw.setText(_translate("Form", "cam 3"))
        self.draw_CAM3.setText(_translate("Form", "Draw"))
        self.remove_CAM3.setText(_translate("Form", "Clean"))

        self.tabWidget.setTabText(self.tabWidget.indexOf(self.multiTab),
                                  _translate("Form", "Multi_IPCam"))
        self.tabWidget.setTabText(self.tabWidget.indexOf(self.playRec),
                                  _translate("Form", "Play Record"))
        self.tabWidget.setTabText(self.tabWidget.indexOf(self.setting),
                                  _translate("Form", "Setting"))

    def open_file(self):
        filename, _ = QFileDialog.getOpenFileName(self, "Open Video")

        if filename != '':
            self.mediaPlayer.setMedia(
                QMediaContent(QUrl.fromLocalFile(filename)))
            self.playBtn.setEnabled(True)

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

    def stop_video(self):
        self.mediaPlayer.stop()

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

    def position_changed(self, position):
        self.slider.setValue(position)

    def duration_changed(self, duration):
        self.slider.setRange(0, duration)

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

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

    def mute(self):
        if not self.mediaPlayer.isMuted():
            self.mediaPlayer.setMuted(True)
            self.volumeBtn.setIcon(self.style().standardIcon(
                QStyle.SP_MediaVolumeMuted))
        else:
            self.mediaPlayer.setMuted(False)
            self.volumeBtn.setIcon(self.style().standardIcon(
                QStyle.SP_MediaVolume))

    def handle_errors(self):
        self.playBtn.setEnabled(False)
        self.label.setText("Error: " + self.mediaPlayer.errorString())

        self.startCAM1.clicked.connect(self.start)
        self.stopCAM1.clicked.connect(self.stop)

    def fullscreen(self):
        if self.windowState() & Qt.WindowFullScreen:
            QApplication.setOverrideCursor(Qt.ArrowCursor)
            self.showNormal()
            print("no Fullscreen")
        else:
            Form.showFullScreen()
            QApplication.setOverrideCursor(Qt.BlankCursor)
            print("Fullscreen entered")

    def fast(self):
        self.mediaPlayer.setPosition(self.mediaPlayer.position() + 10 * 60)

    def slow(self):
        self.mediaPlayer.setPosition(self.mediaPlayer.position() - 10 * 60)

    def image_to_QImage(self, image, label):
        # print(label.width(), label.height())
        # image = cv2.resize(image, (label.width(), label.height()))
        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
        height, width, channel = image.shape
        # print(height, width, channel)
        step = channel * width
        return QImage(image.data, width, height, step, QImage.Format_RGB888)

    def viewCam(self):
        ret, image = self.cap.read()
        self.outVivdeo.write(image)
        self.CAM1_Draw.setPixmap(
            QPixmap.fromImage(
                self.image_to_QImage(
                    self.drawArea(image, self.points_CAM1, self.CAM1_Draw),
                    self.CAM1_Draw)))
        self.CAM1.setPixmap(
            QPixmap.fromImage(self.image_to_QImage(image, self.CAM1)))

    def start_view(self):
        if not self.timer.isActive():
            self.stopCAM1.setEnabled(True)
            self.startCAM1.setEnabled(False)
            self.cap = cv2.VideoCapture(IP_CAM_ADDRESS['CAM1'])
            self.flag_CAM1 = self.cap.isOpened()
            if self.cap.isOpened():
                now = datetime.now()
                self.savePath1 = self.createDir('IP_CAM_1')
                self.startTime1 = str(now.day) + ' - ' + str(
                    now.hour) + 'h' + str(now.minute) + ' - '
                # fourcc = cv2.VideoWriter_fourcc(*'mp4v')
                fourcc = cv2.VideoWriter_fourcc(*'XVID')
                self.outVivdeo = cv2.VideoWriter(
                    self.savePath1 + 'output.avi', fourcc, 30,
                    (int(self.cap.get(3)), int(self.cap.get(4))))
                self.timer.start(0)
            else:
                self.startCAM1.setEnabled(True)
                self.stopCAM1.setEnabled(False)
                image = cv2.imread('no-connection.jpg')
                self.CAM1.setPixmap(
                    QPixmap.fromImage(self.image_to_QImage(image, self.CAM1)))

    def stop_view(self):
        self.startCAM1.setEnabled(True)
        self.stopCAM1.setEnabled(False)
        self.timer.stop()
        self.cap.release()
        self.outVivdeo.release()
        print("ok")
        image = cv2.imread('stopVideo.png')
        self.CAM1.setPixmap(
            QPixmap.fromImage(self.image_to_QImage(image, self.CAM1)))
        print('ok2')
        now = datetime.now()
        fileName = self.startTime1 + str(now.hour) + 'h' + str(
            now.minute) + '.avi'
        os.rename(self.savePath1 + 'output.avi', self.savePath1 + fileName)

    def viewCam2(self):
        ret, image = self.cap2.read()
        self.outVivdeo2.write(image)
        self.CAM2_Draw.setPixmap(
            QPixmap.fromImage(
                self.image_to_QImage(
                    self.drawArea(image, self.points_CAM2, self.CAM2_Draw),
                    self.CAM2_Draw)))
        self.CAM2.setPixmap(
            QPixmap.fromImage(self.image_to_QImage(image, self.CAM2)))

    def start_view2(self):
        if not self.timer2.isActive():
            self.stop_CAM2.setEnabled(True)
            self.start_CAM2.setEnabled(False)
            self.cap2 = cv2.VideoCapture(IP_CAM_ADDRESS['CAM2'])
            self.flag_CAM2 = self.cap2.isOpened()
            if self.cap2.isOpened():
                now = datetime.now()
                self.savePath2 = self.createDir('IP_CAM_2')
                self.startTime2 = str(now.day) + ' - ' + str(
                    now.hour) + 'h' + str(now.minute) + ' - '
                # fourcc = cv2.VideoWriter_fourcc(*'mp4v')
                fourcc = cv2.VideoWriter_fourcc(*'XVID')
                self.outVivdeo2 = cv2.VideoWriter(
                    self.savePath2 + 'output2.avi', fourcc, 30,
                    (int(self.cap2.get(3)), int(self.cap2.get(4))))
                self.timer2.start(0)
            else:
                self.start_CAM2.setEnabled(True)
                self.stop_CAM2.setEnabled(False)
                image = cv2.imread('no-connection.jpg')
                self.CAM2.setPixmap(
                    QPixmap.fromImage(self.image_to_QImage(image, self.CAM2)))

    def stop_view2(self):
        self.start_CAM2.setEnabled(True)
        self.stop_CAM2.setEnabled(False)
        self.timer2.stop()
        self.outVivdeo2.release()
        image = cv2.imread('stopVideo.png')
        self.CAM2.setPixmap(
            QPixmap.fromImage(self.image_to_QImage(image, self.CAM2)))
        self.cap2.release()
        now = datetime.now()
        fileName = self.startTime2 + str(now.hour) + 'h' + str(
            now.minute) + '.avi'
        os.rename(self.savePath2 + 'output2.avi', self.savePath2 + fileName)

    def viewCam3(self):
        ret, image = self.cap3.read()
        self.outVivdeo3.write(image)
        self.CAM3_Draw.setPixmap(
            QPixmap.fromImage(
                self.image_to_QImage(
                    self.drawArea(image, self.points_CAM3, self.CAM3_Draw),
                    self.CAM3_Draw)))
        self.CAM3.setPixmap(
            QPixmap.fromImage(self.image_to_QImage(image, self.CAM3)))

    def start_view3(self):
        if not self.timer3.isActive():
            self.stop_CAM3.setEnabled(True)
            self.start_CAM3.setEnabled(False)
            self.cap3 = cv2.VideoCapture(IP_CAM_ADDRESS['CAM3'])
            self.flag_CAM3 = self.cap3.isOpened()
            if self.cap3.isOpened():
                now = datetime.now()
                self.savePath3 = self.createDir('IP_CAM_3')
                self.startTime3 = str(now.day) + ' - ' + str(
                    now.hour) + 'h' + str(now.minute) + ' - '
                # fourcc = cv2.VideoWriter_fourcc(*'mp4v')
                fourcc = cv2.VideoWriter_fourcc(*'XVID')
                self.outVivdeo3 = cv2.VideoWriter(
                    self.savePath3 + 'output3.avi', fourcc, 30,
                    (int(self.cap3.get(3)), int(self.cap3.get(4))))
                self.timer3.start(0)
            else:
                self.start_CAM3.setEnabled(True)
                self.stop_CAM3.setEnabled(False)
                image = cv2.imread('no-connection.jpg')
                self.CAM3.setPixmap(
                    QPixmap.fromImage(self.image_to_QImage(image, self.CAM3)))

    def stop_view3(self):
        self.start_CAM3.setEnabled(True)
        self.stop_CAM3.setEnabled(False)
        self.timer3.stop()
        self.outVivdeo3.release()
        image = cv2.imread('stopVideo.png')
        self.CAM3.setPixmap(
            QPixmap.fromImage(self.image_to_QImage(image, self.CAM3)))
        self.cap3.release()
        now = datetime.now()
        fileName = self.startTime3 + str(now.hour) + 'h' + str(
            now.minute) + '.avi'
        os.rename(self.savePath3 + 'output3.avi', self.savePath3 + fileName)

    def createDir(self, IP_CAM_Number: str):
        now = datetime.now()
        year = now.year
        month = MONTH[now.month]

        curPath = os.getcwd()
        if not path.exists(curPath + '/IVA'):
            os.mkdir(curPath + '/IVA')
        if not path.exists(curPath + '/IVA/' + IP_CAM_Number):
            os.mkdir(curPath + '/IVA/' + IP_CAM_Number)

        # check path exists
        if path.exists(curPath + '/IVA/' + IP_CAM_Number + '/' + str(year)):
            if path.exists(curPath + '/IVA/' + IP_CAM_Number + '/' +
                           str(year) + '/' + month):
                return curPath + '/IVA/' + IP_CAM_Number + '/' + str(
                    year) + '/' + month + '/'
            else:
                os.mkdir(curPath + '/IVA/' + IP_CAM_Number + '/' + str(year) +
                         '/' + month)
                return curPath + '/IVA/' + IP_CAM_Number + '/' + str(
                    year) + '/' + month + '/'
        else:
            os.mkdir(curPath + '/IVA/' + IP_CAM_Number + '/' + str(year))
            if path.exists(curPath + '/IVA/' + IP_CAM_Number + '/' +
                           str(year) + '/' + month):
                return curPath + '/IVA/' + IP_CAM_Number + '/' + str(
                    year) + '/' + month + '/'
            else:
                os.mkdir(curPath + '/IVA/' + IP_CAM_Number + '/' + str(year) +
                         '/' + month)
                return curPath + '/IVA/' + IP_CAM_Number + '/' + str(
                    year) + '/' + month + '/'

    # Create Mouse Event for draw protected area
    def mouseEventCAM1(self, event):
        if self.remove_CAM1.isEnabled() and (
                not self.startCAM1.isEnabled()) and self.flag_CAM1 == True:
            x = event.pos().x()
            y = event.pos().y()
            self.points_CAM1.append([x, y])
            print("Position clicked is ({}, {})".format(x, y))

    def mouseEventCAM2(self, event):
        if self.remove_CAM2.isEnabled() and (
                not self.start_CAM2.isEnabled()) and self.flag_CAM2 == True:
            x = event.pos().x()
            y = event.pos().y()
            self.points_CAM2.append([x, y])
            print("Position clicked is ({}, {})".format(x, y))

    def mouseEventCAM3(self, event):
        if self.remove_CAM3.isEnabled() and (
                not self.start_CAM3.isEnabled()) and self.flag_CAM3 == True:
            x = event.pos().x()
            y = event.pos().y()
            self.points_CAM3.append([x, y])
            print("Position clicked is ({}, {})".format(x, y))

    def startDrawAreaCAM1(self):
        self.draw_CAM1.setEnabled(False)
        self.remove_CAM1.setEnabled(True)

    def removeAreaCAM1(self):
        while len(self.points_CAM1):
            self.points_CAM1.pop()
        self.draw_CAM1.setEnabled(True)
        self.remove_CAM1.setEnabled(False)

    def startDrawAreaCAM2(self):
        self.draw_CAM2.setEnabled(False)
        self.remove_CAM2.setEnabled(True)

    def removeAreaCAM2(self):
        while len(self.points_CAM2):
            self.points_CAM2.pop()
        self.draw_CAM2.setEnabled(True)
        self.remove_CAM2.setEnabled(False)

    def startDrawAreaCAM3(self):
        self.draw_CAM3.setEnabled(False)
        self.remove_CAM3.setEnabled(True)

    def removeAreaCAM3(self):
        while len(self.points_CAM3):
            self.points_CAM3.pop()
        self.draw_CAM3.setEnabled(True)
        self.remove_CAM3.setEnabled(False)

    def drawArea(self, image, points: list, qlabel: QtWidgets.QLabel):
        image_draw = image.copy()
        image_draw = cv2.resize(image_draw, (qlabel.width(), qlabel.height()))
        if len(points) > 1:
            cv2.polylines(image_draw, np.array([points]), 1, (255, 0, 0), 1)
            b, g, r = cv2.split(image_draw)
            cv2.fillPoly(b, np.array([points]), (0, 255, 0))
            cv2.fillPoly(r, np.array([points]), (0, 255, 0))
            image_draw = cv2.merge([b, g, r])
        return image_draw
Ejemplo n.º 34
0
class Player(QWidget):
    muted = muted
    auto_play = auto_play
    full_screen = full_screen
    model = Movies
    session = session

    def __init__(self):
        super().__init__()
        self.setGeometry(0, 0, 1560, 300)
        from core.view import BaseView
        self.base_view = BaseView([], self)
        p = self.palette()
        p.setColor(QPalette.Window, Qt.black)
        self.setPalette(p)

    def run_window(self):
        self.base_view.set_data(self.id)
        self.set_setings()
        self.data = self.base_view.data
        self.init_ui()
        self.show()
        self.setWindowTitle(self.data.name)

    def set_star(self, stars, id):
        Star = None
        for star_array in stars:
            if star_array.id == id:
                Star = star_array
        return Star

    def set_setings(self):

        self.save_setings()

        with open('player_setings.JSON') as setings:
            data = json.load(setings)
            self.muted = data['muted']
            self.auto_play = data['auto_play']
            self.full_screen = data['full_screen']

    def save_setings(self):

        array = {
            "muted": self.muted,
            "auto_play": self.auto_play,
            "full_screen": self.full_screen
        }

        json_array = json.dumps(array)

        if Path('player_setings.JSON').is_file() is False:
            f = open('player_setings.JSON', "x")
            f.write(json_array)
            f.close()

    def set_player(self):
        if self.muted:
            self.mute_clicked()
        if self.auto_play:
            self.play_video()
        if self.full_screen:
            self.full_screen_switch()

    def init_ui(self):
        self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.VideoSurface)
        self.mediaPlayer.setMedia(
            QMediaContent(QUrl.fromLocalFile(self.data.src)))

        videowidget = QVideoWidget()

        self.playBtn = QPushButton()
        self.playBtn.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay))
        self.playBtn.clicked.connect(self.play_video)

        self.slider = QSlider(Qt.Horizontal)
        self.slider.setRange(0, 0)
        self.slider.sliderMoved.connect(self.set_position)

        self.show_full_screen_button = QPushButton('Full Screen')
        self.show_full_screen_button.clicked.connect(self.full_screen_switch)

        self.movie_info_button = QPushButton('Movie')
        self.movie_info_button.clicked.connect(self.movie_info)

        if self.data.series:
            self.series_info_button = QPushButton('Series')
            self.series_info_button.clicked.connect(self.series_info)

        self.mute = QPushButton()
        self.mute.setIcon(self.style().standardIcon(QStyle.SP_MediaVolume))
        self.mute.clicked.connect(self.mute_clicked)

        self.label = QLabel()
        self.label.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Maximum)

        hboxLayout = QHBoxLayout()
        hboxLayout.setContentsMargins(20, 20, 20, 10)

        hboxLayout.addWidget(self.playBtn)
        hboxLayout.addWidget(self.slider)
        hboxLayout.addWidget(self.mute)
        hboxLayout.addWidget(self.movie_info_button)

        if self.data.series:
            hboxLayout.addWidget(self.series_info_button)
        hboxLayout.addWidget(self.show_full_screen_button)
        self.set_player()

        self.hboxLayout2 = QHBoxLayout()
        self.hboxLayout2.setContentsMargins(10, 10, 10, 10)

        self.buttons_stars = QButtonGroup()
        self.buttons_series = QButtonGroup()

        self.add_grup_movies_buttons()
        # create vbox layout
        vboxLayout = QVBoxLayout()
        vboxLayout.addWidget(videowidget)
        vboxLayout.addLayout(hboxLayout)
        vboxLayout.addLayout(self.hboxLayout2)
        vboxLayout.addWidget(self.label)

        self.setLayout(vboxLayout)

        self.mediaPlayer.setVideoOutput(videowidget)

        # media player signals

        self.mediaPlayer.stateChanged.connect(self.mediastate_changed)
        self.mediaPlayer.positionChanged.connect(self.position_changed)
        self.mediaPlayer.durationChanged.connect(self.duration_changed)

    def series_info(self):
        self.base_view.load_view('series', self.data.series[0])

    def movie_info(self):
        self.base_view.load_view('movies', self.data)

    def buttom_genarator(self, list, fuction, id):
        for button in list.buttons():
            if button is list.button(id):
                fuction(button.data)

    def on_movies_series_play(self, id):
        self.buttom_genarator(self.buttons_series, self.next_series, id)

    def on_movies_star_play(self, id):
        self.buttom_genarator(self.buttons_stars, self.next_star, id)

    def add_grup_movies_buttons(self):
        self.button_series = [
            {
                'button': self.on_movies_series_play,
                'obejct': self.buttons_series
            },
        ]

        index = 0
        for series in self.data.series:
            button = QPushButton('next video in series ' + str(series))
            self.hboxLayout2.addWidget(button)
            button.data = series
            self.button_series[0]['obejct'].addButton(button)
            self.button_series[0]['obejct'].buttonClicked[int].connect(
                self.button_series[0]['button'])
            index = index + 1

        self.buttons_star = [
            {
                'button': self.on_movies_star_play,
                'obejct': self.buttons_stars
            },
        ]

        index = 0
        for star in self.data.stars:
            if len(star.movies) > 3:
                button = QPushButton('next video with star ' + str(star))
                self.hboxLayout2.addWidget(button)
                button.data = star
                self.buttons_star[0]['obejct'].addButton(button)
                self.buttons_star[0]['obejct'].buttonClicked[int].connect(
                    self.buttons_star[0]['button'])
            index = index + 1

    def mute_clicked(self):
        if self.mediaPlayer.isMuted() is False:
            icon = QStyle.SP_MediaVolumeMuted
            self.mediaPlayer.setMuted(True)
            self.muted = True
        else:
            icon = QStyle.SP_MediaVolume
            self.mediaPlayer.setMuted(False)
            self.muted = False

        self.mute.setIcon(self.style().standardIcon(icon))

    def next_series(self, series):
        movies_in_series = self.data.series[0].movies
        self.close()
        self.base_view.load_view('play', self.faind_item(movies_in_series))

    def next_star(self, star):
        star = self.set_star(self.data.stars, star.id)
        movies_with_star = star.movies
        self.close()
        self.base_view.load_view('play', self.faind_item(movies_with_star))

    def faind_item(self, array):
        def faind_item_greater_then_actual_item(array, math_index):
            index_item = 0
            for item in array:
                if index_item > math_index:
                    return index_item
                elif math_index == len(array) - 1:
                    return 0
                index_item = index_item + 1

        math_index = ''
        index_in_array = 0
        for item in array:
            if self.data.id == item.id:
                math_index = index_in_array
            index_in_array = index_in_array + 1

        next_item = faind_item_greater_then_actual_item(array, math_index)
        return array[next_item]

    def full_screen_switch(self):
        if self.isFullScreen() is False:
            self.showFullScreen()
            self.full_screen = True
        else:
            self.showNormal()
            self.full_screen = False

    def mute_switch(self):
        self.changeMuting.emit(not self.muted)

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

    def mediastate_changed(self, state):
        if self.mediaPlayer.state() == QMediaPlayer.PlayingState:
            icon = QStyle.SP_MediaPause

        else:
            icon = QStyle.SP_MediaPlay

        self.playBtn.setIcon(self.style().standardIcon(icon))

    def position_changed(self, position):
        self.slider.setValue(position)

    def duration_changed(self, duration):
        self.slider.setRange(0, duration)

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

    def handle_errors(self):
        self.playBtn.setEnabled(False)
        self.label.setText("Error: " + self.mediaPlayer.errorString())

    def closeEvent(self, QCloseEvent):
        os.remove("player_setings.JSON")
        self.save_setings()
        self.mediaPlayer.stop()
Ejemplo n.º 35
0
class InputManager:
    __instance = None

    def __init__(self):
        if not InputManager.__instance:
            self.ui_manager = UIManager.get_instance()
            self.radio_stations_manager = RadioStationsManager()

            self.player = None
            self.playlist = None
            self.probe = None

            self.load_state()

            if not self.playlist:
                self.init_state()

            self.init_signals()

    def init_signals(self):
        self.player.durationChanged.connect(self.duration_changed_slot)
        self.player.positionChanged.connect(self.position_changed_slot)
        self.player.currentMediaChanged.connect(
            self.current_media_changed_slot)

        self.player.stateChanged.connect(self.state_changed_slot)

    def set_position(self, new_pos):
        self.ui_manager.set_position_slider_value(new_pos)
        self.player.setPosition(new_pos)

    def get_duration(self):
        return self.player.duration()

    def get_position(self):
        return self.player.position()

    def duration_changed_slot(self, duration):
        self.ui_manager.set_position_slider_max_value(duration)

    def position_changed_slot(self, position):
        self.ui_manager.set_position_slider_value(position)

    def get_volume(self):
        return self.player.volume()

    def set_volume(self, value):
        self.ui_manager.set_volume_slider_value(value)
        self.player.setVolume(value)

    def current_media_changed_slot(self):
        self.ui_manager.sync_row(self.get_media_position())

    def state_changed_slot(self, new_state):
        if new_state == QMediaPlayer.StoppedState or new_state == QMediaPlayer.PausedState:
            self.ui_manager.change_play_btn_state(False)
        else:
            self.ui_manager.change_play_btn_state(True)

    def next_media(self):
        self.playlist.next()

    def previous_media(self):
        self.playlist.previous()

    @classmethod
    def get_instance(cls, *args, **kwargs):
        if not cls.__instance:
            cls.__instance = InputManager(*args, **kwargs)
        return cls.__instance

    def init_state(self):
        self.player = QMediaPlayer()
        self.playlist = QMediaPlaylist()

        self.probe = QAudioProbe()
        self.probe.setSource(self.player)
        self.probe_connected = False

        self.timer = QTimer()
        self.timer.setInterval(100)
        self.timer.setSingleShot(True)

        self.recent_files_manager = RecentFilesManager()

        self.ui_manager.set_output(self.player)
        self.player.setPlaylist(self.playlist)

    def load_state(self):
        file = QFile("file.dat")
        file.open(QIODevice.ReadOnly)
        in_stream = QDataStream(file)

        cur_playlist = QVariant()

        in_stream >> cur_playlist

        self.playlist = cur_playlist.value()

    def get_radio_stations(self, limit=None, category=None):
        stations = self.radio_stations_manager.get_all_stations(
            limit, category)
        return stations

    def get_radio_categories(self):
        categories = self.radio_stations_manager.get_all_categories()
        return categories

    def save_state(self):
        file = QFile("file.dat")
        file.open(QIODevice.WriteOnly)
        out = QDataStream(file)

        out << QVariant(self.current_playlist)

    def add_folder(self, path: str):
        files = get_dir_files(path)
        for file in files:
            self.add_media(path + "/" + file, get_format(file))

    def add_file(self, filename: str):
        format = get_format(filename)
        if format != FILE_FORMAT.INVALID:
            return self.add_media(filename, format)
        raise RuntimeError("Invalid file format")

    def add_media(self, filename: str, format: FILE_FORMAT):
        url = QUrl.fromLocalFile(
            filename) if format != FILE_FORMAT.URL else QUrl(filename)
        content = QMediaContent(url)

        self.ui_manager.append_playlist(url.fileName(), format)

        self.recent_files_manager.write_recent_file(url.path())
        self.ui_manager.init_recent_files()

        self.playlist.addMedia(content)

    def set_media_position(self, pos):
        self.playlist.setCurrentIndex(pos)

    def get_media_position(self):
        return self.playlist.currentIndex()

    def get_current_format(self):
        position = self.get_media_position()
        if position == -1:
            return None
        item = self.ui_manager.get_list_item(self.get_media_position())
        return item.data(PlaylistItemDataRole.FORMAT)

    def play(self):
        format = self.get_current_format()
        if format is None:
            return
        self.ui_manager.change_play_btn_state(True)
        if format == FILE_FORMAT.AUDIO:
            self.probe.audioBufferProbed.connect(self.process_buffer)
            self.probe_connected = True
        else:
            self.probe_connected = False
            self.ui_manager.show_video()
        self.player.play()

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

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

    def is_muted(self):
        return self.player.isMuted()

    def is_paused(self):
        return self.player.state() in (QMediaPlayer.StoppedState,
                                       QMediaPlayer.PausedState)

    def mute(self, toggle):
        self.ui_manager.change_mute_state(toggle, self.get_volume())
        self.player.setMuted(toggle)

    def get_playback_rate(self):
        return self.player.playbackRate()

    def set_playback_rate(self, value):
        self.player.setPlaybackRate(value)

    def process_buffer(self, buffer):
        if not self.probe_connected:
            return
        if not self.timer.isActive():
            self.timer.start()
        else:
            if self.timer.remainingTime() == 0:
                data = buffer.data()
                chunked = chunk(list(data.asarray(buffer.byteCount())), 12)

                to_visualizer = [int(sum(e) // 12 // 75) for e in chunked]

                self.show_visualization(to_visualizer)

    def show_visualization(self, to_visualizer):
        self.ui_manager.update_equalizer(to_visualizer)

    def get_audio_devices(self):
        return QAudioDeviceInfo.availableDevices(QAudio.AudioOutput)

    def get_recent_files(self):
        return self.recent_files_manager.get_recent_files()

    def clear_recent_files(self):
        return self.recent_files_manager.clear_recent_files()

    def exit(self):
        self.ui_manager.exit()