Beispiel #1
0
class Player():
    def __init__(self):
        self.player = QMediaPlayer()
        self.state = PLAYER_STATE_STOP

    def setMedia(self, music):
        self.player.setMedia(music)

    def play(self):
        print(self.player.mediaStatus())
        if self.state == PLAYER_STATE_PAUSE:
            self.state = PLAYER_STATE_PLAY
            self.player.play()
        elif self.state == PLAYER_STATE_STOP:
            if self.player.mediaStatus() == LOADED_MEDIA:
                self.state = PLAYER_STATE_PLAY
                self.state.play()

    def pause(self):
        if self.state == PLAYER_STATE_PLAY:
            self.state = PLAYER_STATE_PAUSE

        self.player.pause()

    def stop(self):
        self.player.state = PLAYER_STATE_STOP
Beispiel #2
0
class QMediaPlayerAdapter(Player):
    def __init__(self, interval=1):
        self.__callback = None
        self.__player = QMediaPlayer()
        self.setNotifyInterval(interval)

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

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

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

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

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

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

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

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

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

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

        self.__callback = callback
        self.__player.mediaStatusChanged.connect(
            self.__callback.onMediaStatusChanged)
        self.__player.stateChanged.connect(self.__callback.onStateChanged)
        self.__player.positionChanged.connect(
            self.__callback.onPlayerPositionChanged)
Beispiel #3
0
class MainWindow(ui_mainwindow, qtbaseclass):
    # 详情页面
    detail = None
    # 播放列表dock栏,初始隐藏
    playListDockView = None
    # 当前播放列表
    playList = []
    # 当前播放的歌曲在列表中的索引号
    songIndex = 0
    # 当前播放的歌曲
    song = None
    # 播放器
    player = None
    # api
    func = netease
    # 是否循环播放
    loop = True

    # 记录上次音量值
    lastVolume = 0

    def __init__(self, parent=None):
        if parent == None:
            parent = self
        ui_mainwindow.__init__(parent)
        qtbaseclass.__init__(parent)
        self.setupUi(self)
        self.setWindowTitle("Music")
        self.setWindowFlags(QtCore.Qt.FramelessWindowHint)
        self.setWindowIcon(QIcon('resource/format.ico'))
        with open('QSS/mainWindow.qss', 'r') as f:
            style = f.read()
            self.setStyleSheet(style)

        # 初始化
        self.initList()
        self.initPlayWidgets()
        self.initTabWidgets()
        self.initDetailView()
        self.initPlayListDockView()

    def initList(self):
        # 初始化列表信息

        # 设置推荐列表
        self.recommandList.addItem(
            QListWidgetItem(QIcon('resource/music.png'), " 发现音乐"))
        self.recommandList.addItem(
            QListWidgetItem(QIcon('resource/signal.png'), " 私人FM"))
        self.recommandList.addItem(
            QListWidgetItem(QIcon('resource/movie.png'), " MV"))
        self.recommandList.setCurrentRow(0)

        # 设置我的音乐
        self.myList.addItem(
            QListWidgetItem(QIcon('resource/notes.png'), " 本地音乐"))

        # 设置收藏与创建的歌单
        # 未实现(动态添加)

    def initPlayWidgets(self):
        ''' 初始化播放控件状态'''
        self.player = QMediaPlayer(self)
        # self.player.setVolume(100)
        # 设置音量同时设置进度条
        self.volumeSlider.setValue(100)
        self.player.stateChanged.connect(self.slot_player_stateChanged)
        self.player.positionChanged.connect(self.slot_player_positionChanged)
        self.player.durationChanged.connect(self.slot_player_durationChanged)

        # 隐藏暂停按键
        self.pauseButton.hide()
        self.noVolume.hide()

    def initTabWidgets(self):
        # 初始化主窗口中TabWdidget
        self.detailView.hide()
        self.tabWidget.clear()
        netEase = SongsFrame(self)
        self.tabWidget.addTab(netEase, '网易云音乐')

    def initDetailView(self):
        # 初始化详情页
        self.detail = AlbumDetailView(self)
        self.detailView.setWidget(self.detail)
        self.detail.addSongs.connect(self.slot_addSongs)

    def initPlayListDockView(self):
        # 主显示区域添加播放列表DOCK
        self.playListDockView = PlayListDockWidget(self)
        self.playListDockView.hide()  # 初始状态为隐藏
        self.playListDockView.doubleClicked.connect(
            self.slot_playList_doubleClicked)
        self.mainHorizontalLayout.addWidget(self.playListDockView)

    def mouseMoveEvent(self, event):
        if event.buttons() == QtCore.Qt.MiddleButton:
            # if event.globalPos().x() > self.pos().x():
            #     print("Y")
            # else:
            #     print('N')
            self.move(event.globalPos())
            event.accept()
        else:
            super().mouseMoveEvent(event)

    def slot_prev_page_clicked(self):
        '''上一页'''
        if self.tabWidget.isHidden():
            self.tabWidget.show()
            self.detailView.hide()

    def slot_next_page_clicked(self):
        '''下一页'''
        # if self.detailView.isHidden():
        #     self.tabWidget.hide()
        #     self.detailView.show()
        pass

    def slot_prev_song_clicked(self):
        '''上一首歌'''
        self.player.stateChanged.disconnect()
        self.songIndex = self.songIndex - 1
        if self.songIndex < 0:
            self.songIndex = 0
        else:
            self.song = self.playList[self.songIndex]
            if self.set_player_media():
                self.player.play()
        self.playListDockView.setSelectRow(self.songIndex)
        self.player.stateChanged.connect(self.slot_player_stateChanged)

    def slot_next_song_clicked(self):
        '''下一首歌'''
        self.player.stateChanged.disconnect()
        self.songIndex = (self.songIndex + 1) % len(self.playList)
        self.song = self.playList[self.songIndex]
        if self.set_player_media():
            self.player.play()

        self.playListDockView.setSelectRow(self.songIndex)
        self.player.stateChanged.connect(self.slot_player_stateChanged)

    def slot_play_clicked(self):
        '''播放 点击事件'''
        if self.player.mediaStatus() > 1 and self.player.mediaStatus() < 7:
            self.player.play()
        else:
            # 未添加 音乐
            QMessageBox.warning(self, '警告', '播放列表为空!请先添加音乐到播放列表。')

    def slot_pause_clicked(self):
        '''暂停 点击事件'''
        self.player.pause()
        # self.playButton.show()
        # self.pauseButton.hide()

    def slot_addSongs(self, songsList):
        '''添加歌曲'''
        # 去重合并列表
        ids = [x.id for x in self.playList]
        for song in songsList:
            if song.id not in ids:
                self.playList.append(song)
                # 播放列表变化,更新列表显示
                self.playListDockView.setList(self.playList)
        # 初始化song
        if self.song == None:
            self.song = self.playList[self.songIndex]
            self.set_player_media()

    def slot_player_stateChanged(self):
        '''播放器状态变化'''
        if not self.playList:
            return

        if self.player.state() == QMediaPlayer.StoppedState:
            if self.loop:
                self.songIndex = (self.songIndex + 1) % len(self.playList)
                self.song = self.playList[self.songIndex]
                if self.set_player_media():
                    self.player.play()
            else:
                self.playButton.show()
                self.pauseButton.hide()
        elif self.player.state() == QMediaPlayer.PausedState:
            self.playButton.show()
            self.pauseButton.hide()
        elif self.player.state() == QMediaPlayer.PlayingState:
            self.playButton.hide()
            self.pauseButton.show()

        self.countTime.setText(self.song.time)

    def slot_player_positionChanged(self, pos):
        '''播放时间改变控件位置'''
        t = pos / 1000
        mins = t // 60
        secs = t % 60
        curTime = QtCore.QTime(0, mins, secs).toString('mm:ss')
        self.currentTime.setText(curTime)
        self.timeSlider.setValue(pos)

    def slot_player_durationChanged(self, duration):
        '''设置进度条最大值'''
        self.timeSlider.setRange(0, duration)

    def set_player_media(self):
        '''设置播放器音乐媒体,成功返回True,否则False'''
        try:
            mp3 = self.func.singsUrl([self.song.id])
            if mp3:
                mp3 = mp3[0]['url']
            self.player.setMedia(QMediaContent(QtCore.QUrl(mp3)))
            return True
        except:
            # 网络异常
            QMessageBox.warning(self, '获取音乐地址失败!请检查网络后重试!', '警告')
            return False

    def slot_playList_clicked(self):
        '''播放列表按钮 点击事件'''
        if self.playListDockView.isHidden():
            self.playListDockView.show()
        else:
            self.playListDockView.hide()

    def slot_playList_doubleClicked(self, songIndex):
        '''播放列表双击事件
        songIndex -- 为当前双击歌曲在列表中的索引号。
        执行动作:立即播放该歌曲
        '''
        self.songIndex = songIndex
        if self.set_player_media():
            self.player.play()

    def slot_volumeSlider_valueChanged(self, value):
        '''音量调节'''
        self.player.setVolume(value)
        if value == 0:
            self.noVolume.show()
            self.volume.hide()
        else:
            self.noVolume.hide()
            self.volume.show()

    def slot_noVolume_clicked(self):
        '''静音按钮点击事件,动作:切成原始音量'''
        # self.volumeSlider.setValue(0)
        self.player.setMuted(False)
        self.noVolume.hide()
        self.volume.show()

    def slot_volume_clicked(self):
        '''音量按钮点击事件,动作:切成静音'''
        # self.volumeSlider.setValue(0)
        self.player.setMuted(True)
        self.noVolume.show()
        self.volume.hide()
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
Beispiel #5
0
class QDeckAudioListWidget(QTableWidget):

    deckpath = None
    current_deck_rowid = None
    dbAdapter = None

    current_rowid = None

    config = ConfigFile(None, None)

    audioItemsDict = []
    audioPlayer = None
    audioRecorder = None

    STOPPED = 0
    RECORDING = 1
    PLAYING = 2
    status = 0
    row = None

    default_import_path = os.path.expanduser('~')

    def __init__(self):
        super().__init__()

    def setRowID(self, rowid):
        self.current_rowid = rowid

    def initAudioListWidget(self, dbAdapter, deckpath, current_rowid):
        self.audioItemsDict = []

        self.dbAdapter = dbAdapter
        self.deckpath = deckpath
        self.current_rowid = current_rowid

        self.audioPlayer = QMediaPlayer()
        self.audioPlayer.mediaStatusChanged.connect(self.mediaStatusChanged)

        os_name = platform.uname()[0]
        if os_name == "Windows" or os_name == "Darwin":
            self.audioRecorder = QAudioRecorder()
        else:
            from modules.deck.gstAudioRecorder import GstAudioRecorder
            self.audioRecorder = GstAudioRecorder()

        settings = QAudioEncoderSettings()

        audioformat = self.config.readVar('vocable', 'audioformat')
        if audioformat == 'ogg':
            settings.setCodec("audio/vorbis")
            self.audioRecorder.setContainerFormat("ogg")
        elif audioformat == 'mp3':
            settings.setCodec("audio/mpeg")
            self.audioRecorder.setContainerFormat("mp3")
        elif audioformat == 'amr':
            settings.setCodec("audio/amr")
        else:
            settings.setCodec("audio/PCM")
            self.audioRecorder.setContainerFormat("wav")

        self.audioRecorder.setEncodingSettings(settings)

        self.setColumnCount(6)
        self.setHorizontalHeaderLabels(
            ["description", "", "", "", "", "filename"])
        self.setRowCount(0)

        self.itemChanged.connect(self.onItemChanged)

    def getAudioFromDB(self, rowid):
        self.audioItemsDict = self.dbAdapter.audioFilenamesForDeckRowID(rowid)
        self.setRowCount(len(self.audioItemsDict))

        for i, row in enumerate(self.audioItemsDict):
            self.setItem(i, 0, QTableWidgetItem(row["description"]))

        self.updateAudioListWidget()

    def appendNewAudio(self):
        self.audioItemsDict.append({
            "rowid": None,
            "description": "",
            "filename": None
        })
        self.insertRow(self.rowCount())
        self.updateAudioListWidget()

    def updateAudioListWidget(self):
        for i, row in enumerate(range(self.rowCount())):

            button_delete = QPushButton()
            button_delete.setIcon(QIcon.fromTheme('edit-delete'))
            self.setCellWidget(row, DELETE_BUTTON_COLUMN, button_delete)
            button_delete.clicked.connect(
                partial(self.deleteAudioButtonClicked, row))

            button_open_file = QPushButton()
            button_open_file.setIcon(QIcon.fromTheme('document-open'))
            self.setCellWidget(row, OPEN_FILE_BUTTON_COLUMN, button_open_file)
            button_open_file.clicked.connect(
                partial(self.importAudioFileClicked, row))

            button_edit_file = QPushButton()
            #button_edit_file.setIcon(QIcon.fromTheme('audio-x-generic'))
            button_edit_file.setIcon(QIcon('./assets/icons/audacity.jpg'))
            self.setCellWidget(row, EDIT_FILE_BUTTON, button_edit_file)
            button_edit_file.clicked.connect(
                partial(self.editAudioFileClicked, row))

            self.setItem(
                row, FILE_NAME_COLUMN,
                QTableWidgetItem(str(self.audioItemsDict[row]["filename"])))

            if self.status == self.STOPPED:
                if self.audioItemsDict[i]["filename"]:
                    self.insertPlayButton(row)
                else:
                    self.insertRecordButton(row)

            elif self.status == self.PLAYING:
                if i == self.row:
                    self.insertStopPlayButton(row)
                else:
                    if not self.audioItemsDict[i]["filename"]:
                        self.insertRecordButton(row)
                    else:
                        self.insertPlayButton(row)

            elif self.status == self.RECORDING:
                if i == self.row:
                    self.insertStopRecordButton(row)
                else:
                    if self.audioItemsDict[i]["filename"]:
                        self.insertPlayButton(row)
                    else:
                        self.insertRecordButton(row)

            self.resizeColumnsToContents()

    def insertPlayButton(self, row):
        button_play = QPushButton()
        button_play.setIcon(QIcon.fromTheme('media-playback-start'))
        self.setCellWidget(row, PLAY_BUTTON_COLUMN, button_play)
        button_play.clicked.connect(partial(self.playButtonClicked, row))

    def insertStopPlayButton(self, row):
        button_stop = QPushButton()
        button_stop.setIcon(QIcon.fromTheme('media-playback-stop'))
        self.setCellWidget(row, PLAY_BUTTON_COLUMN, button_stop)
        button_stop.clicked.connect(partial(self.stopPlayButtonClicked, row))

    def insertRecordButton(self, row):
        button_record = QPushButton()
        button_record.setIcon(QIcon.fromTheme('media-record'))
        self.setCellWidget(row, RECORD_BUTTON_COLUMN, button_record)
        button_record.clicked.connect(partial(self.recordButtonClicked, row))

    def insertStopRecordButton(self, row):
        button_stop = QPushButton()
        button_stop.setIcon(QIcon.fromTheme('media-playback-stop'))
        self.setCellWidget(row, RECORD_BUTTON_COLUMN, button_stop)
        button_stop.clicked.connect(partial(self.stopRecordButtonClicked, row))

    def deleteAudioButtonClicked(self, row):
        reply = QMessageBox.question(self, 'Delete Audio', "really?",
                                     QMessageBox.Yes, QMessageBox.No)
        if reply == QMessageBox.Yes:
            self.removeRow(row)

            rowid = self.audioItemsDict[row]["rowid"]
            if rowid:
                self.dbAdapter.deleteAudioItem(rowid)

            filename = self.audioItemsDict[row]["filename"]
            if filename:
                self.dbAdapter.deleteAudioItemByFilename(filename)
                filepath = path.join(self.deckpath, filename)
                if path.exists(filepath):
                    remove(filepath)

            del self.audioItemsDict[row]
            self.updateAudioListWidget()

    def importAudioFileClicked(self, row):
        file_path = QFileDialog.getOpenFileName(self,
                                                'Please select an Audio File',
                                                self.default_import_path)
        self.default_import_path = file_path[0]
        filename = file_path[0].split(os.sep)[::-1][0]
        target_path = os.path.join(self.deckpath, filename)
        #if not os.path.exists(target_path):
        try:
            shutil.copyfile(file_path[0], target_path)
        except FileNotFoundError:
            """ there is simply no file to copy """
            pass
        else:
            self.audioItemsDict[row]["filename"] = filename
            self.status = self.STOPPED
            self.updateAudioListWidget()

            self.saveStateToDB(self.current_rowid)

    def editAudioFileClicked(self, row):
        filename = self.audioItemsDict[row]["filename"]
        target_path = os.path.join(self.deckpath, filename)

        self.process = QProcess()
        self.process.errorOccurred.connect(self.onAudioEditProcessError)
        self.process.stateChanged.connect(self.onAudioStateChangedError)

        os_name = platform.uname()[0]
        if os_name == "Linux":
            open_command = "audacity " + target_path

        elif os_name == "Windows":
            open_command = '"C:\\program files (x86)\\Audacity\\audacity.exe" "' + target_path + '"'

        print(open_command)
        self.process.startDetached(open_command)

    def onAudioEditProcessError(self, error):
        print(error)

    def onAudioStateChangedError(self, state):
        print(state)

    def recordButtonClicked(self, row):
        self.stopPlayButtonClicked(row)
        self.stopRecordButtonClicked(row)

        extension = '.wav'
        audioformat = self.config.readVar('vocable', 'audioformat')
        if audioformat == 'ogg':
            extension = '.ogg'
        elif audioformat == 'mp3':
            extension = '.mp3'
        elif audioformat == 'amr':
            extension = '.amr'
        filename = str(int(time.time())) + self.randomword(5) + extension
        filepath = os.path.join(self.deckpath, filename)
        print(filepath)

        url = QUrl.fromLocalFile(QFileInfo(filepath).absoluteFilePath())
        self.audioRecorder.setOutputLocation(url)
        self.audioRecorder.record()

        self.audioItemsDict[row]["filename"] = filename

        self.status = self.RECORDING
        self.row = row
        self.updateAudioListWidget()

        self.saveStateToDB(self.current_rowid)

    def stopRecordButtonClicked(self, row):
        self.stopPlayButtonClicked(row)
        self.audioRecorder.stop()

        self.status = self.STOPPED
        self.updateAudioListWidget()

    def playButtonClicked(self, row):
        self.stopRecordButtonClicked(row)

        filename = self.audioItemsDict[row]["filename"]
        filepath = path.join(self.deckpath, filename)
        url = QUrl.fromLocalFile(QFileInfo(filepath).absoluteFilePath())
        content = QMediaContent(url)
        self.audioPlayer.setMedia(content)
        self.audioPlayer.play()

        self.status = self.PLAYING
        self.row = row
        self.updateAudioListWidget()

    def stopPlayButtonClicked(self, row):
        self.audioPlayer.stop()

        self.status = self.STOPPED
        self.updateAudioListWidget()

    def stopAllAudio(self):
        row = 1
        self.stopPlayButtonClicked(row)
        self.stopRecordButtonClicked(row)
        self.status = self.STOPPED

    def mediaStatusChanged(self):
        status = self.audioPlayer.mediaStatus()

        if status == 7:
            self.stopAllAudio()

    def onItemChanged(self):

        for i in range(self.rowCount()):
            item = self.item(i, 0)
            if item:
                cell_text = self.item(i, 0).text()
                self.audioItemsDict[i]["description"] = cell_text

    def saveStateToDB(self, deck_rowid):
        self.dbAdapter.saveAudioDict(self.audioItemsDict, deck_rowid)

    def randomword(self, length):
        return ''.join(
            random.choice(string.ascii_lowercase) for i in range(length))
