Esempio n. 1
0
class EditorWidget(QWidget):
    """Widget which contain the editor."""
    def __init__(self, plugin_manager):
        super(EditorWidget, self).__init__()
        os.environ[
            'QT_MULTIMEDIA_PREFERRED_PLUGINS'] = 'windowsmediafoundation'
        self.plugin_manager = plugin_manager

        #parent layout
        self.v_box = QVBoxLayout()
        self.h_box = QHBoxLayout()
        # parent splitter for the text and numbers
        self.text_h_box = QSplitter(Qt.Horizontal)
        self.text_h_box.splitterMoved.connect(self.on_text_changed)

        self.settings = QSettings(c.SETTINGS_PATH, QSettings.IniFormat)
        self.keyboard_settings = QSettings(c.KEYBOARD_SETTINGS_PATH,
                                           QSettings.IniFormat)
        self.theme = self.settings.value(c.THEME, defaultValue=c.THEME_D)

        # font settings
        self.font = QFont(
            self.settings.value(c.FONT, defaultValue="Arial", type=str))
        self.font.setPointSize(
            self.settings.value(c.FONT_SIZE, defaultValue=16, type=int))

        # the text widget itself
        self.text = QPlainTextEdit()
        self.text.setFont(self.font)
        self.text.textChanged.connect(self.on_text_changed)
        self.text.setFocusPolicy(Qt.StrongFocus)

        # the number text widget to show the row numbers
        self.numbers = QPlainTextEdit()
        self.numbers.setFont(self.font)
        self.numbers.setReadOnly(True)
        self.numbers.setMinimumWidth(20)
        self.numbers.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.numbers.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.numbers.setLineWrapMode(QPlainTextEdit.NoWrap)
        self.numbers.setFocusPolicy(Qt.NoFocus)
        self.numbers.setFrameStyle(QFrame.NoFrame)
        self.numbers.setStyleSheet("background-color: rgba(0,0,0,0%)")

        # sync the text widget and number widget
        self.text_bar = self.text.verticalScrollBar()
        self.number_bar = self.numbers.verticalScrollBar()
        #self.number_bar.valueChanged.connect(self.text_bar.setValue)
        self.text_bar.valueChanged.connect(self.number_bar.setValue)

        # add them into their layout
        self.text_h_box.addWidget(self.numbers)
        self.text_h_box.addWidget(self.text)
        self.text_h_box.setSizes([10, 700])

        # layout which holds the media controls in the bottom
        self.media_controls = QHBoxLayout()
        self.media_controls_settings = QVBoxLayout()
        self.media_controls_slider_h_box = QHBoxLayout()

        # direct player controls
        self.btn_size = 75
        self.play_icon = QIcon(
            os.path.join(c.ICON_PATH, self.theme, "play.png"))
        self.pause_icon = QIcon(
            os.path.join(c.ICON_PATH, self.theme, "pause.png"))
        self.play_btn = QPushButton(icon=self.play_icon)
        self.play_btn.clicked.connect(self.on_play)
        self.play_btn.setFixedSize(self.btn_size, self.btn_size)
        self.play_btn.setIconSize(QSize(self.btn_size, self.btn_size))
        self.play_btn.setFlat(True)
        self.play_btn.setShortcut(QKeySequence().fromString(
            self.keyboard_settings.value(c.PLAY_PAUSE_KEY, defaultValue="")))
        self.forward_btn = QPushButton(
            icon=QIcon(os.path.join(c.ICON_PATH, self.theme, "forward.png")))
        self.forward_btn.clicked.connect(self.on_forward)
        self.forward_btn.setFixedSize(self.btn_size, self.btn_size)
        self.forward_btn.setIconSize(QSize(self.btn_size, self.btn_size))
        self.forward_btn.setFlat(True)
        self.forward_btn.setShortcut(QKeySequence().fromString(
            self.keyboard_settings.value(c.FORWARD_KEY, defaultValue="")))
        self.backward_btn = QPushButton(
            icon=QIcon(os.path.join(c.ICON_PATH, self.theme, "backward.png")))
        self.backward_btn.clicked.connect(self.on_backward)
        self.backward_btn.setFixedSize(self.btn_size, self.btn_size)
        self.backward_btn.setIconSize(QSize(self.btn_size, self.btn_size))
        self.backward_btn.setFlat(True)
        self.backward_btn.setShortcut(QKeySequence().fromString(
            self.keyboard_settings.value(c.BACKWARDS_KEY, defaultValue="")))

        # add them to the layout
        self.media_controls.addStretch()
        self.media_controls.addWidget(self.backward_btn)
        self.media_controls.addWidget(self.play_btn)
        self.media_controls.addWidget(self.forward_btn)
        self.media_controls.addStretch(4)

        # slider which shows the current time
        self.time_slider = QSlider(Qt.Horizontal)
        self.time_slider.sliderMoved.connect(self.on_time_slider_moved)

        # label on the right of the slider, which shows the current time
        self.time_label = QLabel("00:00/00:00")
        self.media_controls_slider_h_box.addWidget(self.time_slider)
        self.media_controls_slider_h_box.addWidget(self.time_label)

        # icons for the other sliders
        self.vol_icon = QIcon(
            os.path.join(c.ICON_PATH, self.theme,
                         "volume.png")).pixmap(QSize(32, 32))
        self.rate_icon = QIcon(
            os.path.join(c.ICON_PATH, self.theme,
                         "playbackrate.png")).pixmap(QSize(32, 32))
        self.rewind_icon = QIcon(
            os.path.join(c.ICON_PATH, self.theme,
                         "time.png")).pixmap(QSize(32, 32))

        # display the icons through labels
        self.vol_icon_label = QLabel()
        self.vol_icon_label.setPixmap(self.vol_icon)
        self.rate_icon_label = QLabel()
        self.rate_icon_label.setPixmap(self.rate_icon)
        self.rewind_rewind_label = QLabel()
        self.rewind_rewind_label.setPixmap(self.rewind_icon)

        # init of the other sliders
        self.vol_slider = QSlider(Qt.Horizontal)
        self.vol_slider.sliderMoved.connect(self.on_vol_slider_moved)
        self.vol_slider.setFixedWidth(250)
        self.vol_slider.setRange(1, 100)
        self.rate_slider = QSlider(Qt.Horizontal)
        self.rate_slider.sliderMoved.connect(self.on_rate_slider_moved)
        self.rate_slider.setFixedWidth(250)
        self.rate_slider.setRange(1, 20)
        self.rewind_time = 10
        self.rewind_slider = QSlider(Qt.Horizontal)
        self.rewind_slider.sliderMoved.connect(self.on_rewind_slider_moved)
        self.rewind_slider.setFixedWidth(250)
        self.rewind_slider.setRange(1, 60)
        self.rewind_slider.setValue(self.rewind_time)

        # labels for the values
        self.vol_label = QLabel()
        self.rate_label = QLabel()
        self.rewind_label = QLabel()

        # create hbox for each of the three sliders
        self.vol_h_box = QHBoxLayout()
        self.vol_h_box.addWidget(self.vol_label)
        self.vol_h_box.addWidget(self.vol_slider)
        self.vol_h_box.addWidget(self.vol_icon_label)

        self.rate_h_box = QHBoxLayout()
        self.rate_h_box.addWidget(self.rate_label)
        self.rate_h_box.addWidget(self.rate_slider)
        self.rate_h_box.addWidget(self.rate_icon_label)

        self.rewind_h_box = QHBoxLayout()
        self.rewind_h_box.addWidget(self.rewind_label)
        self.rewind_h_box.addWidget(self.rewind_slider)
        self.rewind_h_box.addWidget(self.rewind_rewind_label)

        # group them together in a vlayout
        self.media_controls_settings.addLayout(self.vol_h_box)
        self.media_controls_settings.addLayout(self.rewind_h_box)
        self.media_controls_settings.addLayout(self.rate_h_box)

        # add this layout to the layout which already contains the buttons
        self.media_controls.addLayout(self.media_controls_settings)

        self.word_by_word_actions = QListWidget()
        self.word_by_word_actions.setMaximumWidth(150)

        self.h_box.addWidget(self.text_h_box)
        self.h_box.addWidget(self.word_by_word_actions)

        # group all ungrouped layouts and widgets to the parent layout
        self.v_box.addLayout(self.h_box, 10)
        self.v_box.addLayout(self.media_controls_slider_h_box, 1)
        self.v_box.addLayout(self.media_controls, 1)

        # set parent layout
        self.setLayout(self.v_box)

        # init media_player
        self.media_player = QMediaPlayer()
        self.video_widget = QVideoWidget()
        self.video_widget.setGeometry(200, 200, 500, 300)
        self.video_widget.setWindowTitle("Output")
        self.media_player.setVideoOutput(self.video_widget)
        self.media_player.positionChanged.connect(self.on_position_change)
        self.media_player.durationChanged.connect(self.on_duration_change)
        self.vol_slider.setValue(self.media_player.volume())
        self.rate_slider.setValue(int(self.media_player.playbackRate() * 10))

        self.on_vol_slider_moved(self.media_player.volume())
        self.on_rate_slider_moved(self.media_player.playbackRate() * 10)
        self.on_rewind_slider_moved(self.rewind_time)

        self.activate_text_modules = False
        self.get_text_modules()

        self.text_option_on = QTextOption()
        self.text_option_on.setFlags(
            QTextOption.ShowTabsAndSpaces
            | QTextOption.ShowLineAndParagraphSeparators)

        self.text_option_off = QTextOption()

        self.transcription_meta_data = None
        self.word_pos = -1
        self.word_start_time = None
        self.word_end_time = None

        self.tcf_highlight = QTextCharFormat()
        self.tcf_highlight.setBackground(Qt.red)
        self.tcf_normal = QTextCharFormat()
        self.tcf_normal.setBackground(Qt.transparent)

        self.show_empty_buttons = self.settings.value(c.SHOW_EMPTY_BUTTONS,
                                                      defaultValue=True,
                                                      type=bool)

    def on_position_change(self, position):
        """Is executed when media is played (position is changed)

        Args:
          position: Current position (ms) of the media player.

        """

        self.time_slider.setValue(position)
        self.time_label.setText(
            create_time_string(position, self.media_player.duration()))

        if self.word_end_time is None:
            return

        if position > self.word_end_time:
            self.on_play()
            self.word_start_time = None
            self.word_end_time = None

    def on_duration_change(self, duration):
        """Is executed when duration of the media changes.

        Args:
          duration: duration of the media.

        """

        self.time_slider.setRange(0, duration)
        self.time_label.setText(
            create_time_string(0, self.media_player.duration()))

    def on_time_slider_moved(self, value):
        """Is executed when the time slider was moved.

        Args:
          value: current value of the slider.

        """

        self.media_player.setPosition(value)

    def on_vol_slider_moved(self, value):
        """Is executed when the volume slider is moved.

        Args:
          value: current value of the slider.

        """

        self.media_player.setVolume(value)
        self.vol_label.setText(str(value) + "%")

    def on_rate_slider_moved(self, value):
        """Is executed when the rate slider is moved.

        Args:
          value: current value of the slider.

        """

        self.media_player.setPlaybackRate(value / 10)
        self.rate_label.setText(str(value / 10) + "x")

    def on_rewind_slider_moved(self, value):
        """Is executed when the rewind slider is moved.

        Args:
          value: current value of the slider.

        """

        self.rewind_time = value
        self.rewind_label.setText(str(value) + "s")

    def on_play(self):
        """Is executed when the play or pause button is pressed."""

        if self.media_player.state() == QMediaPlayer.PlayingState:
            self.media_player.pause()
            self.play_btn.setIcon(self.play_icon)

        else:
            self.media_player.play()
            self.play_btn.setIcon(self.pause_icon)

    def on_forward(self):
        """Is executed when the forward button is pressed."""

        self.media_player.setPosition(self.media_player.position() +
                                      self.rewind_time * 1000)

    def on_backward(self):
        """Is executed when the backward button is pressed."""

        self.media_player.setPosition(self.media_player.position() -
                                      self.rewind_time * 1000)

    def on_text_changed(self):
        """Is executed when the text changed

        Calculates the line numbers and sets the text modules if activated.

        """

        lines = int(
            self.text.document().documentLayout().documentSize().height())
        self.numbers.setPlainText("")
        text = ""
        for i in range(1, lines + 1):
            text = text + str(i) + "\n"

        self.numbers.setPlainText(text)
        self.number_bar.setSliderPosition(self.text_bar.sliderPosition())

        new_text = self.text.toPlainText()

        if self.activate_text_modules == True:
            for key in self.text_modules.keys():
                to_replace = " " + key + " "
                to_replace_with = " " + self.text_modules[key] + " "
                new_text = new_text.replace(to_replace, to_replace_with)

        if self.text.toPlainText() != new_text:
            old_pos = self.text.textCursor().position()
            self.text.setPlainText(new_text)
            cursor = self.text.textCursor()
            cursor.setPosition(old_pos, QTextCursor.MoveAnchor)
            cursor.movePosition(QTextCursor.EndOfWord)
            cursor.movePosition(QTextCursor.NextCharacter)
            self.text.setTextCursor(cursor)

    def show_video(self):
        """Shows or hides the video feed."""

        if self.video_widget.isVisible():
            self.video_widget.hide()
        else:
            self.video_widget.show()

    def open_project(self, project_folder_path):
        """Opens a project.

        Args:
          project_folder_path: folder of the project which should be opened.

        """
        self.project_folder_path = project_folder_path
        self.media_file = file_util.get_file(self.project_folder_path,
                                             c.CON_COPY_POSTFIX)
        if self.media_file is None:
            self.hide()
            return
        self.media_player.setMedia(
            QMediaContent(QUrl.fromLocalFile(self.media_file)))

        self.transcription_path = file_util.get_file(self.project_folder_path,
                                                     c.TRANSCRIPTION)
        if self.transcription_path is None:
            self.hide()
            return
        with open(self.transcription_path, 'r') as f:
            text = f.read()
        self.text.setPlainText(text)
        self.transcription_meta_data = file_util.get_value_from_shelve(
            self.project_folder_path, c.TRANSCRIPTION_META_DATA)
        print(self.transcription_meta_data)

    def change_font(self, new_font, new_size):
        """Changes the font.

        Args:
          new_font: Name of the new font.
          new_size: New font size.

        """
        self.font = QFont(new_font)
        self.font.setPointSize(int(new_size))
        self.text.setFont(self.font)
        self.numbers.setFont(self.font)
        self.settings.setValue(c.FONT_SIZE, int(new_size))
        self.settings.setValue(c.FONT, new_font)

    def get_text_modules(self):
        """Gets the saved text_modules from the settings."""

        self.text_modules = self.settings.value(c.TEXT_MODULES,
                                                defaultValue={})

    def show_special_characters(self, bol):
        """Displays the special characters.

        Args:
          bol: true or false.

        """

        if bol:
            self.text.document().setDefaultTextOption(self.text_option_on)
        else:
            self.text.document().setDefaultTextOption(self.text_option_off)

    def on_word_by_word(self):
        """Selects the next or first word in the on word by word editing mode.

        For that purpose th word_postion is increased and the next word is marked via the textcursor.
        If everything works correctly the population of the list will be started.

        """

        self.word_pos += 1
        #if self.media_player.state() == QMediaPlayer.PlayingState:
        #    return

        if self.word_pos > len(self.text.toPlainText().split()) - 1:
            self.reset_word_by_word()
            return

        cursor = self.text.textCursor()
        if self.word_pos == 0:
            self.show_empty_buttons = self.settings.value(c.SHOW_EMPTY_BUTTONS,
                                                          defaultValue=True,
                                                          type=bool)
            cursor.setPosition(QTextCursor.Start, QTextCursor.MoveAnchor)
            cursor.movePosition(QTextCursor.StartOfWord,
                                QTextCursor.MoveAnchor)
            cursor.movePosition(QTextCursor.EndOfWord, QTextCursor.KeepAnchor)
            self.text.setEnabled(False)
        else:
            cursor.movePosition(QTextCursor.NextWord, QTextCursor.MoveAnchor)
            cursor.movePosition(QTextCursor.EndOfWord, QTextCursor.KeepAnchor)

        self.text.setTextCursor(cursor)

        selected_word = cursor.selectedText()

        if not selected_word:
            self.word_pos -= 1
            self.on_word_by_word()
            return

        # change to find all meta data
        meta_data_with_word = self.find_meta_data(selected_word)

        self.populate_word_actions(selected_word, meta_data_with_word)

    def on_word_by_word_prev(self):
        """Same as word for word but selects to the previous word."""

        if self.word_pos < 1:
            return

        self.word_pos -= 2

        cursor = self.text.textCursor()
        count = 0
        cursor.setPosition(QTextCursor.Start, QTextCursor.MoveAnchor)
        cursor.movePosition(QTextCursor.StartOfWord, QTextCursor.MoveAnchor)
        cursor.movePosition(QTextCursor.EndOfWord, QTextCursor.KeepAnchor)
        while count < self.word_pos:
            cursor.movePosition(QTextCursor.NextWord, QTextCursor.MoveAnchor)
            cursor.movePosition(QTextCursor.EndOfWord, QTextCursor.KeepAnchor)
            count += 1
        self.text.setTextCursor(cursor)
        self.on_word_by_word()

    def reset_word_by_word(self):
        """Resets the word by word editing mode and goes back to the normal editing."""

        self.word_pos = -1
        self.play_to = -1
        self.text.setEnabled(True)
        self.word_by_word_actions.clear()
        cleaned = self.text.textCursor()
        cleaned.clearSelection()
        self.text.setTextCursor(cleaned)

    def populate_word_actions(self, selected, word_meta_data):
        """Calls the plugin_manager to get alle the word for word buttons and initalize the hear again buttons.

        Args:
          selected: The selected word.
          word_meta_data: The meta_data fr the word.

        """

        self.word_by_word_actions.clear()
        if self.word_pos == len(self.text.toPlainText().split()):
            return

        self.plugin_manager.get_word_by_word_actions(selected, word_meta_data,
                                                     self.word_pos)

        btns = []
        for meta_data in word_meta_data:
            media_btn = HearButton(self, meta_data)
            btns.append(media_btn)
        self.add_new_word_by_word_action(btns, "Hear again", selected,
                                         self.word_pos)

    def add_new_word_by_word_action(self, btns, name, word, word_pos):
        """Adds a new word by word action.

        Args:
          btns: The buttons to add.
          name: The (plugin-)name of the buttons.
          word: The word for which these buttons are.
          word_pos: The word position.

        """

        if not self.show_empty_buttons and len(btns) == 0:
            return

        if self.word_pos != word_pos:
            print("old item", word, word_pos, self.word_pos)
            return

        group_item = QListWidgetItem()
        group_item.setFlags(Qt.ItemIsSelectable)
        label = QLabel(name)
        label.setFixedSize(self.word_by_word_actions.width() - 15, 30)
        label.setContentsMargins(5, 0, 0, 0)
        label.setWordWrap(True)
        group_item.setSizeHint(label.size())
        self.word_by_word_actions.addItem(group_item)
        self.word_by_word_actions.setItemWidget(group_item, label)

        for btn in btns:
            btn.setFixedSize(self.word_by_word_actions.width() - 15, 30)
            item = QListWidgetItem()
            item.setSizeHint(btn.size())
            item.setFlags(Qt.ItemIsSelectable)
            self.word_by_word_actions.addItem(item)
            self.word_by_word_actions.setItemWidget(item, btn)

    def find_meta_data(self, word):
        """Gets all the meta_data for the given word.

        Args:
          word: The word for which the meta_data should be found.

        Returns:
          The meta_data
        """

        meta_data_with_word = []

        for m_d in self.transcription_meta_data:
            if m_d.get(c.WORD) == word.lower():
                meta_data_with_word.append(m_d)

        return meta_data_with_word

    def replace_selection(self, new_word):
        """Replace the selection with the given word

        Args:
          new_word: The replacement.

        """

        cursor = self.text.textCursor()
        old_cursor_pos = cursor.position()

        cursor.insertText(new_word)
        cursor.setPosition(old_cursor_pos, QTextCursor.MoveAnchor)
        cursor.movePosition(QTextCursor.EndOfWord, QTextCursor.MoveAnchor)
        self.text.setTextCursor(cursor)
        self.word_by_word_actions.clear()

    def get_selection(self):
        """Returns the current selection

        Returns:
          The current selection.

        """

        return self.text.textCursor().selectedText()

    def get_text(self):
        """Returns the current text

        Returns:
          The current text.

        """

        return self.text.toPlainText()

    def set_text(self, new_text, restore_line_breaks=False):
        """Replace the text with the new text.

        Args:
          new_text: The new text.
          restore_line_breaks: If true, tries to restore the line breaks. (Default value = False)

        """

        cursor = self.text.textCursor()
        old_cursor_pos = cursor.position()

        if restore_line_breaks:
            self.set_text_with_line_breaks(new_text)
        else:
            self.text.setPlainText(new_text)

        cursor.setPosition(old_cursor_pos, QTextCursor.MoveAnchor)
        self.text.setTextCursor(cursor)

    def get_word_at(self, pos):
        """Returns the word at the given position.

        Args:
          pos: The position of the word.

        Returns:
          The word at the given position.

        """

        text = self.text.toPlainText().strip().split()

        if pos < 0 or pos > len(text):
            return None

        return text[pos % len(text)]

    def set_word_at(self, word, pos, replace_old):
        """Sets the word at the given position.

        Args:
          word: The replacement.
          pos: The position.
          replace_old: If true, the old word at the position will be replaced, otherwise the word will be set before the old word.

        """

        old_word = self.get_word_at(pos)
        cursor = self.text.textCursor()
        cursor_pos = cursor.position()

        if pos < 0:
            self.text.setPlainText(word + " " + self.text.toPlainText())
            cursor.setPosition(cursor_pos, QTextCursor.MoveAnchor)
            self.text.setTextCursor(cursor)
            return

        text = self.text.toPlainText().strip().split()
        if replace_old and pos < len(text):
            if word:
                text[pos] = word
            else:
                text.pop(pos)
        else:
            text.insert(pos, word)

        text = " ".join(text)
        self.set_text_with_line_breaks(text)

        cursor_pos += len(word)

        if replace_old:
            cursor_pos -= len(old_word)
            if not word:
                cursor_pos -= 1
        else:
            cursor_pos += 1

        words_to_cursor_pos = self.text.toPlainText()[:cursor_pos].split()
        self.word_pos = len(words_to_cursor_pos) - 1

        cursor.setPosition(cursor_pos, QTextCursor.MoveAnchor)
        cursor.movePosition(QTextCursor.StartOfWord, QTextCursor.MoveAnchor)
        self.text.setTextCursor(cursor)

    def find_line_breaks(self):
        """Returns the lien breaks in the text.

        Returns:
          The positions of the linebreaks

        """

        found = []
        start = 0
        text = self.text.toPlainText()
        while True:
            start = text.find("\n", start)
            if start == -1:
                return found
            found.append(start)
            start += len("\n")

    def set_text_with_line_breaks(self, text):
        """Sets the text with linebreaks.

        Args:
          text: the new text.

        """

        line_breaks = self.find_line_breaks()
        for n in line_breaks:
            text = text[:n + 1] + "\n" + text[n + 1:]

        text = text.replace(" \n", "\n")
        text = text.replace("\n ", "\n")
        self.text.setPlainText(text)

    def insert_time_stamp(self):
        """Inserts the current timestamp at the current cursor position."""

        cursor = self.text.textCursor()
        time = "[" + convert_ms(self.media_player.position()) + "]"
        cursor.insertText(time)

    def start_hear_again(self, start_time, end_time):
        """Starts the audio for the specific word from the hear again button.

        Args:
          start_time: When to start the audio.
          end_time: When to end the audio.

        """

        if self.media_player.state() == QMediaPlayer.PlayingState:
            return
        self.media_player.pause()
        self.word_start_time = start_time
        self.word_end_time = end_time
        self.media_player.setPosition(self.word_start_time)
        self.on_play()
