Exemplo n.º 1
0
 def _on_website(self):
     try:
         QDesktopServices.openUrl(QUrl("https://kokimame.github.io/joytan/"))
     except Exception as e:
         showCritical("Error occured while accessing to the Internet.\n"
                      "Please report this bug to the developers via GitHub.\n"
                      "(%s)" % e)
Exemplo n.º 2
0
    def _translate(self):
        if self.mw.entrylist.count() == 0:
            showCritical("No entries found in your entry list.", title="Error")
            return

        ewkeys = []
        # Get language code of target language to translate to from the library
        destcode = LANGCODES[self.form.langCombo.currentText().lower()]
        # Check which section to translate
        _list = self.form.keyList
        for i in range(_list.count()):
            ch = _list.itemWidget(_list.item(i))
            if ch.isChecked():
                ewkeys.append(ch.text())

        if self.form.onlyCheck.isChecked():
            targets = self.mw.entrylist.get_entry_selected()
        else:
            targets = self.mw.entrylist.get_entry_all()
        self.form.progressBar.setRange(0, len(targets))

        def _on_progress(name):
            self.form.pgMsg.setText("Translating %s." % name)
            val = self.form.progressBar.value()
            self.form.progressBar.setValue(val + 1)

        self.tt = TranslateThread(targets, ewkeys, destcode)
        self.tt.prog.connect(_on_progress)
        self.tt.step.connect(self.mw.entrylist.update_entry)
        self._thread_start()
        self.tt.finished.connect(self.reject)
Exemplo n.º 3
0
 def _on_fail(msg):
     """
     This slot gets called if the dubbing thread encounters an exception,
     then shows a critical error message and kills the thread.
     """
     if self.thread:
         self.thread.terminate()
     showCritical(msg)
Exemplo n.º 4
0
    def _ensure_base_exists(self, base):
        try:
            self._ensure_exists(base)
        except:
            from gui.utils import showCritical
            showCritical("""\
Joytan could not create the folder %s. Please ensure that location is not \
read-only and you have permission to write to it.""" % base, title="Error")
Exemplo n.º 5
0
def on_audiodialog(mw):
    # Check if the user install dependencies for pydub
    if getattr(sys, 'frozen', False):
        pass
    elif not pydub.utils.which("ffmpeg"):
        showCritical("Error: Dependencies not found. "
                     "Please install 'ffmpeg' to create audiobooks")
        return

    gui.dialogs.open("AudioDialog", mw)
Exemplo n.º 6
0
    def _on_download(self):
        url = self.form.urlEdit.text()
        if not self.URL_FORMAT.match(url):
            showCritical("Wrong URL format is detected.\nPlease choose other URL.")
            return

        self.thread = MemriseThread(url)
        self.thread.logger.connect(showCritical)
        self.thread.bar_size.connect(self._set_bar_size)
        self.thread.prog.connect(self._on_progress)
        self.thread.finished.connect(self._completed)
        self.thread.start()
        self.form.dlBtn.setEnabled(False)
        self.form.stopBtn.setEnabled(True)
Exemplo n.º 7
0
    def _on_open(self):
        if not self.path:
            showCritical("File not specified.")
            return

        self.thread = OpenCsvThread(self.path)
        self.thread.reshape.connect(
            lambda x: self.mw.entrylist.set_config('reshape', x))
        self.thread.new_entry.connect(self._on_progress)
        self.thread.finished.connect(self._completed)

        self.form.progressBar.setRange(0, self._count_row())
        self.form.openBtn.setEnabled(False)
        self.form.fileBtn.setEnabled(False)
        self.thread.start()
Exemplo n.º 8
0
    def _on_open(self):
        if not self.path:
            showCritical("File not specified.")
            return

        self.thread = OpenCsvThread(self.path)
        self.thread.reshape.connect(
            lambda x: self.mw.entrylist.set_config('reshape', x))
        self.thread.new_entry.connect(self._on_progress)
        self.thread.finished.connect(self._completed)

        self.form.progressBar.setRange(0, self._count_row())
        self.form.openBtn.setEnabled(False)
        self.form.fileBtn.setEnabled(False)

        if self.form.nameCheck.isChecked():
            mpath = self.form.fileLbl.text().replace(".csv", "")
            midx = mpath.find('/')
            if midx > 0:
                mpath = mpath[midx + 1:len(midx) - 1]
            self.mw.config['title'] = mpath
        self.thread.start()
        if self.form.shuffleCheck.isChecked():
            self.thread.finished.connect(lambda: self._shuffle())
Exemplo n.º 9
0
    def _lookup(self):
        if self.mw.entrylist.count() == 0:
            showCritical("No entries found in your entry list.", title="Error")
            return

        source_name = self.form.sourceCombo.currentText()
        service = DictionaryService[source_name]()

        if self.form.onlyCheck.isChecked():
            targets = self.mw.entrylist.get_entry_selected()
        else:
            targets = self.mw.entrylist.get_entry_all()
        self.form.progressBar.setRange(0, len(targets))

        def _on_progress(name):
            self.form.pgMsg.setText("Looking up %s." % name)
            val = self.form.progressBar.value()
            self.form.progressBar.setValue(val + 1)

        self.lt = LookupThread(targets, service)
        self.lt.prog.connect(_on_progress)
        self.lt.step.connect(self.mw.entrylist.update_entry)
        self._thread_start()
        self.lt.finished.connect(self.reject)