class Player(QMediaPlayer):
    def __init__(self, parent=None):
        super(Player, self).__init__(parent)
        self.parent = parent
        self.player = QMediaPlayer()
        self.queueList = QMediaPlaylist()
        self.player.setPlaylist(self.queueList)
        self.queueData = []
        self.position = 0
        self.volume = 100

        self.player.mediaStatusChanged.connect(self.qmp_mediaStatusChanged)
        self.player.positionChanged.connect(self.qmp_positionChanged)
        self.player.durationChanged.connect(self.durationChanged)
        self.queueList.currentIndexChanged.connect(self.playlistPosChanged)

    def add(self, data):
        """Add track to the queue"""
        queueData = {
            'pc_title': data['pc_title'],
            'title': data['title'],
            'url': data['url'],
            'date': data['date_format'],
            'description': data['description']
        }
        self.queueData.append(queueData)
        self.queueList.addMedia(QMediaContent(QUrl(data['url'])))

    def playPause(self):
        icon = QIcon.fromTheme("media-playback-pause")

        if self.player.state() == QMediaPlayer.StoppedState:
            if self.player.mediaStatus() == QMediaPlayer.NoMedia:
                if self.queueList.mediaCount() != 0:
                    self.player.play()
            elif self.player.mediaStatus() == QMediaPlayer.LoadedMedia:
                self.queueList.setCurrentIndex(self.position)
                self.player.play()
            elif self.player.mediaStatus() == QMediaPlayer.BufferedMedia:
                self.player.play()
        elif self.player.state() == QMediaPlayer.PlayingState:
            icon = QIcon.fromTheme("media-playback-start")
            self.player.pause()
        elif self.player.state() == QMediaPlayer.PausedState:
            self.player.play()

        self.parent.playBtn.setIcon(icon)

    def startPlay(self):
        data = self.queueData[0]
        self.queueList.setCurrentIndex(0)
        self.parent.curPCLabel.setText(data['pc_title'])
        self.parent.curTrackName.setText(data['title'])
        self.player.play()
        icon = QIcon.fromTheme("media-playback-pause")
        self.parent.playBtn.setIcon(icon)

    def stop(self):
        self.player.stop()
        icon = QIcon.fromTheme("media-playback-start")
        self.parent.playBtn.setIcon(icon)

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

    def durationChanged(self, duration):
        total_time = '0:00:00'
        duration = self.player.duration()
        total_time = ms_to_time(duration)
        self.parent.timeSlider.setMaximum(duration)
        self.currentTrackDuration = duration
        self.parent.totalTimeLabel.setText(total_time)

    def qmp_mediaStatusChanged(self, status):
        icon = QIcon.fromTheme("media-playback-pause")
        if self.player.state() == QMediaPlayer.StoppedState:
            icon = QIcon.fromTheme("media-playback-start")
        elif self.player.state() == QMediaPlayer.PausedState:
            icon = QIcon.fromTheme("media-playback-start")

        self.parent.playBtn.setIcon(icon)

    def qmp_positionChanged(self, position, senderType=False):
        self.currentTime = position
        current_time = '0:00:00'

        if position != -1:
            current_time = ms_to_time(position)
            self.parent.timeLabel.setText(current_time)

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

    def playlistPosChanged(self):
        pos = self.queueList.currentIndex()
        data = self.queueData[pos]
        self.parent.curPCLabel.setText(data['pc_title'])
        self.parent.curTrackName.setText(data['title'])
        windowTitle = '{0} - {1}'.format(data['pc_title'], data['title'])
        self.parent.setWindowTitle(windowTitle)
        if self.queueList.mediaCount() > 1:
            if pos < self.queueList.mediaCount() - 1:
                self.parent.queueNextBtn.setEnabled(True)
            else:
                self.parent.queueNextBtn.setEnabled(False)

            if pos > 0:
                self.parent.queuePrevBtn.setEnabled(True)
            else:
                self.parent.queuePrevBtn.setEnabled(False)

            if pos < self.queueList.mediaCount():
                prevPos = 0
                if self.position < pos:
                    prevPos = pos - 1
                else:
                    prevPos = pos + 1
                prevItem = self.parent.queueList.item(prevPos)
                prevWidget = self.parent.queueList.itemWidget(prevItem)
                if prevItem:
                    prevWidget.statusIcon.setPixmap(QPixmap())

        self.position = pos
        item = self.parent.queueList.item(pos)
        widget = self.parent.queueList.itemWidget(item)
        if widget:
            icon = QIcon.fromTheme("media-playback-start")
            widget.statusIcon.setPixmap(icon.pixmap(16, 16))

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

    def rev10Secs(self):
        position = self.player.position()
        new_pos = position - 10000
        self.player.setPosition(new_pos)

    def for10Secs(self):
        position = self.player.position()
        new_pos = position + 10000
        self.player.setPosition(new_pos)

    def delete(self, position):
        """ Delete the track and her data from position"""
        self.queueData.pop(position)
        self.queueList.removeMedia(position)
        if (position == self.position):
            self.playlistPosChanged()
Beispiel #7
0
class Window(QtWidgets.QMainWindow, Ui_MainWindow):
    def __init__(self, parent=None):
        super().__init__(parent)

        # load config
        self.data = yaml_loader()

        # load ui
        self.setupUi(self)

        # load icons
        self.setWindowTitle("Sputofy")
        self.setWindowIcon(QIcon(os.path.join(RES_PATH, "logo.svg")))

        loopIcon = QIcon()
        loopIcon.addPixmap(QPixmap(os.path.join(RES_PATH, "loopIconOFF.svg")))
        self.loopBtn.setIcon(loopIcon)
        prevIcon = QIcon()
        prevIcon.addPixmap(QPixmap(os.path.join(RES_PATH, "backwardIcon.svg")))
        self.prevBtn.setIcon(prevIcon)
        playIcon = QIcon()
        playIcon.addPixmap(QPixmap(os.path.join(RES_PATH, "playIcon.svg")))
        self.playBtn.setIcon(playIcon)
        nextIcon = QIcon()
        nextIcon.addPixmap(QPixmap(os.path.join(RES_PATH, "forwardIcon.svg")))
        self.nextBtn.setIcon(nextIcon)
        randomIcon = QIcon()
        randomIcon.addPixmap(
            QPixmap(os.path.join(RES_PATH, "randomIconOFF.svg")))
        self.randomBtn.setIcon(randomIcon)
        volumeIcon = QIcon()
        volumeIcon.addPixmap(QPixmap(os.path.join(RES_PATH, "volumeIcon.svg")))
        self.volumeBtn.setIcon(volumeIcon)

        # window's settings
        self.xCor = self.data['last_position']['xPos']
        self.yCor = self.data['last_position']['yPos']
        self.widthSize = self.data['last_window_size']['width']
        self.heightSize = self.data['last_window_size']['height']

        self.setGeometry(self.xCor, self.yCor, self.widthSize, self.heightSize)

        # load YouTubeToMP3
        self.YouTubeToMP3 = YouTubeToMP3Window()

        # open YouTubeToMP3 using button
        self.actionYT_MP3.triggered.connect(self.YouTubeToMP3.show_window)

        # info action
        self.actionInfo.triggered.connect(self.info_handle)

        #===========================  mediaplayer  ==============================

        # create media player object
        self.mediaPlayer = QMediaPlayer(None)

        # open button
        self.actionOpen_Song.triggered.connect(self.open_song)
        self.actionOpen_Folder.triggered.connect(self.open_folder)

        # play button
        self.playBtn.setEnabled(False)
        self.playBtn.clicked.connect(
            self.play_video
        )  # when btn is pressed: if it is playing it pause, if it is paused it plays
        # QShortcut(QKeySequence("Space"), self).activated.connect(self.play_video)metodo da ricordare in caso di problemi #TODO

        # duration slider
        self.durationSlider.setEnabled(False)
        self.durationSliderMaxValue = 0
        self.durationSlider.valueChanged.connect(
            self.mediaPlayer.setPosition
        )  # set mediaPlayer position using the value took from the slider
        QShortcut('Right', self, lambda: self.durationSlider.setValue(
            self.durationSlider.value() + 10000))  # 1s = 1000ms
        QShortcut('Left', self, lambda: self.durationSlider.setValue(
            self.durationSlider.value() - 10000))  # 1s = 1000ms
        QShortcut('Shift+Right', self, lambda: self.durationSlider.setValue(
            self.durationSliderMaxValue - 1000))  # jump to the end-1s of song
        QShortcut('Shift+Left', self,
                  lambda: self.durationSlider.setValue(0))  # restart song

        # volumeSlider
        self.volumeSlider.setProperty("value", 100)
        self.volumeSlider.setRange(0, 100)
        self.volumeSlider.setValue(
            self.data['volume']
            if self.data['volume'] != 0 else self.data['volume'] + 1
        )  # set slider value | if saved volume is equal to 0 load with volume = 1 else load the saved volume
        self.mediaPlayer.setVolume(
            self.data['volume']
            if self.data['volume'] != 0 else self.data['volume'] + 1
        )  # set mediaPlayer volume | if saved volume is equal to 0 load with volume = 1 else load the saved volume
        self.volumeLabel.setText(
            f"{self.data['volume']}%"
            if self.data['volume'] != 0 else f"{self.data['volume']+1}%"
        )  # set volume label text | if saved volume is equal to 0 load with volume = 1 else load the saved volume
        self.volumeSlider.valueChanged.connect(
            self.mediaPlayer.setVolume
        )  # set mediaPlayer volume using the value took from the slider

        QShortcut('Up', self, lambda: self.volumeSlider.setValue(
            self.volumeSlider.value() + 1))  # volume + 1
        QShortcut('Down', self, lambda: self.volumeSlider.setValue(
            self.volumeSlider.value() - 1))  # volume - 1

        QShortcut(
            'Shift+Up', self,
            lambda: self.volumeSlider.setValue(100))  # set maximum volume
        QShortcut(
            'Shift+Down', self,
            lambda: self.volumeSlider.setValue(0))  # set minimun volume(mute)

        # volumeBtn
        self.volumeBtn.clicked.connect(
            self.volume_toggle)  # mute/unmute volume pressing btn
        self.isMuted = False  # starting with a non-muted volume
        self.previousVolume = self.data[
            'volume']  # loading last registered volume

        # media player signals
        self.mediaPlayer.durationChanged.connect(
            self.duration_changed)  # set range of duration slider
        self.mediaPlayer.positionChanged.connect(
            self.position_changed)  # duration slider progress
        self.mediaPlayer.stateChanged.connect(
            self.player_state)  # see when it's playing or in pause
        self.mediaPlayer.volumeChanged.connect(
            self.volume_icon)  # change volumebtn icon

        #===========================  playlist  ==============================

        # create the playlist
        self.playlist = QMediaPlaylist()
        self.playlist.setPlaybackMode(2)
        self.mediaPlayer.setPlaylist(self.playlist)

        # clear the playlist
        self.playlistIsEmpty = True

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

        #===========================  playlist function  ==============================

        self.mediaList = []  # array of loaded songs
        self.currentPlaylist = ""  # current loaded playlist name
        self.isCustomPlaylist = False

        # add song name on title
        self.playlist.currentMediaChanged.connect(self.set_title)

        # playlist buttons
        self.nextBtn.clicked.connect(self.next_song)  # seek track forward

        self.prevBtn.clicked.connect(self.prev_song)  # seek track backward

        self.mediaPlayer.mediaStatusChanged.connect(
            self.auto_next_track
        )  # once song is ended seek track forward and play it

        self.actionLoopIt.triggered.connect(
            self.loop_song)  # (1) loop the same song

        self.actionShuffle.triggered.connect(
            self.shuffle_playlist)  # change song's order

        self.loopBtn.clicked.connect(self.loop)  # (3) loop the playlist

        self.randomBtn.clicked.connect(
            self.random)  # (4) play random song without end

        # create new playlist
        self.actionCreatePlaylist.triggered.connect(self.custom_playlist)

        # delete current playlist
        self.actionDeletePlaylist.triggered.connect(self.delete_playlist)

        # remove all songs
        self.actionClearQueue.triggered.connect(self.clear_queue)

        # load playlist
        self.actionDict = {}  # dictionary of action Objects

        for action in self.data['playlistList']:
            self.actionDict[action] = self.menuPlaylist.addAction(
                action, partial(self.load_playlist, action))

        if len(self.data['playlistList']) == 0:
            self.menuPlaylist.menuAction().setVisible(False)

#================== Songs opening ==================#

    def open_folder(self):
        foldername = QFileDialog.getExistingDirectory(self, "Open folder",
                                                      "c:\\")

        if foldername:
            self.playlist.clear()
            self.mediaList.clear()

            for song in os.listdir(foldername):
                media = f"{foldername}/{song}"
                self.playlist.addMedia(QMediaContent(QUrl(media)))
                self.mediaList.append(media)

            self.playlist.setCurrentIndex(0)

            self.playBtn.setEnabled(True)
            self.durationSlider.setEnabled(True)

            self.playlistIsEmpty = False
            self.isCustomPlaylist = False

            self.model.layoutChanged.emit()  # load songs in list view
            self.set_title()

            self.mediaPlayer.pause()  # adjust play/pause icon

    def open_song(self):
        filename, _ = QFileDialog.getOpenFileName(self, "Open Song", "c:\\")

        if filename:
            if self.playlistIsEmpty == False:
                self.playlist.clear()
                self.mediaList.clear()
                self.playlistIsEmpty = True

            self.playlist.addMedia(QMediaContent(QUrl.fromLocalFile(filename)))
            self.mediaList.append(filename)

            self.playBtn.setEnabled(True)
            self.durationSlider.setEnabled(True)

            self.isCustomPlaylist = False

            self.model.layoutChanged.emit()  # load song in list view
            self.set_title()

            # adjust play/pause icon
            if self.playlist.mediaCount(
            ) == 1:  # if there is 1 song and you add another
                self.playlist.setCurrentIndex(0)
                self.mediaPlayer.pause()

    def load_playlist(self, playlistName):
        self.playlist.clear()
        self.mediaList.clear()

        # reload config
        self.data = yaml_loader()

        for song in self.data['playlistList'][playlistName]:
            self.playlist.addMedia(QMediaContent(QUrl.fromLocalFile(song)))
            self.mediaList.append(song)

        self.playlist.setCurrentIndex(0)

        self.playBtn.setEnabled(True)
        self.durationSlider.setEnabled(True)

        self.playlistIsEmpty = False
        self.isCustomPlaylist = True

        self.model.layoutChanged.emit()  # load songs in list view

        self.currentPlaylist = playlistName  # name of current loaded playlist
        self.set_title()

        self.statusbar.showMessage(f'Playlist "{playlistName}" loaded', 4000)
        self.menuPlaylist.menuAction().setVisible(True)

        # adjust play/pause icon
        self.mediaPlayer.pause()

    def set_title(self):
        if self.playlist.mediaCount() == 0:
            self.setWindowTitle("Sputofy")

        else:
            if self.isCustomPlaylist == False:
                self.setWindowTitle(
                    f"Sputofy - {os.path.splitext(self.playlist.currentMedia().canonicalUrl().fileName())[0]} - {self.playlist.currentIndex()+1}/{self.playlist.mediaCount()}"
                )
            else:
                self.setWindowTitle(
                    f"Sputofy - {self.currentPlaylist} - {os.path.splitext(self.playlist.currentMedia().canonicalUrl().fileName())[0]} - {self.playlist.currentIndex()+1}/{self.playlist.mediaCount()}"
                )

#=======================================================#

#================== Player Functions ==================#

    def play_video(self):
        if self.durationSlider.isEnabled():  # if slider was enabled
            if self.mediaPlayer.state() == QMediaPlayer.PlayingState:
                self.mediaPlayer.pause()
            else:
                self.mediaPlayer.play()

    def duration_changed(self, duration):
        self.durationSlider.setRange(0, duration)

        if duration > 0:
            self.totalTime_Label.setText(time_format(round(
                duration / 1000)))  # duration is in ms
        self.durationSliderMaxValue = duration

    def position_changed(self, position):
        if position >= 0:
            self.elapsedTime_Label.setText(time_format(
                (position / 1000)))  # position is in ms

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

#=======================================================#

#================== Playlist Settings ==================#
#TODO Work in progress

    def playlist_array(self):
        index = self.playlist.mediaCount()
        mediaList = []
        for i in range(index):
            # songPath = (self.playlist.media(path).canonicalUrl().path())#.split("/",1)[1]
            # mediaList.append(songPath)
            # print(self.playlist.media(i).canonicalUrl().path())
            mediaList.append(self.playlist.media(i).canonicalUrl().fileName())
        return mediaList

    def custom_playlist(self):
        if not self.playlist.mediaCount() == 0:
            name, is_notEmpty = QInputDialog.getText(self, "playlist",
                                                     "save playlist as:")

            if name:

                if name in self.data['playlistList']:
                    self.statusbar.showMessage(
                        "playlist not created (name is already used)", 4000)
                else:
                    self.data['playlistList'][name] = self.mediaList
                    yaml_dump(self.data)

                    # add new action Object to dictionary
                    self.actionDict[name] = self.menuPlaylist.addAction(
                        name, partial(self.load_playlist, name))

                    self.load_playlist(
                        name)  # instantly loading the new playlist
            else:
                self.statusbar.showMessage(
                    "playlist not created (you should give a name to your baby :/)",
                    4000)
        else:
            self.statusbar.showMessage("there are no songs to playlist", 4000)

    def delete_playlist(self):
        if self.isCustomPlaylist:

            if len(self.data['playlistList']) == 1:
                self.menuPlaylist.menuAction().setVisible(False)

            self.data['playlistList'].pop(
                self.currentPlaylist)  # remove playlist from dictionary

            self.menuPlaylist.removeAction(self.actionDict[
                self.currentPlaylist])  # remove relative action
            self.actionDict.pop(
                self.currentPlaylist)  # remove relative action Object

            self.playlist.clear()
            self.model.layoutChanged.emit()
            self.setWindowTitle("Sputofy")

            yaml_dump(self.data)

            self.statusbar.showMessage(
                'succesfully deleted "' + self.currentPlaylist + '" playlist',
                4000)
        else:
            self.statusbar.showMessage("cannot delete a non custom playlist",
                                       4000)

    def clear_queue(self):
        self.playlist.clear()
        self.mediaList.clear()
        self.playBtn.setEnabled(False)
        self.model.layoutChanged.emit()

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

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

#=======================================================#

#================== Playback Settings ==================#

    def next_song(self):
        if self.playlist.currentIndex() == self.playlist.mediaCount() - 1:
            self.playlist.setCurrentIndex(0)
        else:
            self.playlist.next()

    def prev_song(self):
        if self.playlist.currentIndex() == 0:
            self.playlist.setCurrentIndex(self.playlist.mediaCount() - 1)
        else:
            self.playlist.previous()

    def loop_song(self):
        if self.playlist.playbackMode() != 1:

            self.playlist.setPlaybackMode(1)

            self.actionLoopIt.setText("Loop it: ON")
            self.loopBtn.setIcon(
                QIcon(os.path.join(RES_PATH, "loopIconOFF.svg")))
            self.randomBtn.setIcon(
                QIcon(os.path.join(RES_PATH, "randomIconOFF.svg")))
        else:
            self.playlist.setPlaybackMode(2)
            self.actionLoopIt.setText("Loop it: OFF")

    def shuffle_playlist(self):
        if self.playlist.mediaCount():
            self.playlist.shuffle()
            self.model.layoutChanged.emit()
        else:
            self.statusbar.showMessage("there are no songs to shuffle", 4000)

    def loop(self):
        if self.playlist.playbackMode() != 3:
            self.playlist.setPlaybackMode(3)

            self.loopBtn.setIcon(
                QIcon(os.path.join(RES_PATH, "loopIconON.svg")))
            self.randomBtn.setIcon(
                QIcon(os.path.join(RES_PATH, "randomIconOFF.svg")))
            self.actionLoopIt.setText("Loop it: OFF")

        else:
            self.playlist.setPlaybackMode(2)
            self.loopBtn.setIcon(
                QIcon(os.path.join(RES_PATH, "loopIconOFF.svg")))

    def random(self):
        if self.playlist.playbackMode() != 4:
            self.playlist.setPlaybackMode(4)

            self.randomBtn.setIcon(
                QIcon(os.path.join(RES_PATH, "randomIconON.svg")))
            self.loopBtn.setIcon(
                QIcon(os.path.join(RES_PATH, "loopIconOFF.svg")))
            self.actionLoopIt.setText("Loop it: OFF")

        else:
            self.playlist.setPlaybackMode(2)
            self.randomBtn.setIcon(
                QIcon(os.path.join(RES_PATH, "randomIconOFF.svg")))

    def auto_next_track(self):

        if self.mediaPlayer.mediaStatus() == QMediaPlayer.EndOfMedia:
            if self.playlist.playbackMode() == 2:
                # index starts from 0       mediacount starts from 1
                if self.playlist.currentIndex(
                ) != self.playlist.mediaCount() - 1:
                    self.playlist.next()
                    self.mediaPlayer.play()
                else:  # if ended song was the last one set the index to the first one and pause
                    self.playlist.setCurrentIndex(0)
                    self.mediaPlayer.pause()

            # loop playlist
            elif self.playlist.playbackMode() == 3:
                self.playlist.next()
                self.mediaPlayer.play()

            # random song
            elif self.playlist.playbackMode() == 4:
                while self.playlist.previousIndex(
                ) == self.playlist.currentIndex(
                ):  # preventing repeating the same song
                    self.playlist.setCurrentIndex(
                        random.randint(0,
                                       self.playlist.mediaCount() - 1))