Esempio n. 2
0
class MainWindow(QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        self.ui.pblecture.clicked.connect(self.lectureClicked)
        self.ui.pbpause.clicked.connect(self.pauseClicked)
        self.ui.pbstop.clicked.connect(self.stopClicked)
        self.ui.pbmoins.clicked.connect(self.supprMedia)
        self.ui.pbplus.clicked.connect(self.ajouterMedia)
        self.ui.pbprecedent.clicked.connect(self.precedentClicked)
        self.ui.pbsuivant.clicked.connect(self.suivantClicked)
        self.mediaPlayer = QMediaPlayer()  #creation de la variable mediaPlayer
        self.mediaPlayer.setVideoOutput(
            self.ui.ecran)  #on projette la var mediaPlayer sur ecran.
        self.ui.dialVolume.valueChanged.connect(self.volumeChanged)
        self.mediaPlayer.durationChanged.connect(self.mediaDurationChanged)
        self.mediaPlayer.positionChanged.connect(self.mediaPositionChanged)
        self.ui.listWidget.itemDoubleClicked.connect(self.mediaSelected)

        # Commande qui permet de lancer le film (depuis le début)
        mediaContent = QMediaContent(QUrl.fromLocalFile("big_buck_bunny.avi"))
        self.mediaPlayer.setMedia(mediaContent)

    #def slideChanged(self):
    #    self.mediaPlayer.position()
    #    self.ui.timeline.setValue()
    def ajouterMedia(self):
        nomMedia = QFileDialog.getOpenFileName(
            self, "ChoixFilm", "c:/Users/AELION/PycharmProjects/lect_video",
            "(*.avi *.mp4)")
        fInfo = QFileInfo(nomMedia[0])
        fShortName = fInfo.baseName()
        item = QListWidgetItem(fShortName)
        item.setToolTip(nomMedia[0])
        self.ui.listWidget.addItem(item)

    def suivantClicked(self):
        currentItemRow = self.ui.listWidget.currentRow()
        if currentItemRow == -1:
            return
        totalItems = self.ui.listWidget.count()
        self.ui.listWidget.setCurrentRow((currentItemRow + 1) % totalItems)
        self.mediaSelected()

    def precedentClicked(self):
        currentItemRow = self.ui.listWidget.currentRow()
        if currentItemRow == -1:
            return
        totalItems = self.ui.listWidget.count()
        self.ui.listWidget.setCurrentRow((currentItemRow - 1) % totalItems)
        self.mediaSelected()

    def supprMedia(self):
        rowItem = self.ui.listWidget.currentRow()
        if rowItem != -1:  #au cas ou on appuie sur Supp et qu'il n'y a pas d'objet
            self.ui.listWidget.takeItem(rowItem)

    def mediaSelected(self):
        currentItem = self.ui.listWidget.currentItem()
        mediaContent = QMediaContent(QUrl.fromLocalFile(currentItem.toolTip()))
        self.mediaPlayer.setMedia(mediaContent)
        self.lectureClicked()

    def mediaDurationChanged(self):
        self.ui.debut.setText("00:00:00")
        mediaDuration = self.mediaPlayer.duration(
        )  #recoit le temps total en Millisec
        self.ui.timeline.setRange(
            0, mediaDuration
        )  #découpe le timeline proportionnelement au temps en millisec
        totalTimeMedia = QTime(0, 0, 0)
        totalTimeMedia = totalTimeMedia.addMSecs(
            mediaDuration)  #convertit le temps total en h:m:s
        self.ui.fin.setText(totalTimeMedia.toString("HH:mm:ss"))

    def mediaPositionChanged(self):
        mediaPosition = self.mediaPlayer.position()
        self.ui.timeline.setValue(mediaPosition)
        currentTimeMedia = QTime(
            0,
            0,
            0,
        )
        currentTimeMedia = currentTimeMedia.addMSecs(mediaPosition)
        self.ui.debut.setText(currentTimeMedia.toString("HH:mm:ss"))

    def volumeChanged(self):
        self.mediaPlayer.setVolume(self.ui.dialVolume.value())
        self.ui.labelVol.setText(str(self.ui.dialVolume.value()) + "%")

    def lectureClicked(self):
        print("Lecture!!")
        self.mediaPlayer.play()

    def pauseClicked(self):
        print("Pause !!")
        if self.mediaPlayer.state() == QMediaPlayer.PausedState:
            self.mediaPlayer.play()
        elif self.mediaPlayer.state() == QMediaPlayer.PlayingState:
            self.mediaPlayer.pause()

    def stopClicked(self):
        print("Stop!!")
        self.mediaPlayer.stop()
Esempio n. 3
0
class MainWindow(QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        self.ui.pbPlay.clicked.connect(self.lectureClicked)
        self.ui.pbPause.clicked.connect(self.pauseClicked)
        self.ui.pbStop.clicked.connect(self.stopClicked)
        self.ui.pbNext.clicked.connect(self.nextClicked)
        self.ui.pbPrevious.clicked.connect(self.previousClicked)
        self.ui.pbAdd.clicked.connect(self.addClicked)
        self.ui.pbDelete.clicked.connect(self.deleteClicked)
        self.ui.dVolume.valueChanged.connect(self.volume)
        self.mediaPlayer = QMediaPlayer()
        self.mediaPlayer.setVideoOutput(self.ui.wLecteur)
        self.mediaPlayer.durationChanged.connect(self.mediaDurationCnahged)
        self.mediaPlayer.positionChanged.connect(self.mediaPositionCnahged)
        self.ui.wList.itemDoubleClicked.connect(self.mediaSelected)

        mediaContent = QMediaContent(QUrl.fromLocalFile("big_buck_bunny.avi"))
        self.mediaPlayer.setMedia(mediaContent)

    def lectureClicked(self):
        print("Play")
        self.mediaPlayer.play()

    def pauseClicked(self):
        print("Pause")
        if self.mediaPlayer.state() == QMediaPlayer.PausedState:
            self.mediaPlayer.play()
        else:
            self.mediaPlayer.pause()

    def stopClicked(self):
        print("Stop")
        self.mediaPlayer.stop()

    def nextClicked(self):
        print("Next")
        self.mediaPlayer.next()

    def previousClicked(self):
        print("Previous")
        self.mediaPlayer.previous()

    def volume(self):
        valeurVolume = self.ui.dVolume.value()
        self.mediaPlayer.setVolume(valeurVolume)
        self.ui.lPourcent.setText(str(valeurVolume) + "%")

    def mediaDurationCnahged(self):
        print("mediaLoaded")
        self.ui.lTemps.setText("00:00:00")  #12
        mediaDuration = self.mediaPlayer.duration(
        )  #donne le temps en milisecondes
        self.ui.sTimeLine.setRange(0, mediaDuration)  #12
        totalTimeMedia = QTime(0, 0, 0)
        totalTimeMedia = totalTimeMedia.addMSecs(
            mediaDuration)  #convertir de milisecondes en H:m:s
        self.ui.lTempsTotal.setText(totalTimeMedia.toString("HH:mm:ss"))

    def mediaPositionCnahged(self):
        mediaPosition = self.mediaPlayer.position()
        self.ui.sTimeLine.setValue(mediaPosition)  #12
        currentTimeMedia = QTime(0, 0, 0)
        currentTimeMedia = currentTimeMedia.addMSecs(mediaPosition)
        self.ui.lTemps.setText(currentTimeMedia.toString("HH:mm:ss"))

    def mediaSelected(self):
        currentItem = self.ui.wList.currentItem()
        mediaContent = QMediaContent(QUrl.fromLocalFile((currentItem.text())))
        self.mediaPlayer.setMedia(mediaContent)
        self.lectureClicked()

    def addClicked(self):
        print("+")
        nomMedia = QFileDialog.getOpenFileName(
            self, "Choix Film",
            "C:/Users/AELION/Desktop/Aelion/PyCharm/VideoProject",
            "Movie files (*.avi *.mp4)")
        # item = QListWidgetItem(nomMedia[0])
        # self.ui.wList.addItem(item)
        fInfo = QFileInfo(nomMedia[0])
        fShortName = fInfo.baseName()
        item = QListWidgetItem(fShortName)
        item.setToolTip(nomMedia[0])
        self.ui.wList.addItem(item)

    def deleteClicked(self):
        print("-")
        rowItem = self.ui.wList.currentRow()
        if rowItem != -1:
            self.ui.wList.takeItem(rowItem)
Esempio n. 4
0
class MainWindow(QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        #Connection du decodeur et lecteur
        self.mediaPlayer = QMediaPlayer()
        self.mediaPlayer.setVideoOutput(self.ui.ecranWidget)

        #chargement du media
        mediaContent = QMediaContent(QUrl.fromLocalFile("big_buck_bunny.avi"))
        self.mediaPlayer.setMedia(mediaContent)

       #connect push boutons
        self.ui.pbLecture.clicked.connect(self.lectureClicked)
        self.ui.pbPause.clicked.connect(self.pauseClicked)
        self.ui.pbStop.clicked.connect(self.stopClicked)
        self.ui.dialVolume.valueChanged.connect(self.volControl)
        self.ui.nivoVolume.setText(str(self.ui.dialVolume.value()))
        self.ui.nivoVolume.setText('{}%'.format(str(self.ui.dialVolume.value())))
        self.mediaPlayer.durationChanged.connect(self.affTemp)
        self.mediaPlayer.positionChanged.connect(self.avanceTemp)
        self.ui.barreLect.valueChanged.connect(self.avanceSlider)
        self.ui.pbPlus.clicked.connect(self.pbPlusCtrl)
        self.ui.pbMoins.clicked.connect(self.pbMoinsCtrl)
        self.ui.listWidget.itemDoubleClicked.connect(self.mediaSelected)
        self.ui.pbSuivant.clicked.connect(self.suivantBouton)
        self.ui.pbPrecedent.clicked.connect(self.precedentBouton)



    #fonction qui gere les click
    def lectureClicked(self):
        self.mediaPlayer.play()

    def pauseClicked(self):

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

    def stopClicked(self):
        self.mediaPlayer.stop()

    def volControl(self):
        self.mediaPlayer.setVolume(self.ui.dialVolume.value())
        self.ui.nivoVolume.setText('{}%'.format(str(self.ui.dialVolume.value())))

    def affTemp(self):
        tempTotl = QTime(0, 0, 0)
        tempTotl = tempTotl.addMSecs(self.mediaPlayer.duration() - self.mediaPlayer.position())

        posTemp = QTime(0, 0, 0)
        posTemp = posTemp.addMSecs((self.mediaPlayer.position()))

        self.ui.tempRestant.setText("- {}".format(tempTotl.toString("HH:mm:ss")))
        self.ui.tempLecture.setText(posTemp.toString("HH:mm:ss"))
        self.ui.barreLect.setRange(0,self.mediaPlayer.duration())

    def avanceTemp(self):
        tempTotl= QTime(0,0,0)
        tempTotl = tempTotl.addMSecs(self.mediaPlayer.duration()-self.mediaPlayer.position())


        posTemp= QTime(0,0,0)
        posTemp = posTemp.addMSecs((self.mediaPlayer.position()))

        self.ui.tempRestant.setText("-{}".format(tempTotl.toString("HH:mm:ss")))
        self.ui.tempLecture.setText(posTemp.toString("HH:mm:ss"))
        self.ui.barreLect.setSliderPosition(self.mediaPlayer.position())

    def avanceSlider(self):
        self.mediaPlayer.setPosition(self.ui.barreLect.sliderPosition())

    def pbPlusCtrl(self):

        fileName = QFileDialog.getOpenFileName(self,"choix film","/home","Film(*.avi *.mp4)")
        fInfo = QFileInfo(fileName[0])
        fShortName = fInfo.baseName()
        item = QListWidgetItem(fShortName)
        item.setToolTip(fileName[0])
        self.ui.listWidget.addItem(item)
        print(item.toolTip().title())

    def pbMoinsCtrl(self):
        rowItem= self.ui.listWidget.currentRow()
        if rowItem != -1:
            self.ui.listWidget.takeItem(rowItem)

    def mediaSelected(self):
        currentItem = self.ui.listWidget.currentItem()
        mediaContent = QMediaContent(QUrl.fromLocalFile(currentItem.toolTip()))
        self.mediaPlayer.setMedia(mediaContent)
        self.lectureClicked()

    def suivantBouton(self):

        if self.ui.listWidget.count() != 0 :
            self.ui.listWidget.setCurrentRow((self.ui.listWidget.currentRow()+1) % self.ui.listWidget.count() )
            mediaContent = QMediaContent(QUrl.fromLocalFile(self.ui.listWidget.currentItem().toolTip()))
            self.mediaPlayer.setMedia(mediaContent)
            self.lectureClicked()

    def precedentBouton(self):

        if self.ui.listWidget.count() != 0 :
            self.ui.listWidget.setCurrentRow((self.ui.listWidget.currentRow()-1) % self.ui.listWidget.count() )
            mediaContent = QMediaContent(QUrl.fromLocalFile(self.ui.listWidget.currentItem().toolTip()))
            self.mediaPlayer.setMedia(mediaContent)
            self.lectureClicked()
Esempio n. 5
0
class SoundPlayer:
    def __init__(self, soundfile, parent):
        self.soundfile = soundfile
        self.isplaying = False
        self.time = 0  # current audio position in frames
        self.audio = QMediaPlayer()
        self.decoder = QAudioDecoder()
        self.is_loaded = False
        self.volume = 100
        self.isplaying = False
        self.decoded_audio = {}
        self.only_samples = []
        self.decoding_is_finished = False
        self.max_bits = 32768
        self.signed = False
        # File Loading is Asynchronous, so we need to be creative here, doesn't need to be duration but it works
        self.audio.durationChanged.connect(self.on_durationChanged)
        self.decoder.finished.connect(self.decode_finished_signal)
        self.audio.setMedia(QUrl.fromLocalFile(soundfile))
        self.decoder.setSourceFilename(
            soundfile)  # strangely inconsistent file-handling
        self.top_level_widget = None

        for widget in QtWidgets.QApplication.topLevelWidgets():
            if "lip_sync_frame" in dir(widget):
                self.top_level_widget = widget
        self.top_level_widget.lip_sync_frame.status_progress.show()
        self.top_level_widget.lip_sync_frame.status_progress.reset()
        self.top_level_widget.lip_sync_frame.status_progress.setMinimum(0)
        self.top_level_widget.lip_sync_frame.status_progress.setMaximum(0)
        # It will hang here forever if we don't process the events.
        while not self.is_loaded:
            QCoreApplication.processEvents()
            time.sleep(0.01)
        self.top_level_widget.lip_sync_frame.status_progress.setMaximum(
            self.decoder.duration())
        self.decode_audio(
            self.top_level_widget.lip_sync_frame.status_bar_progress)
        self.top_level_widget.lip_sync_frame.status_progress.hide()
        self.np_data = np.array(self.only_samples)
        if not self.signed:  # don't ask me why this fixes 8 bit samples...
            self.np_data = self.np_data - self.max_bits / 2
        print(len(self.only_samples))
        print(self.max_bits)
        self.isvalid = True

    def audioformat_to_datatype(self, audioformat):
        num_bits = audioformat.sampleSize()
        signed = audioformat.sampleType()
        self.max_bits = 2**int(num_bits)
        if signed == QAudioFormat.SampleType.UnSignedInt:
            self.signed = False
            return "uint{0}_t".format(str(num_bits))
        elif signed == QAudioFormat.SampleType.SignedInt:
            self.signed = True
            self.max_bits = int(self.max_bits / 2)
            return "int{0}_t".format(str(num_bits))

    def decode_audio(self, progress_callback):
        self.decoder.start()
        while not self.decoding_is_finished:
            QCoreApplication.processEvents()
            if self.decoder.bufferAvailable():
                tempdata = self.decoder.read()
                # We use the Pointer Address to get a cffi Pointer to the data (hopefully)
                cast_data = self.audioformat_to_datatype(tempdata.format())
                possible_data = ffi.cast(
                    "{1}[{0}]".format(tempdata.sampleCount(), cast_data),
                    int(tempdata.constData()))
                self.only_samples.extend(possible_data)
                self.decoded_audio[self.decoder.position()] = [
                    possible_data,
                    len(possible_data),
                    tempdata.byteCount(),
                    tempdata.format()
                ]
            progress_callback(self.decoder.position())

    def decode_finished_signal(self):
        self.decoding_is_finished = True

    def on_durationChanged(self, duration):
        self.is_loaded = True

    def get_audio_buffer(self, bufferdata):
        print(bufferdata)

    def IsValid(self):
        return self.isvalid

    def Duration(self):
        return self.audio.duration() / 1000.0

    def GetRMSAmplitude(self, time_pos, sample_dur):
        # time_start = time_pos * (len(self.only_samples)/self.Duration())
        # time_end = (time_pos + sample_dur) * (len(self.only_samples)/self.Duration())
        # samples = self.only_samples[int(time_start):int(time_end)]
        time_start = time_pos * (len(self.np_data) / self.Duration())
        time_end = (time_pos + sample_dur) * (len(self.np_data) /
                                              self.Duration())
        samples = self.np_data[int(time_start):int(time_end)]

        if len(samples):
            return np.sqrt(np.mean(samples**2))
        else:
            return 1

    def is_playing(self):
        if self.audio.state() == QMediaPlayer.PlayingState:
            return True
        else:
            return False

    def set_cur_time(self, newtime):
        self.time = newtime * 1000.0
        self.audio.setPosition(self.time)

    def stop(self):
        self.isplaying = False
        self.audio.stop()

    def current_time(self):
        self.time = self.audio.position() / 1000.0
        return self.time

    def set_volume(self, newvolume):
        self.volume = newvolume
        self.audio.setVolume(self.volume)

    def play(self, arg):
        self.isplaying = True  # TODO: We should be able to replace isplaying with queries to self.audio.state()
        self.audio.play()

    def play_segment(self, start, length):
        if not self.is_playing():  # otherwise this get's kinda echo-y
            self.isplaying = True
            self.audio.setPosition(start * 1000.0)
            self.audio.play()
            thread.start_new_thread(self._wait_for_segment_end,
                                    (start, length))

    def _wait_for_segment_end(self, newstart, newlength):
        start = newstart * 1000.0
        length = newlength * 1000.0
        end = start + length
        while self.audio.position() < end:
            if not self.isplaying:
                return 0
            QCoreApplication.processEvents()
            time.sleep(0.001)
        self.audio.stop()
        self.isplaying = False
Esempio n. 6
0
class MainWindow(QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        self.ui.pbLecture.clicked.connect(self.lectureClicked)
        self.ui.pbPause.clicked.connect(self.pauseClicked)
        self.ui.pbStop.clicked.connect(self.stopClicked)
        self.ui.dVolume.valueChanged.connect(self.volumeChanged)
        self.ui.sTpsCourant.valueChanged.connect(self.sliderPositionChanged)
        self.ui.pbAjout.clicked.connect(self.ajouterMedia2)
        self.ui.pbSuppr.clicked.connect(self.supprMedia)
        self.ui.lPlaylist.itemDoubleClicked.connect(self.mediaSelected2)

        self.mediaPlayer = QMediaPlayer()
        self.mediaPlayer.setVideoOutput(self.ui.wVideo)

        self.mediaPlayer.durationChanged.connect(self.mediaDurationChanged)
        self.mediaPlayer.positionChanged.connect(self.mediaPositionChanged)

        self.ui.pbSuivant.clicked.connect(self.suivantClicked)
        self.ui.pbPrecedent.clicked.connect(self.precedentClicked)

    def lectureClicked(self):
        print("Lecture !!")
        self.mediaPlayer.play()

    def pauseClicked(self):
        print("Pause !!")
        if self.mediaPlayer.state() == QMediaPlayer.PausedState:
            self.mediaPlayer.play()
        elif self.mediaPlayer.state() == QMediaPlayer.PlayingState:
            self.mediaPlayer.pause()

    def stopClicked(self):
        self.mediaPlayer.stop()

    def volumeChanged(self):
        self.mediaPlayer.setVolume(self.ui.dVolume.value())
        self.ui.lVolume.setText(str(self.ui.dVolume.value()) + "%")

    def mediaDurationChanged(self):
        print("mediaLoaded")
        self.ui.lTpsCourant.setText("00:00:00")
        mediaDuration = self.mediaPlayer.duration()
        self.ui.sTpsCourant.setRange(0, mediaDuration)  ###############
        totalTimeMedia = QTime(0, 0, 0)
        totalTimeMedia = totalTimeMedia.addMSecs(mediaDuration)
        self.ui.lTpsTotal.setText(totalTimeMedia.toString("HH:mm:ss"))

    def mediaPositionChanged(self):
        self.ui.sTpsCourant.valueChanged.disconnect(self.sliderPositionChanged)
        mediaPosition = self.mediaPlayer.position()
        self.ui.sTpsCourant.setValue(mediaPosition)  ##############
        currentTimeMedia = QTime(0, 0, 0)
        currentTimeMedia = currentTimeMedia.addMSecs(mediaPosition)
        self.ui.lTpsCourant.setText(currentTimeMedia.toString("HH:mm:ss"))
        self.ui.sTpsCourant.valueChanged.connect(self.sliderPositionChanged)

    def sliderPositionChanged(self):
        self.mediaPlayer.positionChanged.disconnect(self.mediaPositionChanged)
        self.mediaPlayer.setPosition(self.ui.sTpsCourant.value())
        self.mediaPlayer.positionChanged.connect(self.mediaPositionChanged)

    def ajouterMedia(self):
        nomMedia = QFileDialog.getOpenFileName(self, "Choix Film", "c:/",
                                               "Movie Files (*.avi *.mp4)")
        item = QListWidgetItem(nomMedia[0])
        self.ui.lPlaylist.addItem(item)

    def ajouterMedia2(self):
        nomMedia = QFileDialog.getOpenFileName(self, "Choix Film", "c:/",
                                               "Movie Files (*.avi *.mp4)")

        if nomMedia[0] == "":  #si aucun fichier selectionné
            return

        fInfo = QFileInfo(nomMedia[0])
        fShortName = fInfo.baseName()
        item = QListWidgetItem(fShortName)
        item.setToolTip(nomMedia[0])
        self.ui.lPlaylist.addItem(item)

    def supprMedia(self):
        rowItem = self.ui.lPlaylist.currentRow()
        if rowItem != -1:
            self.ui.lPlaylist.takeItem(rowItem)

    def mediaSelected(self):
        currentItem = self.ui.lPlaylist.currentItem()
        mediaContent = QMediaContent(QUrl.fromLocalFile(currentItem.text()))
        self.mediaPlayer.setMedia(mediaContent)
        self.lectureClicked()

    def mediaSelected2(self):
        currentItem = self.ui.lPlaylist.currentItem()
        mediaContent = QMediaContent(QUrl.fromLocalFile(currentItem.toolTip()))
        self.mediaPlayer.setMedia(mediaContent)
        self.lectureClicked()

    def suivantClicked(self):
        currentItemRow = self.ui.lPlaylist.currentRow()
        if currentItemRow == -1:
            return
        totalItems = self.ui.lPlaylist.count()
        self.ui.lPlaylist.setCurrentRow((currentItemRow + 1) % totalItems)
        self.mediaSelected2()

    def precedentClicked(self):
        currentItemRow = self.ui.lPlaylist.currentRow()
        if currentItemRow == -1:
            return
        totalItems = self.ui.lPlaylist.count()
        self.ui.lPlaylist.setCurrentRow((currentItemRow - 1) % totalItems)
        self.mediaSelected2()
Esempio n. 7
0
class MainWindow(QMainWindow):  # Main window
    def __init__(self):
        super().__init__()
        self.setWindowTitle = 'DD烤肉机'
        self.resize(1870, 820)
        self.mainWidget = QWidget()
        self.mainLayout = QGridLayout()  # Grid layout
        self.mainLayout.setSpacing(10)
        self.mainWidget.setLayout(self.mainLayout)
        self.duration = 60000
        self.bitrate = 2000
        self.fps = 60

        self.initProcess = InitProcess()
        self.previewSubtitle = PreviewSubtitle()
        self.dnldWindow = YoutubeDnld()
        self.exportWindow = exportSubtitle()
        self.videoDecoder = VideoDecoder()
        self.exportWindow.exportArgs.connect(self.exportSubtitle)
        self.stack = QStackedWidget()
        self.stack.setFixedWidth(1300)
        self.mainLayout.addWidget(self.stack, 0, 0, 10, 8)
        buttonWidget = QWidget()
        buttonLayout = QHBoxLayout()
        buttonWidget.setLayout(buttonLayout)
        self.playButton = QPushButton('从本地打开')
        self.playButton.clicked.connect(self.open)
        self.playButton.setFixedWidth(400)
        self.playButton.setFixedHeight(75)
        self.dnldButton = QPushButton('Youtube下载器')
        self.dnldButton.clicked.connect(self.popDnld)
        self.dnldButton.setFixedWidth(400)
        self.dnldButton.setFixedHeight(75)
        buttonLayout.addWidget(self.playButton)
        buttonLayout.addWidget(self.dnldButton)
        self.stack.addWidget(buttonWidget)

        self.videoPath = ''
        self.videoWidth = 1920
        self.videoHeight = 1080
        self.globalInterval = 200
        self.setPlayer()
        self.setSubtitle()
        self.setToolBar()
        self.setCentralWidget(self.mainWidget)
        self.playStatus = False
        self.volumeStatus = True
        self.volumeValue = 100
        self.subSelectedTxt = ''
        self.subReplayTime = 1
        self.clipBoard = []
        self.grabKeyboard()
        self.show()

    def setPlayer(self):
        self.playerWidget = QGraphicsVideoItem()
        self.scene = QGraphicsScene()
        self.view = QGraphicsView(self.scene)
        self.view.resize(1280, 730)
        self.scene.addItem(self.playerWidget)
        self.stack.addWidget(self.view)
        self.player = QMediaPlayer(self, QMediaPlayer.VideoSurface)
        self.player.setVideoOutput(self.playerWidget)
        self.view.installEventFilter(self)
        self.view.show()
        self.srtTextItemDict = {0: QGraphicsTextItem(), 1: QGraphicsTextItem(), 2: QGraphicsTextItem(), 3: QGraphicsTextItem(), 4: QGraphicsTextItem()}
        for _, srtTextItem in self.srtTextItemDict.items():
            self.scene.addItem(srtTextItem)

    def setSubtitle(self):
        self.subtitleDict = {x: {-1: [100, '']} for x in range(5)}
        self.subTimer = QTimer()
        self.subTimer.setInterval(100)
        self.subtitle = QTableWidget()
        self.subtitle.setAutoScroll(False)
        self.subtitle.setEditTriggers(QAbstractItemView.NoEditTriggers)
        self.mainLayout.addWidget(self.subtitle, 0, 8, 10, 12)
        self.subtitle.setColumnCount(5)
        self.subtitle.selectRow(0)
        self.subtitle.setHorizontalHeaderLabels(['%s' % (i + 1) for i in range(5)])
        self.subtitle.setVerticalHeaderLabels([cnt2Time2(i, self.globalInterval) for i in range(self.subtitle.rowCount())])
        for index in range(5):
            self.subtitle.setColumnWidth(index, 130)
        self.subtitle.setHorizontalScrollMode(QAbstractItemView.ScrollPerPixel)
        self.subtitle.setEditTriggers(QAbstractItemView.DoubleClicked)
        self.subtitle.horizontalHeader().sectionClicked.connect(self.addSubtitle)
        self.subtitle.doubleClicked.connect(self.releaseKeyboard)
        self.subtitle.cellChanged.connect(self.subEdit)
        self.subtitle.verticalHeader().sectionClicked.connect(self.subHeaderClick)
        self.subtitle.setContextMenuPolicy(Qt.CustomContextMenu)
        self.subtitle.customContextMenuRequested.connect(self.popTableMenu)
        self.initSubtitle()

    def initSubtitle(self):
        self.initProcess.show()
        self.subtitle.cellChanged.disconnect(self.subEdit)
        for x in range(self.subtitle.columnCount()):
            for y in range(self.subtitle.rowCount()):
                self.subtitle.setSpan(y, x, 1, 1)
        self.subtitle.setRowCount(self.duration // self.globalInterval + 1)
        for x in range(self.subtitle.columnCount()):
            for y in range(self.subtitle.rowCount()):
                self.subtitle.setItem(y, x, QTableWidgetItem(''))
                self.subtitle.item(y, x).setBackground(QBrush(QColor('#232629')))
        self.subtitle.setVerticalHeaderLabels([cnt2Time2(i, self.globalInterval) for i in range(self.subtitle.rowCount())])
        self.subtitle.cellChanged.connect(self.subEdit)
        self.initProcess.hide()

    def addSubtitle(self, index):
        subtitlePath = QFileDialog.getOpenFileName(self, "请选择字幕", None, "字幕文件 (*.srt *.vtt *.ass *.ssa)")[0]
        if subtitlePath:
            self.initProcess.show()
            self.subtitle.cellChanged.disconnect(self.subEdit)
            if subtitlePath.endswith('.ass') or subtitlePath.endswith('.ssa'):
                p = subprocess.Popen(['utils/ffmpeg.exe', '-y', '-i', subtitlePath, 'temp_sub.srt'])
                p.wait()
                subtitlePath = 'temp_sub.srt'
            subData = {}
            with open(subtitlePath, 'r', encoding='utf-8') as f:
                f = f.readlines()
            subText = ''
            YoutubeAutoSub = False
            for l in f:
                if '<c>' in l:
                    YoutubeAutoSub = True
                    break
            for cnt, l in enumerate(f):
                if '<c>' in l:
                    lineData = l.split('c>')
                    if len(lineData) > 3:
                        subText, start, _ = lineData[0].split('<')
                        start = calSubTime(start[:-1]) // self.globalInterval * self.globalInterval
                        if start not in self.subtitleDict[index]:
                            end = calSubTime(lineData[-3][1:-2]) // self.globalInterval * self.globalInterval
                            for i in range(len(lineData) // 2):
                                subText += lineData[i * 2 + 1][:-2]
                            subData[start] = [end - start, subText]
                    else:
                        subText, start, _ = lineData[0].split('<')
                        start = calSubTime(start[:-1]) // self.globalInterval * self.globalInterval
                        if start not in self.subtitleDict[index]:
                            subText += lineData[1][:-2]
                            subData[start] = [self.globalInterval, subText]
                elif '-->' in l and f[cnt + 2].strip() and '<c>' not in f[cnt + 2]:
                    subText = f[cnt + 2][:-1]
                    start = calSubTime(l[:12]) // self.globalInterval * self.globalInterval
                    if start not in self.subtitleDict[index]:
                        end = calSubTime(l[17:29]) // self.globalInterval * self.globalInterval
                        subData[start] = [end - start, subText]
                if '-->' in l and f[cnt + 1].strip() and not YoutubeAutoSub:
                    start = calSubTime(l[:12]) // self.globalInterval * self.globalInterval
                    if start not in self.subtitleDict[index]:
                        end = calSubTime(l[17:29]) // self.globalInterval * self.globalInterval
                        delta = end - start
                        if delta > 10:
                            if '<b>' in f[cnt + 1]:
                                subData[start] = [delta, f[cnt + 1].split('<b>')[1].split('<')[0]]
                            else:
                                subData[start] = [delta, f[cnt + 1][:-1]]
            self.subtitleDict[index].update(subData)
            maxRow = 0
            for _, v in self.subtitleDict.items():
                startMax = max(v.keys())
                rowCount = (startMax + v[startMax][0]) // self.globalInterval
                if rowCount > maxRow:
                    maxRow = rowCount
            if maxRow < self.duration // self.globalInterval + 1:
                maxRow = self.duration // self.globalInterval
            else:
                self.duration = maxRow * self.globalInterval
            self.subtitle.setRowCount(maxRow)
            self.subtitle.setVerticalHeaderLabels([cnt2Time2(i, self.globalInterval) for i in range(self.subtitle.rowCount())])
            for start, rowData in subData.items():
                startRow = start // self.globalInterval
                endRow = startRow + rowData[0] // self.globalInterval
                for row in range(startRow, endRow):
                    self.subtitle.setItem(row, index, QTableWidgetItem(rowData[1]))
                    self.subtitle.item(row, index).setBackground(QBrush(QColor('#35545d')))
                self.subtitle.setSpan(startRow, index, endRow - startRow, 1)
            self.refreshComboBox()
            self.subtitle.cellChanged.connect(self.subEdit)
            self.initProcess.hide()

    def subTimeOut(self):
        fontColor = self.previewSubtitle.fontColor
        fontSize = (self.previewSubtitle.fontSize + 5) / 2.5
        fontBold = self.previewSubtitle.bold
        fontItalic = self.previewSubtitle.italic
        fontShadowOffset = self.previewSubtitle.shadowOffset
        for _, srtTextItem in self.srtTextItemDict.items():
            srtTextItem.setDefaultTextColor(fontColor)
            font = QFont()
            font.setFamily("微软雅黑")
            font.setPointSize(fontSize)
            font.setBold(fontBold)
            font.setItalic(fontItalic)
            srtTextItem.setFont(font)
            srtTextShadow = QGraphicsDropShadowEffect()
            srtTextShadow.setOffset(fontShadowOffset)
            srtTextItem.setGraphicsEffect(srtTextShadow)
        try:
            selected = self.subtitle.selectionModel().selection().indexes()
            for x, i in enumerate(selected):
                if self.subtitle.item(i.row(), x):
                    txt = self.subtitle.item(i.row(), x).text()
                    if txt:
                        self.srtTextItemDict[x].setPlainText('#%s:' % (x + 1) + txt)
                        txtSize = self.srtTextItemDict[x].boundingRect().size()
                        posY = self.playerWidget.size().height() - txtSize.height() * (x + 1)
                        posX = (self.playerWidget.size().width() - txtSize.width()) / 2
                        self.srtTextItemDict[x].setPos(posX, posY)
                    else:
                        self.srtTextItemDict[x].setPlainText('')
                else:
                    self.srtTextItemDict[x].setPlainText('')
        except:
            pass

    def subHeaderClick(self, index):
        if self.player.duration():
            position = index * self.globalInterval
            self.player.setPosition(position)
            self.videoSlider.setValue(position * 1000 // self.player.duration())
            self.setTimeLabel()

    def subEdit(self, row, index):
        repeat = self.subtitle.rowSpan(row, index)
        self.setSubtitleDict(row, index, repeat, self.subtitle.item(row, index).text())
        self.subtitle.cellChanged.disconnect(self.subEdit)
        for cnt in range(repeat):
            if self.subtitle.item(row + cnt, index).text():
                self.subtitle.item(row, index).setBackground(QBrush(QColor('#35545d')))
            else:
                self.subtitle.item(row, index).setBackground(QBrush(QColor('#232629')))
        self.subtitle.cellChanged.connect(self.subEdit)

    def setSubtitleDict(self, row, index, num, text):
        self.subtitleDict[index][row * self.globalInterval] = [num * self.globalInterval, text]

    def popTableMenu(self, pos):
        self.subtitle.cellChanged.disconnect(self.subEdit)
        pos = QPoint(pos.x() + 55, pos.y() + 30)
        menu = QMenu()
        copy = menu.addAction('复制')
        paste = menu.addAction('粘贴')
        setSpan = menu.addAction('合并')
        clrSpan = menu.addAction('拆分')
        addSub = menu.addAction('导入字幕')
        cutSub = menu.addAction('裁剪字幕')
        action = menu.exec_(self.subtitle.mapToGlobal(pos))
        selected = self.subtitle.selectionModel().selection().indexes()
        yList = [selected[0].row(), selected[-1].row()]
        xSet = set()
        for i in range(len(selected)):
            xSet.add(selected[i].column())
        if action == copy:
            for x in xSet:
                self.clipBoard = []
                for y in range(yList[0], yList[1] + 1):
                    if self.subtitle.item(y, x):
                        self.clipBoard.append(self.subtitle.item(y, x).text())
                    else:
                        self.clipBoard.append('')
                break
        elif action == paste:
            self.subtitle.cellChanged.connect(self.subEdit)
            for x in xSet:
                for cnt, text in enumerate(self.clipBoard):
                    self.subtitle.setItem(yList[0] + cnt, x, QTableWidgetItem(text))
                    self.subtitleDict[x][(yList[0] + cnt) * self.globalInterval] = [self.globalInterval, text]
            self.subtitle.cellChanged.disconnect(self.subEdit)
        elif action == setSpan:
            for x in xSet:
                if not self.subtitle.item(yList[0], x):
                    firstItem = ''
                else:
                    firstItem = self.subtitle.item(yList[0], x).text()
                for y in range(yList[0], yList[1] + 1):
                    self.subtitle.setSpan(y, x, 1, 1)
                    self.subtitle.setItem(y, x, QTableWidgetItem(firstItem))
                    self.subtitle.item(y, x).setBackground(QBrush(QColor('#35545d')))
                    if y * self.globalInterval in self.subtitleDict[x]:
                        del self.subtitleDict[x][y * self.globalInterval]
            for x in xSet:
                self.subtitle.setSpan(yList[0], x, yList[1] - yList[0] + 1, 1)
            self.setSubtitleDict(yList[0], x, yList[1] - yList[0] + 1, firstItem)
        elif action == clrSpan:
            for x in xSet:
                if not self.subtitle.item(yList[0], x):
                    firstItem = ''
                else:
                    firstItem = self.subtitle.item(yList[0], x).text()
                for cnt, y in enumerate(range(yList[0], yList[1] + 1)):
                    self.subtitle.setSpan(y, x, 1, 1)
                    if not cnt:
                        self.subtitle.setItem(yList[0], x, QTableWidgetItem(firstItem))
                        if firstItem:
                            self.subtitle.item(y, x).setBackground(QBrush(QColor('#35545d')))
                        else:
                            self.subtitle.item(y, x).setBackground(QBrush(QColor('#232629')))
                    else:
                        self.subtitle.setItem(y, x, QTableWidgetItem(''))
                        self.subtitle.item(y, x).setBackground(QBrush(QColor('#232629')))
                    self.setSubtitleDict(yList[0], x, yList[1] - yList[0] + 1, firstItem)
                break
        elif action == addSub:
            self.subtitle.cellChanged.connect(self.subEdit)
            for x in xSet:
                self.addSubtitle(x)
            self.subtitle.cellChanged.disconnect(self.subEdit)
        elif action == cutSub:
            for x in xSet:
                start = yList[0] * self.globalInterval
                end = yList[1] * self.globalInterval
                self.exportSubWindow(start, end, x + 1)
        self.subtitle.cellChanged.connect(self.subEdit)

    def setToolBar(self):
        '''
        menu bar, file menu, play menu, tool bar.
        '''
        toolBar = QToolBar()
        self.setContextMenuPolicy(Qt.NoContextMenu)
        self.addToolBar(toolBar)
        fileMenu = self.menuBar().addMenu('&文件')
        openAction = QAction(QIcon.fromTheme('document-open'), '&打开...', self, shortcut=QKeySequence.Open, triggered=self.open)
        fileMenu.addAction(openAction)
        downloadAction = QAction(QIcon.fromTheme('document-open'), '&Youtube下载器', self, triggered=self.popDnld)
        fileMenu.addAction(downloadAction)
        exitAction = QAction(QIcon.fromTheme('application-exit'), '&退出', self, shortcut='Ctrl+Q', triggered=self.close)
        fileMenu.addAction(exitAction)

        playMenu = self.menuBar().addMenu('&功能')
        self.playIcon = self.style().standardIcon(QStyle.SP_MediaPlay)
        self.pauseIcon = self.style().standardIcon(QStyle.SP_MediaPause)
        self.playAction = toolBar.addAction(self.playIcon, '播放')
        self.playAction.triggered.connect(self.mediaPlay)
        self.volumeIcon = self.style().standardIcon(QStyle.SP_MediaVolume)
        self.volumeMuteIcon = self.style().standardIcon(QStyle.SP_MediaVolumeMuted)
        self.volumeAction = toolBar.addAction(self.volumeIcon, '静音')
        self.volumeAction.triggered.connect(self.volumeMute)
        previewAction = QAction(QIcon.fromTheme('document-open'), '&设置预览字幕', self, triggered=self.popPreview)
        playMenu.addAction(previewAction)

        decodeMenu = self.menuBar().addMenu('&输出')
        decodeAction = QAction(QIcon.fromTheme('document-open'), '&输出字幕及视频', self, triggered=self.decode)
        decodeMenu.addAction(decodeAction)

        self.volSlider = Slider()
        self.volSlider.setOrientation(Qt.Horizontal)
        self.volSlider.setMinimum(0)
        self.volSlider.setMaximum(100)
        self.volSlider.setFixedWidth(120)
        self.volSlider.setValue(self.player.volume())
        self.volSlider.setToolTip(str(self.volSlider.value()))
        self.volSlider.pointClicked.connect(self.setVolume)
        toolBar.addWidget(self.volSlider)

        self.videoPositionEdit = LineEdit('00:00')
        self.videoPositionEdit.setAlignment(Qt.AlignRight)
        self.videoPositionEdit.setFixedWidth(75)
        self.videoPositionEdit.setFont(QFont('Timers', 14))
        self.videoPositionEdit.clicked.connect(self.mediaPauseOnly)
        self.videoPositionEdit.editingFinished.connect(self.mediaPlayOnly)
        self.videoPositionLabel = QLabel(' / 00:00  ')
        self.videoPositionLabel.setFont(QFont('Timers', 14))
        toolBar.addWidget(QLabel('    '))
        toolBar.addWidget(self.videoPositionEdit)
        toolBar.addWidget(self.videoPositionLabel)

        self.timer = QTimer()
        self.timer.setInterval(100)
        self.videoSlider = Slider()
        self.videoSlider.setEnabled(False)
        self.videoSlider.setOrientation(Qt.Horizontal)
        self.videoSlider.setMinimum(0)
        self.videoSlider.setMaximum(1000)
        self.videoSlider.setFixedWidth(1000)
        self.videoSlider.sliderMoved.connect(self.timeStop)
        self.videoSlider.sliderReleased.connect(self.timeStart)
        self.videoSlider.pointClicked.connect(self.videoSliderClick)
        toolBar.addWidget(self.videoSlider)

        toolBar.addWidget(QLabel('   '))
        self.globalIntervalComBox = QComboBox()
        self.globalIntervalComBox.addItems(['间隔 100ms', '间隔 200ms', '间隔 500ms', '间隔 1s'])
        self.globalIntervalComBox.setCurrentIndex(1)
        self.globalIntervalComBox.currentIndexChanged.connect(self.setGlobalInterval)
        toolBar.addWidget(self.globalIntervalComBox)
        toolBar.addWidget(QLabel('  '))
        self.subEditComBox = QComboBox()
        self.refreshComboBox()
        toolBar.addWidget(self.subEditComBox)
        toolBar.addWidget(QLabel('  '))
        moveForward = QPushButton('- 1')
        moveForward.setFixedWidth(50)
        toolBar.addWidget(moveForward)
        toolBar.addWidget(QLabel('  '))
        moveAfterward = QPushButton('+ 1')
        moveAfterward.setFixedWidth(50)
        toolBar.addWidget(moveAfterward)
        toolBar.addWidget(QLabel('  '))
        clearSub = QPushButton('清空')
        clearSub.setFixedWidth(50)
        toolBar.addWidget(clearSub)
        toolBar.addWidget(QLabel('  '))
        outputSub = QPushButton('裁剪')
        outputSub.setFixedWidth(50)
        toolBar.addWidget(outputSub)
        moveForward.clicked.connect(self.moveForward)
        moveAfterward.clicked.connect(self.moveAfterward)
        clearSub.clicked.connect(self.clearSub)
        outputSub.clicked.connect(self.exportSubWindow)

    def setGlobalInterval(self, index):
        if not self.playStatus:
            self.mediaPlay()
        self.globalInterval = {0: 100, 1: 200, 2: 500, 3: 1000}[index]
        self.initSubtitle()
        self.initProcess.show()
        self.subtitle.cellChanged.disconnect(self.subEdit)
        for index, subData in self.subtitleDict.items():
            for start, rowData in subData.items():
                startRow = start // self.globalInterval
                deltaRow = rowData[0] // self.globalInterval
                if deltaRow:
                    endRow = startRow + deltaRow
                    for row in range(startRow, endRow):
                        self.subtitle.setItem(row, index, QTableWidgetItem(rowData[1]))
                        if row >= 0:
                            self.subtitle.item(row, index).setBackground(QBrush(QColor('#35545d')))
                    self.subtitle.setSpan(startRow, index, endRow - startRow, 1)
        self.subtitle.cellChanged.connect(self.subEdit)
        self.initProcess.hide()

    def moveForward(self):
        self.initProcess.show()
        self.subtitle.cellChanged.disconnect(self.subEdit)
        index = self.subEditComBox.currentIndex()
        for y in range(self.subtitle.rowCount()):
            self.subtitle.setSpan(y, index, 1, 1)
            self.subtitle.setItem(y, index, QTableWidgetItem(''))
            self.subtitle.item(y, index).setBackground(QBrush(QColor('#232629')))
        tmpDict = self.subtitleDict[index]
        self.subtitleDict[index] = {}
        for start, rowData in tmpDict.items():
            self.subtitleDict[index][start - self.globalInterval] = rowData
        for start, rowData in self.subtitleDict[index].items():
            startRow = start // self.globalInterval
            endRow = startRow + rowData[0] // self.globalInterval
            for row in range(startRow, endRow):
                self.subtitle.setItem(row, index, QTableWidgetItem(rowData[1]))
                self.subtitle.item(row, index).setBackground(QBrush(QColor('#35545d')))
            self.subtitle.setSpan(startRow, index, endRow - startRow, 1)
        self.subtitle.cellChanged.connect(self.subEdit)
        self.initProcess.hide()

    def moveAfterward(self):
        self.initProcess.show()
        self.subtitle.cellChanged.disconnect(self.subEdit)
        index = self.subEditComBox.currentIndex()
        for y in range(self.subtitle.rowCount()):
            self.subtitle.setSpan(y, index, 1, 1)
            self.subtitle.setItem(y, index, QTableWidgetItem(''))
            self.subtitle.item(y, index).setBackground(QBrush(QColor('#232629')))
        tmpDict = self.subtitleDict[index]
        self.subtitleDict[index] = {}
        for start, rowData in tmpDict.items():
            self.subtitleDict[index][start + self.globalInterval] = rowData
        for start, rowData in self.subtitleDict[index].items():
            startRow = start // self.globalInterval
            endRow = startRow + rowData[0] // self.globalInterval
            for row in range(startRow, endRow):
                self.subtitle.setItem(row, index, QTableWidgetItem(rowData[1]))
                self.subtitle.item(row, index).setBackground(QBrush(QColor('#35545d')))
            self.subtitle.setSpan(startRow, index, endRow - startRow, 1)
        self.subtitle.cellChanged.connect(self.subEdit)
        self.initProcess.hide()

    def clearSub(self):
        index = self.subEditComBox.currentIndex()
        reply = QMessageBox.information(self, '清空字幕', '清空第 %s 列字幕条?' % (index + 1), QMessageBox.Yes | QMessageBox.No)
        if reply == QMessageBox.Yes:
            self.initProcess.show()
            self.subtitle.cellChanged.disconnect(self.subEdit)
            self.subtitleDict[index] = {0: [self.globalInterval, '']}
            for i in range(self.subtitle.rowCount()):
                self.subtitle.setSpan(i, index, 1, 1)
                self.subtitle.setItem(i, index, QTableWidgetItem(''))
                self.subtitle.item(i, index).setBackground(QBrush(QColor('#232629')))
                self.subtitle.setHorizontalHeaderItem(index, QTableWidgetItem('%s' % (index + 1)))
            self.subtitle.cellChanged.connect(self.subEdit)
            self.initProcess.hide()

    def exportSubWindow(self, start=0, end=0, index=None):
        self.releaseKeyboard()
        self.exportWindow.hide()
        self.exportWindow.show()
        start = '00:00.0' if not start else self.splitTime(start)
        end = self.splitTime(self.duration) if not end else self.splitTime(end)
        if not index:
            index = self.subEditComBox.currentIndex() + 1
        self.exportWindow.setDefault(start, end, index)

    def exportSubtitle(self, exportArgs):
        start = calSubTime2(exportArgs[0])
        end = calSubTime2(exportArgs[1])
        subStart = calSubTime2(exportArgs[2])
        index = exportArgs[3] - 1
        subData = self.subtitleDict[index]
        rowList = sorted(subData.keys())
        exportRange = []
        for t in rowList:
            if t >= start and t <= end:
                exportRange.append(t)
        subNumber = 1
        with open(exportArgs[-1], 'w', encoding='utf-8') as exportFile:
            for t in exportRange:
                text = subData[t][1]
                if text:
                    start = ms2Time(t + subStart)
                    end = ms2Time(t + subStart + subData[t][0])
                    exportFile.write('%s\n%s --> %s\n%s\n\n' % (subNumber, start, end, text))
                    subNumber += 1
        QMessageBox.information(self, '导出字幕', '导出完成', QMessageBox.Yes)
        self.exportWindow.hide()

    def refreshComboBox(self):
        self.subEditComBox.clear()
        for i in range(self.subtitle.columnCount()):
            self.subEditComBox.addItem('字幕 ' + str(i + 1))

    def open(self):
        self.videoPath = QFileDialog.getOpenFileName(self, "请选择视频文件", None, "MP4格式 (*.mp4);;所有文件(*.*)")[0]
        if self.videoPath:
            cmd = ['utils/ffmpeg.exe', '-i', self.videoPath]
            p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
            p.wait()
            for l in p.stdout.readlines():
                l = l.decode('utf8')
                if 'Duration' in l:
                    self.duration = calSubTime(l.split(' ')[3][:-1])
                if 'Stream' in l and 'DAR' in l:
                    self.videoWidth, self.videoHeight = map(int, l.split(' [')[0].split(' ')[-1].split('x'))
                    args = l.split(',')
                    for cnt, arg in enumerate(args):
                        if 'kb' in arg:
                            self.bitrate = int(arg.split('kb')[0])
                            self.fps = int(args[cnt + 1].split('fps')[0])
                            break
                    break
            self.initProcess.show()
            self.subtitle.cellChanged.disconnect(self.subEdit)
            self.subtitle.setRowCount(self.duration // self.globalInterval + 1)
            self.subtitle.setVerticalHeaderLabels([cnt2Time2(i, self.globalInterval) for i in range(self.subtitle.rowCount())])
            self.subtitle.cellChanged.connect(self.subEdit)
            self.initProcess.hide()
            url = QUrl.fromLocalFile(self.videoPath)
            self.stack.setCurrentIndex(1)
            self.playerWidget.setSize(QSizeF(1280, 720))
            self.player.setMedia(url)
            self.playStatus = True
            self.videoSlider.setEnabled(True)
            self.mediaPlay()
            self.timer.start()
            self.timer.timeout.connect(self.timeOut)
            self.subTimer.start()
            self.subTimer.timeout.connect(self.subTimeOut)

    def popDnld(self):
        self.releaseKeyboard()
        self.dnldWindow.hide()
        self.dnldWindow.show()

    def popPreview(self):
        self.releaseKeyboard()
        self.previewSubtitle.hide()
        self.previewSubtitle.show()

    def decode(self):
        self.releaseKeyboard()
        self.videoDecoder.setDefault(self.videoPath, self.videoWidth, self.videoHeight, self.duration, self.bitrate, self.fps, self.subtitleDict)
        self.videoDecoder.hide()
        self.videoDecoder.show()

    def mediaPlay(self):
        if self.playStatus:
            self.player.play()
            self.grabKeyboard()
            self.timeStart()
            self.playStatus = False
            self.playAction.setIcon(self.pauseIcon)
            self.playAction.setText('暂停')
        else:
            self.player.pause()
            self.timeStop()
            self.playStatus = True
            self.playAction.setIcon(self.playIcon)
            self.playAction.setText('播放')

    def mediaPlayOnly(self):
        self.grabKeyboard()
        try:
            timeText = self.videoPositionEdit.text().split(':')
            m, s = timeText[:2]
            if not m:
                m = '00'
            if not s:
                s = '00'
            if len(m) > 3:
                m = m[:3]
            if len(s) > 2:
                s = s[:2]
            if m.isdigit():
                m = int(m)
            if s.isdigit():
                s = int(s)
            if s > 60:
                s = 60
            total_m = self.player.duration() // 60000
            if m > total_m:
                m = total_m
            self.player.setPosition(m * 60000 + s * 1000)
            self.videoSlider.setValue(self.player.position() * 1000 / self.player.duration())
        except:
            pass
        self.videoPositionEdit.setReadOnly(True)
        self.timeStart()

    def mediaPauseOnly(self):
        self.releaseKeyboard()
        self.videoPositionEdit.setReadOnly(False)
        self.player.pause()
        self.timeStop()
        self.playStatus = True
        self.playAction.setIcon(self.playIcon)
        self.playAction.setText('播放')

    def splitTime(self, playTime):
        playTime = playTime // 1000
        m = str(playTime // 60)
        s = playTime % 60
        s = ('0%s' % s)[-2:]
        if len(m) > 2:
            t = '%3s:%2s' % (m, s)
        else:
            t = '%2s:%2s' % (m, s)
        return t

    def timeOut(self):
        row = self.player.position() // self.globalInterval
        self.subtitle.selectRow(row)
        self.subtitle.verticalScrollBar().setValue(row - 10)
        if self.dnldWindow.isHidden() or self.exportWindow.isHidden() or self.videoDecoder.isHidden():
            self.grabKeyboard()
        try:
            self.videoSlider.setValue(self.player.position() * 1000 / self.player.duration())
            self.setTimeLabel()
        except:
            pass

    def timeStop(self):
        self.timer.stop()

    def timeStart(self):
        self.timer.start()

    def videoSliderClick(self, p):
        self.videoSlider.setValue(p.x())
        self.player.setPosition(p.x() * self.player.duration() // 1000)
        self.setTimeLabel()

    def setVolume(self, p):
        self.volumeValue = p.x()
        if self.volumeValue > 100:
            self.volumeValue = 100
        if self.volumeValue < 0:
            self.volumeValue = 0
        self.volSlider.setValue(self.volumeValue)
        self.player.setVolume(self.volumeValue)
        self.volSlider.setToolTip(str(self.volSlider.value()))
        if self.volumeValue:
            self.volumeStatus = True
            self.volumeAction.setIcon(self.volumeIcon)
        else:
            self.volumeStatus = False
            self.volumeAction.setIcon(self.volumeMuteIcon)

    def volumeMute(self):
        if self.volumeStatus:
            self.volumeStatus = False
            self.old_volumeValue = self.player.volume()
            self.player.setVolume(0)
            self.volSlider.setValue(0)
            self.volumeAction.setIcon(self.volumeMuteIcon)
        else:
            self.volumeStatus = True
            self.player.setVolume(self.old_volumeValue)
            self.volSlider.setValue(self.old_volumeValue)
            self.volumeAction.setIcon(self.volumeIcon)

    def setTimeLabel(self):
        now = self.player.position()
        total = self.player.duration()
        now = self.splitTime(now)
        total = self.splitTime(total)
        self.videoPositionEdit.setText(now)
        self.videoPositionLabel.setText(' / %s  ' % total)

    def eventFilter(self, obj, event):
        if obj == self.view:
            if event.type() == QEvent.MouseButtonPress:
                self.mediaPlay()
        return QMainWindow.eventFilter(self, obj, event)

    def keyPressEvent(self, QKeyEvent):
        key = QKeyEvent.key()
        if key == Qt.Key_Left:
            if self.videoSlider.isEnabled():
                self.player.setPosition(self.player.position() - 5000)
                self.videoSlider.setValue(self.player.position() * 1000 / self.player.duration())
                self.setTimeLabel()
        elif key == Qt.Key_Right:
            if self.videoSlider.isEnabled():
                self.player.setPosition(self.player.position() + 5000)
                self.videoSlider.setValue(self.player.position() * 1000 / self.player.duration())
                self.setTimeLabel()
        elif key == Qt.Key_Up:
            self.volumeValue += 10
            if self.volumeValue > 100:
                self.volumeValue = 100
            self.volSlider.setValue(self.volumeValue)
            self.player.setVolume(self.volumeValue)
        elif key == Qt.Key_Down:
            self.volumeValue -= 10
            if self.volumeValue < 0:
                self.volumeValue = 0
            self.volSlider.setValue(self.volumeValue)
            self.player.setVolume(self.volumeValue)
        elif key == Qt.Key_Space:
            self.mediaPlay()
Esempio n. 8
0
class MainWindow(QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        self.ui.lecture.clicked.connect(self.lectureClicked)
        self.mediaPlayer = QMediaPlayer()
        self.mediaPlayer.setVideoOutput(self.ui.ecran)

        self.ui.pause.clicked.connect(self.pauseClicked)
        self.ui.suivant.clicked.connect(self.suivantClicked)
        self.ui.stop.clicked.connect(self.stopClicked)
        self.ui.precedent.clicked.connect(self.precedentClicked)

        self.ui.dialVol.valueChanged.connect(self.dVol)

        self.ui.slider.sliderMoved.connect(self.sliderMov)

        mediaContent = QMediaContent(QUrl.fromLocalFile("big_buck_bunny.avi"))
        self.mediaPlayer.setMedia(mediaContent)
        self.mediaPlayer.positionChanged.connect(self.mediaDurationChange)
        self.mediaPlayer.positionChanged.connect(self.mediapositionChange)

    def lectureClicked(self):
        print("Lecture !!!")
        self.mediaPlayer.play()
        #self.sliderMov.connect()

    def pauseClicked(self):
        print("Pause !!!")
        if self.mediaPlayer.state() == QMediaPlayer.PausedState:
            self.mediaPlayer.play()
        else:
            self.mediaPlayer.pause()

    def stopClicked(self):
        print("----------------stooooooop-----------------!")
        self.mediaPlayer.stop()

    def precedentClicked(self):
        print("Précédent !")

    def suivantClicked(self):
        print("Suivant !")

    def sliderMov(self):
        print("Slide .....")
        self.mediaPlayer.setPosition(self.ui.slider.value())

    def onceu(self):
        ttalTimeMedia = self.mediaPlayer.duration()

    def mediaDurationChange(self):
        print("medialoaded")
        mediaDuration = self.mediaPlayer.duration()
        ttalTimeMedia = QTime(0, 0, 0)
        ttalTimeMedia = ttalTimeMedia.addMSecs(mediaDuration)
        self.ui.toBe.setText(ttalTimeMedia.toString("HH:mm:ss"))
        #self.ui.slider.setValue(mediaPosition)

    def mediapositionChange(self):
        mediaPosition = self.mediaPlayer.position()
        currentTimeMedia = QTime(0, 0, 0)
        currentTimeMedia = currentTimeMedia.addMSecs(mediaPosition)

        self.ui.onceU.setText(currentTimeMedia.toString("HH:mm:ss"))
        self.ui.slider.setRange(0, self.mediaPlayer.duration())
        self.ui.slider.setValue(self.mediaPlayer.position())

    def dVol(self):
        self.ui.pourcent.setText(str(self.ui.dialVol.value()) + "%")
        self.mediaPlayer.setVolume(self.ui.dialVol.value())
Esempio n. 9
0
class MainWindow(QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        self.ui.pBLecture.clicked.connect(self.lecture)
        self.ui.pBPause.clicked.connect(self.pause)
        self.ui.pBStop.clicked.connect(self.stop)
        self.ui.pBPrecedent.clicked.connect(self.precedent)
        self.ui.pBSuivant.clicked.connect(self.suivant)

        self.ui.pBAjout.clicked.connect(self.ajoutListe)
        self.ui.pBSupp.clicked.connect(self.suppListe)
        self.ui.listWidget.itemDoubleClicked.connect(self.mediaSelected)

        self.ui.dBVolume.valueChanged.connect(self.volume)
        self.ui.dBVolume.setRange(0, 100)
        self.ui.suiviVol.setText(f'{str(self.ui.dBVolume.value())} %')
        self.ui.sTpsCourant.valueChanged.connect(self.avanceSlider)

        self.mediaPlayer = QMediaPlayer()
        self.mediaPlayer.setVideoOutput(self.ui.Lecteur)

        self.mediaPlayer.durationChanged.connect(self.duree)
        self.mediaPlayer.positionChanged.connect(self.avancee)

        # mediaContent = QMediaContent(QUrl.fromLocalFile("big_buck_bunny.avi"))
        # self.mediaPlayer.setMedia(mediaContent)

    def lecture(self):
        print("Lecture")
        if self.mediaPlayer.state() == QMediaPlayer.StoppedState:
            self.mediaSelected()
        else:
            self.mediaPlayer.play()

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

    def stop(self):
        print("Stop")
        self.mediaPlayer.stop()

    def precedent(self):
        currentItemRow = self.ui.listWidget.currentRow()
        if currentItemRow == -1:
            return
        totalItems = self.ui.listWidget.count()
        self.ui.listWidget.setCurrentRow((currentItemRow - 1) % totalItems)
        self.mediaSelected()
        print("Précédent")

    def suivant(self):
        currentItemRow = self.ui.listWidget.currentRow()
        if currentItemRow == -1:
            return
        totalItems = self.ui.listWidget.count()
        self.ui.listWidget.setCurrentRow((currentItemRow + 1) % totalItems)
        self.mediaSelected()
        print("Suivant")

    # def ajoutListe (self):
    #     print("Ajout dans playlist")
    #     newFile=QFileDialog.getOpenFileName(self, "Choix Film", "/home", "Movie Files (*.avi, *.mp4)")
    #     newMovie=QListWidgetItem(newFile[0])
    #     self.ui.listWidget.addItem(newMovie)

    def ajoutListe(self):
        print("Ajout dans playlist")
        newFile = QFileDialog.getOpenFileName(self, "Choix Film", "/home",
                                              "Movie Files (*.avi, *.mp4)")
        fInfo = QFileInfo(newFile[0])
        fShortName = fInfo.baseName()
        newMovie = QListWidgetItem(fShortName)
        newMovie.setToolTip(newFile[0])
        self.ui.listWidget.addItem(newMovie)

    def suppListe(self):
        print("Supprimer de playList")
        rowItem = self.ui.listWidget.currentRow()
        if rowItem != -1:
            self.ui.listWidget.takeItem(rowItem)

    # def mediaSelected (self):
    #     currentItem = self.ui.listWidget.currentItem()
    #     mediaContent = QMediaContent(QUrl.fromLocalFile(currentItem.text()))
    #     self.mediaPlayer.setMedia(mediaContent)
    #     self.lecture()

    def mediaSelected(self):
        currentItem = self.ui.listWidget.currentItem()
        mediaContent = QMediaContent(QUrl.fromLocalFile(currentItem.toolTip()))
        self.mediaPlayer.setMedia(mediaContent)
        self.mediaPlayer.play()

    def volume(self):
        self.mediaPlayer.setVolume(self.ui.dBVolume.value())
        self.ui.suiviVol.setText(f'{str(self.ui.dBVolume.value())} %')

    def duree(self):
        mediaDuration = self.mediaPlayer.duration()
        self.ui.sTpsCourant.setRange(0, mediaDuration)
        totalTimeMedia = QTime(0, 0, 0)
        totalTimeMedia = totalTimeMedia.addMSecs(mediaDuration)
        self.ui.lRestantTps.setText(totalTimeMedia.toString("HH:mm:ss"))

    def avancee(self):
        self.ui.sTpsCourant.valueChanged.disconnect(self.avanceSlider)
        mediaPosition = self.mediaPlayer.position()
        currentTimeMedia = QTime(0, 0, 0)
        currentTimeMedia = currentTimeMedia.addMSecs(mediaPosition)
        self.ui.lAvanceeTps.setText(currentTimeMedia.toString("HH:mm:ss"))
        self.ui.sTpsCourant.setValue(mediaPosition)
        self.ui.sTpsCourant.valueChanged.connect(self.avanceSlider)

    def avanceSlider(self):
        self.mediaPlayer.positionChanged.disconnect(self.avancee)
        self.mediaPlayer.setPosition(self.ui.sTpsCourant.sliderPosition())
        self.mediaPlayer.positionChanged.connect(self.avancee)
Esempio n. 10
0
class MainWindow(QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.ui = Ui_MainWindow()
        self.ui.setupUi(
            self
        )  #permet de charger tous les composants graphiques coder dans un autre fichier
        # partir du fichier .py (au lieu du .ui) permet d'accéder à la complétion cad la liste des fonctions, widgets...

        self.ui.pbLect.clicked.connect(self.lectClicked)
        self.ui.pbPause.clicked.connect(self.pauseClicked)
        self.ui.pbStop.clicked.connect(self.stopClicked)
        self.ui.pbPreced.clicked.connect(self.precedClicked)
        self.ui.pbSuiv.clicked.connect(self.suivClicked)
        # self.ui.pbAjout.clicked.connect(self.ajoutClicked)
        self.ui.pbAjout.clicked.connect(self.ajoutClicked2)
        self.ui.pbSuppr.clicked.connect(self.supprClicked)
        self.ui.dlVolume.valueChanged.connect(self.volumeChange)

        self.mediaPlayer = QMediaPlayer()
        self.mediaPlayer.setVideoOutput(self.ui.videoScreen)

        self.mediaPlayer.durationChanged.connect(self.mediaDurationChanged)
        self.mediaPlayer.positionChanged.connect(self.mediaPositionChanged)
        self.ui.slTimeBarre.valueChanged.connect(self.timeBarreChanged)

        self.ui.listFilm.itemDoubleClicked.connect(
            self.filmSelectDC)  #film démmarre si double clique sur son titre
        # self.ui.listFilm.itemClicked.connect(self.filmSelectSC)

    def filmSelectDC(self):  #double clique
        currentItem = self.ui.listFilm.currentItem()
        mediaContent = QMediaContent(QUrl.fromLocalFile(
            currentItem.toolTip()))  #currentItem.text() si ajoutClicked
        self.mediaPlayer.setMedia(mediaContent)
        self.lectClicked()

    # def filmSelectSC(self): #simple clique
    #     currentItem = self.ui.listFilm.currentItem()
    #     mediaContent = QMediaContent(QUrl.fromLocalFile(currentItem.toolTip()))  #currentItem.text() si ajoutClicked
    #     self.mediaPlayer.setMedia(mediaContent)

    # def mediaSelected2(self):
    #     currentItem = self.ui.listFilm.currentItem()
    #     mediaContent = QMediaContent(QUrl.fromLocalFile(currentItem.toolTip()))  #currentItem.text() si ajoutClicked
    #     self.mediaPlayer.setMedia(mediaContent)
    #     self.lectureClicked()

    def lectClicked(self):
        print("Lecture!!")
        self.mediaPlayer.play()

    def pauseClicked(self):
        #print("Pause")
        self.mediaPlayer.pause()

    def stopClicked(self):
        #print("Stop")
        self.mediaPlayer.stop()

    # def ajoutClicked(self):
    #     print("Ajout")
    #     ajoutFilm = QFileDialog.getOpenFileName(self, "Choix Film", "C:/Users/AELION/BCH/Qt_interface_graphique/QtPython_ExoLecteurVideo", "Movie Files(*.avi *.mp4)")
    #     item = QListWidgetItem(ajoutFilm[0])
    #     self.ui.listFilm.addItem(item)

    def ajoutClicked2(self):
        # print("Ajout2")
        nomMedia = QFileDialog.getOpenFileName(
            self, "Choix Film",
            "C:/Users/AELION/BCH/Qt_interface_graphique/QtPython_ExoLecteurVideo",
            "Movie Files(*.avi *.mp4)")
        if nomMedia[
                0] == "":  # si aucun fichier selectionné pour éviter l'affichage d'une ligne vide dans la liste
            return
        fInfo = QFileInfo(nomMedia[0])
        fShortName = fInfo.baseName()
        item = QListWidgetItem(fShortName)
        item.setToolTip(
            nomMedia[0]
        )  #permet en plus d'afficher bandeau info fichier quand survol souris
        self.ui.listFilm.addItem(item)

    def supprClicked(self):
        # print("Supprime")
        supprFilm = self.ui.listFilm.currentRow()
        if supprFilm != -1:  #-1 retourner quand rien à supprimer, sinon bug
            self.ui.listFilm.takeItem(supprFilm)

    def volumeChange(self):
        #print("Volume %s" %self.ui.dlVolume.value())
        self.mediaPlayer.setVolume(self.ui.dlVolume.value())
        self.ui.lbVolumePourc.setText(str(self.ui.dlVolume.value()) + "%")

    def mediaDurationChanged(self):
        mediaDuration = self.mediaPlayer.duration()
        self.ui.slTimeBarre.setRange(0, mediaDuration)
        totTime = QTime(0, 0, 0)
        totTime = totTime.addMSecs(mediaDuration)
        self.ui.lbTimeTot.setText(totTime.toString("HH:mm:ss"))

    def mediaPositionChanged(self):
        self.ui.slTimeBarre.valueChanged.disconnect(self.timeBarreChanged)
        mediaPosition = self.mediaPlayer.position()
        self.ui.slTimeBarre.setValue(mediaPosition)
        currentTime = QTime(0, 0, 0)
        currentTime = currentTime.addMSecs(mediaPosition)
        self.ui.lbTimeReal.setText(currentTime.toString("HH:mm:ss"))
        self.ui.slTimeBarre.valueChanged.connect(self.timeBarreChanged)

    def timeBarreChanged(self):
        self.mediaPlayer.positionChanged.disconnect(self.mediaPositionChanged)
        self.mediaPlayer.setPosition(self.ui.slTimeBarre.value())
        self.mediaPlayer.positionChanged.connect(self.mediaPositionChanged)

    def precedClicked(self):
        print("Précédent")

    def suivClicked(self):
        print("Suivant")
Esempio n. 11
0
class MainWindow(QObject):

    #class constructor
    def __init__(self, ui_file, parent=None):

        #reference to our music player
        self.music_player = QMediaPlayer()

        self.music_playlist = QMediaPlaylist()
        self.music_player.setVolume(80)

        #call parent QObject constructor
        super(MainWindow, self).__init__(parent)

        #load the UI file into Python
        ui_file = QFile(ui_file)
        ui_file.open(QFile.ReadOnly)
        loader = QUiLoader()
        self.window = loader.load(ui_file)

        self.window.setWindowFlags(Qt.MSWindowsFixedSizeDialogHint)
        self.window.setWindowTitle("SynthWAV")

        #always remember to close files
        ui_file.close()

        #add event listeners
        open_action = self.window.findChild(QAction, 'action_open')
        open_action.triggered.connect(self.open_action_triggered)

        quit_action = self.window.findChild(QAction, 'action_quit')
        quit_action.triggered.connect(self.quit_action_triggered)

        open_button = self.window.findChild(QPushButton, 'open_button')
        open_button.clicked.connect(self.open_action_triggered)

        quit_button = self.window.findChild(QPushButton, 'quit_button')
        quit_button.clicked.connect(self.quit_action_triggered)

        play_button = self.window.findChild(QPushButton, 'play_button')
        play_button.clicked.connect(self.play_button_clicked)

        pause_button = self.window.findChild(QPushButton, 'pause_button')
        pause_button.clicked.connect(self.pause_button_clicked)

        stop_button = self.window.findChild(QPushButton, 'stop_button')
        stop_button.clicked.connect(self.stop_button_clicked)

        progress_slider = self.window.findChild(QSlider, 'progress_slider')
        self.music_player.positionChanged.connect(self.update_progress)
        progress_slider.sliderMoved.connect(self.scrub_progress)

        volume_slider = self.window.findChild(QSlider, 'volume_slider')
        volume_slider.setValue(self.music_player.volume())
        volume_slider.sliderMoved.connect(self.adjust_volume)

        next_button = self.window.findChild(QPushButton, 'next_button')
        next_button.clicked.connect(self.next_button_clicked)

        previous_button = self.window.findChild(QPushButton, 'previous_button')
        previous_button.clicked.connect(self.previous_button_clicked)

        fforward_button = self.window.findChild(QPushButton, 'fforward_button')
        fforward_button.clicked.connect(self.fforward_button_clicked)

        fbackward_button = self.window.findChild(QPushButton,
                                                 'fbackward_button')
        fbackward_button.clicked.connect(self.fbackward_button_clicked)

        self.music_playlist.currentMediaChanged.connect(self.change_title)

        #show window to user
        self.window.show()

    def open_action_triggered(self):
        files = QFileDialog.getOpenFileNames(self.window,
                                             "Add songs to playlist")
        for i in range(len(files[0])):
            self.music_playlist.addMedia(QUrl.fromLocalFile(str(files[0][i])))
        self.music_playlist.setCurrentIndex(0)
        self.music_player.setPlaylist(self.music_playlist)

    def change_title(self):
        title_label = self.window.findChild(QLabel, 'media_title')
        show_title_path = self.music_playlist.currentMedia().canonicalUrl(
        ).fileName()
        show_title = os.path.splitext(show_title_path)
        title_label.setText(show_title[0])

    def quit_action_triggered(self):
        self.window.close()

    def play_button_clicked(self):
        self.music_player.play()

    def pause_button_clicked(self):
        self.music_player.pause()

    def stop_button_clicked(self):
        self.music_player.stop()

    def next_button_clicked(self):
        self.music_playlist.next()

    def previous_button_clicked(self):
        self.music_playlist.previous()

    def fforward_button_clicked(self):
        self.music_player.setPosition(self.music_player.position() + 10000)

    def fbackward_button_clicked(self):
        self.music_player.setPosition(self.music_player.position() - 10000)

    def update_progress(self):
        progress_slider = self.window.findChild(QSlider, 'progress_slider')

        if self.music_player.duration != 0:
            progress_slider.setMaximum(self.music_player.duration())
            total_sec = (self.music_player.duration() / 1000) % 60
            total_min = (self.music_player.duration() / (1000 * 60)) % 60
            if (total_sec < 10):
                total_time = ("%d:0%d" % (int(total_min), int(total_sec)))
            else:
                total_time = ("%d:%d" % (int(total_min), int(total_sec)))
            track_duration_label = self.window.findChild(
                QLabel, 'track_duration_label')
            track_duration_label.setText(total_time)

        progress = self.music_player.position()
        progress_slider.setValue(progress)
        cur_sec = (self.music_player.position() / 1000) % 60
        cur_min = (self.music_player.position() / (1000 * 60)) % 60
        if (cur_sec < 10):
            cur_time = ("%d:0%d" % (int(cur_min), int(cur_sec)))
        else:
            cur_time = ("%d:%d" % (int(cur_min), int(cur_sec)))
        track_current_label = self.window.findChild(QLabel,
                                                    'track_current_label')
        track_current_label.setText(cur_time)

    def scrub_progress(self):
        progress_slider = self.window.findChild(QSlider, 'progress_slider')
        self.music_player.setPosition(progress_slider.sliderPosition())
        cur_min = (self.music_player.position() / 1000) % 60
        cur_sec = (self.music_player.position() / (1000 * 60)) % 60
        if (cur_sec < 10):
            cur_time = ("%d:0%d" % (int(cur_min), int(cur_sec)))
        else:
            cur_time = ("%d:%d" % (int(cur_min), int(cur_sec)))
        track_current_label = self.window.findChild(QLabel,
                                                    'track_current_label')
        track_current_label.setText(cur_time)

    def adjust_volume(self):
        volume_slider = self.window.findChild(QSlider, 'volume_slider')
        self.music_player.setVolume(volume_slider.sliderPosition())
Esempio n. 12
0
class SoundPlayer:
    def __init__(self, soundfile, parent):
        self.soundfile = soundfile
        self.isplaying = False
        self.time = 0  # current audio position in frames
        self.audio = QMediaPlayer()
        self.decoder = QAudioDecoder()
        self.is_loaded = False
        self.volume = 100
        self.isplaying = False
        self.decoded_audio = {}
        self.only_samples = []
        self.decoding_is_finished = False
        self.max_bits = 32768
        # File Loading is Asynchronous, so we need to be creative here, doesn't need to be duration but it works
        self.audio.durationChanged.connect(self.on_durationChanged)
        #self.decoder.finished.connect(self.decode_finished_signal)
        self.audio.setMedia(QUrl.fromLocalFile(soundfile))
        #self.decoder.setSourceFilename(soundfile)  # strangely inconsistent file-handling
        # It will hang here forever if we don't process the events.
        while not self.is_loaded:
            QCoreApplication.processEvents()
            time.sleep(0.1)

        #self.decode_audio()
        #self.np_data = np.array(self.only_samples)
        #self.np_data = np.abs(self.np_data / self.max_bits)
        # A simple normalisation, with this the samples should all be between 0 and 1
        # for i in self.decoded_audio.items():
        #     self.only_samples.extend(i[1][0])
        # t = []
        # for i in self.only_samples:
        #     if i != []:
        #         t.append(i + -(min(self.only_samples)))
        #
        # t2 = []
        # for i in t:
        #     t2.append(i / max(t))
        # self.only_samples = t2
        #print(len(self.only_samples))
        #print(self.max_bits)


        self.isvalid = True
        self.pydubfile = None
        if AudioSegment:
            if which("ffmpeg") is not None:
                AudioSegment.converter = which("ffmpeg")
            elif which("avconv") is not None:
                AudioSegment.converter = which("avconv")
            else:
                if platform.system() == "Windows":
                    AudioSegment.converter = os.path.join(get_main_dir(), "ffmpeg.exe")
                    #AudioSegment.converter = os.path.dirname(os.path.realpath(__file__)) + "\\ffmpeg.exe"
                else:
                    # TODO: Check if we have ffmpeg or avconv installed
                    AudioSegment.converter = "ffmpeg"

        try:
            if AudioSegment:
                print(self.soundfile)
                self.pydubfile = AudioSegment.from_file(self.soundfile, format=os.path.splitext(self.soundfile)[1][1:])
            else:
                self.wave_reference = wave.open(self.soundfile)

            self.isvalid = True

        except:
            traceback.print_exc()
            self.wave_reference = None
            self.isvalid = False

        #self.audio.play()

    def audioformat_to_datatype(self, audioformat):
        num_bits = audioformat.sampleSize()
        signed = audioformat.sampleType()
        self.max_bits = 2 ** int(num_bits)
        if signed == QAudioFormat.SampleType.UnSignedInt:
            return "uint" + str(num_bits) + "_t"
        elif signed == QAudioFormat.SampleType.SignedInt:
            self.max_bits = int(self.max_bits / 2)
            return "int" + str(num_bits) + "_t"

    def decode_audio(self):
        self.decoder.start()
        while not self.decoding_is_finished:
            QCoreApplication.processEvents()
            if self.decoder.bufferAvailable():
                tempdata = self.decoder.read()
                # We use the Pointer Address to get a cffi Pointer to the data (hopefully)
                cast_data = self.audioformat_to_datatype(tempdata.format())
                possible_data = ffi.cast("{1}[{0}]".format(tempdata.sampleCount(), cast_data), int(tempdata.constData()))

                current_sample_data = []
                for i in possible_data:
                    current_sample_data.append(int(ffi.cast(cast_data, i)))
                #x = int(ffi.cast("int16_t", possible_data[0]))
                self.only_samples.extend(current_sample_data)
                self.decoded_audio[self.decoder.position()] = [current_sample_data, len(possible_data), tempdata.byteCount(), tempdata.format()]

    def decode_finished_signal(self):
        self.decoding_is_finished = True

    def on_durationChanged(self, duration):
        print("Changed!")
        print(duration)
        self.is_loaded = True

    def get_audio_buffer(self, bufferdata):
        print(bufferdata)

    def IsValid(self):
        return self.isvalid

    def Duration(self):
        return self.audio.duration() / 1000.0

    def GetRMSAmplitude(self, time, sampleDur):
        if AudioSegment:
            return self.pydubfile[time*1000.0:(time+sampleDur)*1000.0].rms
        else:
            startframe = int(round(time * self.wave_reference.getframerate()))
            samplelen = int(round(sampleDur * self.wave_reference.getframerate()))
            self.wave_reference.setpos(startframe)
            frame = self.wave_reference.readframes(samplelen)
            width = self.wave_reference.getsampwidth()
            return audioop.rms(frame, width)

    def is_playing(self):
        if self.audio.state() == QMediaPlayer.PlayingState:
            return True
        else:
            return False

    def set_cur_time(self, newtime):
        self.time = newtime * 1000.0
        self.audio.setPosition(self.time)

    def stop(self):
        self.isplaying = False
        self.audio.stop()

    def current_time(self):
        self.time = self.audio.position() / 1000.0
        return self.time

    def set_volume(self, newvolume):
        self.volume = newvolume
        self.audio.setVolume(self.volume)

    def play(self, arg):
        self.isplaying = True  # TODO: We should be able to replace isplaying with queries to self.audio.state()
        self.audio.play()

    def play_segment(self, start, length):
        print("Playing Segment")
        if not self.isplaying:  # otherwise this get's kinda echo-y
            self.isplaying = True
            self.audio.setPosition(start * 1000.0)
            self.audio.play()
            thread.start_new_thread(self._wait_for_segment_end, (start, length))

    def _wait_for_segment_end(self, newstart, newlength):
        start = newstart * 1000.0
        length = newlength * 1000.0
        end = start + length
        print(start)
        print(length)
        print(end)
        while self.audio.position() < end:
            QCoreApplication.processEvents()
            print(self.audio.position())
            time.sleep(0.001)
        self.audio.stop()
        self.isplaying = False
Esempio n. 13
0
class Form(QMainWindow):
    def __init__(self, parent=None):
        super(Form, self).__init__(parent)
        self.setObjectName("MainWindow")
        self.resize(804, 559)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred,
                                           QtWidgets.QSizePolicy.Preferred)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.sizePolicy().hasHeightForWidth())
        self.setSizePolicy(sizePolicy)
        self.centralwidget = QtWidgets.QWidget(self)
        self.centralwidget.setObjectName("centralwidget")
        self.horizontalLayout_5 = QtWidgets.QHBoxLayout(self.centralwidget)
        self.horizontalLayout_5.setObjectName("horizontalLayout_5")
        self.horizontalLayout = QtWidgets.QHBoxLayout()
        self.horizontalLayout.setObjectName("horizontalLayout")
        self.verticalLayout = QtWidgets.QVBoxLayout()
        self.verticalLayout.setObjectName("verticalLayout")
        self.wVideo = QVideoWidget(self.centralwidget)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding,
                                           QtWidgets.QSizePolicy.Expanding)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.wVideo.sizePolicy().hasHeightForWidth())
        self.wVideo.setSizePolicy(sizePolicy)
        self.wVideo.setObjectName("wVideo")
        self.verticalLayout.addWidget(self.wVideo)
        self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
        self.horizontalLayout_2.setObjectName("horizontalLayout_2")
        self.lStartTime = QtWidgets.QLabel(self.centralwidget)
        self.lStartTime.setObjectName("lStartTime")
        self.horizontalLayout_2.addWidget(self.lStartTime)
        self.sProgression = QtWidgets.QSlider(self.centralwidget)
        self.sProgression.setOrientation(QtCore.Qt.Horizontal)
        self.sProgression.setObjectName("sProgression")
        self.horizontalLayout_2.addWidget(self.sProgression)
        self.lEndTime = QtWidgets.QLabel(self.centralwidget)
        self.lEndTime.setObjectName("lEndTime")
        self.horizontalLayout_2.addWidget(self.lEndTime)
        self.verticalLayout.addLayout(self.horizontalLayout_2)
        self.lBoutons = QtWidgets.QHBoxLayout()
        self.lBoutons.setObjectName("lBoutons")
        self.pbLecture = QtWidgets.QPushButton(self.centralwidget)
        self.pbLecture.setObjectName("pbLecture")
        self.lBoutons.addWidget(self.pbLecture)
        self.pbPause = QtWidgets.QPushButton(self.centralwidget)
        self.pbPause.setObjectName("pbPause")
        self.lBoutons.addWidget(self.pbPause)
        self.pbStop = QtWidgets.QPushButton(self.centralwidget)
        self.pbStop.setObjectName("pbStop")
        self.lBoutons.addWidget(self.pbStop)
        self.pbSuivant = QtWidgets.QPushButton(self.centralwidget)
        self.pbSuivant.setObjectName("pbSuivant")
        self.lBoutons.addWidget(self.pbSuivant)
        self.pbPrecedent = QtWidgets.QPushButton(self.centralwidget)
        self.pbPrecedent.setObjectName("pbPrecedent")
        self.lBoutons.addWidget(self.pbPrecedent)
        self.verticalLayout.addLayout(self.lBoutons)
        self.horizontalLayout.addLayout(self.verticalLayout)
        self.verticalLayout_3 = QtWidgets.QVBoxLayout()
        self.verticalLayout_3.setObjectName("verticalLayout_3")
        self.line = QtWidgets.QFrame(self.centralwidget)
        self.line.setBaseSize(QtCore.QSize(0, 0))
        self.line.setFrameShape(QtWidgets.QFrame.VLine)
        self.line.setFrameShadow(QtWidgets.QFrame.Sunken)
        self.line.setObjectName("line")
        self.verticalLayout_3.addWidget(self.line)
        spacerItem = QtWidgets.QSpacerItem(20, 100,
                                           QtWidgets.QSizePolicy.Minimum,
                                           QtWidgets.QSizePolicy.Fixed)
        self.verticalLayout_3.addItem(spacerItem)
        self.horizontalLayout.addLayout(self.verticalLayout_3)
        self.verticalLayout_2 = QtWidgets.QVBoxLayout()
        self.verticalLayout_2.setObjectName("verticalLayout_2")
        self.label_3 = QtWidgets.QLabel(self.centralwidget)
        self.label_3.setObjectName("label_3")
        self.verticalLayout_2.addWidget(self.label_3)
        self.listWidget = QtWidgets.QListWidget(self.centralwidget)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum,
                                           QtWidgets.QSizePolicy.Expanding)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.listWidget.sizePolicy().hasHeightForWidth())
        self.listWidget.setSizePolicy(sizePolicy)
        self.listWidget.setObjectName("listWidget")
        self.verticalLayout_2.addWidget(self.listWidget)
        self.horizontalLayout_3 = QtWidgets.QHBoxLayout()
        self.horizontalLayout_3.setObjectName("horizontalLayout_3")
        spacerItem1 = QtWidgets.QSpacerItem(40, 20,
                                            QtWidgets.QSizePolicy.Minimum,
                                            QtWidgets.QSizePolicy.Minimum)
        self.horizontalLayout_3.addItem(spacerItem1)
        self.pbAjout = QtWidgets.QPushButton(self.centralwidget)
        self.pbAjout.setObjectName("pbAjout")
        self.horizontalLayout_3.addWidget(self.pbAjout)
        self.pbSuppr = QtWidgets.QPushButton(self.centralwidget)
        self.pbSuppr.setObjectName("pbSuppr")
        self.horizontalLayout_3.addWidget(self.pbSuppr)
        self.verticalLayout_2.addLayout(self.horizontalLayout_3)
        self.horizontalLayout_4 = QtWidgets.QHBoxLayout()
        self.horizontalLayout_4.setObjectName("horizontalLayout_4")
        spacerItem2 = QtWidgets.QSpacerItem(40, 20,
                                            QtWidgets.QSizePolicy.Minimum,
                                            QtWidgets.QSizePolicy.Minimum)
        self.horizontalLayout_4.addItem(spacerItem2)
        self.label_4 = QtWidgets.QLabel(self.centralwidget)
        self.label_4.setObjectName("label_4")
        self.horizontalLayout_4.addWidget(self.label_4)
        self.dVolume = QtWidgets.QDial(self.centralwidget)
        self.dVolume.setObjectName("dVolume")
        self.horizontalLayout_4.addWidget(self.dVolume)
        self.lPourcentVolume = QtWidgets.QLabel(self.centralwidget)
        self.lPourcentVolume.setObjectName("lPourcentVolume")
        self.horizontalLayout_4.addWidget(self.lPourcentVolume)
        self.verticalLayout_2.addLayout(self.horizontalLayout_4)
        self.horizontalLayout.addLayout(self.verticalLayout_2)
        self.horizontalLayout_5.addLayout(self.horizontalLayout)
        self.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(self)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 804, 21))
        self.menubar.setObjectName("menubar")
        self.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(self)
        self.statusbar.setObjectName("statusbar")
        self.setStatusBar(self.statusbar)

        self.retranslateUi(self)
        QtCore.QMetaObject.connectSlotsByName(self)

        self.mediaPlayer = QMediaPlayer()
        self.mediaPlayer.setVideoOutput(self.wVideo)

        self.pbLecture.clicked.connect(self.lectureClic)
        self.pbPause.clicked.connect(self.pauseClic)
        self.pbStop.clicked.connect(self.stopClic)
        self.pbSuivant.clicked.connect(self.suivantClic)
        self.pbPrecedent.clicked.connect(self.precedentClic)
        self.dVolume.valueChanged.connect(self.volumeChange)
        self.mediaPlayer.positionChanged.connect(self.progressionChange)
        self.sProgression.sliderMoved.connect(self.progressionDeplace)
        self.pbSuppr.clicked.connect(self.supprVid)
        self.pbAjout.clicked.connect(self.addVid)
        self.listWidget.itemDoubleClicked.connect(self.listeDoubleClic)

        self.dVolume.setMaximum(100)
        self.lEndTime.setText("")
        self.lStartTime.setText("")
        self.lPourcentVolume.setText("")
        self.dVolume.setValue(31)

    def progressionDeplace(self):
        self.mediaPlayer.setPosition(self.sProgression.value())

    def progressionChange(self):
        self.lEndTime.setText(convertMillis(self.mediaPlayer.duration()))
        self.lStartTime.setText(str(convertMillis(
            self.mediaPlayer.position())))
        self.sProgression.setRange(0, self.mediaPlayer.duration())
        self.sProgression.setValue(self.mediaPlayer.position())

    def lectureClic(self):
        mediaContent = QMediaContent(QUrl.fromLocalFile(self.openFile[0]))
        self.mediaPlayer.setMedia(mediaContent)
        self.mediaPlayer.play()

    def pauseClic(self):
        print("Pause")
        if self.mediaPlayer.state() == QMediaPlayer.PausedState:
            self.mediaPlayer.play()
        else:
            self.mediaPlayer.pause()

    def stopClic(self):
        self.mediaPlayer.stop()

    def suivantClic(self):
        currentItemRow = self.listWidget.currentRow()
        if currentItemRow == -1:
            return
        totalItems = self.listWidget.count()
        self.listWidget.setCurrentRow((currentItemRow + 1) % totalItems)
        self.listeDoubleClic()

    def precedentClic(self):
        currentItemRow = self.listWidget.currentRow()
        if currentItemRow == -1:
            return
        totalItems = self.listWidget.count()
        self.listWidget.setCurrentRow((currentItemRow - 1) % totalItems)
        self.listeDoubleClic()

    def volumeChange(self):
        self.lPourcentVolume.setText(str(self.dVolume.value()))
        self.mediaPlayer.setVolume(self.dVolume.value())

    def supprVid(self):
        if self.listWidget.currentRow() != -1:
            self.listWidget.takeItem(self.listWidget.currentRow())

    def addVid(self):
        self.openFile = QFileDialog.getOpenFileName(
            self, "Ouvrir...", ".", "Image Files (*.avi *.mp4)")
        self.listWidget.addItem(self.openFile[0])

    def listeDoubleClic(self):
        self.mediaPlayer.setMedia(
            QMediaContent(
                QUrl.fromLocalFile(self.listWidget.currentItem().text())))
        self.mediaPlayer.play()

    def retranslateUi(self, MainWindow):
        self.setWindowTitle(
            QtWidgets.QApplication.translate("MainWindow", "MainWindow", None,
                                             -1))
        self.lStartTime.setText(
            QtWidgets.QApplication.translate("MainWindow", "$start_time", None,
                                             -1))
        self.lEndTime.setText(
            QtWidgets.QApplication.translate("MainWindow", "$end_time", None,
                                             -1))
        self.pbLecture.setText(
            QtWidgets.QApplication.translate("MainWindow", "Lecture", None,
                                             -1))
        self.pbPause.setText(
            QtWidgets.QApplication.translate("MainWindow", "Pause", None, -1))
        self.pbStop.setText(
            QtWidgets.QApplication.translate("MainWindow", "Stop", None, -1))
        self.pbSuivant.setText(
            QtWidgets.QApplication.translate("MainWindow", "Suivant", None,
                                             -1))
        self.pbPrecedent.setText(
            QtWidgets.QApplication.translate("MainWindow", "Précédent", None,
                                             -1))
        self.label_3.setText(
            QtWidgets.QApplication.translate("MainWindow",
                                             "Liste de lecture :", None, -1))
        self.pbAjout.setText(
            QtWidgets.QApplication.translate("MainWindow", "+", None, -1))
        self.pbSuppr.setText(
            QtWidgets.QApplication.translate("MainWindow", "-", None, -1))
        self.label_4.setText(
            QtWidgets.QApplication.translate("MainWindow", "Volume :", None,
                                             -1))
        self.lPourcentVolume.setText(
            QtWidgets.QApplication.translate("MainWindow", "$volume", None,
                                             -1))
Esempio n. 14
0
class MainWindow(QMainWindow):
    """Display video loop and controls"""
    audio_changed = Signal(str)
    def __init__(self, parent=None):
        super().__init__(parent)

        # Default values. Updated if found in config.JSON
        self.use_qt_thread = False
        self.rhythm_algorithm = "multifeature"
        self.default_device_name = ""
        self.show_video_preview = True
        self.video_loop_bpm = 60
        self.video_update_skip_ms = 100
        self.limit_tempo_by_default = False
        self.tempo_lower_limit = 60.0
        self.tempo_upper_limit = 120.0
        self.screen = 0

        self.spotify_track_id = ""

        self.read_config()

        self.setWindowTitle("Gandalf Enjoys Music")
        self.desktop = QApplication.desktop()

        self.audio = AudioDevice(self.default_device_name)
        self.input_devices = self.audio.get_input_device_names()

        self.audio_changed.connect(self.audio.change_audio_input)

        if self.use_qt_thread:
            self.bpm_extractor = BPMQt(self.update_bpm,
                                       algorithm=self.rhythm_algorithm)
        else:
            self.bpm_extractor = BPMmp(self.update_bpm,
                                       algorithm=self.rhythm_algorithm)

        self.audio.data_ready.connect(self.bpm_extractor.start_bpm_calculation)

        self.init_ui()

    def init_ui(self):
        dir_path = os.path.dirname(os.path.realpath(__file__))
        file_location = dir_path + "/resources/gandalf_icon_256px.png"
        self.icon_pixmap = QPixmap(file_location)
        self.icon = QIcon(self.icon_pixmap)
        self.setWindowIcon(self.icon)
        self.setWindowIconText("Gandalf Enjoys Music")

        self.central = QWidget(self)
        self.setCentralWidget(self.central)
        self.layout = QVBoxLayout()

        self.lock_checkbox = QCheckBox("Manual tempo", self)
        self.lock_checkbox.clicked.connect(self.update_lock_checkbox)

        self.limit_layout = QVBoxLayout()
        self.limit_checkbox = QCheckBox("Limit tempo between:", self)
        self.limit_checkbox.setChecked(self.limit_tempo_by_default)
        self.limit_checkbox.clicked.connect(self.update_bpm_manually)

        self.init_video()

        if self.show_video_preview:
            self.setFixedSize(QSize(500, 350))
            self.layout.addWidget(self.video_widget)
        else:
            self.setFixedSize(500, 100)
            self.fullscreen_button = QPushButton(self)
            self.fullscreen_button.setText("Go Fullscreen")
            self.layout.addWidget(self.fullscreen_button)
            self.fullscreen_button.clicked.connect(self.show_fullscreen)
            self.video_widget.fullscreen_changed.connect(
                self.update_button_text)

        self.video_widget.fullscreen_changed.connect(
            self.reset_video_position
        )

        self.tempo_control_layout = QVBoxLayout()
        self.tempo_control_layout.addWidget(self.lock_checkbox)

        self.set_bpm_widget = QLineEdit("{:.1f}".format(self.old_bpm), self)
        self.set_bpm_widget.setMaxLength(5)
        self.set_bpm_widget.returnPressed.connect(self.update_bpm_manually)
        self.set_bpm_palette = QPalette()
        self.set_bpm_palette.setColor(QPalette.Text, Qt.gray)
        self.set_bpm_widget.setPalette(self.set_bpm_palette)
        self.set_bpm_widget.setFixedWidth(50)
        self.tempo_control_layout.addWidget(self.set_bpm_widget)

        self.limit_layout.addWidget(self.limit_checkbox)

        self.limits = QHBoxLayout()

        self.lower_bpm_widget = QLineEdit(str(self.tempo_lower_limit), self)
        self.lower_bpm_widget.setMaxLength(5)
        self.lower_bpm_widget.returnPressed.connect(self.update_lower_limit)
        self.lower_bpm_widget.setFixedWidth(50)
        self.limits.addWidget(self.lower_bpm_widget)

        self.upper_bpm_widget = QLineEdit(str(self.tempo_upper_limit), self)
        self.upper_bpm_widget.setMaxLength(5)
        self.upper_bpm_widget.returnPressed.connect(self.update_upper_limit)
        self.upper_bpm_widget.setFixedWidth(50)
        self.limits.addWidget(self.upper_bpm_widget)
        self.limit_layout.addLayout(self.limits)

        self.control_layout = QHBoxLayout()
        self.control_layout.addLayout(self.tempo_control_layout)
        self.control_layout.addLayout(self.limit_layout)

        self.save_settings_button = QPushButton("Save settings", self)
        self.save_settings_button.clicked.connect(self.save_config)
        self.control_layout.addWidget(self.save_settings_button)

        self.layout.addLayout(self.control_layout)

        self.device_layout = QHBoxLayout()
        self.audio_select_label = QLabel("Audio device:", self)
        self.device_layout.addWidget(self.audio_select_label)

        self.audio_selection = QComboBox(self)
        self.audio_selection.addItems(self.input_devices)
        self.audio_selection.currentIndexChanged.connect(self.audio_selection_changed)
        self.device_layout.addWidget(self.audio_selection)

        self.layout.addLayout(self.device_layout)

        self.central.setLayout(self.layout)

    def init_video(self):
        self.old_bpm = 1.0

        self.video_widget = VideoWidget(self,
                                        self.show_video_preview,
                                        self.screen)
        self.media_player = QMediaPlayer(self.central)
        self.media_player.setVideoOutput(self.video_widget)

        self.playlist = QMediaPlaylist(self.media_player)
        dir_path = os.path.dirname(os.path.realpath(__file__))
        file_location = dir_path + "/resources/video_long.mp4"
        self.video_file = QUrl.fromLocalFile(file_location)
        self.playlist.addMedia(self.video_file)
        self.playlist.setPlaybackMode(QMediaPlaylist.Loop)
        self.playlist.setCurrentIndex(0)
        self.media_player.setPlaylist(self.playlist)
        self.media_player.mediaStatusChanged.connect(self.handle_media_state_changed)

        self.media_player.play()

        self.change_playback_rate(self.video_loop_bpm)

        if not self.show_video_preview:
            self.video_widget.hide()

    def handle_media_state_changed(self, state):
        if state == QMediaPlayer.MediaStatus.BufferedMedia:
            playback_speed = self.old_bpm / self.video_loop_bpm
            self.media_player.setPlaybackRate(playback_speed)
            self.media_player.setPosition(0)

    def change_playback_rate(self, bpm):
        """Update playback speed for video loop."""
        if bpm != self.old_bpm:
            # Prevent switching between double and half tempo during the same song in spotify
            track_id = get_spotify_track()
            if not self.lock_checkbox.isChecked()\
                    and not self.limit_checkbox.isChecked()\
                    and (math.isclose(bpm*2,self.old_bpm, rel_tol=3e-2)\
                    or math.isclose(bpm, self.old_bpm*2, rel_tol=3e-2))\
                    and track_id and track_id == self.spotify_track_id:
                self.spotify_track_id = track_id
                return
            self.spotify_track_id = track_id
            
            self.old_bpm = bpm
            playback_speed = bpm / self.video_loop_bpm

            # Workaround for a bug which causes irregular video playback speed
            # after changing playback rate
            current_position = self.media_player.position()
            self.media_player.setPlaybackRate(playback_speed)
            self.media_player.setPosition(current_position
                                          + self.video_update_skip_ms
                                          * playback_speed)

    def update_bpm(self, bpm, manual=False):
        if not manual:
            if self.lock_checkbox.isChecked():
                return
            bpm = float(int(bpm+0.5))
        if self.limit_checkbox.isChecked():
            while bpm < self.tempo_lower_limit:
                bpm = bpm * 2.0
            while bpm > self.tempo_upper_limit:
                bpm = bpm / 2.0
        self.change_playback_rate(bpm)
        self.set_bpm_widget.setText("{:.1f}".format(self.old_bpm))

    def update_bpm_manually(self):
        bpm = self.set_bpm_widget.text()
        try:
            bpm = float(bpm)
            if bpm < 1.0:
                raise ValueError
        except ValueError:
            return
        self.spotify_track_id = ""
        self.update_bpm(bpm, manual=True)

    def update_lock_checkbox(self):
        if self.lock_checkbox.isChecked():
            self.set_bpm_palette = QPalette()
            self.set_bpm_palette.setColor(QPalette.Text, Qt.black)
            self.set_bpm_widget.setPalette(self.set_bpm_palette)
            self.set_bpm_widget.setReadOnly(False)
        else:
            self.set_bpm_palette = QPalette()
            self.set_bpm_palette.setColor(QPalette.Text, Qt.gray)
            self.set_bpm_widget.setPalette(self.set_bpm_palette)
            self.set_bpm_widget.setReadOnly(True)

    def update_lower_limit(self, value=None):
        if not value:
            value = self.lower_bpm_widget.text()
        try:
            value = float(value)
            if value < 1.0:
                raise ValueError
        except ValueError:
            return
        if value <= self.tempo_upper_limit / 2.0:
            self.tempo_lower_limit = value
        else:
            self.tempo_lower_limit = self.tempo_upper_limit / 2.0
        self.lower_bpm_widget.setText("{:.1f}".format(self.tempo_lower_limit))

    def update_upper_limit(self, value=None):
        if not value:
            value = self.upper_bpm_widget.text()
        try:
            value = float(value)
            if value < 1.0:
                raise ValueError
        except ValueError:
            return
        if value >= self.tempo_lower_limit * 2.0:
            self.tempo_upper_limit = value
        else:
            self.tempo_upper_limit = self.tempo_lower_limit * 2.0
        self.upper_bpm_widget.setText("{:.1f}".format(self.tempo_upper_limit))

    def audio_selection_changed(self, idx):
        self.audio_changed.emit(self.audio_selection.currentText())

    @Slot()
    def show_fullscreen(self):
        self.reset_video_position()
        if self.video_widget.isFullScreen():
            self.video_widget.hide()
            self.fullscreen_button.setText("Go Fullscreen")
        else:
            self.video_widget.setFullScreen(True)
            self.video_widget.setGeometry(self.desktop.screenGeometry(self.screen))
            self.fullscreen_button.setText("Hide Fullscreen")

    @Slot()
    def reset_video_position(self):
        self.media_player.setPosition(0)

    @Slot(bool)
    def update_button_text(self, fullscreen_status):
        if fullscreen_status:
            self.fullscreen_button.setText("Hide Fullscreen")
        else:
            self.fullscreen_button.setText("Go Fullscreen")

    def read_config(self):
        with open("config.JSON") as config_file:
            config = json.load(config_file)

            if "no_multiprocess" in config:
                self.use_qt_thread = config["no_multiprocess"]
            if config.get("rhythm_algorithm_faster"):
                self.rhythm_algorithm = "degara"
            if config.get("default_device"):
                self.default_device_name = config["default_device"]
            if "show_video_preview" in config:
                self.show_video_preview = config.get("show_video_preview")
            if config.get("video_loop_bpm"):
                self.video_loop_bpm = config["video_loop_bpm"]
            if config.get("video_update_skip_time_ms"):
                self.video_update_skip_ms = config["video_update_skip_time_ms"]
            if config.get("limit_tempo_by_default"):
                self.limit_tempo_by_default = config["limit_tempo_by_default"]
            if config.get("tempo_lower_limit"):
                self.tempo_lower_limit = config["tempo_lower_limit"]
            if config.get("tempo_upper_limit"):
                self.tempo_upper_limit = config["tempo_upper_limit"]
            if "screen" in config:
                self.screen = config["screen"]

    @Slot()
    def save_config(self):
        fast_rhythm_algo = self.rhythm_algorithm == "degara"
        data = {
            "no_multiprocess": self.use_qt_thread,
            "rhythm_algorithm_faster": fast_rhythm_algo,
            "default_device": self.audio_selection.currentText(),
            "show_video_preview": self.show_video_preview,
            "video_loop_bpm": self.video_loop_bpm,
            "video_update_skip_time_ms": self.video_update_skip_ms,
            "limit_tempo_by_default": self.limit_checkbox.isChecked(),
            "tempo_lower_limit": self.tempo_lower_limit,
            "tempo_upper_limit": self.tempo_upper_limit,
            "screen": self.screen
        }
        with open("config.JSON", "w", encoding="utf-8") as f:
            json.dump(data, f, ensure_ascii=False, indent=4)
Esempio n. 15
0
class SoundPlayer:
    def __init__(self, soundfile, parent):
        self.soundfile = soundfile
        self.isplaying = False
        self.time = 0  # current audio position in frames
        self.audio = QMediaPlayer()
        self.is_loaded = False
        self.volume = 100
        self.isplaying = False
        self.max_bits = 32768
        # File Loading is Asynchronous, so we need to be creative here, doesn't need to be duration but it works
        self.audio.durationChanged.connect(self.on_durationChanged)
        # self.decoder.finished.connect(self.decode_finished_signal)
        self.audio.setMedia(QUrl.fromLocalFile(soundfile))
        # self.decoder.setSourceFilename(soundfile)  # strangely inconsistent file-handling
        # It will hang here forever if we don't process the events.
        self.audio_file = audioread.audio_open(self.soundfile)
        self.audio_data = []
        for buf in self.audio_file:
            self.audio_data.extend(
                struct.unpack("<{}H".format(int(len(list(buf)) / 2)), buf))
        print(self.audio_data)
        print(len(self.audio_data))
        print(len(self.audio_data) / self.audio_file.samplerate)
        print(self.audio_file.duration)
        print(self.audio_file.channels)
        print("DATAEND")
        while not self.is_loaded:
            QCoreApplication.processEvents()
            time.sleep(0.1)

        self.isvalid = True
        self.pydubfile = None
        if AudioSegment:
            if which("ffmpeg") is not None:
                AudioSegment.converter = which("ffmpeg")
            elif which("avconv") is not None:
                AudioSegment.converter = which("avconv")
            else:
                if platform.system() == "Windows":
                    AudioSegment.converter = os.path.join(
                        get_main_dir(), "ffmpeg.exe")
                    # AudioSegment.converter = os.path.dirname(os.path.realpath(__file__)) + "\\ffmpeg.exe"
                else:
                    # TODO: Check if we have ffmpeg or avconv installed
                    AudioSegment.converter = "ffmpeg"

        self.isvalid = True

        # self.audio.play()

    def on_durationChanged(self, duration):
        print("Changed!")
        print(duration)
        self.is_loaded = True

    def get_audio_buffer(self, bufferdata):
        print(bufferdata)

    def IsValid(self):
        return self.isvalid

    def Duration(self):
        return self.audio.duration() / 1000.0

    def GetRMSAmplitude(self, time_pos, sample_dur):
        if AudioSegment:
            return self.pydubfile[time_pos * 1000.0:(time_pos + sample_dur) *
                                  1000.0].rms
        else:
            if time_pos > 0:
                sample_pos = int(self.audio_file.samplerate * time_pos)
            else:
                sample_pos = 0
            sample_end = int(sample_pos +
                             sample_dur * self.audio_file.samplerate)
            return audioop.rms(
                struct.pack(
                    "<{}H".format(len(self.audio_data[sample_pos:sample_end])),
                    *self.audio_data[sample_pos:sample_end]), 2)

    def is_playing(self):
        if self.audio.state() == QMediaPlayer.PlayingState:
            return True
        else:
            return False

    def set_cur_time(self, newtime):
        self.time = newtime * 1000.0
        self.audio.setPosition(self.time)

    def stop(self):
        self.isplaying = False
        self.audio.stop()

    def current_time(self):
        self.time = self.audio.position() / 1000.0
        return self.time

    def set_volume(self, newvolume):
        self.volume = newvolume
        self.audio.setVolume(self.volume)

    def play(self, arg):
        self.isplaying = True  # TODO: We should be able to replace isplaying with queries to self.audio.state()
        self.audio.play()

    def play_segment(self, start, length):
        print("Playing Segment")
        if not self.isplaying:  # otherwise this get's kinda echo-y
            self.isplaying = True
            self.audio.setPosition(start * 1000.0)
            self.audio.play()
            thread.start_new_thread(self._wait_for_segment_end,
                                    (start, length))

    def _wait_for_segment_end(self, newstart, newlength):
        start = newstart * 1000.0
        length = newlength * 1000.0
        end = start + length
        print(start)
        print(length)
        print(end)
        while self.audio.position() < end:
            if not self.isplaying:
                return 0
            QCoreApplication.processEvents()
            print(self.audio.position())
            time.sleep(0.001)
        self.audio.stop()
        self.isplaying = False
Esempio n. 16
0
class MainWindow(QMainWindow):

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

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

        toolBar = QToolBar()
        self.addToolBar(toolBar)

        fileMenu = self.menuBar().addMenu("&File")
        openAction = QAction(QIcon.fromTheme("document-open"),
                             "&Open...", self, shortcut=QKeySequence.Open,
                             triggered=self.open)
        fileMenu.addAction(openAction)
        exitAction = QAction(QIcon.fromTheme("application-exit"), "E&xit",
                             self, shortcut="Ctrl+Q", triggered=self.close)
        fileMenu.addAction(exitAction)

        playMenu = self.menuBar().addMenu("&Play")
        playIcon = self.style().standardIcon(QStyle.SP_MediaPlay)
        self.playAction = toolBar.addAction(playIcon, "Play")
        self.playAction.triggered.connect(self.player.play)
        playMenu.addAction(self.playAction)

        previousIcon = self.style().standardIcon(QStyle.SP_MediaSkipBackward)
        self.previousAction = toolBar.addAction(previousIcon, "Previous")
        self.previousAction.triggered.connect(self.previousClicked)
        playMenu.addAction(self.previousAction)

        pauseIcon = self.style().standardIcon(QStyle.SP_MediaPause)
        self.pauseAction = toolBar.addAction(pauseIcon, "Pause")
        self.pauseAction.triggered.connect(self.player.pause)
        playMenu.addAction(self.pauseAction)

        nextIcon = self.style().standardIcon(QStyle.SP_MediaSkipForward)
        self.nextAction = toolBar.addAction(nextIcon, "Next")
        self.nextAction.triggered.connect(self.playlist.next)
        playMenu.addAction(self.nextAction)

        stopIcon = self.style().standardIcon(QStyle.SP_MediaStop)
        self.stopAction = toolBar.addAction(stopIcon, "Stop")
        self.stopAction.triggered.connect(self.player.stop)
        playMenu.addAction(self.stopAction)

        self.volumeSlider = QSlider()
        self.volumeSlider.setOrientation(Qt.Horizontal)
        self.volumeSlider.setMinimum(0)
        self.volumeSlider.setMaximum(100)
        self.volumeSlider.setFixedWidth(app.desktop().availableGeometry(self).width() / 10)
        self.volumeSlider.setValue(self.player.volume())
        self.volumeSlider.setTickInterval(10)
        self.volumeSlider.setTickPosition(QSlider.TicksBelow)
        self.volumeSlider.setToolTip("Volume")
        self.volumeSlider.valueChanged.connect(self.player.setVolume)
        toolBar.addWidget(self.volumeSlider)

        aboutMenu = self.menuBar().addMenu("&About")
        aboutQtAct = QAction("About &Qt", self, triggered=qApp.aboutQt)
        aboutMenu.addAction(aboutQtAct)

        self.videoWidget = QVideoWidget()
        self.setCentralWidget(self.videoWidget)
        self.player.setPlaylist(self.playlist)
        self.player.stateChanged.connect(self.updateButtons)
        self.player.setVideoOutput(self.videoWidget)

        self.updateButtons(self.player.state())

    def open(self):
        fileDialog = QFileDialog(self)
        supportedMimeTypes = QMediaPlayer.supportedMimeTypes()
        if not supportedMimeTypes:
            supportedMimeTypes.append("video/x-msvideo") # AVI
        fileDialog.setMimeTypeFilters(supportedMimeTypes)
        moviesLocation = QStandardPaths.writableLocation(QStandardPaths.MoviesLocation)
        fileDialog.setDirectory(moviesLocation)
        if fileDialog.exec_() == QDialog.Accepted:
            self.playlist.addMedia(fileDialog.selectedUrls()[0])
            self.player.play()

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

    def updateButtons(self, state):
        mediaCount = self.playlist.mediaCount()
        self.playAction.setEnabled(mediaCount > 0
            and state != QMediaPlayer.PlayingState)
        self.pauseAction.setEnabled(state == QMediaPlayer.PlayingState)
        self.stopAction.setEnabled(state != QMediaPlayer.StoppedState)
        self.previousAction.setEnabled(self.player.position() > 0)
        self.nextAction.setEnabled(mediaCount > 1)
Esempio n. 17
0
class MainWindow(QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        # Create widgets
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        self.mediaPlayer = QMediaPlayer()
        self.playlist = QMediaPlaylist()

        #mediaContent1 = QMediaContent(QUrl.fromLocalFile("big_buck_bunny.avi"))
        #mediaContent2=QMediaContent(QUrl.fromLocalFile("Doom.Patrol1.mp4"))
        #self.playlist.addMedia(mediaContent1)
        #self.playlist.addMedia(mediaContent2)
        #self.playlist.setCurrentIndex(1)

        #self.mediaPlayer.setMedia(self.playlist)
        self.mediaPlayer.setVideoOutput(self.ui.wvideo)

        self.ui.ltemps.setText("")
        self.ui.lduree.setText("")
        self.ui.dialVolume.setValue(0)
        self.ui.lvolume_2.setText(str(self.ui.dialVolume.value()))

        self.ui.pblecture.clicked.connect(self.lectureClicked)
        self.ui.pbpause.clicked.connect(self.pauseClicked)
        self.ui.pbstop.clicked.connect(self.stopClicked)
        self.ui.pbsuivant.clicked.connect(self.suivantClicked)
        self.ui.pbprecedent.clicked.connect(self.precedentClicked)
        self.ui.pbajouter.clicked.connect(self.ajouter2)
        self.ui.pbsupprimer.clicked.connect(self.supprimer)
        self.ui.listWidget.itemDoubleClicked.connect(self.mediaSelected2)

        self.ui.dialVolume.valueChanged.connect(self.volumeChanged)
        #self.mediaPlayer.positionChanged.connect(self.tempsChanged)

        self.mediaPlayer.positionChanged.connect(self.lectureEnCours)
        #self.mediaPlayer.positionChanged.connect(self.progressionChanged)
        self.ui.stpscourant.sliderMoved.connect(self.sliderMove)

    def sliderMove(self):
        self.mediaPlayer.setPosition(self.ui.stpscourant.value())

    def lectureEnCours(self):
        mediaPosition = self.mediaPlayer.position()
        currentTimeMedia = QTime(0, 0, 0)

        currentTimeMedia = currentTimeMedia.addMSecs(mediaPosition)
        mediaDuration = self.mediaPlayer.duration()
        totalTimeMedia = QTime(0, 0, 0)
        totalTimeMedia = totalTimeMedia.addMSecs(mediaDuration)
        self.ui.ltemps.setText(currentTimeMedia.toString("HH:mm:ss"))
        self.ui.lduree.setText(totalTimeMedia.toString("HH:mm:ss"))
        self.ui.stpscourant.setRange(0, self.mediaPlayer.duration())
        self.ui.stpscourant.setValue(self.mediaPlayer.position())

    def lectureClicked(self):
        print("Lecture!!")
        self.mediaPlayer.play()

    def pauseClicked(self):
        print("pause!!")
        if self.mediaPlayer.state() == QMediaPlayer.PausedState:
            self.mediaPlayer.play()
        else:
            self.mediaPlayer.pause()

    def stopClicked(self):
        print("stop!!")
        self.mediaPlayer.stop()

    def suivantClicked(self):
        print("suivant!!")
        currentItemRow = self.ui.listWidget.currentRow()
        if currentItemRow == -1:
            return
        totalItems = self.ui.listWidget.count()
        self.ui.listWidget.setCurrentRow((currentItemRow + 1) % totalItems)
        self.mediaSelected2()

    def precedentClicked(self):
        print("precedent!!")
        currentItemRow = self.ui.listWidget.currentRow()
        if currentItemRow == -1:
            return
        totalItems = self.ui.listWidget.count()
        self.ui.listWidget.setCurrentRow((currentItemRow - 1) % totalItems)
        self.mediaSelected2()

    def volumeChanged(self):
        self.ui.dialVolume.setMaximum(100)
        self.mediaPlayer.setVolume(self.ui.dialVolume.value())
        self.ui.lvolume_2.setText(str(self.ui.dialVolume.value()))

    def ajouter(self):
        nomMedia = QFileDialog.getOpenFileName(
            self, "Choix Film", "C:/Users/AELION/PycharmProjects/videoLHector",
            "Movie Files (*.avi *.mp4)")
        item = QListWidgetItem(nomMedia[0])
        self.ui.listWidget.addItem(item)

    def ajouter2(self):
        nomMedia = QFileDialog.getOpenFileName(
            self, "Choix Film", "C:/Users/AELION/PycharmProjects/videoLHector",
            "Movie Files (*.avi *.mp4)")
        fInfo = QFileInfo(nomMedia[0])
        fShortName = fInfo.baseName()
        print(fShortName)
        item = QListWidgetItem(fShortName)
        item.setToolTip(nomMedia[0])
        self.ui.listWidget.addItem(item)

    def supprimer(self):
        rowItem = self.ui.listWidget.currentRow()
        if rowItem != -1:
            self.ui.listWidget.takeItem(rowItem)

    def mediaSelected1(self):
        currentItem = self.ui.listWidget.currentItem()
        mediaContent = QMediaContent(QUrl.fromLocalFile(currentItem.text()))
        self.mediaPlayer.setMedia(mediaContent)
        self.lectureClicked()

    def mediaSelected2(self):
        currentItem = self.ui.listWidget.currentItem()
        mediaContent = QMediaContent(QUrl.fromLocalFile(currentItem.toolTip()))
        self.mediaPlayer.setMedia(mediaContent)
        self.lectureClicked()
Esempio n. 18
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.lbl.selectionChanged.connect(lambda: self.lbl.setSelection(0, 0))

        self.elbl = QLineEdit('00:00:00')
        self.elbl.setReadOnly(True)
        self.elbl.setFixedWidth(70)
        self.elbl.setUpdatesEnabled(True)
        self.elbl.setStyleSheet(stylesheet(self))
        self.elbl.selectionChanged.connect(
            lambda: self.elbl.setSelection(0, 0))

        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.setSingleStep(2)
        self.positionSlider.setPageStep(20)
        self.positionSlider.setAttribute(Qt.WA_TranslucentBackground, True)

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

        self.myurl = ""

        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.durationChanged.connect(self.durationChanged)
        self.mediaPlayer.error.connect(self.handleError)

        print("QT5 Player started")
        print("press 'o' to open file (see context menu for more)")
        self.suspend_screensaver()

    def mouseDoubleClickEvent(self, event):
        self.handleFullscreen()

    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)
        mtime = QTime(0, 0, 0, 0)
        mtime = mtime.addMSecs(self.mediaPlayer.position())
        self.lbl.setText(mtime.toString())

    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,
                             round((mwidth + mscale) / 1.778))
        else:
            self.setGeometry(mleft, mtop, mwidth + mscale,
                             round((mwidth + mscale) / 1.33))
        #elif self.positionSlider.hasFocus():
        #    self.positionSlider.value = self.positionSlider.value + 5

    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, round(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, round(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, round(mwidth / 1.778))
        else:
            self.setGeometry(mleft, mtop, mwidth, round(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, round(mwidth / 1.55))
        else:
            self.setGeometry(mleft, mtop, mwidth, round(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 mousePressEvent(self, evt):
        self.oldPos = evt.globalPos()

    def mouseMoveEvent(self, evt):
        delta = QPoint(evt.globalPos() - self.oldPos)
        self.move(self.x() + delta.x(), self.y() + delta.y())
        self.oldPos = evt.globalPos()

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

    def dropEvent(self, event):
        print("drop")
        if event.mimeData().hasUrls():
            url = event.mimeData().urls()[0].toString()
            print("url = ", url)
            self.mediaPlayer.stop()
            self.mediaPlayer.setMedia(QMediaContent(QUrl(url)))
            self.playButton.setEnabled(True)
            self.mediaPlayer.play()
        elif event.mimeData().hasText():
            mydrop = event.mimeData().text()
            ### 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))
                if int(res.partition("x")[0]) / int(
                        res.partition("x")[2]) < 1.5:
                    self.screen43()
                else:
                    self.screen169()
            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)
Esempio n. 19
0
class MainWindow(QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.ui = Ui_MainWindow(
        )  # on veut utiliser qu'il y a dans le fichier généré
        self.ui.setupUi(
            self)  # on charge tous les composants graphiques qui sont dedans

        self.mediaPlayer = QMediaPlayer()
        self.mediaPlayer.setVideoOutput(self.ui.videoWidget)

        self.ui.dial.setValue(50)  # pour avoir le son à 50% de base
        self.mediaPlayer.setVolume(self.ui.dial.value())
        self.ui.volume.setText(f"{self.ui.dial.value()}%")

        self.ui.pbLecture.clicked.connect(self.lectureClicked)
        self.ui.pbPause.clicked.connect(self.pauseClicked)
        self.ui.pbStop.clicked.connect(self.stopClicked)

        self.ui.dial.valueChanged.connect(self.displayVolume)

        self.mediaPlayer.durationChanged.connect(self.mediaDurationChanged)
        self.mediaPlayer.positionChanged.connect(self.mediaPositionChanged)
        self.ui.sTempsCourant.valueChanged.connect(self.sliderPositionChanged)

        self.ui.pbAjouter.clicked.connect(self.ajouterMedia2)
        self.ui.pbSupprimer.clicked.connect(self.supprMedia)
        self.ui.listeLecture.itemDoubleClicked.connect(self.mediaSelected2)

        self.ui.pbPrec.clicked.connect(self.precClicked)
        self.ui.pbSuiv.clicked.connect(self.suivClicked)

        # mediaContent = QMediaContent(QUrl.fromLocalFile("big_buck_bunny.avi"))
        # self.mediaPlayer.setMedia(mediaContent)

    def lectureClicked(self):
        print("Lecture !")
        self.mediaPlayer.play()

    def pauseClicked(self):
        print("Pause !")
        self.mediaPlayer.pause()

    def stopClicked(self):
        print("Stop !")
        self.mediaPlayer.stop()
        totalTimeMedia = QTime(0, 0, 0)
        self.ui.lTempsTotal.setText(totalTimeMedia.toString("HH:mm:ss"))

    def displayVolume(self):
        self.mediaPlayer.setVolume(self.ui.dial.value())
        self.ui.volume.setText(f"{self.ui.dial.value()}%")
        print(f"Volume modifié à {self.ui.dial.value()}%")

    def mediaDurationChanged(self):
        print("mediaLoaded")
        self.ui.lTempsCourant.setText("00:00:00")
        mediaDuration = self.mediaPlayer.duration()
        self.ui.sTempsCourant.setRange(0, mediaDuration)  ##########
        totalTimeMedia = QTime(0, 0, 0)
        totalTimeMedia = totalTimeMedia.addMSecs(mediaDuration)
        self.ui.lTempsTotal.setText(totalTimeMedia.toString("HH:mm:ss"))

    def mediaPositionChanged(self):
        self.ui.sTempsCourant.valueChanged.disconnect(
            self.sliderPositionChanged)
        mediaPosition = self.mediaPlayer.position()
        self.ui.sTempsCourant.setValue(mediaPosition)  ###########
        currentTimeMedia = QTime(0, 0, 0)
        currentTimeMedia = currentTimeMedia.addMSecs(mediaPosition)
        self.ui.lTempsCourant.setText(currentTimeMedia.toString("HH:mm:ss"))
        self.ui.sTempsCourant.valueChanged.connect(self.sliderPositionChanged)

    def sliderPositionChanged(self):  # comment ça marche ???
        self.mediaPlayer.positionChanged.disconnect(self.mediaPositionChanged)
        self.mediaPlayer.setPosition(self.ui.sTempsCourant.value())
        self.mediaPlayer.positionChanged.connect(self.mediaPositionChanged)

    def ajouterMedia(self):
        nomMedia = QFileDialog.getOpenFileName(self, "Choix Film", "c:/",
                                               "Movie Files (*.mp4 *.avi)")
        item = QListWidgetItem(nomMedia[0])
        self.ui.listeLecture.addItem(item)
        print("Média ajouté !")

    def ajouterMedia2(self):
        nomMedia = QFileDialog.getOpenFileName(self, "Choix Film", "c:/",
                                               "Movie Files (*.avi *.mp4)")
        if nomMedia[
                0] == "":  #si aucun fichier selectionné (si "Annuler" est sélectionné)
            return  # return + vide => sortie de la fonction

        fInfo = QFileInfo(nomMedia[0])
        fShortName = fInfo.baseName()
        item = QListWidgetItem(fShortName)
        item.setToolTip(nomMedia[0])
        self.ui.listeLecture.addItem(item)

    def supprMedia(self):
        rowItem = self.ui.listeLecture.currentRow()
        if rowItem != -1:
            self.ui.listeLecture.takeItem(rowItem)
        print("Média supprimé !")
        self.stopClicked()

    def mediaSelected(self):
        currentItem = self.ui.listeLecture.currentItem()
        mediaContent = QMediaContent(QUrl.fromLocalFile(currentItem.text()))
        self.mediaPlayer.setMedia(mediaContent)
        self.lectureClicked()
        print("Média sélectionné !")

    def mediaSelected2(self):
        currentItem = self.ui.listeLecture.currentItem()
        mediaContent = QMediaContent(QUrl.fromLocalFile(currentItem.toolTip()))
        self.mediaPlayer.setMedia(mediaContent)
        self.lectureClicked()

    def suivClicked(self):
        currentItemRow = self.ui.listeLecture.currentRow()
        if currentItemRow == -1:
            return
        totalItems = self.ui.listeLecture.count()
        self.ui.listeLecture.setCurrentRow((currentItemRow + 1) % totalItems)
        print("Morceau suivant !")
        self.mediaSelected2()

    def precClicked(self):
        currentItemRow = self.ui.listeLecture.currentRow()
        if currentItemRow == -1:
            return
        totalItems = self.ui.listeLecture.count()
        self.ui.listeLecture.setCurrentRow((currentItemRow - 1) % totalItems)
        print("Morceau précédent !")
        self.mediaSelected2()
Esempio n. 20
0
class SoundPlayer:
    def __init__(self, soundfile, parent):
        self.soundfile = soundfile
        self.isplaying = False
        self.time = 0  # current audio position in frames
        self.audio = QMediaPlayer()
        self.decoder = QAudioDecoder()
        self.is_loaded = False
        self.volume = 100
        self.isplaying = False
        self.decoded_audio = {}
        self.only_samples = []
        self.decoding_is_finished = False
        self.max_bits = 32768
        self.signed = False
        # File Loading is Asynchronous, so we need to be creative here, doesn't need to be duration but it works
        self.audio.durationChanged.connect(self.on_durationChanged)
        self.decoder.finished.connect(self.decode_finished_signal)
        self.audio.setMedia(QUrl.fromLocalFile(soundfile))
        self.decoder.setSourceFilename(soundfile)  # strangely inconsistent file-handling
        # It will hang here forever if we don't process the events.
        while not self.is_loaded:
            QCoreApplication.processEvents()
            time.sleep(0.1)

        self.decode_audio()
        self.np_data = np.array(self.only_samples)
        if not self.signed:  # don't ask me why this fixes 8 bit samples...
            self.np_data = self.np_data - self.max_bits / 2
        print(len(self.only_samples))
        print(self.max_bits)
        self.isvalid = True

    def audioformat_to_datatype(self, audioformat):
        num_bits = audioformat.sampleSize()
        signed = audioformat.sampleType()
        self.max_bits = 2 ** int(num_bits)
        if signed == QAudioFormat.SampleType.UnSignedInt:
            self.signed = False
            return "uint" + str(num_bits) + "_t"
        elif signed == QAudioFormat.SampleType.SignedInt:
            self.signed = True
            self.max_bits = int(self.max_bits / 2)
            return "int" + str(num_bits) + "_t"

    def decode_audio(self):
        self.decoder.start()
        while not self.decoding_is_finished:
            QCoreApplication.processEvents()
            if self.decoder.bufferAvailable():
                tempdata = self.decoder.read()
                # We use the Pointer Address to get a cffi Pointer to the data (hopefully)
                cast_data = self.audioformat_to_datatype(tempdata.format())
                possible_data = ffi.cast("{1}[{0}]".format(tempdata.sampleCount(), cast_data), int(tempdata.constData()))
                self.only_samples.extend(possible_data)
                self.decoded_audio[self.decoder.position()] = [possible_data, len(possible_data), tempdata.byteCount(), tempdata.format()]

    def decode_finished_signal(self):
        self.decoding_is_finished = True

    def on_durationChanged(self, duration):
        print("Changed!")
        print(duration)
        self.is_loaded = True

    def get_audio_buffer(self, bufferdata):
        print(bufferdata)

    def IsValid(self):
        return self.isvalid

    def Duration(self):
        return self.audio.duration() / 1000.0

    def GetRMSAmplitude(self, time, sampleDur):
        # time_start = time * (len(self.only_samples)/self.Duration())
        # time_end = (time + sampleDur) * (len(self.only_samples)/self.Duration())
        # samples = self.only_samples[int(time_start):int(time_end)]
        time_start = time * (len(self.np_data) / self.Duration())
        time_end = (time + sampleDur) * (len(self.np_data) / self.Duration())
        samples = self.np_data[int(time_start):int(time_end)]

        if len(samples):
            return np.sqrt(np.mean(samples ** 2))
        else:
            return 1

    def is_playing(self):
        if self.audio.state() == QMediaPlayer.PlayingState:
            return True
        else:
            return False

    def set_cur_time(self, newtime):
        self.time = newtime * 1000.0
        self.audio.setPosition(self.time)

    def stop(self):
        self.isplaying = False
        self.audio.stop()

    def current_time(self):
        self.time = self.audio.position() / 1000.0
        return self.time

    def set_volume(self, newvolume):
        self.volume = newvolume
        self.audio.setVolume(self.volume)

    def play(self, arg):
        self.isplaying = True  # TODO: We should be able to replace isplaying with queries to self.audio.state()
        self.audio.play()

    def play_segment(self, start, length):
        print("Playing Segment")
        if not self.is_playing():  # otherwise this get's kinda echo-y
            self.isplaying = True
            self.audio.setPosition(start * 1000.0)
            self.audio.play()
            thread.start_new_thread(self._wait_for_segment_end, (start, length))

    def _wait_for_segment_end(self, newstart, newlength):
        start = newstart * 1000.0
        length = newlength * 1000.0
        end = start + length
        print(start)
        print(length)
        print(end)
        while self.audio.position() < end:
            if not self.isplaying:
                return 0
            QCoreApplication.processEvents()
            print(self.audio.position())
            time.sleep(0.001)
        self.audio.stop()
        self.isplaying = False
Esempio n. 21
0
class MainWindow(QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()

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

        toolBar = QToolBar()
        self.addToolBar(toolBar)
        playIcon = self.style().standardIcon(QStyle.SP_MediaPlay)
        previousIcon = self.style().standardIcon(QStyle.SP_MediaSkipBackward)
        nextIcon = self.style().standardIcon(QStyle.SP_MediaSkipForward)
        pauseIcon = self.style().standardIcon(QStyle.SP_MediaPause)
        stopIcon = self.style().standardIcon(QStyle.SP_MediaStop)

        self.playAction = toolBar.addAction(playIcon, "Play")
        self.previousAction = toolBar.addAction(previousIcon, "Previous")
        self.nextAction = toolBar.addAction(nextIcon, "Next")
        self.pauseAction = toolBar.addAction(pauseIcon, "Pause")
        self.stopAction = toolBar.addAction(stopIcon, "Stop")
        self.playAction.triggered.connect(self.player.play)
        self.previousAction.triggered.connect(self.previousClicked)
        self.nextAction.triggered.connect(self.playlist.next)
        self.pauseAction.triggered.connect(self.player.pause)
        self.stopAction.triggered.connect(self.player.stop)

        self.volSlider = QSlider()
        self.volSlider.setOrientation(Qt.Horizontal)
        self.volSlider.setMinimum(0)
        self.volSlider.setMaximum(100)
        self.volSlider.setFixedWidth(120)
        self.volSlider.setValue(self.player.volume())
        self.volSlider.setTickInterval(10)
        self.volSlider.setTickPosition(QSlider.TicksBelow)
        self.volSlider.setToolTip("Volume")
        self.volSlider.valueChanged.connect(self.player.setVolume)
        toolBar.addWidget(self.volSlider)

        openAction = QAction(QIcon.fromTheme("document-open"),
                             "&Open...",
                             self,
                             shortcut=QKeySequence.Open,
                             triggered=self.open)
        exitAction = QAction(QIcon.fromTheme("application-exit"),
                             "E&xit",
                             self,
                             shortcut="Ctrl+Q",
                             triggered=self.close)
        aboutQtAct = QAction("About &Qt", self, triggered=qApp.aboutQt)
        fileMenu = self.menuBar().addMenu("&File")
        fileMenu.addAction(openAction)
        fileMenu.addAction(exitAction)
        playMenu = self.menuBar().addMenu("&Play")
        playMenu.addAction(self.playAction)
        playMenu.addAction(self.previousAction)
        playMenu.addAction(self.nextAction)
        playMenu.addAction(self.pauseAction)
        playMenu.addAction(self.stopAction)
        aboutMenu = self.menuBar().addMenu("&About")
        aboutMenu.addAction(aboutQtAct)

        self.videoWidget = QVideoWidget()
        self.setCentralWidget(self.videoWidget)

        self.player.setPlaylist(self.playlist)
        self.player.stateChanged.connect(self.updateButtons)
        self.player.setVideoOutput(self.videoWidget)
        self.updateButtons(self.player.state())

    def open(self):
        fileDialog = QFileDialog(self)
        supportedMimeTypes = ["video/mp4", "*.*"]
        fileDialog.setMimeTypeFilters(supportedMimeTypes)
        moviesLocation = QStandardPaths.writableLocation(
            QStandardPaths.MoviesLocation)
        fileDialog.setDirectory(moviesLocation)
        if fileDialog.exec_() == QDialog.Accepted:
            self.playlist.addMedia(fileDialog.selectedUrls()[0])
            self.player.play()

    def previousClicked(self):
        if self.player.position() <= 5000:
            self.playlist.previous()
        else:
            player.setPosition(0)

    def updateButtons(self, state):
        mediaCount = self.playlist.mediaCount()
        self.playAction.setEnabled(mediaCount > 0
                                   and state != QMediaPlayer.PlayingState)
        self.pauseAction.setEnabled(state == QMediaPlayer.PlayingState)
        self.stopAction.setEnabled(state != QMediaPlayer.StoppedState)
        self.previousAction.setEnabled(self.player.position() > 0)
        self.nextAction.setEnabled(mediaCount > 1)
Esempio n. 22
0
class MainWindow(QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        self.ui.PLAY_Button.clicked.connect(self.PLAY)
        self.ui.PAUSE_Button.clicked.connect(self.PAUSE)
        self.ui.STOP_Button.clicked.connect(self.STOP)
        self.ui.PREV_Button.clicked.connect(self.PREV)
        self.ui.NEXT_Button.clicked.connect(self.NEXT)
        self.ui.next_file_button.clicked.connect(self.nextFile)
        self.ui.del_file_button.clicked.connect(self.delFile)
        self.ui.dial_volumen.setMinimum(0)
        self.ui.dial_volumen.setMaximum(100)
        self.ui.dial_volumen.setValue(3)
        self.ui.volumen_level.setText(str(self.ui.dial_volumen.value()) + '%')

        self.ui.sliderTime.setMinimum(0)
        self.ui.sliderTime.setMaximum(3600)
        self.ui.sliderTime.setValue(0)
        self.ui.timePlayed.setText(str(self.ui.sliderTime.value()) + 's')

        self.mediaPlayer = QMediaPlayer()
        self.mediaPlayer.setVideoOutput(self.ui.wVideo)
        #mediaContent = QMediaContent(QUrl.fromLocalFile('big_buck_bunny.avi'))
        #self.mediaPlayer.setMedia(mediaContent)
        #Dialog
        self.ui.dial_volumen.valueChanged.connect(self.changeVolDial)
        self.mediaPlayer.positionChanged.connect(self.updateTime)
        self.ui.sliderTime.valueChanged.connect(self.changeTime)
        self.ui.file_list.itemDoubleClicked.connect(self.loadfile)

    def changeVolDial(self):
        print('VOLUMEN CHANGED')
        self.ui.volumen_level.setText(str(self.ui.dial_volumen.value()) + '%')
        self.mediaPlayer.setVolume(self.ui.dial_volumen.value())

    def updateTime(self):
        self.ui.sliderTime.valueChanged.disconnect(self.changeTime)
        localTime = QTime(0, 0, 0)
        currentTime = localTime.addMSecs(self.mediaPlayer.position())
        #print(self.mediaPlayer.position()-self.mediaPlayer.duration())
        timeLeft = localTime.addMSecs(self.mediaPlayer.duration() -
                                      self.mediaPlayer.position())
        #h, res = divmod(t, 3600)
        #m, s = divmod(res, 60)
        #time_str = f'{int(h):02}:{int(m):02}:{int(s):02}'
        self.ui.timePlayed.setText(currentTime.toString("HH:mm:ss"))
        self.ui.timeTotal.setText('-' + timeLeft.toString("HH:mm:ss"))
        self.ui.sliderTime.setValue(self.mediaPlayer.position())
        self.ui.sliderTime.valueChanged.connect(self.changeTime)

    def loadfile(self):
        #rowItem=self.ui.file_list.currentRow()
        currentItem = self.ui.file_list.currentItem()
        print(self.ui.file_list.currentItem().text())
        #mediaContent=QMediaContent(QUrl.fromLocalFile(currentItem.toolTip()))
        mediaContent = QMediaContent(QUrl.fromLocalFile(currentItem.text()))
        #mediaContent = QMediaContent(QUrl.fromLocalFile('big_buck_bunny.avi'))
        self.mediaPlayer.setMedia(mediaContent)
        self.PLAY()
        #print(self.ui.file_list.takeItem(0))

    def changeTime(self):
        self.mediaPlayer.positionChanged.disconnect(self.updateTime)
        print('Time CHANGED')
        self.mediaPlayer.setPosition(self.ui.sliderTime.value())
        localTime = QTime(0, 0, 0)
        currentTime = localTime.addMSecs(self.mediaPlayer.position())
        self.ui.timePlayed.setText(currentTime.toString("HH:mm:ss"))
        self.mediaPlayer.positionChanged.connect(self.updateTime)

    def delFile(self):
        print('delFile PRESSED')
        rowItem = self.ui.file_list.currentRow()
        if rowItem != -1:
            self.ui.file_list.takeItem(rowItem)

    def nextFile(self):
        print('nextFile PRESSED')
        filename = QFileDialog.getOpenFileName(self, "Choix Film")
        item = QListWidgetItem(filename[0])
        self.ui.file_list.addItem(item)

    def PLAY(self):
        print('PLAY PRESSED')
        self.mediaPlayer.setVolume(self.ui.dial_volumen.value())
        self.mediaPlayer.play()
        localTime = QTime(0, 0, 0)
        totalTime = localTime.addMSecs(self.mediaPlayer.duration())
        self.ui.sliderTime.setMaximum(self.mediaPlayer.duration())
        self.ui.timeTotal.setText(totalTime.toString("HH:mm:ss"))

    def PAUSE(self):
        print('PAUSE PRESSED')
        if self.mediaPlayer.state() == QMediaPlayer.PausedState:
            self.mediaPlayer.play()
        else:
            self.mediaPlayer.pause()

    def PREV(self):
        print('PREV PRESSED')
        rowItem = self.ui.file_list.currentRow()
        if rowItem == -1:
            return
        else:
            self.ui.file_list.setCurrentRow((rowItem - 1))
            filename = self.ui.file_list.currentItem().text()
            print('Loading ' + filename)
            mediaContent = QMediaContent(QUrl.fromLocalFile(filename))
            self.mediaPlayer.setMedia(mediaContent)
            self.PLAY()

    def NEXT(self):
        print('NEXT PRESSED')
        totalItems = self.ui.file_list.count()
        rowItem = self.ui.file_list.currentRow()

        if rowItem + 1 > totalItems:
            return
        else:
            self.ui.file_list.setCurrentRow((rowItem + 1))
            filename = self.ui.file_list.currentItem().text()
            print('Loading ' + filename)
            mediaContent = QMediaContent(QUrl.fromLocalFile(filename))
            self.mediaPlayer.setMedia(mediaContent)
            self.PLAY()

    def STOP(self):
        print('STOP PRESSED')
        self.mediaPlayer.stop()

    def get_str_time(t):
        h, res = divmod(t, 3600)
        m, s = divmod(res, 60)
        return f'{int(h):02}:{int(m):02}:{int(s):02}'