Exemplo n.º 10
0
    def _on_create(self):
        # Validation before starting to create audiobooks
        if self.mw.entrylist.count() == 0:
            showCritical("No entries found in your entry list.")
            return
        self.form.pauseBtn.setEnabled(True)
        # entries: The Entry to be included in the upcoming audiobook.
        if self.form.allBtn.isChecked():
            entries = self.mw.entrylist.get_entry_all()
        else:
            _from, _to = self.form.fromSpin.value(), self.form.toSpin.value()
            if _from > _to:
                showCritical("The value in 'to' field is out of range.")
                self._ui_spin()
                return
            else:
                try:
                    entries = self.mw.entrylist.get_entry_all()[_from - 1:_to]
                except IndexError:
                    showCritical("Index is out of range.")
                    self._ui_spin()
                    return
        _piecesNum = self.form.pieceSpin.value()
        # Open TTS setting dialog if TTS setting is incomplete.
        _list = self.form.flowList
        undefs = self.mw.entrylist.get_config('undefined')
        for i in range(_list.count()):
            fi = _list.itemWidget(_list.item(i))
            if isinstance(fi, EwkeyObject) and fi.ewkey in undefs:
                showCritical(
                    "Please choose Text-to-speech voice for every Entry section to be read."
                )
                gui.dialogs.open("Preferences",
                                 self.mw,
                                 back_to=self,
                                 tab="TTS")
                return

        if os.path.isdir(self._destdir()):
            # When dubbing thread gets interrupted by exceptions that it fails to find dependencies
            # (e.g, ffmpeg) while creating audio files, it may leave these files, like index.mp3, open.
            # This situation causes permission error on Windows if user starts the thread again and
            # tries to remove existing folders, because some of files in the folders are in use.
            # Therefore, let's ignore errors from shutil below and let pydub raise an error later.
            shutil.rmtree(self._destdir(), ignore_errors=True)
            os.makedirs(self._destdir(), exist_ok=True)

        setting = self._get_setting()

        class DubbingThread(QThread):
            prog = pyqtSignal(str)
            fail = pyqtSignal(str)

            def __init__(self, mw, worker):
                QThread.__init__(self)
                self.mw = mw
                self.worker = worker

            def run(self):
                self.completed = False
                self.prog.emit(
                    "Setting up audio files. This may take a few minutes")
                self.worker.setup_audio()
                self.wait = 0
                entryNum = len(entries)
                pieceSize = entryNum / _piecesNum

                for i in range(_piecesNum):
                    numStr = str(i) if _piecesNum > 1 else ""
                    sidx = int(i * pieceSize)
                    eidx = int((i + 1) * pieceSize)
                    for ew in entries[sidx:eidx]:
                        self.prog.emit("Creating audio file of Entry #%d" %
                                       (ew.row + 1))
                        os.makedirs(os.path.join(setting['dest'],
                                                 ew.str_index()),
                                    exist_ok=True)
                        # self.worker.onepass(ew)
                        tryNum = 0
                        while tryNum < 3:
                            if self.wait > 0:
                                if (self.wait == 1):
                                    self.prog.emit("Paused.")
                                    self.wait = 2
                                self.sleep(1)
                                tryNum = 0
                                continue
                            try:
                                self.worker.onepass(ew)
                                tryNum = 3
                            except Exception as e:
                                msg = "Error:" + str(e).replace(
                                    '\n', '').replace('/r', '').strip()
                                self.prog.emit(msg)
                                tryNum += 1
                                if tryNum == 2:
                                    showWarning(
                                        "Error occurs while creating audiobook at Entry"
                                        " No.%d. System stops with exception '%s'\n"
                                        "Would retry after 100 seconds." %
                                        (ew.row + 1, e))
                                if tryNum == 3:
                                    self.fail.emit(
                                        "Error occurs while creating audiobook at Entry"
                                        " No.%d. System stops with exception '%s'"
                                        % (ew.row + 1, e))
                                self.sleep(100)
                    self.prog.emit(
                        "Mixing with BGM. This may take a few minutes.")

                    acapella = sum(self.worker.acapellas)
                    # Is this good for memory efficiency?
                    # del self.worker.acapellas

                    if len(setting['loop']) != 0:
                        try:
                            finalmp3 = acapella.overlay(
                                self.worker.get_bgmloop(len(acapella)))
                            finalmp3.export(setting['dest'] + numStr + ".mp3")
                        except Exception as e:
                            self.fail.emit(
                                "Error occurs while making a looped BGM. System stops "
                                "with exception '%s'" % e)
                    else:
                        acapella.export(setting['dest'] + numStr + ".mp3")

                    if setting['lrc']:
                        self.worker.make_lyrics(setting['dest'] + numStr +
                                                ".lrc")

                    self.worker.cleanData()

                self.completed = True
                self.quit()

        def _on_progress(msg):
            self.form.pgMsg.setText(msg)
            val = self.form.progressBar.value()
            if msg.find("Error:") < 0 or msg.find("Paus") < 0:
                self.form.progressBar.setValue(val + 1)
            elif msg.find("Error:") > 0:
                self.form.progressBar.setValue(val - 1)

        def _on_fail(msg):
            """
            This slot gets called if the dubbing thread encounters an exception,
            then shows a critical error message and kills the thread.
            """
            if self.thread:
                self.thread.terminate()
            showCritical(msg)

        from joytan.routine.dubbing import DubbingWorker
        worker = DubbingWorker(setting)
        self.thread = DubbingThread(self.mw, worker)
        self.thread.prog.connect(_on_progress)
        self.thread.fail.connect(_on_fail)
        self.thread.start()
        self.thread.finished.connect(lambda: self._completed(setting['dest']))

        self.form.createBtn.setEnabled(False)
        self.form.stopBtn.setEnabled(True)
        self.form.pauseBtn.setEnabled(True)
        # Progress contains fixed 2 step; setting up audio files, mixing with BGM
        self.form.progressBar.setRange(0, len(entries) + 2 + _piecesNum)