#=======================================================#

#================== Volume Settings ==================#

    def volume_icon(self, volume):

        self.volumeLabel.setText(f"{volume}%")

        if volume:
            volumeIcon = QIcon()
            volumeIcon.addPixmap(
                QPixmap(os.path.join(RES_PATH, "volumeIcon.svg")),
                QIcon.Normal, QIcon.Off)
            self.volumeBtn.setIcon(volumeIcon)
            self.previousVolume = self.volumeSlider.value()
            self.isMuted = False
        else:
            volumeMutedIcon = QIcon()
            volumeMutedIcon.addPixmap(
                QPixmap(os.path.join(RES_PATH, "volumeMutedIcon.svg")),
                QIcon.Normal, QIcon.Off)
            self.volumeBtn.setIcon(volumeMutedIcon)
            self.isMuted = True

    def volume_toggle(self):
        if self.isMuted == False:
            self.volumeSlider.setValue(0)
            self.isMuted = True

        elif self.isMuted == True:
            if self.previousVolume == 0:
                self.volumeSlider.setValue(10)
            else:
                self.volumeSlider.setValue(self.previousVolume)
            self.isMuted = False


#=======================================================#

    def mousePressEvent(self, event):
        ''' remove the border around the buttons created by using tab key '''

        focused_widget = QtWidgets.QApplication.focusWidget()
        try:
            focused_widget.clearFocus()
        except:
            pass
        QMainWindow.mousePressEvent(self, event)

    def player_state(self, event):
        ''' event handler that adjust the play/pause icon '''

        if event == QMediaPlayer.PlayingState:
            pauseIcon = QIcon()
            pauseIcon.addPixmap(
                QPixmap(os.path.join(RES_PATH, "pauseIcon.svg")), QIcon.Normal,
                QIcon.Off)
            self.playBtn.setIcon(pauseIcon)
        elif event == QMediaPlayer.PausedState:
            playIcon = QIcon()
            playIcon.addPixmap(QPixmap(os.path.join(RES_PATH, "playIcon.svg")),
                               QIcon.Normal, QIcon.Off)
            self.playBtn.setIcon(playIcon)

    def closeEvent(self, event):
        ''' event handler that take window information and save it in config before the window close '''

        # retrieve position
        xAxis = self.geometry().x()
        yAxis = self.geometry().y()

        self.data['last_position']['xPos'] = xAxis
        self.data['last_position']['yPos'] = yAxis

        # retrieve size
        width = self.width()
        height = self.height()

        self.data['last_window_size']['width'] = width
        self.data['last_window_size']['height'] = height

        # retrieve volume
        self.data['volume'] = self.mediaPlayer.volume()

        # retrieve user
        user = os.getlogin()
        self.data[
            'default_folder'] = f"C:\\Users\\{user}\\Desktop\\sputofy_songs"

        yaml_dump(self.data)

    def info_handle(self):

        info = "Sputofy\n1.0.0\n©2020 "+\
        "Sputofy is a free audio player based on the converted youtube songs made by a_str0\n\n"+\
        "Sputofy is written using python 3.x and PyQt5 modules"

        msg = QMessageBox.about(self, "About", info)
Beispiel #8
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 
Beispiel #9
0
class PlayManager(QWidget):

    NO_PLAYING_SONG = "没有正在播放的歌曲"

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

        self.player = QMediaPlayer(self)
        self.player.setAudioRole(QAudio.MusicRole)

        self.player.durationChanged.connect(self.duration_changed)
        self.player.positionChanged.connect(self.position_changed)
        self.player.mediaStatusChanged.connect(self.status_changed)
        self.player.bufferStatusChanged.connect(self.buffering_progress)
        self.player.stateChanged.connect(self.state_changed)
        self.player.error[QMediaPlayer.Error].connect(
            self.display_error_message)

        self.play_control = PlayControl(layout, parent)
        self.play_control.set_state(self.player.state())
        self.play_control.play.connect(self.player.play)
        self.play_control.pause.connect(self.player.pause)
        self.play_control.stop.connect(self.player.stop)

        self.player.stateChanged.connect(self.play_control.set_state)

        self.song_label = QLabel()
        self.song_label.setText(self.NO_PLAYING_SONG)
        self.song_label.setWordWrap(True)

        song_grid = QGridLayout(parent)
        song_grid.addWidget(self.song_label, 0, 0)

        self.duration_label = QLabel()
        self.duration_label.setText("00:00 / 00:00")
        self.slider = QSlider(Qt.Horizontal, parent)
        self.slider.setRange(0, self.player.duration() / 1000)
        self.slider.sliderMoved.connect(self.seek)
        progress_layout = QHBoxLayout(parent)
        progress_layout.insertWidget(0, self.duration_label)
        progress_layout.insertWidget(0, self.slider)
        song_grid.addLayout(progress_layout, 1, 0)

        self.status_label = QLabel()
        song_grid.addWidget(self.status_label, 2, 0)

        layout.addLayout(song_grid)

        if not self.is_player_available():
            QMessageBox.warning(self, "警告", "QMediaPlayer 对象无可用的服务")
            return

        self.song = None

    def is_player_available(self):
        return self.player.isAvailable()

    def add_to_play(self, spider, song):
        self.song = song
        spider.get_song_url(song)
        url = song.url
        if url is None or len(url) == 0:
            return
        req = QNetworkRequest(QUrl(url))
        req.setHeader(QNetworkRequest.UserAgentHeader,
                      HttpRequestConfig.CHROME_USER_AGENT)
        self.player.setMedia(QMediaContent(req))

    def duration_changed(self, duration):
        self.duration = int(duration / 1000)
        self.slider.setMaximum(self.duration)
        t = "00:00 / %s" % (self.song.get_time())
        self.duration_label.setText(t)

    def position_changed(self, progress):
        if not self.slider.isSliderDown():
            self.slider.setValue(int(progress / 1000))

        self.update_duration_info(int(progress / 1000))

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

    def state_changed(self, state):
        if QMediaPlayer.PlayingState == state \
                or QMediaPlayer.PausedState == state:
            self.song_label.setText("%s - %s" %
                                    (self.song.get_singers(), self.song.name))
        else:
            self.song_label.setText(self.NO_PLAYING_SONG)

    def status_changed(self, status):
        if QMediaPlayer.UnknownMediaStatus == status \
                or QMediaPlayer.NoMedia == status \
                or QMediaPlayer.LoadedMedia == status \
                or QMediaPlayer.BufferedMedia == status:
            self.set_status_info("")
        elif QMediaPlayer.LoadingMedia == status:
            self.set_status_info("加载中...")
        elif QMediaPlayer.BufferingMedia == status:
            self.set_status_info("缓存中...")
        elif QMediaPlayer.StalledMedia == status:
            self.set_status_info("等待中...")
        elif QMediaPlayer.EndOfMedia == status:
            QApplication.alert(self)
        elif QMediaPlayer.InvalidMedia == status:
            self.display_error_message()

    @pyqtSlot(int)
    def buffering_progress(self, progress):
        if self.player.mediaStatus() == QMediaPlayer.StalledMedia:
            self.set_status_info("等待中 %d%%" % (progress, ))
        else:
            self.set_status_info("缓存中 %d%%" % (progress, ))

    def set_status_info(self, info):
        self.status_label.setText(info)

    def display_error_message(self):
        self.set_status_info(self.player.errorString())

    def update_duration_info(self, current_info):
        s = time.strftime("%M:%S", time.gmtime(current_info))
        t = "%s / %s" % (s, self.song.get_time())
        self.duration_label.setText(t)
Beispiel #10
0
class VideoSortApp(QMainWindow, Ui_MainWindow, QWidget):

    def __init__(self):
        super(VideoSortApp, self).__init__()
        self.setupUi(self)
        self.filename = None
        self.directory = None
        self.sort.setEnabled(False)
        self.fileOpen.clicked.connect(self.fileDialog)
        self.dirOpen.clicked.connect(self.folderDialog)
        self.sort.clicked.connect(self.sortVideo)
        self.results.setViewMode(self.results.IconMode)
        self.results.setResizeMode(self.results.Adjust)
        self.features = []
        self.sorted = None

        #player properties
        self.player = QMediaPlayer(None, QMediaPlayer.VideoSurface)
        self.playlist = QMediaPlaylist(self.player)
        self.videoItem = QGraphicsVideoItem()
        self.videoItem.setSize(QtCore.QSizeF(640, 480))
        scene = QGraphicsScene(self)
        scene.addItem(self.videoItem)
        self.graphicsView.setScene(scene)
        self.player.setVideoOutput(self.videoItem)
        self.graphicsView.resize(640,480)
        self.graphicsView.show()
        self.results.itemDoubleClicked.connect(self.seekVideo)
        self.videoLoaded = False

    def sizeHint(self):
        return QtCore.QSize(640,480)

    def fileDialog(self):
        dialog = QFileDialog()
        if dialog.getOpenFileName:
            self.filename = dialog.getOpenFileName()[0]
            self.sort.setEnabled(True)

    def folderDialog(self):
        dialog = QFileDialog()
        if dialog.getExistingDirectory:
            self.directory = dialog.getExistingDirectory()
            self.sort.setEnabled(True)

    def sortVideo(self):

        dialog = QFileDialog()
        folder = dialog.getExistingDirectory(self, 'Select output directory for thumbnail images')
        if folder:
            if self.filename:
                self.getThread = VideoSort(self.filename, folder, 'frame')
                #self.results.setIconSize(QtCore.QSize(self.getThread.thumbInfo['resolution'][0], self.getThread.thumbInfo['resolution'][1]))
                #slot
                self.getThread.resultsSignal.connect(self.setFeatures)
                self.getThread.start()
                self.player.setMedia(QMediaContent(QtCore.QUrl.fromLocalFile(self.filename)))
                self.currentMedia = self.filename

            if self.directory:
                formatList = ['.mp4', '.mov', '.mkv', '.avi']
                for dirname, dirnames, filenames in os.walk(self.directory):
                    supportedFiles = [os.path.abspath(os.path.join(dirname, path)) for path in filenames if os.path.splitext(path)[1] in formatList]

                for filename in supportedFiles:
                    self.getThread = VideoSort(filename, folder, os.path.splitext(filename.split('/')[-1])[0])
                    self.getThread.resultsSignal.connect(self.setFeatures)
                    self.getThread.start()
                    self.player.setMedia(QMediaContent(QtCore.QUrl.fromLocalFile(filename)))
                #Just set the last file as the current file
                self.player.setMedia(QMediaContent(QtCore.QUrl.fromLocalFile(filename)))
                self.currentMedia = filename

    def setFeatures(self, features):
        for feature in features:
            self.features.append(feature)
        self.hue.toggled.connect(self.displayResults)
        self.saturation.toggled.connect(self.displayResults)
        self.contours.toggled.connect(self.displayResults)

    def displayResults(self):
        self.results.clear()
        if self.hue.isChecked():
            sortedFeatures = sorted(self.features, key=lambda res: res['hue']['std'], reverse=False)
            self.sorted = True
        if self.saturation.isChecked():
            sortedFeatures = sorted(self.features, key=lambda res: res['sat']['std'], reverse=False)
            self.sorted = True
        if self.contours.isChecked():
            sortedFeatures = sorted(self.features, key=lambda res: res['contours']['area'], reverse=False)
            self.sorted = True

        if self.sorted:
            for feature in sortedFeatures:
                icon = QtGui.QIcon(feature['thumbnail'])
                item = VideoListItem(icon, feature)
                self.results.addItem(item)

    def seekVideo(self, Qitem):
        #Need to write a callback function to only seek once player is loaded - provide loading media graphic or progress bar
        self.player.stop()
        print self.player.mediaStatus()
        if Qitem.feature['video'] != self.currentMedia:
            self.player.setMedia(QMediaContent(QtCore.QUrl.fromLocalFile(Qitem.feature['video'])))
            self.videoLoadProgress(self.player)
            self.currentMedia = Qitem.feature['video']

        else:
            self.videoLoaded = True

        if self.videoLoaded:
            self.player.setPosition(Qitem.feature['milliseconds'])
            self.player.play()

        else:

            #set up progress bar here, or loading text

    def videoLoadProgress(self, QMediaPlayerObject):
        self.videoStatus = VideoLoadStatus(QMediaPlayerObject)
        self.videoStatus.videoLoaded.connect(self.getVideoStatus)

    def getVideoStatus(self, status):
        self.status = status
Beispiel #11
0
class DBPlayer(QWidget):
    # signal
    signaltxt = pyqtSignal(str)
    signalnum = pyqtSignal(int)

    def __init__(self):
        super(DBPlayer, self).__init__()
        self.setMaximumSize(16777215, 35)
        # Init Player
        self.messtitle = TITL_PROG
        self.namemedia = ''
        self.albumname = ''
        self.currentPlaylist = QMediaPlaylist()
        self.player = QMediaPlayer()
        self.player.stateChanged.connect(self.qmp_stateChanged)
        self.player.positionChanged.connect(self.qmp_positionChanged)
        self.player.volumeChanged.connect(self.qmp_volumeChanged)
        self.player.durationChanged.connect(self.qmp_durationChanged)
        self.player.setVolume(60)
        # Init GUI
        self.setLayout(self.addControls())
        self.infoBox = None

    def addControls(self):
        # buttons
        self.playBtn = QPushButton()
        self.playBtn.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay))
        self.playBtn.setStyleSheet('border: 0px;')
        stopBtn = QPushButton()
        stopBtn.setIcon(self.style().standardIcon(QStyle.SP_MediaStop))
        stopBtn.setStyleSheet('border: 0px;')
        prevBtn = QPushButton()
        prevBtn.setIcon(self.style().standardIcon(QStyle.SP_MediaSkipBackward))
        prevBtn.setStyleSheet('border: 0px;')
        nextBtn = QPushButton()
        nextBtn.setIcon(self.style().standardIcon(QStyle.SP_MediaSkipForward))
        nextBtn.setStyleSheet('border: 0px;')
        volumeDescBtn = QPushButton('▼')
        volumeDescBtn.setIcon(self.style().standardIcon(QStyle.SP_MediaVolume))
        volumeDescBtn.setMaximumWidth(30)
        volumeDescBtn.setStyleSheet('border: 0px;')
        volumeIncBtn = QPushButton('▲')
        volumeIncBtn.setIcon(self.style().standardIcon(QStyle.SP_MediaVolume))
        volumeIncBtn.setMaximumWidth(40)
        volumeIncBtn.setStyleSheet('border: 0px;')
        infoBtn = QPushButton()
        infoBtn.setIcon(self.style().standardIcon(
            QStyle.SP_FileDialogContentsView))
        infoBtn.setStyleSheet('border: 0px;')

        # seek slider
        self.seekSlider = QSlider(Qt.Horizontal, self)
        self.seekSlider.setMinimum(0)
        self.seekSlider.setMaximum(100)
        self.seekSlider.setTracking(False)

        # labels position start/end
        self.seekSliderLabel1 = QLabel('0:00')
        self.seekSliderLabel2 = QLabel('0:00')

        # layout
        controlArea = QHBoxLayout()
        controlArea.addWidget(prevBtn)
        controlArea.addWidget(self.playBtn)
        controlArea.addWidget(stopBtn)
        controlArea.addWidget(nextBtn)
        controlArea.addWidget(self.seekSliderLabel1)
        controlArea.addWidget(self.seekSlider)
        controlArea.addWidget(self.seekSliderLabel2)
        controlArea.addWidget(infoBtn)
        controlArea.addWidget(volumeDescBtn)
        controlArea.addWidget(volumeIncBtn)

        # link buttons to media
        self.seekSlider.sliderMoved.connect(self.seekPosition)
        self.playBtn.clicked.connect(self.playHandler)
        stopBtn.clicked.connect(self.stopHandler)
        volumeDescBtn.clicked.connect(self.decreaseVolume)
        volumeIncBtn.clicked.connect(self.increaseVolume)
        prevBtn.clicked.connect(self.prevItemPlaylist)
        nextBtn.clicked.connect(self.nextItemPlaylist)
        infoBtn.clicked.connect(self.displaySongInfo)

        return controlArea

    def playHandler(self):
        if self.player.state() == QMediaPlayer.PlayingState:
            self.player.pause()
            message = (' [Paused at position %s]' %
                       self.seekSliderLabel1.text())
            self.messtitle = self.namemedia + message
            self.signaltxt.emit(self.messtitle)
        else:
            if self.player.state() == QMediaPlayer.StoppedState:
                if self.player.mediaStatus() == QMediaPlayer.NoMedia:
                    if self.currentPlaylist.mediaCount() != 0:
                        self.player.setPlaylist(self.currentPlaylist)
                elif self.player.mediaStatus() == QMediaPlayer.LoadedMedia:
                    self.player.play()
                elif self.player.mediaStatus() == QMediaPlayer.BufferedMedia:
                    self.player.play()
            elif self.player.state() == QMediaPlayer.PlayingState:
                pass
            elif self.player.state() == QMediaPlayer.PausedState:
                self.player.play()
            if self.player.volume() is not None and self.player.state(
            ) == QMediaPlayer.PlayingState:
                message = ' [Volume %d]' % self.player.volume()
                self.messtitle = self.namemedia + message
                self.signaltxt.emit(self.messtitle)

    def stopHandler(self):
        if self.player.state() == QMediaPlayer.PlayingState:
            self.stopState = True
            self.player.stop()
        elif self.player.state() == QMediaPlayer.PausedState:
            self.player.stop()
        elif self.player.state() == QMediaPlayer.StoppedState:
            pass
        if self.player.volume() is not None and self.player.state(
        ) == QMediaPlayer.PlayingState:
            self.messtitle = self.namemedia + (' [Stopped]')
            self.signaltxt.emit(self.messtitle)

    def qmp_stateChanged(self):
        if self.player.state() == QMediaPlayer.StoppedState:
            self.player.stop()
        # buttons icon play/pause change
        if self.player.state() == QMediaPlayer.PlayingState:
            self.playBtn.setIcon(self.style().standardIcon(
                QStyle.SP_MediaPause))
        else:
            self.playBtn.setIcon(self.style().standardIcon(
                QStyle.SP_MediaPlay))

    def qmp_positionChanged(self, position):
        # update position slider
        self.seekSlider.setValue(position)
        # update the text label
        self.seekSliderLabel1.setText(
            '%d:%02d' % (int(position / 60000), int((position / 1000) % 60)))

    def seekPosition(self, position):
        sender = self.sender()
        if isinstance(sender, QSlider):
            if self.player.isSeekable():
                self.player.setPosition(position)

    def qmp_volumeChanged(self):
        if self.player.volume() is not None:
            message = (' [Playing at Volume %d]' % (self.player.volume()))
            if self.namemedia != '':
                self.messtitle = self.namemedia + message
            else:
                self.messtitle = "Initialisation player " + message
            self.signaltxt.emit(self.messtitle)

    def qmp_durationChanged(self, duration):
        self.seekSlider.setRange(0, duration)
        self.seekSliderLabel2.setText(
            '%d:%02d' % (int(duration / 60000), int((duration / 1000) % 60)))
        nummedia = self.currentPlaylist.mediaCount()
        curmedia = self.currentPlaylist.currentIndex()
        #artist = self.player.metaData(QMediaMetaData.Author)
        #tittle = self.player.metaData(QMediaMetaData.Title)
        self.namemedia = path.basename(self.homMed[curmedia])
        self.namemedia = '[%02d/%02d' % (
            curmedia + 1, nummedia) + '] "' + self.namemedia + '"'
        self.buildPlaylist()
        message = (' [Playing at Volume %d]' % (self.player.volume()))
        if self.player.volume() is not None and self.player.state(
        ) == QMediaPlayer.PlayingState:
            self.messtitle = self.namemedia + message
            self.signaltxt.emit(self.messtitle)

    def buildPlaylist(self):
        """Build play list."""
        nummedia = self.currentPlaylist.mediaCount()
        curmedia = self.currentPlaylist.currentIndex() + 1
        compteur = 1
        self.textplaylist = '<b>' + self.albumname + '</b>'
        self.textplaylist += '<table class="tftable" border="0">'
        for namemedia in self.homMed:
            media = path.basename(namemedia)
            media = '[%02d/%02d' % (compteur, nummedia) + '] "' + media + '"'
            if curmedia == compteur:
                self.textplaylist += '<tr><td><b>' + media + '</b></td></tr>'
            else:
                self.textplaylist += '<tr><td>' + media + '</td></tr>'
            compteur += 1
        self.textplaylist = self.textplaylist + '</table>'
        self.playBtn.setToolTip(self.textplaylist)
        self.signalnum.emit(curmedia - 1)

    def increaseVolume(self):
        """Volume +."""
        vol = self.player.volume()
        vol = min(vol + 5, 100)
        self.player.setVolume(vol)

    def decreaseVolume(self):
        """Volume -."""
        vol = self.player.volume()
        vol = max(vol - 5, 0)
        self.player.setVolume(vol)

    def prevItemPlaylist(self):
        self.player.playlist().previous()
        if self.currentPlaylist.currentIndex() == -1:
            self.player.playlist().previous()

    def nextItemPlaylist(self):
        self.player.playlist().next()
        if self.currentPlaylist.currentIndex() == -1:
            self.player.playlist().next()

    def addMediaslist(self, listmedias, position, albumname):
        if self.currentPlaylist.mediaCount() > 0:
            self.currentPlaylist.removeMedia(0,
                                             self.currentPlaylist.mediaCount())
            self.player.stop()
            self.stopHandler()
        self.currentPlaylist.removeMedia(0, self.currentPlaylist.mediaCount())
        self.albumname = albumname
        if listmedias:
            self.homMed = listmedias
            for media in self.homMed:
                self.currentPlaylist.addMedia(
                    QMediaContent(QUrl.fromLocalFile(media)))
            self.currentPlaylist.setCurrentIndex(position)
            self.playHandler()

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

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

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

    def ManageDB(self):
        self.player.pause()
        shapeFileFirst,_ =  QFileDialog.getSaveFileName(caption = 'Save shape file', filter = "Esri shp (*.shp)")
        if shapeFileFirst:
            if shapeFileFirst.split('.')[-1] == 'shp':
                shapeFile = shapeFileFirst
            else:
                shapeFile = shapeFileFirst + '.shp'
            try:
                os.remove(shapeFile)
                os.remove(shapeFileFirst.split('.')[0]+'.qpg')
                os.remove(shapeFileFirst.split('.')[0]+'.prj')
                os.remove(shapeFileFirst.split('.')[0]+'.cpg')
                os.remove(shapeFileFirst.split('.')[0]+'.shx')
                os.remove(shapeFileFirst.split('.')[0]+'.dbf')
                
            except OSError:
                pass 
            crs = QgsCoordinateReferenceSystem(4326, QgsCoordinateReferenceSystem.EpsgCrsId)
            fields = QgsFields()
            QgsVectorFileWriter(shapeFile, "CP1250", fields, QgsWkbTypes.Point, crs, "ESRI Shapefile")
            EmptyLayer = QgsVectorLayer(shapeFile, shapeFile.split('.')[0].split('/')[-1], 'ogr')
            self.dialoga = TableManager(self.iface, EmptyLayer,self)
            self.dialoga.exec_()
    
    def AcceptNewDB(self,DB):
        self.DB = DB
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
Beispiel #14
0
class MediaWindow(QWidget):
    def __init__(self, stimulusWindow):
        super(MediaWindow, self).__init__()
        self.setFocusPolicy(Qt.StrongFocus)
        self.setStyleSheet('''
            QWidget{
                border-style: none;
            }
            ''')

        #self.setWindowFlags(Qt.WindowStaysOnTopHint | Qt.FramelessWindowHint)

        self.showFullScreen()

        self.stimulusWindow = stimulusWindow
        stimulusWindow.showFullScreen()

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

        self.videoProbe = QVideoProbe()
        self.videoProbe.videoFrameProbed.connect(self.onVideoFrame)
        self.videoProbe.setSource(self.mediaPlayer)

        self.graphicsVideoItem = QGraphicsVideoItem()

        self.graphicsScene = QGraphicsScene()
        self.graphicsView = QGraphicsView(self.graphicsScene)
        geom = stimulusWindow.geometry()
        self.graphicsView.setFixedSize(geom.width(), geom.height())
        self.graphicsScene.addItem(self.graphicsVideoItem)

        self.graphicsView.setViewport(self.stimulusWindow)
        self.graphicsView.setViewportUpdateMode(
            QGraphicsView.FullViewportUpdate)

        print(self.graphicsView.contentsRect())

        layout = QVBoxLayout()
        layout.setContentsMargins(0, 0, 0, 0)
        layout.alignmentRect
        layout.addWidget(self.graphicsView)

        self.setLayout(layout)
        self.graphicsView.setFocusPolicy(Qt.NoFocus)
        self.graphicsView.viewport().installEventFilter(self)
        self.hide()
        #self.showFullScreen()

        self.ticker = None

    def eventFilter(self, object, event):
        if event.type() == QEvent.MouseMove:
            self.mouseMoveEvent(event)
        return False

    def playVideo(self, videoPath, duration):
        self.showFullScreen()

        url = QUrl.fromLocalFile(videoPath)
        self.mediaContent = QMediaContent(url)

        self.mediaPlayer.setVideoOutput(self.graphicsVideoItem)
        self.mediaPlayer.setMedia(self.mediaContent)

        self.stimulusWindow.measuredFrameInterval_s = self.stimulusWindow.expectedFrameInterval_s
        self.stimulusWindow.gracePeriodForFpsMeasurement = 60
        print('mediaplayer: video start')
        print(self.mediaPlayer.mediaStatus())
        self.timer.stop()
        self.mediaPlayer.play()
        self.framesToGo = duration
        print('frames to go: ' + str(self.framesToGo))

    def stopVideo(self):
        #self.stimulusWindow.showFullScreen()
        print('mediaplayer: video stop')
        self.mediaPlayer.stop()
        self.timer.start()

    def onVideoFrame(self, frame):
        gears.onDisplayHidden()
        self.framesToGo = self.framesToGo - 1
        if self.framesToGo == 0:
            self.stopVideo()

    def start(self, launcherWindow):
        print("Starting media window.")
        print(datetime.datetime.now().time())

        self.launcherWindow = launcherWindow
        sequence = gears.getSequence().getPythonObject()
        self.expectedFrameInterval_s = sequence.getFrameInterval_s()
        self.measuredFrameInterval_s = self.expectedFrameInterval_s
        self.gracePeriodForFpsMeasurement = 60

        if sequence.getUsesBusyWaitingThreadForSingals():
            self.ticker = gears.startTicker()
        else:
            self.ticker = None
        self.timer = QTimer(self)
        self.timer.setInterval(0)
        self.timer.timeout.connect(self.onTimer)

        self.stimulusWindow.mediaWindow = self
        self.timer.start()
        self.firstFrame = True
        self.setFocus()

        print("Showing media window.")
        print(datetime.datetime.now().time())

        self.showFullScreen()

    def stop(self):
        self.timer.stop()
        sequence = gears.getSequence().getPythonObject()
        if self.ticker:
            self.ticker.stop()
        self.launcherWindow.wake()
        QApplication.instance().processEvents()
        gears.reset()
        self.hide()
        self.lower()

    def onBufferSwap(self):
        if self.ticker:
            self.ticker.onBufferSwap()

    def onTimer(self):
        #print("Media window timer tick.")
        #print(datetime.datetime.now().time())
        self.stimulusWindow.updateNative()

    def keyReleaseEvent(self, event):
        stimulus = gears.getCurrentStimulus().getPythonObject()
        try:
            for cb in stimulus.onKeyUp:
                cb(event)
        except AttributeError:
            pass

    def keyPressEvent(self, event):
        sequence = gears.getSequence().getPythonObject()
        if event.text() == 'q' or event.key() == Qt.Key_Escape:
            gears.skip(100000000)
        elif event.text() == 'f':
            self.showFps = not self.showFps
        elif event.key() == Qt.Key_Right or event.text() == 's':
            gears.skip(1)
        elif event.key() == Qt.Key_Left or event.text() == 'b':
            gears.skip(-1)
        elif event.text() == 'p' or event.text() == 'a':
            gears.pause()
        elif event.text() == 'y':
            gears.instantlyClearSignal(sequence.onKeySpikeChannel)
            gears.instantlyRaiseSignal(sequence.onKeySpikeChannel)
        elif event.text() == 'h':
            gears.instantlyRaiseSignal(sequence.onKeySpikeChannel)
            gears.instantlyClearSignal(sequence.onKeySpikeChannel)
        else:
            if event.text() == ' ':
                gears.setText("_____toggle info",
                              "Press SPACE to hide this text.")
                gears.showText()
            stimulus = gears.getCurrentStimulus().getPythonObject()
            try:
                for cb in stimulus.onKey:
                    cb(event)
            except AttributeError:
                pass

    def mouseMoveEvent(self, event):
        stimulus = gears.getCurrentStimulus().getPythonObject()
        try:
            for cb in stimulus.onMouse:
                cb(event)
        except AttributeError:
            pass

    def mousePressEvent(self, event):
        stimulus = gears.getCurrentStimulus().getPythonObject()
        try:
            for cb in stimulus.onMouseClick:
                cb(event)
        except AttributeError:
            pass

    def wheelEvent(self, event):
        stimulus = gears.getCurrentStimulus().getPythonObject()
        try:
            for cb in stimulus.onWheel:
                cb(event)
        except AttributeError:
            pass
Beispiel #15
0
class MainWindow(QMainWindow):
    markers_img: Image = None
    board_img: Image = None

    calibration_photo_files: np.ndarray = None
    calibration_info = property()
    _calib_info: CalibrationInfo = None

    video_files: np.ndarray = None
    player = None
    playlist = None

    video_position = pyqtSignal(int)

    def __init__(self, parent=None, *args, **kwargs):
        super(MainWindow, self).__init__(*args, **kwargs)
        uic.loadUi('./mainwindow.ui', self)
        self.setup_ui(self)
        self.connect_events()

    def setup_ui(self, window):
        self.gen_markers_arucoDict.addItems(ArucDict_dict.keys())
        self.gen_markers_arucoDict.setCurrentIndex(0)

        self.gen_board_arucoDict.addItems(ArucDict_dict.keys())
        self.gen_board_arucoDict.setCurrentIndex(0)

        self.calibrate_aruco_dict.addItems(ArucDict_dict.keys())
        self.calibrate_aruco_dict.setCurrentIndex(0)

        self.gen_marker_Gview = widgets_ext.MyPicBox(self.gen_marker_Gview)
        self.gen_board_Gview = widgets_ext.MyPicBox(self.gen_board_Gview)
        self.calibrate_Gview = widgets_ext.MyPicBox(self.calibrate_Gview)

        self.calibrate_photo_list.setSelectionMode(
            QAbstractItemView.SingleSelection)

        self.player = QMediaPlayer(None, QMediaPlayer.VideoSurface)
        self.player.setVideoOutput(self.video)
        self.player.mediaStatusChanged.connect(self.print_status)
        # self.playlist = QMediaPlaylist(self.player)
        # self.player.setPlaylist(self.playlist)

    def connect_events(self):
        self.gen_markers_run_btn.clicked.connect(self.gen_markers_and_show)
        self.gen_markers_save_btn.clicked.connect(self.gen_markers_save)

        self.gen_board_run_btn.clicked.connect(self.gen_board_and_show)
        self.gen_board_save_btn.clicked.connect(self.gen_board_save)

        self.calibrate_load_photo.clicked.connect(self.load_photo_dir)
        self.calibrate_photo_list.itemSelectionChanged.connect(
            self.on_calibration_photo_selected)

        self.calibrate_start_btn.clicked.connect(self.calibrate_start)
        self.calibrate_load_settings.clicked.connect(self.load_settings)
        self.calibrate_save_settings.clicked.connect(self.save_settings)

        self.video_tracking_load_video_bnt.clicked.connect(
            self.load_videos_dir)
        self.video_tracking_list.itemSelectionChanged.connect(
            self.on_video_file_selected)

        self.play_btn.clicked.connect(self.player.play)
        self.pause_btn.clicked.connect(self.player.pause)
        self.stop_btn.clicked.connect(self.player.stop)

        # self.video_position.connect(self.player.position)
        # self.video_position.connect(self.video_slider.setValue)

    @calibration_info.getter
    def calibration_info(self):
        return self._calib_info

    @calibration_info.setter
    def calibration_info(self, value: CalibrationInfo):
        self._calib_info = value
        if value is None:
            return

        self.calibration_status.setText("Да")
        r = self._calib_info.calib_photos_ratio
        r1, r2 = r.numerator, r.denominator
        self.calibration_ratio.setText(f"{r1}:{r2}")
        d = self._calib_info.aruco_dict

        found = False
        for name, dict in ArucDict_dict.items():
            if dict == d:
                self.calibration_dictionary.setText(name)
                found = True
                break

        if not found and d is None:
            msg = "В калибровочной информации отсутствует словрь меток!"
            mbox = QMessageBox()
            mbox.setWindowTitle('Ошибка!')
            mbox.setText(msg)
            mbox.exec()
            self.calibration_info = None

    def gen_markers_and_show(self):
        key = self.gen_markers_arucoDict.currentText()
        aruco_dict = ArucDict_dict[key]

        markers_num = self.gen_markers_num.value()
        markers_size = self.gen_markers_size.value()
        print_dpi = self.gen_markers_dpi.value()

        try:
            img = TremResearcher.gen_marks(aruco_dict=aruco_dict,
                                           markers_num=markers_num,
                                           real_size_mm=markers_size,
                                           print_dpi=print_dpi)
            self.markers_img = img
        except Exception as ex:
            mbox = QMessageBox()
            mbox.setWindowTitle('Ошибка!')
            mbox.setText(str(ex))
            mbox.exec()
            return

        MainWindow.show_img_on_view(img, self.gen_marker_Gview)

    def gen_markers_save(self):
        if self.markers_img is None:
            mbox = QMessageBox()
            mbox.setWindowTitle('Ошибка!')
            mbox.setText("Маркеры еще не сгенирированы.")
            mbox.exec()
            return

        file_name, _ = QFileDialog.getSaveFileName(self,
                                                   'Сохранить',
                                                   filter='png(*.png)')
        if file_name is not None and file_name != "":
            self.markers_img.save(file_name)

    def gen_board_and_show(self):
        key = self.gen_board_arucoDict.currentText()
        aruco_dict = ArucDict_dict[key]
        resolution = self.gen_board_scr_w.value(), self.gen_board_scr_h.value()

        try:
            img = TremResearcher.gen_board(aruco_dict=aruco_dict,
                                           screen_resolution=resolution)
            self.board_img = img
        except Exception as ex:
            mbox = QMessageBox()
            mbox.setWindowTitle('Ошибка!')
            mbox.setText(str(ex))
            mbox.exec()
            return

        MainWindow.show_img_on_view(img, self.gen_board_Gview)

    def gen_board_save(self):
        if self.board_img is None:
            mbox = QMessageBox()
            mbox.setWindowTitle('Ошибка!')
            mbox.setText("Маркеры еще не сгенирированы.")
            mbox.exec()
            return

        file_name, _ = QFileDialog.getSaveFileName(self,
                                                   'Сохранить',
                                                   filter='png(*.png)')
        if file_name is not None and file_name != "":
            self.board_img.save(file_name)

    def load_photo_dir(self):
        dialog = QFileDialog()
        dialog.setWindowTitle('Выберете папку с калибровочными фотографиями')
        dialog.setAcceptMode(QFileDialog.AcceptOpen)
        dialog.setFileMode(QFileDialog.Directory)

        if dialog.exec_() == QFileDialog.Accepted:
            photo_dir: str = dialog.selectedFiles()[0]
            files = FilesHelper.photo_files(photo_dir)
            self.calibration_photo_files = files
            self.calibrate_photo_list.clear()
            self.calibrate_photo_list.addItems(
                [f.rsplit(OS_SLASH, 1)[1] for f in files])

    def on_calibration_photo_selected(self):
        inx: QModelIndex = self.calibrate_photo_list.currentRow()
        file = self.calibration_photo_files[inx]
        pix = QPixmap(file)
        self.calibrate_Gview.setPixmap(pix)

    def calibrate_start(self):
        key = self.calibrate_aruco_dict.currentText()
        aruco_dict = ArucDict_dict[key]
        resolution = self.calibrate_screen_width.value(),\
                     self.calibrate_screem_height.value()
        screen_inches = self.calibrate_screen_inches.value()
        photos = self.calibration_photo_files
        try:
            calib = TremResearcher.calibrate_by_monitor_photo(
                aruco_dict, photos, resolution, screen_inches)
            self.calibration_info = calib
        except Exception as ex:
            mbox = QMessageBox()
            mbox.setWindowTitle('Ошибка!')
            mbox.setText(str(ex))
            mbox.exec()
        else:
            mbox = QMessageBox()
            mbox.setWindowTitle('Сообщение')
            mbox.setText('Калибровка завершена.')
            mbox.exec()

    def load_settings(self):
        file_name, _ = QFileDialog.getOpenFileName(self,
                                                   'Открыть',
                                                   filter='pkl(*.pkl)')
        if file_name is not None and file_name != "":
            calib = CalibrationInfo.load_calibration_info(file_name)
            self.calibration_info = calib

    def save_settings(self):
        file_name, _ = QFileDialog.getSaveFileName(self,
                                                   'Сохранить',
                                                   filter='pkl(*.pkl)')
        if file_name is not None and file_name != "":
            self.calibration_info.save(file_name)

    @staticmethod
    def show_img_on_view(img: Image, view: widgets_ext.MyPicBox):
        p1 = ImageQt(img)
        p2 = QImage(p1)
        p3 = QPixmap(p2)
        view.setPixmap(QPixmap(p3))

    def load_videos_dir(self):
        dialog = QFileDialog()
        dialog.setWindowTitle('Выберете папку с видеофайлами')
        dialog.setAcceptMode(QFileDialog.AcceptOpen)
        dialog.setFileMode(QFileDialog.Directory)

        if dialog.exec_() == QFileDialog.Accepted:
            photo_dir: str = dialog.selectedFiles()[0]
            files = FilesHelper.video_files(photo_dir)
            self.video_files = files
            self.video_tracking_list.clear()
            self.video_tracking_list.addItems(
                [f.rsplit(OS_SLASH, 1)[1] for f in files])

    def on_video_file_selected(self):
        inx: QModelIndex = self.video_tracking_list.currentRow()
        file = self.video_files[inx]

        self.player.setMedia(
            QMediaContent(QUrl("https://www.youtube.com/watch?v=7cQ5n9j5Guo")))
        #self.player.setMedia(QMediaContent(QUrl.fromLocalFile(file)))

    def print_status(self):
        print("Status changed to:", self.player.mediaStatus())
        self.video_slider.setMaximum(self.player.duration())
Beispiel #16
0
class Player(QFrame):
    '''
    音乐播放器
    TODO 歌词系统
    '''

    sig_music_status_changed = pyqtSignal(bool)

    def __init__(self, parent):
        super().__init__(parent)
        self.parent_widget = parent
        self.setObjectName('Player')
        self.set_UI()

        # if parent == None:
        #     self.setWindowFlags(Qt.FramelessWindowHint)
        '''用于播放音乐的对象'''
        self.music_player = QMediaPlayer(self)
        self.music_player.setVolume(70)
        self.music_player.setObjectName('MusicPlayer')
        '''
        歌曲列表
        列表要显示在播放器之外的地方,因此不能把父窗口设置成self
        '''
        self.play_list = PlayList(parent)
        '''播放进度'''
        self.millionsecond = 0
        self.second = 0

        self.lyric_panel = LyricPanel()

        self.set_connections()

    def set_UI(self):
        self.setFrameShape(QFrame.NoFrame)
        self.setMinimumSize(1200, 80)
        self.setMaximumHeight(100)

        self.set_buttons()
        self.set_sliders()
        self.set_labels()
        self.set_layout()

        with open('.\\QSS\\player.qss', 'r') as file_obj:
            self.setStyleSheet(file_obj.read())

    def set_buttons(self):
        '''
        创建按钮
        '上一首'按钮、'播放'按钮、'暂停'按钮、'下一首'按钮、'静音'按钮、'恢复音量'按钮、'播放模式'按钮、'歌词'按钮、'播放列表'按钮
        '''
        self.previous_button = QPushButton(self)
        self.previous_button.setObjectName('PreviousButton')
        self.previous_button.setToolTip('上一首')

        self.play_button = QPushButton(self)
        self.play_button.setObjectName('PlayButton')
        self.play_button.setToolTip('播放')

        self.pause_button = QPushButton(self)
        self.pause_button.setObjectName('PauseButton')
        self.pause_button.setToolTip('暂停')
        self.pause_button.hide()

        self.next_button = QPushButton(self)
        self.next_button.setObjectName('NextButton')
        self.next_button.setToolTip('下一首')

        self.mute_button = QPushButton(self)
        self.mute_button.setObjectName('MuteButton')
        self.mute_button.setToolTip('静音')

        self.recover_button = QPushButton(self)
        self.recover_button.setObjectName('RecoverButton')
        self.recover_button.setToolTip('恢复音量')
        self.recover_button.hide()

        self.random_button = QPushButton(self)
        self.random_button.setObjectName('RandomButton')
        self.random_button.setToolTip('随机播放')
        #self.random_button.hide()

        self.loop_button = QPushButton(self)
        self.loop_button.setObjectName('LoopButton')
        self.loop_button.setToolTip('列表循环')
        self.loop_button.hide()

        self.repeat_button = QPushButton(self)
        self.repeat_button.setObjectName('RepeatButton')
        self.repeat_button.setToolTip('单曲循环')
        self.repeat_button.hide()

        self.show_lyric_button = QPushButton(self)
        self.show_lyric_button.setObjectName('ShowLyricButton')
        self.show_lyric_button.setText('词')
        self.show_lyric_button.setFont(QFont('YouYuan', 14))
        self.show_lyric_button.setToolTip('打开歌词')

        self.hide_lyric_button = QPushButton(self)
        self.hide_lyric_button.setObjectName('HideLyricButton')
        self.hide_lyric_button.setText('词')
        self.hide_lyric_button.setFont(QFont('YouYuan', 14))
        self.hide_lyric_button.setToolTip('关闭歌词')
        self.hide_lyric_button.hide()

        self.list_button = QPushButton(self)
        self.list_button.setObjectName('ListButton')
        self.list_button.setToolTip('播放列表')

    def set_sliders(self):
        '''
        创建滑块
        播放进度条、音量控制条
        '''
        self.progress_slider = QSlider(self)
        self.progress_slider.setObjectName('ProgressSlider')
        self.progress_slider.setOrientation(Qt.Horizontal)
        self.progress_slider.setTracking(False)

        self.volume_slider = QSlider(self)
        self.volume_slider.setObjectName('VolumeSlider')
        self.volume_slider.setOrientation(Qt.Horizontal)
        self.volume_slider.setRange(0, 100)
        self.volume_slider.setValue(100)

    def set_labels(self):
        '''
        创建标签
        当前播放时间、歌曲总时间
        '''
        self.time_label = QLabel(self)
        self.time_label.setObjectName('TimeLabel')
        self.time_label.setFont(QFont('YouYuan'))

        self.duration_label = QLabel(self)
        self.duration_label.setObjectName('DurationLabel')
        self.duration_label.setFont(QFont('YouYuan'))

    def set_layout(self):
        '''
        创建布局
        '''

        self.layout = QHBoxLayout()
        self.layout.setObjectName('Layout')

        self.layout.addWidget(self.previous_button)
        self.layout.addSpacing(10)
        self.layout.addWidget(self.play_button)
        self.layout.addWidget(self.pause_button)
        self.layout.addSpacing(10)
        self.layout.addWidget(self.next_button)

        self.layout.addSpacing(20)
        self.layout.addWidget(self.time_label)
        self.layout.addSpacing(10)
        self.layout.addWidget(self.progress_slider)
        self.layout.addSpacing(10)
        self.layout.addWidget(self.duration_label)

        self.layout.addSpacing(20)
        self.layout.addWidget(self.mute_button)
        self.layout.addWidget(self.recover_button)
        self.layout.addWidget(self.volume_slider)

        self.layout.addSpacing(20)
        self.layout.addWidget(self.loop_button)
        self.layout.addWidget(self.random_button)
        self.layout.addWidget(self.repeat_button)

        self.layout.addSpacing(20)
        self.layout.addWidget(self.show_lyric_button)
        self.layout.addWidget(self.hide_lyric_button)

        self.layout.addSpacing(20)
        self.layout.addWidget(self.list_button)

        self.layout.setStretchFactor(self.previous_button, 3)
        self.layout.setStretchFactor(self.play_button, 3)
        self.layout.setStretchFactor(self.pause_button, 3)
        self.layout.setStretchFactor(self.next_button, 3)
        self.layout.setStretchFactor(self.time_label, 2)
        self.layout.setStretchFactor(self.progress_slider, 25)
        self.layout.setStretchFactor(self.duration_label, 2)
        self.layout.setStretchFactor(self.mute_button, 2)
        self.layout.setStretchFactor(self.recover_button, 2)
        self.layout.setStretchFactor(self.volume_slider, 7)
        self.layout.setStretchFactor(self.loop_button, 2)
        self.layout.setStretchFactor(self.random_button, 2)
        self.layout.setStretchFactor(self.repeat_button, 2)
        # self.layout.setStretchFactor(self.show_lyric_button, 2)
        # self.layout.setStretchFactor(self.hide_lyric_button, 2)
        self.layout.setStretchFactor(self.list_button, 2)

        self.setLayout(self.layout)
        self.layout.setContentsMargins(20, 5, 20, 5)

    def set_connections(self):
        '''
        连接信号和槽
        '''
        self.previous_button.clicked.connect(self.on_previous_clicked)
        self.play_button.clicked.connect(self.on_play_clicked)
        self.pause_button.clicked.connect(self.on_pause_clicked)
        self.next_button.clicked.connect(self.on_next_clicked)

        self.random_button.clicked.connect(self.on_random_clicked)
        self.repeat_button.clicked.connect(self.on_repeat_clicked)
        self.loop_button.clicked.connect(self.on_loop_clicked)
        self.list_button.clicked.connect(self.on_list_clicked)

        self.mute_button.clicked.connect(self.on_mute_clicked)
        self.recover_button.clicked.connect(self.on_recover_clicked)

        self.show_lyric_button.clicked.connect(self.on_show_lyric_clicked)
        self.hide_lyric_button.clicked.connect(self.on_hide_lyric_clicked)

        self.music_player.durationChanged.connect(self.on_music_changed)

        self.music_player.positionChanged.connect(
            self.on_millionsecond_changed)
        self.music_player.positionChanged.connect(
            self.lyric_panel.on_millionsecond_changed)
        self.progress_slider.valueChanged.connect(self.on_progress_changed)
        self.volume_slider.valueChanged.connect(self.on_volume_changed)
        '''通过点击切歌'''
        self.play_list.sig_music_index_changed.connect(
            self.on_music_index_changed)
        '''播放状态改变,同时改变图标'''
        self.sig_music_status_changed.connect(
            self.play_list.on_music_status_changed)

        # self.play_button.clicked.connect(self.play_list.on_music_played)
        # self.pause_button.clicked.connect(self.play_list.on_music_paused)

    def on_random_clicked(self):
        self.random_button.hide()
        self.repeat_button.show()
        self.play_list.set_play_mode(PlayMode.REPEAT)

    def on_repeat_clicked(self):
        self.repeat_button.hide()
        self.loop_button.show()
        self.play_list.set_play_mode(PlayMode.LOOP)

    def on_loop_clicked(self):
        self.loop_button.hide()
        self.random_button.show()
        self.play_list.set_play_mode(PlayMode.RANDOM)

    def on_list_clicked(self):
        if self.play_list.isVisible():
            self.play_list.hide()
        else:
            self.set_list_geometry()
            self.play_list.show()
            self.play_list.raise_()

    def on_previous_clicked(self):
        content = self.play_list.previous_music()
        self.play_music(content)
        if content:
            self.play_button.hide()
            self.pause_button.show()
            self.sig_music_status_changed.emit(False)

    def on_play_clicked(self):
        flag = True
        if self.music_player.mediaStatus() == QMediaPlayer.NoMedia:
            '''检查播放器中是否有歌曲'''
            content = self.play_list.get_music()
            if content == None:
                '''歌单中没有歌曲'''
                flag = False
            self.play_music(content)
        else:
            self.play_music()
        if flag:
            self.play_button.hide()
            self.pause_button.show()
            self.sig_music_status_changed.emit(False)

            if self.lyric_panel.isVisible():
                self.lyric_panel.restart_lyric()

    def on_pause_clicked(self):
        self.music_player.pause()
        self.pause_button.hide()
        self.play_button.show()
        self.sig_music_status_changed.emit(True)

        if self.lyric_panel.isVisible():
            self.lyric_panel.pause_lyric()

    def on_next_clicked(self):
        content = self.play_list.next_music()
        self.play_music(content)
        if content:
            self.play_button.hide()
            self.pause_button.show()
            self.sig_music_status_changed.emit(False)

    def on_mute_clicked(self):
        self.music_player.setMuted(True)
        self.mute_button.hide()
        self.recover_button.show()

    def on_recover_clicked(self):
        self.music_player.setMuted(False)
        self.recover_button.hide()
        self.mute_button.show()

    def on_music_changed(self):
        self.time_label.setText(utils.time_int_to_str(0))
        total_time = self.music_player.duration() // 1000
        if total_time > 0:
            self.duration_label.setText(utils.time_int_to_str(total_time))
            '''处理没有连接的异常'''
            try:
                self.progress_slider.valueChanged.disconnect(
                    self.on_progress_changed)
                self.progress_slider.setRange(0, total_time)
                self.progress_slider.setValue(0)
                self.progress_slider.valueChanged.connect(
                    self.on_progress_changed)
            except TypeError:
                self.progress_slider.setRange(0, total_time)
                self.progress_slider.setValue(0)

            if self.lyric_panel.isVisible():
                lyric, title = self.play_list.get_lyric_and_title()
                current_time = 0
                total_time = self.music_player.duration()
                self.lyric_panel.show_lyric(lyric, title, current_time,
                                            total_time)

    def on_millionsecond_changed(self, current_position):
        self.millionsecond = current_position
        current_position = current_position // 1000
        if current_position != self.second:
            self.second = current_position
            self.on_second_changed()

    def on_second_changed(self):
        self.time_label.setText(utils.time_int_to_str(self.second))
        '''处理没有连接的异常,disconnect和connect必须配对使用,否则听歌体验极差'''
        try:
            self.progress_slider.valueChanged.disconnect(
                self.on_progress_changed)
            self.increase_progress()
            self.progress_slider.valueChanged.connect(self.on_progress_changed)
        except TypeError:
            self.increase_progress()

    def on_progress_changed(self, progress):
        ratio = progress / self.progress_slider.maximum()
        position = int(self.music_player.duration() * ratio)
        self.music_player.setPosition(position)

    def on_volume_changed(self, volume):
        '''播放器原本的音量较大,这里稍微减少一些'''
        volume = int(volume / 100 * 70)
        self.music_player.setVolume(volume)
        '''用户拖动音量条,自动从静音中恢复'''
        self.on_recover_clicked()

    def on_music_index_changed(self):
        '''
        播放列表中正在播放的歌曲切换了
        有可能是通过点击播放列表切歌
        也有可能是播放新加入的歌曲
        '''
        content = self.play_list.get_music()
        self.play_music(content)

        self.pause_button.show()
        self.play_button.hide()

        self.sig_music_status_changed.emit(False)

    def on_show_lyric_clicked(self):
        self.show_lyric_button.hide()
        self.hide_lyric_button.show()

        if self.music_player.mediaStatus() != QMediaPlayer.NoMedia:
            lyric, title = self.play_list.get_lyric_and_title()
            current_time = self.millionsecond
            total_time = self.music_player.duration()
            self.lyric_panel.show_lyric(lyric, title, current_time, total_time)
        else:
            self.lyric_panel.show_lyric(None, None, None, None)

    def on_hide_lyric_clicked(self):
        self.hide_lyric_button.hide()
        self.show_lyric_button.show()
        self.lyric_panel.hide_lyric()

    def moveEvent(self, event):
        self.set_list_geometry()

    def increase_progress(self):
        '''进度增加1'''
        value = self.progress_slider.value()
        value += 1
        if value > self.progress_slider.maximum():
            self.on_next_clicked()
        else:
            self.progress_slider.setValue(value)

    def play_music(self, content=None):
        if content:
            self.music_player.setMedia(content)
        self.music_player.play()

    def set_list_geometry(self):
        x = self.x() + self.width() - self.play_list.width()
        y = self.y() - self.play_list.height()
        self.play_list.move(x, y)
Beispiel #17
0
class PMusic(QWidget):
    '''central widget'''

    DEFAULT_IMG = '/usr/share/pmusic/pMusic.png'

    def __init__(self, parent):
        '''initialize instance'''

        super().__init__(parent)

        self.player = QMediaPlayer()
        self.player.mediaStatusChanged.connect(self.onmedia_status_changed)
        self.playlist = QMediaPlaylist()
        self.playlist.setPlaybackMode(QMediaPlaylist.Loop)

        self.player.setVolume(100)

        self.resize(parent.width(), parent.height())
        self.setContentsMargins(0, 0, 0, 0)

        self.current_albumart = ''
        pixmap = QPixmap(PMusic.DEFAULT_IMG)
        self.img_label = PImage(self, pixmap)
        self.img_label.resize(self.width(), self.height())
        self.img_label.clicked.connect(self.onclick_img_label)

        self.buttonbar = PButtonBar(self)
        self.buttonbar.hide()
        # position: at the bottom
        self.buttonbar.move(0, self.height() - self.buttonbar.height())
        self.buttonbar.clicked_left.connect(self.onclick_prev)
        self.buttonbar.clicked_mid.connect(self.onclick_main)
        self.buttonbar.clicked_right.connect(self.onclick_next)

        # toggle button for shuffle
        self.shufflebutton = QPushButton(self)
        self.shufflebutton.hide()
        self.shufflebutton.setCheckable(True)
        self.shufflebutton.setText('S')
        # position: top left corner
        button_size = int(self.width() * 0.2)
        self.shufflebutton.setGeometry(0, 0, button_size, button_size)
        self.shufflebutton.clicked.connect(self.onclick_shuffle)

        self.quitbutton = QPushButton(self)
        self.quitbutton.hide()
        self.quitbutton.setStyleSheet('color: rgb(240, 0, 0)')      # red
        self.quitbutton.setFont(QFont('webdings', 10))
        self.quitbutton.setText('r')                                # cross
        # position: top right corner
        self.quitbutton.setGeometry(self.width() - button_size, 0, button_size, button_size)
        self.quitbutton.clicked.connect(self.onclick_quit)

        self.show()

    def enterEvent(self, event):
        '''on mouse enter, show the buttons'''

        super().enterEvent(event)

        self.buttonbar.show()
        self.shufflebutton.show()
        self.quitbutton.show()

    def leaveEvent(self, event):
        '''on mouse leave, hide the buttons'''

        super().leaveEvent(event)

        self.buttonbar.hide()
        self.shufflebutton.hide()
        self.quitbutton.hide()

    @pyqtSlot()
    def onclick_shuffle(self):
        '''shuffle button was toggled'''

        if self.shufflebutton.isChecked():
            debug('shuffle: on')
            self.playlist.setPlaybackMode(QMediaPlaylist.Random)
        else:
            debug('shuffle: off')
            self.playlist.setPlaybackMode(QMediaPlaylist.Loop)

    @pyqtSlot()
    def onclick_quit(self):
        '''quit button was clicked'''

        debug('quit')
        self.stop()
        self.parent().close()

    @pyqtSlot()
    def onclick_img_label(self):
        '''image label was clicked'''

        debug('onclick_img_label')
        self.pause()

    @pyqtSlot()
    def onclick_prev(self):
        '''back button was pressed'''

        debug('onclick_prev')
        self.playlist.previous()

        if self.player.state() != QMediaPlayer.PlayingState:
            debug('player.state == {}'.format(self.player.state()))
            self.play()

    @pyqtSlot()
    def onclick_next(self):
        '''next button was pressed'''

        debug('onclick_next')
        self.playlist.next()

        if self.player.state() != QMediaPlayer.PlayingState:
            debug('player.state == {}'.format(self.player.state()))
            self.play()

    @pyqtSlot()
    def onclick_main(self):
        '''main button was pressed'''

        debug('onclick_main')

        # bring up directory selection dialog
        # have a preference for $HOME/Music/
        try:
            homedir = os.environ['HOME']
            if not os.path.isdir(homedir):
                homedir = os.path.curdir
        except KeyError:
            homedir = os.path.curdir
        music_dir = os.path.join(homedir, 'Music')
        if not os.path.isdir(music_dir):
            music_dir = os.path.curdir

        path = QFileDialog.getExistingDirectory(self, 'Select directory', music_dir, QFileDialog.ShowDirsOnly)
        debug('path == [{}]'.format(path))
        if not path:
            # cancel
            return

        self.stop()
        self.load_playlist(path)
        self.play()

    def onmedia_status_changed(self):
        '''media changed; player switched to next song'''

        debug('onmedia_status_changed')
        debug('player.state == {}'.format(self.player.state()))
        debug('player.mediastate == {}'.format(self.player.mediaStatus()))

        # we want to load albumart if the song is in another directory
        # and display filename on stdout or console log
        # this is only relevant if the QMediaPlayer is now loading new media

        if self.player.mediaStatus() == QMediaPlayer.LoadingMedia:
            media = self.player.currentMedia()
            if media.isNull():
                debug('media isNull')
                return

            filename = media.canonicalUrl().path()
            debug('current media == [{}]'.format(filename))

            # make a short path for informational message
            short_path = filename
            try:
                homedir = os.environ['HOME'] + os.path.sep
                if short_path.startswith(homedir):
                    short_path = filename[len(homedir):]
            except KeyError:
                pass
            if short_path.startswith('Music/'):
                short_path = short_path[len('Music/'):]
            print('now playing: {}'.format(short_path))

            folder = os.path.dirname(filename)
            self.load_albumart(folder)

        elif self.player.mediaStatus() == QMediaPlayer.NoMedia:
            debug('no media present, change albumart to default image')
            # change to default image
            pixmap = QPixmap(PMusic.DEFAULT_IMG)
            self.img_label.setPixmap(pixmap)
            self.current_albumart = ''

    def load_playlist(self, path):
        '''load new playlist'''

        debug('load playlist')
        self.playlist.clear()

        # Note: not actually sure these formats are all supported ...
        files = QDirIterator(path, ['*.mp3', '*.ogg', '*.wav', '*.flac'], flags=QDirIterator.Subdirectories)
        while files.hasNext():
            filename = files.next()
            debug('+ {}'.format(filename))

            url = QUrl.fromLocalFile(filename)
            if not self.playlist.addMedia(QMediaContent(url)):
                debug('addMedia() => False')

        self.player.setPlaylist(self.playlist)

    def load_albumart(self, path):
        '''load album art'''

        debug('load albumart, path == {}'.format(path))

        # load album art
        found = False
        for name in ('cover.jpg', 'Folder.jpg', 'folder.jpg', 'cover.png', 'AlbumArt.jpg', 'AlbumArtSmall.jpg'):
            filename = os.path.join(path, name)
            if os.path.isfile(filename):
                found = True
                if filename == self.current_albumart:
                    debug('same albumart, already loaded')
                    break

                debug('loading albumart {}'.format(filename))
                pixmap = QPixmap(filename)
                self.img_label.setPixmap(pixmap)
                self.current_albumart = filename
                break

        if not found:
            if not self.current_albumart:
                debug('no albumart found, keeping default image')
            else:
                # put default image
                debug('no albumart found, putting default image')
                pixmap = QPixmap(PMusic.DEFAULT_IMG)
                self.img_label.setPixmap(pixmap)
                self.current_albumart = ''


    def stop(self):
        '''stop playing'''

        debug('stop')
        self.player.stop()

    def play(self):
        '''start playing'''

        debug('play()')
        self.player.play()

    def pause(self):
        '''pause playing'''

        if self.player.state() == QMediaPlayer.PlayingState:
            debug('pause')
            self.player.pause()

        elif self.player.state() in (QMediaPlayer.StoppedState, QMediaPlayer.PausedState):
            self.player.play()
Beispiel #18
0
class VideoWindow(QMainWindow):
    def __init__(self, parent=None):
        super(VideoWindow, self).__init__(parent)

        self.readConfig()

        self.setWindowTitle("Endless Reddit Player")

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

        videoWidget = QVideoWidget()

        self.data = requests.get(
            f'https://www.reddit.com/r/{self.subreddit}/{self.sortby}.json?limit=100',
            headers={
                'User-agent': 'endless video bot uwu'
            }).json()

        self.playButton = QPushButton()
        self.playButton.setEnabled(False)
        self.playButton.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay))
        self.playButton.clicked.connect(self.play)

        self.skipButton = QPushButton()
        self.skipButton.setEnabled(True)
        self.skipButton.setIcon(self.style().standardIcon(
            QStyle.SP_MediaSkipForward))
        self.skipButton.clicked.connect(self.selectNewVideo)

        self.positionSlider = QSlider(Qt.Horizontal)
        self.positionSlider.setRange(0, 0)
        self.positionSlider.sliderMoved.connect(self.setPosition)

        self.errorLabel = QLabel()
        self.errorLabel.setSizePolicy(QSizePolicy.Preferred,
                                      QSizePolicy.Maximum)

        # Create new action
        openAction = QAction(QIcon('open.png'), '&Open', self)
        openAction.setShortcut('Ctrl+O')
        openAction.setStatusTip('Open movie')
        openAction.triggered.connect(self.openFile)

        # Create exit action
        exitAction = QAction(QIcon('exit.png'), '&Exit', self)
        exitAction.setShortcut('Ctrl+Q')
        exitAction.setStatusTip('Exit application')
        exitAction.triggered.connect(self.exitCall)

        # Create menu bar and add action
        menuBar = self.menuBar()
        fileMenu = menuBar.addMenu('&File')
        #fileMenu.addAction(newAction)
        fileMenu.addAction(openAction)
        fileMenu.addAction(exitAction)

        # Create a widget for window contents
        wid = QWidget(self)
        self.setCentralWidget(wid)

        # Create layouts to place inside widget
        controlLayout = QHBoxLayout()
        controlLayout.setContentsMargins(0, 0, 0, 0)
        controlLayout.addWidget(self.playButton)
        controlLayout.addWidget(self.skipButton)
        controlLayout.addWidget(self.positionSlider)

        layout = QVBoxLayout()
        layout.addWidget(videoWidget)
        layout.addLayout(controlLayout)
        layout.addWidget(self.errorLabel)

        # Set widget to contain window contents
        wid.setLayout(layout)

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

    def readConfig(self):
        with open('config.json', 'r') as file:
            config = json.load(file)
            self.subreddit = config['subreddit']
            self.sortby = config['sortby']
            self.offlineMode = config['offlineMode']

    def openFile(self):
        fileName, _ = QFileDialog.getOpenFileName(self, "Open Movie",
                                                  QDir.homePath())

        if fileName != '':
            self.mediaPlayer.setMedia(
                QMediaContent(QUrl.fromLocalFile(fileName)))
            self.playButton.setEnabled(True)

    def exitCall(self):
        sys.exit(app.exec_())

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

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

    def mediaStatusChanged(self, status):
        if self.mediaPlayer.mediaStatus() == QMediaPlayer.EndOfMedia:
            self.mediaPlayer.pause()
            self.selectNewVideo()

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

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

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

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

    def selectNewVideo(self):
        if len(self.data['data']['children']) == 0:
            if (self.data["data"]["after"]):
                self.data = requests.get(
                    f'https://www.reddit.com/r/{self.subreddit}/{self.sortby}.json?limit=100&after={self.data["data"]["after"]}',
                    headers={
                        'User-agent': 'endless video bot uwu'
                    }).json()
            else:
                self.data = requests.get(
                    f'https://www.reddit.com/r/{self.subreddit}/{self.sortby}.json?limit=100',
                    headers={
                        'User-agent': 'endless video bot uwu'
                    }).json()
        number = random.randrange(len(self.data['data']['children']))
        if self.data['data']['children'][number]['data']['is_video']:
            self.url = self.data['data']['children'][number]['data']['media'][
                'reddit_video']['fallback_url']
            print("selected next: " + self.url + ", " +
                  str(len(self.data['data']['children'])) +
                  " left before rescan.")
            self.mediaPlayer.setMedia(QMediaContent(QUrl(self.url)))
            self.playButton.setEnabled(True)
            self.mediaPlayer.play()
            del self.data['data']['children'][number]
        else:
            del self.data['data']['children'][number]
            self.selectNewVideo()
Beispiel #19
0
class Music(QtWidgets.QMainWindow):
    def __init__(self):
        super().__init__()
        self.setFixedSize(400,200)
        self.setWindowTitle("🎧+📚=😊")
        self.setWindowOpacity(0.8)

        self.init_ui()
        self.custom_style()
        self.play_status = False # 播放状态初始化为否
        self.player = QMediaPlayer(self)

        self.timer = QtCore.QTimer()
        self.timer.setInterval(1000)
        self.timer.start()
        self.timer.timeout.connect(self.check_music_status)


    # 设置样式
    def custom_style(self):
        self.setStyleSheet('''
            #main_widget{
                border-radius:5px;
                background:black;
            }
            #play_btn,#pervious_btn,#next_btn{
                border:none;
            }
            #play_btn:hover,#pervious_btn:hover,#next_btn:hover{
                background:	#696969;
                border-radius:5px;
                cursor:pointer;
            }
        ''')
        self.close_btn.setStyleSheet('''
            QPushButton{
                background:#F76677;
                border-radius:5px;
                }
            QPushButton:hover{
                background:red;
                }''')
        self.status_label.setStyleSheet('''
            QLabel{
                background:#FFD85A;
                border-radius:5px;
                }
        ''')

    def init_ui(self):
        # 窗口布局

        self.main_widget = QtWidgets.QWidget()
        self.main_widget.setObjectName("main_widget")
        self.main_layout = QtWidgets.QGridLayout()
        self.main_widget.setLayout(self.main_layout)

        # 标题 半成,接口部分未找到适合的
        '''
        slogan=requests.get('https://api.xygeng.cn/one').json()['data']['content']
        self.title_lable = QtWidgets.QLabel(slogan)
        self.title_lable.setFont(font)
       '''
        self.title_lable = QtWidgets.QLabel('🌥WindPlayer')
        self.title_lable.setStyleSheet('''
        QLabel{
                color:"gray";
                }
        ''')
        self.title_lable.setFont(font)
        self.title_lable.setAlignment(QtCore.Qt.AlignCenter)
        # 关闭按钮
        self.close_btn = QtWidgets.QPushButton("")  # 关闭按钮
        self.close_btn.clicked.connect(self.close_btn_event)
        self.close_btn.setFixedSize(15,15)

        # 音乐状态按钮
        self.status_label = QtWidgets.QLabel("")
        # self.swith_btn.clicked.connect(self.swith_background) #此处还未完成 Darkmode 和 LightMode 的切换
        self.status_label.setFixedSize(15,15)

        # 播放按钮
        play_icon = qta.icon("fa.play-circle-o",)
        self.play_btn = QtWidgets.QPushButton(play_icon,"")
        self.play_btn.setIconSize(QtCore.QSize(80, 80))
        self.play_btn.setFixedSize(82,82)
        self.play_btn.setObjectName("play_btn")
        self.play_btn.clicked.connect(self.play_music)
        self.play_btn.setStyleSheet('''
                    QPushButton{
                        background:black;
                        border-radius:5px;
                        }
                    QPushButton:hover{
                        background:	#696969;
                        }''')


        # 下一首按钮
        next_icon = qta.icon("fa.chevron-right")
        self.next_btn = QtWidgets.QPushButton(next_icon,"")
        self.next_btn.setIconSize(QtCore.QSize(80,80))
        self.next_btn.setFixedSize(82,82)
        self.next_btn.setObjectName("next_btn")
        self.next_btn.clicked.connect(self.next_music)
        self.next_btn.setStyleSheet('''
            QPushButton{
                background:black;
                border-radius:5px;
                }
            QPushButton:hover{
                background:	#696969;
                }''')

        # 进度条
        self.process_bar = QtWidgets.QProgressBar()
        self.process_value = 0
        self.process_bar.setValue(self.process_value)
        self.process_bar.setFixedHeight(5)
        self.process_bar.setTextVisible(False)
        self.process_bar.setStyleSheet('''QProgressBar {   border: 2px solid grey;   border-radius: 5px;   background-color: #FFFFFF;}QProgressBar::chunk {   background-color: #05B8CC;   width: 28px;}QProgressBar {   border: 2px solid grey;   border-radius: 5px;   text-align: center;}
        ''')

        self.main_layout.addWidget(self.close_btn,0,0,1,1)
        self.main_layout.addWidget(self.title_lable,0,1,1,1)
        self.main_layout.addWidget(self.status_label,1,0,1,1)
        self.main_layout.addWidget(self.play_btn, 1, 1, 1, 1)
        self.main_layout.addWidget(self.next_btn, 1, 2, 1, 1)
        self.main_layout.addWidget(self.process_bar,2,0,1,3)

        self.setCentralWidget(self.main_widget)
        self.setWindowFlag(QtCore.Qt.FramelessWindowHint)  # 隐藏边框

    # 关闭程序
    def close_btn_event(self):
        self.close()
    # 夜间模式切换 (未完成 )
    def swich_background(self):
        self.main_widget.setStyleSheet('''
        QWidget{
        "background-color: black"}
        ''')
    # 鼠标长按事件
    def mousePressEvent(self, event):
        if event.button() == QtCore.Qt.LeftButton:
            self.m_drag = True
            self.m_DragPosition = event.globalPos() - self.pos()
            event.accept()
            self.setCursor(QtGui.QCursor(QtCore.Qt.OpenHandCursor))

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

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

    # 播放音乐
    def play_music(self):
        try:
            # 播放音乐
            if self.play_status is False:
                self.play_status = True # 设置播放状态为是
                self.play_btn.setIcon(qta.icon("fa.pause-circle")) # 设置播放图标
                player_status = self.player.mediaStatus() # 获取播放器状态
                # print("当前播放状态:",player_status)
                if player_status == 6:
                    # 设置状态标签为绿色
                    self.status_label.setStyleSheet('''QLabel{background:#72EA72;border-radius:5px;}''')
                    self.player.play()
                else:
                    self.next_music()
            # 暂停音乐
            else:
                # 设置状态为蓝色
                self.status_label.setStyleSheet('''QLabel{background:#0099CC;border-radius:5px;}''')
                self.play_status = False
                self.play_btn.setIcon(qta.icon("fa.play-circle"))
                self.player.pause()
        except Exception as e:
            print(repr(e))

    # 下一首音乐
    def next_music(self):
        try:
            # 设置状态为黄色
            self.status_label.setStyleSheet('''
                QLabel{
                    background:#FFBF00;
                    border-radius:5px;
                    }
            ''')
            self.play_status = True # 设置播放状态为是
            self.play_btn.setIcon(qta.icon("fa.pause-circle")) # 修改播放图标
            self.process_value = 0 # 重置进度值

            # 获取网络歌曲
            self.get_music_thread = GetMusicThread()
            self.get_music_thread.finished_signal.connect(self.init_player)
            self.get_music_thread.start()
        except Exception as e:
            print(traceback.print_exc())

    # 设置播放器
    def init_player(self,url):
        # print("获取到音乐链接:",url)
        content = QMediaContent(QtCore.QUrl(url))
        self.player.setMedia(content)
        self.player.setVolume(50)
        self.player.play()
        self.duration = self.player.duration()  # 音乐的时长
        # 设置状态为绿色
        self.status_label.setStyleSheet('''
            QLabel{
                background:#72EA72;
                border-radius:5px;
                }
        ''')

        # 进度条计时器
        self.process_timer = QtCore.QTimer()
        self.process_timer.setInterval(1000)
        self.process_timer.start()
        self.process_timer.timeout.connect(self.process_timer_status)


    # 定时器
    def check_music_status(self):
        player_status = self.player.mediaStatus()
        player_duration = self.player.duration()
        # print("音乐时间:",player_duration)
        # print("当前播放器状态",player_status)
        if player_status == 7:
            self.next_music()

        if player_duration > 0:
            self.duration = player_duration

    # 进度条定时器
    def process_timer_status(self):
        try:
            if self.play_status is True:
                self.process_value +=float(100 / (self.duration/1000))
                #print("当前进度:",self.process_value)
                self.process_bar.setValue(self.process_value)
        except Exception as e:
            print('')
Beispiel #20
0
class MainWindowMusicPlayer(QMainWindow):
    stopState: bool

    def __init__(self):
        super().__init__()
        self.currentPlaylist = QMediaPlaylist()
        self.player = QMediaPlayer()
        self.userAction = -1  # 0 - stopped, 1 - playing 2 - paused
        self.player.mediaStatusChanged.connect(self.qmp_media_status_changed)
        self.player.stateChanged.connect(self.qmp_state_changed)
        self.player.positionChanged.connect(self.qmp_position_changed)
        self.player.volumeChanged.connect(self.qmp_volume_changed)
        self.player.setVolume(60)
        # Status bar
        self.statusBar().showMessage('No Media'
                                     ' :: %d' % self.player.volume())
        self.home_screen()

    def home_screen(self):
        self.setWindowTitle('Music Player')

        self.create_menubar()

        self.create_toolbar()

        controlBar = self.add_controls()

        # need to add both information screen
        # and control bar to the central widget.
        centralWidget = QWidget()
        centralWidget.setLayout(controlBar)
        self.setCentralWidget(centralWidget)

        # Set size of the MainWindow
        self.resize(200, 100)

        self.show()

    def create_menubar(self):
        menubar = self.menuBar()
        file_menu = menubar.addMenu('File')
        file_menu.addAction(self.file_open())
        file_menu.addAction(self.song_info())
        file_menu.addAction(self.folder_open())
        file_menu.addAction(self.exit_action())

    def create_toolbar(self):
        pass

    def add_controls(self):
        controlArea = QVBoxLayout()
        seekSliderLayout = QHBoxLayout()
        controls = QHBoxLayout()
        playlistCtrlLayout = QHBoxLayout()

        # creating buttons
        playBtn = QPushButton('Play')  # play button
        pauseBtn = QPushButton('Pause')  # pause button
        stopBtn = QPushButton('Stop')  # stop button
        volumeDescBtn = QPushButton('V (-)')  # Decrease Volume
        volumeIncBtn = QPushButton('V (+)')  # Increase Volume

        # creating playlist controls
        prevBtn = QPushButton('Prev Song')
        nextBtn = QPushButton('Next Song')

        # creating seek slider
        seekSlider = QSlider()
        seekSlider.setMinimum(0)
        seekSlider.setMaximum(100)
        seekSlider.setOrientation(Qt.Horizontal)
        seekSlider.setTracking(False)
        seekSlider.sliderMoved.connect(self.seek_position)
        # seekSlider.valueChanged.connect(self.seekPosition)

        seekSliderLabel1 = QLabel('0.00')
        seekSliderLabel2 = QLabel('0.00')
        seekSliderLayout.addWidget(seekSliderLabel1)
        seekSliderLayout.addWidget(seekSlider)
        seekSliderLayout.addWidget(seekSliderLabel2)

        # Add handler for each button. Not using the default slots.
        playBtn.clicked.connect(self.play_handler)
        pauseBtn.clicked.connect(self.pause_handler)
        stopBtn.clicked.connect(self.stop_handler)
        volumeDescBtn.clicked.connect(self.decrease_volume)
        volumeIncBtn.clicked.connect(self.increase_volume)

        # Adding to the horizontal layout
        controls.addWidget(volumeDescBtn)
        controls.addWidget(playBtn)
        controls.addWidget(pauseBtn)
        controls.addWidget(stopBtn)
        controls.addWidget(volumeIncBtn)

        # playlist control button handlers
        prevBtn.clicked.connect(self.prev_item_playlist)
        nextBtn.clicked.connect(self.next_item_playlist)
        playlistCtrlLayout.addWidget(prevBtn)
        playlistCtrlLayout.addWidget(nextBtn)

        # Adding to the vertical layout
        controlArea.addLayout(seekSliderLayout)
        controlArea.addLayout(controls)
        controlArea.addLayout(playlistCtrlLayout)
        return controlArea

    # Music playback function
    def play_handler(self):
        self.userAction = 1
        self.statusBar().showMessage('Playing at Volume %d' %
                                     self.player.volume())
        if self.player.state() == QMediaPlayer.StoppedState:
            if self.player.mediaStatus() == QMediaPlayer.NoMedia:
                print(self.currentPlaylist.mediaCount())
                if self.currentPlaylist.mediaCount() == 0:
                    self.open_file()
                if self.currentPlaylist.mediaCount() != 0:
                    self.player.setPlaylist(self.currentPlaylist)
            elif self.player.mediaStatus() ==\
                    QMediaPlayer.LoadedMedia:
                self.player.play()
            elif self.player.mediaStatus() ==\
                    QMediaPlayer.BufferedMedia:
                self.player.play()
        elif self.player.state() == QMediaPlayer.PlayingState:
            pass
        elif self.player.state() == QMediaPlayer.PausedState:
            self.player.play()

    # Music pause function
    def pause_handler(self):
        self.userAction = 2
        self.statusBar().showMessage(
            'Paused %s at position'
            ' %s at Volume %d' %
            (self.player.metaData(QMediaMetaData.Title),
             self.centralWidget().layout().itemAt(0).layout().itemAt(
                 0).widget().text(), self.player.volume()))
        self.player.pause()

    # Music stop function
    def stop_handler(self):
        self.userAction = 0
        self.statusBar().showMessage('Stopped at Volume %d' %
                                     (self.player.volume()))
        if self.player.state() == QMediaPlayer.PlayingState:
            self.stopState = True
            self.player.stop()
        elif self.player.state() == QMediaPlayer.PausedState:
            self.player.stop()
        elif self.player.state() == QMediaPlayer.StoppedState:
            pass

    # Music status change function
    def qmp_media_status_changed(self):
        if self.player.mediaStatus() == QMediaPlayer.LoadedMedia \
                and self.userAction == 1:
            durationT = self.player.duration()
            self.centralWidget().layout().itemAt(0).layout() \
                .itemAt(1).widget().setRange(0, durationT)
            self.centralWidget().layout().itemAt(0).layout() \
                .itemAt(2).widget().setText(
                '%d:%02d' % (int(durationT / 60000),
                             int((durationT / 1000) % 60)))
            self.player.play()

    # Music playing change function
    def qmp_state_changed(self):
        if self.player.state() == QMediaPlayer.StoppedState:
            self.player.stop()

    # Music time change function
    def qmp_position_changed(self, position, senderType=False):
        sliderLayout = self.centralWidget().layout().itemAt(0)\
            .layout()
        if not senderType:
            sliderLayout.itemAt(1).widget().setValue(position)
        # update the text label
        sliderLayout.itemAt(0).widget()\
            .setText('%d:%02d' %
                     (int(position / 60000),
                      int((position / 1000) % 60)))

    def seek_position(self, position):
        sender = self.sender()
        if isinstance(sender, QSlider):
            if self.player.isSeekable():
                self.player.setPosition(position)

    # Music volume change function
    def qmp_volume_changed(self):
        msg = self.statusBar().currentMessage()
        msg = msg[:-2] + str(self.player.volume())
        self.statusBar().showMessage(msg)

    # Music volume + change function
    def increase_volume(self):
        vol = self.player.volume()
        vol = min(vol + 5, 100)
        self.player.setVolume(vol)

    # Music volume - change function
    def decrease_volume(self):
        vol = self.player.volume()
        vol = max(vol - 5, 0)
        self.player.setVolume(vol)

    # File open function
    def file_open(self):
        fileAc = QAction(QIcon('icons\\open.png'), 'Open File', self)
        fileAc.setShortcut('Ctrl+O')
        fileAc.setStatusTip('Open File')
        fileAc.triggered.connect(self.open_file)
        return fileAc

    # File opening function
    def open_file(self):
        file_Chosen = QFileDialog.getOpenFileUrl(self, 'Open Music File',
                                                 expanduser('~'),
                                                 'Audio (*.mp3 *.ogg *.wav)',
                                                 '*.mp3 *.ogg *.wav')
        if file_Chosen is not None:
            self.currentPlaylist.addMedia(QMediaContent(file_Chosen[0]))

    # Folder open function
    def folder_open(self):
        folderAc = QAction(QIcon('icons\\open_fld.png'), 'Open Folder', self)
        folderAc.setShortcut('Ctrl+D')
        folderAc.setStatusTip('Open Folder '
                              '(Will add all the files in'
                              ' the folder)')
        folderAc.triggered.connect(self.add_files)
        return folderAc

    # Folder opening function
    def add_files(self):
        folder_Chosen = QFileDialog\
            .getExistingDirectory(self,
                                  'Open Music Folder',
                                  expanduser('~'))
        if folder_Chosen is not None:
            it = QDirIterator(folder_Chosen)
            it.next()
            while it.hasNext():
                if it.fileInfo().isDir() == False\
                        and it.filePath() != '.':
                    fInfo = it.fileInfo()
                    print(it.filePath(), fInfo.suffix())
                    if fInfo.suffix() in ('mp3', 'ogg', 'wav'):
                        print('added file ', fInfo.fileName())
                        self.currentPlaylist. \
                            addMedia(QMediaContent(
                            QUrl.fromLocalFile(it.filePath())))
                it.next()

    # Song information function
    def song_info(self):
        infoAc = QAction(QIcon('icons\\info.png'), 'Info', self)
        infoAc.setShortcut('Ctrl+I')
        infoAc.setStatusTip('Displays Current Song Information')
        infoAc.triggered.connect(self.display_song_info)
        return infoAc

    # Show song information
    def display_song_info(self):
        metaDataKeyList = self.player.availableMetaData()
        fullText = '<table class="tftable" border="0">'
        for key in metaDataKeyList:
            value = self.player.metaData(key)
            fullText = \
                fullText + '<tr><td>' + key + '</td><td>' + \
                str(value) + '</td></tr>'
        fullText = fullText + '</table>'
        infoBox = QMessageBox(self)
        infoBox.setWindowTitle('Detailed Song Information')
        infoBox.setTextFormat(Qt.RichText)
        infoBox.setText(fullText)
        infoBox.addButton('OK', QMessageBox.AcceptRole)
        infoBox.show()

    # Switch to previous song
    def prev_item_playlist(self):
        self.player.playlist().previous()

    # Switch to next song
    def next_item_playlist(self):
        self.player.playlist().next()

    # exit function
    def exit_action(self):
        exitAc = QAction(QIcon('icons\\exit.png'), '&Exit', self)
        exitAc.setShortcut('Ctrl+Q')
        exitAc.setStatusTip('Exit App')
        exitAc.triggered.connect(self.close)
        return exitAc

    # exiting function
    @staticmethod
    def exit():
        sys.exit(app.exec_())
Beispiel #21
0
class MainWindowAction(QMainWindow, Ui_MainWindow):
    def __init__(self, parent=None):
        super(MainWindowAction, self).__init__(parent)

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

        self.local_music_path = []

        self.setupUi(self)
        self.init()
        self.show()

    def init(self):
        # self.setWindowFlags(Qt.FramelessWindowHint)

        self.loadParams()

        self.playlist.setPlaybackMode(self.playlist.Loop)

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

        exit_normal_icon_path = QUrl.fromLocalFile(EXIT_ICON_PATH)
        self.exit_normal_icon = QIcon(EXIT_ICON_PATH)

        self.exitButton.setStyleSheet(EXIT_BUTTON_STYLE)

        self.exitButton.clicked.connect(self.close)
        self.minButton.clicked.connect(self.showMinimized)
        # self.playButton.clicked.connect(self.playControl)

        self.nextButton.clicked.connect(self.playlist.next)
        self.prevButton.clicked.connect(self.playlist.previous)
        self.playButton.clicked.connect(self.controlPlay)

        self.player.currentMediaChanged.connect(self.initProgressBar)
        self.player.stateChanged.connect(self.changePlayState)
        self.player.positionChanged.connect(self.changeBar)

        self.playProgressBar.sliderReleased.connect(self.changePlayPosition)

    def loadParams(self):
        with open(CONFIG_PATH, 'r') as file:
            params = json.load(file)

            self.local_music_dirs = params['initParams']['LocalMusicDirs']
            last_playlist = params['lastPlayParams']['Playlist']

            self.initPlayList(last_playlist)

    def initPlayList(self, playlist_name):
        playlist_path = './PlayList/' + playlist_name + '.json'
        with open(playlist_path, 'r', encoding='UTF-8') as file:
            music_list = json.load(file)
            music_path_list = music_list['Songs']

        for music_path in music_path_list:
            path = QUrl.fromLocalFile(music_path)
            music = QMediaContent(path)
            self.playlist.addMedia(music)

    def controlPlay(self):
        if self.player.state() == self.player.PlayingState:
            self.player.pause()
            # self.playButton.setText("Play")
        elif self.player.state() == self.player.PausedState:
            self.player.play()
        elif self.player.state() == self.player.StoppedState:
            if self.player.mediaStatus() in [
                    self.player.LoadingMedia, self.player.LoadedMedia,
                    self.player.BufferedMedia, self.player.BufferingMedia
            ]:
                self.player.play()

    def changePlayState(self):
        if self.player.state() == self.player.PlayingState:
            self.playButton.setText("Pause")
        else:
            self.playButton.setText("Play")

    def initProgressBar(self):
        print(self.playlist.currentMedia().resources()[0].url().fileName())
        self.playProgressBar.setValue(0)

    def changeBar(self):

        if self.player.state() == self.player.PlayingState:
            duration = self.player.duration()
            if duration > 0:
                value = self.player.position() * 100 // duration
                self.playProgressBar.setValue(value)

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

        duration = self.player.duration()
        value = self.playProgressBar.value() * duration // 100

        self.player.setPosition(value)

        self.player.play()
Beispiel #22
0
class YtdlMusic(QMainWindow, Ui_MainWindow):
    def __init__(self, *args, **kwargs):
        QMainWindow.__init__(self, *args, **kwargs)
        self.setupUi(self)
        self.setWindowIcon(QIcon(LOCAL_DIR + '/ytdl_music.svg'))

        self.player = QMediaPlayer()
        self.player.isSeekable()
        self.playList = QMediaPlaylist()
        self.playListData = []
        self.player.setPlaylist(self.playList)
        self.currentPos = 0
        self.currentTrackDuration = '0:00:00'

        self.player.positionChanged.connect(self.positionChanged)
        self.player.durationChanged.connect(self.durationChanged)
        self.playList.currentIndexChanged.connect(self.playlistPosChanged)
        self.playlistTable.itemDoubleClicked.connect(self.changeTrack)
        self.playlistTable.itemSelectionChanged.connect(self.selectedTracks)
        # self.timeSlider.valueChanged.connect(self.setPosition)
        self.addBtn.clicked.connect(self.addDialog)
        self.removeBtn.clicked.connect(self.delTracks)
        self.playBtn.clicked.connect(self.playPause)
        self.stopBtn.clicked.connect(self.stop)
        self.prevBtn.clicked.connect(self.playList.previous)
        self.nextBtn.clicked.connect(self.playList.next)

        self.playlistTable.setHorizontalHeaderLabels([
            '',
            _translate('MainWindow', 'Channel'),
            _translate('MainWindow', 'Title')
        ])
        header = self.playlistTable.horizontalHeader()
        header.setSectionResizeMode(1, QHeaderView.Stretch)
        header.setSectionResizeMode(2, QHeaderView.Stretch)

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

    def durationChanged(self, duration):
        total_time = '0:00:00'
        duration = self.player.duration()
        total_time = ms_to_time(duration)
        # self.timeSlider.setMaximum(duration)
        self.currentTrackDuration = duration
        # self.totalTimeLabel.setText(total_time)
        self.currentTrackDuration = total_time

    def mediaStatusChanged(self, status):
        icon = QIcon.fromTheme("media-playback-pause")
        if self.player.state() == QMediaPlayer.StoppedState:
            icon = QIcon.fromTheme("media-playback-start")
        elif self.player.state() == QMediaPlayer.PausedState:
            icon = QIcon.fromTheme("media-playback-start")

        self.playBtn.setIcon(icon)

    def positionChanged(self, position, senderType=False):
        self.currentTime = position
        current_time = '0:00:00'

        if position != -1:
            current_time = ms_to_time(position)
            self.timeLabel.setText('{0} / {1}'.format(
                current_time, self.currentTrackDuration))
        '''self.timeSlider.blockSignals(True)
        self.timeSlider.setValue(position)
        self.timeSlider.blockSignals(False)'''

    def playlistPosChanged(self):
        pos = self.playList.currentIndex()
        data = self.playListData[pos]
        self.setWindowTitle('YouTube-dl Music: ' + data['title'])
        duration = ms_to_time(data['duration'] * 1000)
        self.timeLabel.setText('0:00:00 / {0}'.format(duration))
        # self.totalTimeLabel.setText(ms_to_time(data['duration'] * 1000))
        if self.playList.mediaCount() > 1:
            if pos < self.playList.mediaCount() - 1:
                self.nextBtn.setEnabled(True)
            else:
                self.nextBtn.setEnabled(False)

            if pos > 0:
                self.prevBtn.setEnabled(True)
            else:
                self.prevBtn.setEnabled(False)

            prevPos = 0
            if pos < self.playList.mediaCount():
                if self.currentPos < pos:
                    prevPos = pos - 1
                else:
                    prevPos = pos + 1

                statusItem = QLabel()
                icon = QIcon.fromTheme("media-playback-start")
                statusItem.setPixmap(icon.pixmap(16, 16))
                statusItem.setAlignment(Qt.AlignCenter)
                self.playlistTable.setCellWidget(pos, 0, statusItem)
                if prevPos > -1:
                    self.playlistTable.setCellWidget(prevPos, 0, QLabel())
            else:
                self.playlistTable.setItem(pos, 0, QTableWidgetItem(''))

            self.currentPos = pos

        else:
            statusItem = QLabel()
            icon = QIcon.fromTheme("media-playback-start")
            statusItem.setPixmap(icon.pixmap(16, 16))
            statusItem.setAlignment(Qt.AlignCenter)
            self.playlistTable.setCellWidget(pos, 0, statusItem)

    def playPause(self):
        icon = QIcon.fromTheme("media-playback-pause")

        if self.player.state() == QMediaPlayer.StoppedState:
            if self.player.mediaStatus() == QMediaPlayer.NoMedia:
                if self.playList.mediaCount() != 0:
                    self.player.play()
            elif self.player.mediaStatus() == QMediaPlayer.LoadedMedia:
                self.playList.setCurrentIndex(self.currentPos)
                self.player.play()
            elif self.player.mediaStatus() == QMediaPlayer.BufferedMedia:
                self.player.play()
        elif self.player.state() == QMediaPlayer.PlayingState:
            icon = QIcon.fromTheme("media-playback-start")
            self.player.pause()
        elif self.player.state() == QMediaPlayer.PausedState:
            self.player.play()

        self.playBtn.setIcon(icon)

    def stop(self):
        self.player.stop()
        icon = QIcon.fromTheme("media-playback-start")
        self.playBtn.setIcon(icon)

    def insertTrack(self, data):
        if data:
            self.playListData.append(data)
            totalTracks = self.playList.mediaCount()
            pos = totalTracks
            self.playlistTable.insertRow(totalTracks)
            self.playlistTable.setRowCount(totalTracks + 1)
            self.playlistTable.setItem(pos, 0, QTableWidgetItem(''))
            self.playlistTable.setItem(pos, 1,
                                       QTableWidgetItem(data['channel']))
            self.playlistTable.setItem(pos, 2, QTableWidgetItem(data['title']))
            media = QMediaContent(QUrl(data['url']))
            self.playList.addMedia(media)
            if totalTracks > 1:
                self.nextBtn.setEnabled(True)
        else:
            self.statusBar().showMessage('Total pistas: {0}'.format(
                self.playList.mediaCount()))

    def addDialog(self):
        url, ok = QInputDialog.getText(
            self, _translate('MainWindow', 'Add video/playlist'), 'URL:')
        if ok and url != '':
            self.addPCThread = addVideos(self, url)
            self.addPCThread.video.connect(self.insertTrack)
            self.addPCThread.start()

    def changeTrack(self, item):
        pos = item.row()
        self.playlistTable.setCellWidget(self.currentPos, 0, QLabel())
        self.playList.setCurrentIndex(pos)
        if self.player.state() == QMediaPlayer.StoppedState:
            icon = QIcon.fromTheme("media-playback-pause")
            self.playBtn.setIcon(icon)
            self.player.play()

    def delTracks(self):
        indexes = self.playlistTable.selectionModel().selectedRows()
        del_first = True
        for index in sorted(indexes):
            pos = index.row()
            if not del_first:
                pos -= 1
            else:
                del_first = False

            self.playlistTable.removeRow(pos)
            self.playListData.pop(pos)
            self.playList.removeMedia(pos)

        self.playlistPosChanged()

    def selectedTracks(self):
        totalSelected = len(self.playlistTable.selectedItems())
        if totalSelected > 0:
            self.removeBtn.setEnabled(True)
        else:
            self.removeBtn.setEnabled(False)
Beispiel #23
0
class VideoPlayer(QWidget):
    def __init__(self, aPath, parent=None):
        super(VideoPlayer, self).__init__(parent)

        self.setAttribute(Qt.WA_NoSystemBackground, True)
        self.setAcceptDrops(True)
        self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.StreamPlayback)
        self.mediaPlayer.mediaStatusChanged.connect(self.printMediaData)
        self.mediaPlayer.setVolume(80)
        self.videoWidget = QVideoWidget(self)

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

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

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

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

        self.clip = QApplication.clipboard()
        self.process = QProcess(self)
        self.process.readyRead.connect(self.dataReady)
        #        self.process.started.connect(lambda: print("grabbing YouTube URL"))
        self.process.finished.connect(self.playFromURL)

        self.myurl = ""

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

        layout = QVBoxLayout()
        layout.setContentsMargins(0, 0, 0, 0)
        layout.addWidget(self.videoWidget)
        layout.addLayout(controlLayout)

        self.setLayout(layout)

        self.myinfo = "©2016\nAxel Schneider\n\nMouse Wheel = Zoom\nUP = Volume Up\nDOWN = Volume Down\n" + \
            "LEFT = < 1 Minute\nRIGHT = > 1 Minute\n" + \
                "SHIFT+LEFT = < 10 Minutes\nSHIFT+RIGHT = > 10 Minutes"

        self.widescreen = True

        #### shortcuts ####
        self.shortcut = QShortcut(QKeySequence("q"), self)
        self.shortcut.activated.connect(self.handleQuit)
        self.shortcut = QShortcut(QKeySequence("u"), self)
        self.shortcut.activated.connect(self.playFromURL)

        self.shortcut = QShortcut(QKeySequence("y"), self)
        self.shortcut.activated.connect(self.getYTUrl)

        self.shortcut = QShortcut(QKeySequence("o"), self)
        self.shortcut.activated.connect(self.openFile)
        self.shortcut = QShortcut(QKeySequence(" "), self)
        self.shortcut.activated.connect(self.play)
        self.shortcut = QShortcut(QKeySequence("f"), self)
        self.shortcut.activated.connect(self.handleFullscreen)
        self.shortcut = QShortcut(QKeySequence("i"), self)
        self.shortcut.activated.connect(self.handleInfo)
        self.shortcut = QShortcut(QKeySequence("s"), self)
        self.shortcut.activated.connect(self.toggleSlider)
        self.shortcut = QShortcut(QKeySequence(Qt.Key_Right), self)
        self.shortcut.activated.connect(self.forwardSlider)
        self.shortcut = QShortcut(QKeySequence(Qt.Key_Left), self)
        self.shortcut.activated.connect(self.backSlider)
        self.shortcut = QShortcut(QKeySequence(Qt.Key_Up), self)
        self.shortcut.activated.connect(self.volumeUp)
        self.shortcut = QShortcut(QKeySequence(Qt.Key_Down), self)
        self.shortcut.activated.connect(self.volumeDown)
        self.shortcut = QShortcut(
            QKeySequence(Qt.ShiftModifier + Qt.Key_Right), self)
        self.shortcut.activated.connect(self.forwardSlider10)
        self.shortcut = QShortcut(QKeySequence(Qt.ShiftModifier + Qt.Key_Left),
                                  self)
        self.shortcut.activated.connect(self.backSlider10)

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

        print("QT5 Player started")
        self.suspend_screensaver()
        #        msg = QMessageBox.information(self, "Qt5Player", "press o to open file")
        self.loadFilm("/home/brian/Dokumente/Qt5PlayerIntro.m4v")

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

    def getYTUrl(self):
        cmd = "youtube-dl -g -f best " + self.clip.text()
        print("grabbing YouTube URL")
        self.process.start(cmd)

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

    def suspend_screensaver(self):
        'suspend linux screensaver'
        proc = subprocess.Popen(
            'gsettings set org.gnome.desktop.screensaver idle-activation-enabled false',
            shell=True)
        proc.wait()

    def resume_screensaver(self):
        'resume linux screensaver'
        proc = subprocess.Popen(
            'gsettings set org.gnome.desktop.screensaver idle-activation-enabled true',
            shell=True)
        proc.wait()

    def openFile(self):
        fileName, _ = QFileDialog.getOpenFileName(
            self, "Open Movie",
            QDir.homePath() + "/Videos",
            "Media (*.webm *.mp4 *.ts *.avi *.mpeg *.mpg *.mkv *.VOB *.m4v *.3gp *.mp3 *.m4a *.wav *.ogg *.flac *.m3u *.m3u8)"
        )

        if fileName != '':
            self.loadFilm(fileName)
            print("File loaded")

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

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

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

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

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

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

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

    def contextMenuRequested(self, point):
        menu = QMenu()
        actionFile = menu.addAction(QIcon.fromTheme("video-x-generic"),
                                    "open File (o)")
        actionclipboard = menu.addSeparator()
        actionURL = menu.addAction(QIcon.fromTheme("browser"),
                                   "URL from Clipboard (u)")
        actionclipboard = menu.addSeparator()
        actionYTurl = menu.addAction(QIcon.fromTheme("youtube"),
                                     "URL from YouTube (y)")
        actionclipboard = menu.addSeparator()
        actionToggle = menu.addAction(QIcon.fromTheme("next"),
                                      "show / hide Slider (s)")
        actionFull = menu.addAction(QIcon.fromTheme("view-fullscreen"),
                                    "Fullscreen (f)")
        action169 = menu.addAction(QIcon.fromTheme("tv-symbolic"), "16 : 9")
        action43 = menu.addAction(QIcon.fromTheme("tv-symbolic"), "4 : 3")
        actionSep = menu.addSeparator()
        actionInfo = menu.addAction(QIcon.fromTheme("help-about"), "Info (i)")
        action5 = menu.addSeparator()
        actionQuit = menu.addAction(QIcon.fromTheme("application-exit"),
                                    "Exit (q)")

        actionFile.triggered.connect(self.openFile)
        actionQuit.triggered.connect(self.handleQuit)
        actionFull.triggered.connect(self.handleFullscreen)
        actionInfo.triggered.connect(self.handleInfo)
        actionToggle.triggered.connect(self.toggleSlider)
        actionURL.triggered.connect(self.playFromURL)
        actionYTurl.triggered.connect(self.getYTUrl)
        action169.triggered.connect(self.screen169)
        action43.triggered.connect(self.screen43)
        menu.exec_(self.mapToGlobal(point))

    def wheelEvent(self, event):
        mwidth = self.frameGeometry().width()
        mheight = self.frameGeometry().height()
        mleft = self.frameGeometry().left()
        mtop = self.frameGeometry().top()
        mscale = event.angleDelta().y() / 5
        if self.widescreen == True:
            self.setGeometry(mleft, mtop, mwidth + mscale,
                             (mwidth + mscale) / 1.778)
        else:
            self.setGeometry(mleft, mtop, mwidth + mscale,
                             (mwidth + mscale) / 1.33)

    def screen169(self):
        self.widescreen = True
        mwidth = self.frameGeometry().width()
        mheight = self.frameGeometry().height()
        mleft = self.frameGeometry().left()
        mtop = self.frameGeometry().top()
        mratio = 1.778
        self.setGeometry(mleft, mtop, mwidth, mwidth / mratio)

    def screen43(self):
        self.widescreen = False
        mwidth = self.frameGeometry().width()
        mheight = self.frameGeometry().height()
        mleft = self.frameGeometry().left()
        mtop = self.frameGeometry().top()
        mratio = 1.33
        self.setGeometry(mleft, mtop, mwidth, mwidth / mratio)

    def handleFullscreen(self):
        if self.windowState() & Qt.WindowFullScreen:
            QApplication.setOverrideCursor(Qt.ArrowCursor)
            self.showNormal()
            print("no Fullscreen")
        else:
            self.showFullScreen()
            QApplication.setOverrideCursor(Qt.BlankCursor)
            print("Fullscreen entered")

    def handleInfo(self):
        msg = QMessageBox.about(self, "QT5 Player", self.myinfo)

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

    def hideSlider(self):
        self.playButton.hide()
        self.lbl.hide()
        self.positionSlider.hide()
        self.elbl.hide()
        mwidth = self.frameGeometry().width()
        mheight = self.frameGeometry().height()
        mleft = self.frameGeometry().left()
        mtop = self.frameGeometry().top()
        if self.widescreen == True:
            self.setGeometry(mleft, mtop, mwidth, mwidth / 1.778)
        else:
            self.setGeometry(mleft, mtop, mwidth, mwidth / 1.33)

    def showSlider(self):
        self.playButton.show()
        self.lbl.show()
        self.positionSlider.show()
        self.elbl.show()
        mwidth = self.frameGeometry().width()
        mheight = self.frameGeometry().height()
        mleft = self.frameGeometry().left()
        mtop = self.frameGeometry().top()
        if self.widescreen == True:
            self.setGeometry(mleft, mtop, mwidth, mwidth / 1.55)
        else:
            self.setGeometry(mleft, mtop, mwidth, mwidth / 1.33)

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

    def forwardSlider10(self):
        self.mediaPlayer.setPosition(self.mediaPlayer.position() + 10000 * 60)

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

    def backSlider10(self):
        self.mediaPlayer.setPosition(self.mediaPlayer.position() - 10000 * 60)

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

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

    def mouseMoveEvent(self, event):
        if event.buttons() == Qt.LeftButton:
            self.move(event.globalPos() \
                      - QPoint(self.frameGeometry().width() / 2, \
                                 self.frameGeometry().height() / 2))
            event.accept()

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

    def dropEvent(self, event):
        if event.mimeData().hasUrls():
            url = event.mimeData().urls()[0].toString()
            print("url = ", url)
            self.mediaPlayer.stop()
            self.mediaPlayer.setMedia(QMediaContent(QUrl(url)))
            self.playButton.setEnabled(True)
            self.mediaPlayer.play()
        elif event.mimeData().hasText():
            mydrop = event.mimeData().text()
            ### YouTube url
            if "youtube" in mydrop:
                print("is YouTube", mydrop)
                self.clip.setText(mydrop)
                self.getYTUrl()
            else:
                ### normal url
                print("generic url = ", mydrop)
                self.mediaPlayer.setMedia(QMediaContent(QUrl(mydrop)))
                self.playButton.setEnabled(True)
                self.mediaPlayer.play()
                self.hideSlider()

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

    def printMediaData(self):
        if self.mediaPlayer.mediaStatus() == 6:
            if self.mediaPlayer.isMetaDataAvailable():
                res = str(self.mediaPlayer.metaData("Resolution")).partition(
                    "PyQt5.QtCore.QSize(")[2].replace(", ",
                                                      " x ").replace(")", "")
                print("%s%s" % ("Video Resolution = ", res))
            else:
                print("no metaData available")

    def openFileAtStart(self, filelist):
        matching = [s for s in filelist if ".myformat" in s]
        if len(matching) > 0:
            self.loadFilm(matching)

##################### update Label ##################################

    def handleLabel(self):
        self.lbl.clear()
        mtime = QTime(0, 0, 0, 0)
        self.time = mtime.addMSecs(self.mediaPlayer.position())
        self.lbl.setText(self.time.toString())
class Window(QWidget):
    def __init__(self):
        super().__init__()
 
        self.setWindowTitle("PyQt5 Media Player")
        self.setGeometry(350, 100, 700, 500)
        self.setWindowIcon(QIcon('player.png'))
        
        
        #reqdata = req.get('http://192.168.0.47:2000/getcsvfile/strenght-weakness_bp')
        #data = reqdata.json()
        
        #print("data", data)
        
        #192.168.0.47
        #http://192.168.0.47:2000/getvideo/strenght-weakness_bp
 
        #p =self.palette()
        #p.setColor(QPalette.Window, Qt.black)
        #self.setPalette(p)
        
        #data = {'name': 'Peter'}

       # resp = req.post("http://192.168.0.34:2000/upload/interview/postdata", data)
       # print(resp.text)
        
       # self.clientsocket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
       # self.clientsocket.connect(('192.168.0.34',2000))
        
        milli_sec = int(round(time.time() * 1000))
        print(milli_sec)
        
        self.timer = QTimer()
         
        self.timer.timeout.connect(self.viewCam)
        
        fourcc = cv2.VideoWriter_fourcc(*'XVID') 
        self.out = cv2.VideoWriter('C:/Users/brahm/OneDrive/Desktop/webcam/'+str(milli_sec)+'.mp4', fourcc, 30.0, (640, 480))
        
        self.init_ui()
 
 
        self.show()
 
 
    def init_ui(self):
 
        #create media player object
        self.mediaPlayer = QMediaPlayer(None, QMediaPlayer.VideoSurface)
 
 
        #create videowidget object
 
        videowidget = QVideoWidget()
 
 
        #create open button
        openBtn = QPushButton('Open Video')
        openBtn.clicked.connect(self.open_file)
        
        self.videobutton = QPushButton('start')
        self.videobutton.clicked.connect(self.record)
 
 
 
        #create button for playing
        self.playBtn = QPushButton()
        #self.playBtn.setEnabled(False)
        self.playBtn.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay))
        self.playBtn.clicked.connect(self.play_video)
 
 
 
        #create slider
        self.slider = QSlider(Qt.Horizontal)
        self.slider.setRange(0,0)
        self.slider.sliderMoved.connect(self.set_position)
 
 
 
        #create label
        self.label = QLabel()
        self.label.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Maximum)
 
 
        #create hbox layout
        hboxLayout = QHBoxLayout()
        hboxLayout.setContentsMargins(0,0,0,0)
 
        #set widgets to the hbox layout
        #hboxLayout.addWidget(openBtn)
        hboxLayout.addWidget(self.videobutton)
        hboxLayout.addWidget(self.playBtn)
        hboxLayout.addWidget(self.slider)
 
 
 
        #create vbox layout
        vboxLayout = QVBoxLayout()
        vboxLayout.addWidget(videowidget)
        vboxLayout.addLayout(hboxLayout)
        vboxLayout.addWidget(self.label)
 
 
        self.setLayout(vboxLayout)
 
        self.mediaPlayer.setVideoOutput(videowidget)
        
        self.mediaPlayer.setMedia(QMediaContent(QUrl.fromLocalFile("C:/Users/brahm/OneDrive/Desktop/face exp node/రాష్ట్రపతి పాలన ఎప్పుడు, ఎందుకు విధిస్తారు_ ఆర్టికల్ 356 ఏం చెబుతోంది_ - BBC New.wmv")))
 
        #media player signals
 
        self.mediaPlayer.stateChanged.connect(self.mediastate_changed)
        self.mediaPlayer.positionChanged.connect(self.position_changed)
        self.mediaPlayer.durationChanged.connect(self.duration_changed)
        self.mediaPlayer.error.connect(self.handle_errors)
 
    def open_file(self):
        #sender = self.sender()
        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()
            
            print('mediaStatus: ' + str(self.mediaPlayer.mediaStatus()))
 
 
    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):
        print("position", position)
        self.mediaPlayer.setPosition(position)
 
 
    def handle_errors(self):
        print(self.mediaPlayer.error, 'error')
        print('error: ' + str(self.mediaPlayer.error()))
        print('mediaStatus: ' + str(self.mediaPlayer.mediaStatus()))
        self.playBtn.setEnabled(False)
        self.label.setText("Error: " + self.mediaPlayer.errorString())
 
 
    def viewCam(self):
        # read image in BGR format
        ret, image = self.cap.read()
        
        #data = {'name': image}
        
        #resp = req.post("https://httpbin.org/post", data)
        #print(resp.text)
        
        
        
        
        #data = pickle.dumps(image)
        
        
        #print("data", data)
        
        #self.clientsocket.sendall(struct.pack("H", len(data))+data)
        
        
        
        self.out.write(image) 
        
        
        #dtime = int(round(time.time() * 1000))
        
        #data = QByteArray()
        #data.append("name=Peter&")
        #data.append("age=34")
        
        #videofilename = str(dtime)+'.mp4'
        
        
        #data.append('videoname', videofilename);
        
        
        #print("data", data)
        
        
        # convert image to RGB format
            
    def record(self):
        if not self.timer.isActive():
           self.cap = cv2.VideoCapture(0)
           self.timer.start()
           self.videobutton.setText("Stop")
        else:
            self.timer.stop()
            self.cap.release()
            print("data", self.out)
            self.out.release()
            
            
            
            
            # update control_bt text
            self.videobutton.setText("Start")
Beispiel #25
0
class VideoWindow(QWidget):
    sigTimeChanged = pyqtSignal(object)

    def __init__(self, project=None, parent=None):
        super(VideoWindow, self).__init__(parent)
        self.project = project
        self.setWindowTitle("Video")
        self.mediaPlayer = QMediaPlayer()  #None, QMediaPlayer.VideoSurface)
        self.last_position = 0
        self.position_on_new_file = 0
        self.duration = -1
        self.waiting_for_file = False
        self.media_state_before_file_transition = self.mediaPlayer.state()
        self.video_time_offset = 0.0

        self.play_icon = QIcon(play_icon_file)
        self.clock_icon = QIcon(clock_icon_file)
        self.pause_icon = QIcon(pause_icon_file)

        videoWidget = QVideoWidget()
        self.videoWidget = videoWidget
        self.playButton = QPushButton()
        self.playButton.setEnabled(False)
        self.playButton.setIcon(self.play_icon)
        self.playButton.clicked.connect(self.play)

        self.timeOffsetButton = QPushButton()
        self.timeOffsetButton.setIcon(self.clock_icon)
        self.timeOffsetButton.clicked.connect(self.setTimeOffset)

        self.positionSlider = QSlider(Qt.Horizontal)
        self.positionSlider.setRange(0, 0)
        self.positionSlider.sliderMoved.connect(self.setPosition)

        self.errorLabel = QLabel()
        self.errorLabel.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Maximum)

        # Create layouts to place inside widget
        controlLayout = QHBoxLayout()
        controlLayout.setContentsMargins(0, 0, 0, 0)
        controlLayout.addWidget(self.timeOffsetButton)
        controlLayout.addWidget(self.playButton)
        controlLayout.addWidget(self.positionSlider)

        layout = QVBoxLayout()
        layout.addWidget(videoWidget)
        layout.addLayout(controlLayout)
        layout.addWidget(self.errorLabel)  # Hide error Label

        # Set widget to contain window contents
        self.setLayout(layout)

        self.mediaPlayer.setVideoOutput(videoWidget)
        self.mediaPlayer.stateChanged.connect(self.mediaStateChanged)
        self.mediaPlayer.positionChanged.connect(self.positionChanged)
        self.mediaPlayer.durationChanged.connect(self.durationChanged)
        self.mediaPlayer.mediaStatusChanged.connect(self.mediaStatusChanged)
        self.mediaPlayer.error.connect(self.handleError)
        self.mediaPlayer.setNotifyInterval(40)  # 25 fps

        if self.project is None:
            self.current_time_range = [0, 0]
            self.current_file = ''
            # self.mediaPlayer.setMedia(QMediaContent(QUrl.fromLocalFile(self.current_file)))
            # self.playButton.setEnabled(True)
            # self.mediaPlayer.play()
        elif self.project.current_animal.video_files:
            self.current_file = self.project.current_animal.video_files[0]
            self.current_time_range = [
                self.project.current_animal.video_init_time[0],
                self.project.current_animal.video_init_time[0] +
                self.project.current_animal.video_duration[0]
            ]
            self.mediaPlayer.setMedia(
                QMediaContent(QUrl.fromLocalFile(self.current_file)))
            self.playButton.setEnabled(True)
        else:
            self.current_file = ''
            self.current_time_range = [0, 0]

    def setTimeOffset(self):
        offset, okpressed = QInputDialog.getDouble(
            self,
            'Video time offset',
            'Offset video time position (seconds)',
            value=self.video_time_offset)
        if okpressed:
            self.video_time_offset = offset
            current_position = self.current_time_range[
                0] + self.last_position / 1000
            self.setGlobalPosition(0)
            self.setGlobalPosition(current_position)

    def openFile(self):
        fileName, _ = QFileDialog.getOpenFileName(self, "Open Movie",
                                                  QDir.homePath())

        if fileName != '':
            self.mediaPlayer.setMedia(
                QMediaContent(QUrl.fromLocalFile(fileName)))
            self.playButton.setEnabled(True)

    def exitCall(self):
        sys.exit(app.exec_())

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

    def mediaStateChanged(self, state):
        if self.mediaPlayer.state() == QMediaPlayer.PlayingState:
            self.playButton.setIcon(self.pause_icon)
        else:
            self.playButton.setIcon(self.play_icon)

    def positionChanged(self, position):
        # Connected to video player
        # print('positionChanged',position,self.last_position,self.waiting_for_file,self.duration,self.current_time_range)
        # if self.duration == -1:
        #     print('positionChanged: no file - duration ==-1')
        #     return
        # if self.waiting_for_file:
        #     print('positionChanged: Waiting to load file')
        #     return
        # if position == 0:
        #     print('positionChanged: avoiding setting positions to 0')
        #     return
        if position == 0 or self.waiting_for_file or self.duration == -1 or position == self.last_position:
            # avoid position changes on file transitions or repeated signals on same position
            return
        if position < self.duration - 40:  # avoid time changes when switching files
            self.last_position = position
            self.positionSlider.setValue(position)
            self.sigTimeChanged.emit(position / 1000 +
                                     self.current_time_range[0])
        else:  # position is at the end of file - try to switch to next file
            pos = self.current_time_range[1] + .04
            print('Trying to jump to next file', self.current_time_range[1],
                  self.duration, pos)
            self.setGlobalPosition(pos)

    def durationChanged(self, duration):
        # print('duration changed',duration)
        self.duration = duration
        self.positionSlider.setRange(0, duration)
        self.mediaPlayer.setPosition(
            self.position_on_new_file
        )  # if duration changes avoid the position going back to 0

    def setPosition(self, position):
        # connected to slider
        # print('setPosition',position)
        self.mediaPlayer.setPosition(
            position)  #  milliseconds since the beginning of the media

    def setGlobalPosition(self, pos):
        # Connected to project main model sigTimeChanged
        # open the right media
        if self.current_time_range[0] <= pos <= self.current_time_range[
                1]:  # correct file opened
            position = int((pos - self.current_time_range[0]) * 1000)
            if self.mediaPlayer.state() == QMediaPlayer.PlayingState and abs(
                    position - self.last_position) < 200:
                # skip position setting by signal of main model to ensure smooth video plaback
                return
            # go to correct relative position
            self.mediaPlayer.setPosition(position)  # UNIX time
            return
        else:
            for i, file in enumerate(self.project.current_animal.video_files
                                     ):  # search for file to open
                arange = [
                    self.project.current_animal.video_init_time[i] +
                    self.video_time_offset,
                    self.project.current_animal.video_init_time[i] +
                    self.project.current_animal.video_duration[i] +
                    self.video_time_offset
                ]
                if (arange[0] <= pos <= arange[1]):
                    print('Changing video file: ', file)
                    self.current_file = file
                    self.errorLabel.setText("File: " + self.current_file)
                    self.current_time_range = arange
                    self.waiting_for_file = True
                    self.media_state_before_file_transition = self.mediaPlayer.state(
                    )
                    self.mediaPlayer.stop()
                    position = (pos - self.current_time_range[0]) * 1000
                    self.position_on_new_file = int(position)
                    # print('Changing position_on_new_file: ', self.position_on_new_file,pos)
                    self.mediaPlayer.setMedia(
                        QMediaContent(QUrl.fromLocalFile(file)))
                    self.playButton.setEnabled(True)
                    # self.duration = (arange[1]-arange[0])*1000
                    return
        print('no video file found for current position')
        self.errorLabel.setText("No video file found for current position")
        self.mediaPlayer.stop()
        self.mediaPlayer.setMedia(QMediaContent())
        self.current_file = ''
        self.current_time_range = [0, 0]
        # self.duration = 0
        self.playButton.setEnabled(False)
        self.positionSlider.setRange(0, 0)
        self.positionSlider.setValue(0)

    def mediaStatusChanged(self, status):
        if self.waiting_for_file:
            if self.mediaPlayer.mediaStatus() == QMediaPlayer.LoadedMedia:
                self.waiting_for_file = False
                # print('finished loading file')
                # self.mediaPlayer.stop()
                self.mediaPlayer.setPosition(self.position_on_new_file)
                self.mediaPlayer.play()
                time.sleep(.05)
                self.mediaPlayer.pause()
                if self.media_state_before_file_transition == QMediaPlayer.PlayingState:
                    self.mediaPlayer.play()
                # print('finished setting position on new file')

    def handleError(self):
        self.playButton.setEnabled(False)
        self.errorLabel.setText("Error: " + self.mediaPlayer.errorString())
        print("Video - Error: " + self.mediaPlayer.errorString())
Beispiel #26
0
class Player(QObject):
    # 信号: 当音量变化时, 参数为当前音量.
    volumeChanged = QtCore.pyqtSignal(int)

    # 信号: 当播放位置变化时, 参数为当前位置
    positionChanged = QtCore.pyqtSignal(int)

    # 信号: 当播放状态变化时, 参数为当前状态
    stateChanged = QtCore.pyqtSignal(int)

    # 信号: 当媒体状态变化时, 参数为当前状态
    mediaStatusChanged = QtCore.pyqtSignal(int)

    # 信号: 当静音状态变化时, 参数为当前状态
    mutedChanged = QtCore.pyqtSignal(int)
    localAppDataDir = os.getenv("LOCALAPPDATA")
    # like:
    #   Windows: C:/Users/win10/AppData/Local/kon-windows/Temp/Music
    #   Linux  : Not test.
    tempDir = localAppDataDir + "/kon-windows/Temp/Music/"

    def __init__(self) -> None:
        super().__init__()
        self.__path = None
        self.__lock = Lock()
        self.__player = QMediaPlayer()
        self.__player.setVolume(50)
        self.__player.positionChanged.connect(self.__onPositionChanged)
        self.__player.mediaStatusChanged.connect(self.__onMediaStatusChanged)
        if not os.path.exists(self.tempDir):
            os.makedirs(self.tempDir)

    def init(self):
        pass

    def play(self, music: Music):
        if music is None:
            return
        self.__lock.acquire()
        """
        开始或继续播放。如果以前已暂停播放,则将从暂停的位置继续播放。
        如果播放已停止或之前从未开始过,则播放将从头开始。
        """
        status = self.__player.mediaStatus()
        path = music.path
        if status == QMediaPlayer.NoMedia or self.__path != path:
            self.stop()
            content = QMediaContent(QUrl.fromLocalFile(self.__trans2wave(music)))
            self.__player.setMedia(content)
        self.__path = path
        state = self.__player.state()
        if state == QMediaPlayer.PlayingState:
            self.__player.pause()
        else:
            self.__player.play()
        player_state = self.__player.state()
        self.stateChanged.emit(player_state)
        self.__lock.release()

    def pause(self):
        """ 暂停播放 """
        self.__player.pause()
        self.stateChanged.emit(self.__player.state())

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

    def getVolume(self) -> int:
        """ 获取音量 """
        return self.__player.volume()

    def setVolume(self, volume: int):
        """
        设置音量, 范围从0(静音)到100(全音量).
        默认情况下,音量为100.
        """
        self.__player.setVolume(volume)
        self.volumeChanged.emit(volume)

    def getMuted(self) -> bool:
        """ 获取静音状态. """
        return self.__player.isMuted()

    def setMuted(self, muted: bool):
        """ 设置静音状态. """
        self.__player.setMuted(muted)
        self.mutedChanged.emit(muted)

    def toggleMuted(self):
        """ 切换静音状态. """
        self.__player.setMuted(not self.__player.isMuted())
        self.mutedChanged.emit(self.__player.isMuted())

    def getState(self) -> int:
        """ 获取播放状态. """
        return self.__player.state()

    def playing(self) -> bool:
        """ 当前是否处于播放状态. """
        return self.__player.state() == QMediaPlayer.PlayingState

    def setPosition(self, position: int):
        """
        跳跃到指定的时间位置。
        :param position: 绝对时间位置, 毫秒。
        """
        self.__player.setPosition(position)
        self.positionChanged.emit(position)

    def getPosition(self) -> int:
        """ 获取当前播放进度. """
        return self.__player.position()

    def getDuration(self) -> int:
        """ 获取时长. """
        return self.__player.duration()

    def __onPositionChanged(self, position: int):
        self.positionChanged.emit(position)

    def __onMediaStatusChanged(self, mediaStatus: int):
        self.mediaStatusChanged.emit(mediaStatus)

    def __trans2wave(self, music: Music) -> str:
        """ 转换格式为 wave """
        path = music.path
        if path.endswith(".wav"):
            return path
        dest = self.tempDir + str(music.id) + ".wav"
        if os.path.exists(dest):
            return dest
        # 最多保留一百个歌曲缓存
        olds = os.listdir(self.tempDir)
        if len(olds) >= 100:
            # 删掉一个
            os.remove(self.tempDir + olds[0])
        Commons.export2wave(path, dest)
        return dest