This commit is contained in:
恍兮惚兮 2024-08-10 20:17:15 +08:00
parent c81f6a3d9f
commit 795416fa96
32 changed files with 122 additions and 177 deletions

3
.gitmodules vendored
View File

@ -4,9 +4,6 @@
[submodule "plugins/libs/tinymp3"]
path = plugins/libs/tinymp3
url = https://github.com/cpuimage/tinymp3
[submodule "plugins/libs/miniaudio"]
path = plugins/libs/miniaudio
url = https://github.com/mackron/miniaudio
[submodule "plugins/libs/rapidfuzz-cpp"]
path = plugins/libs/rapidfuzz-cpp
url = https://github.com/rapidfuzz/rapidfuzz-cpp

View File

@ -38,7 +38,7 @@ from myutils.utils import (
targetmod,
loopbackrecorder,
)
from myutils.audioplayer import player_mci
from myutils.audioplayer import playonce
from gui.codeacceptdialog import codeacceptdialog
from gui.inputdialog import (
noundictconfigdialog1,
@ -2823,21 +2823,19 @@ class viewpixmap_x(QWidget):
return
mp3 = extradatas["imagerefmp3"][self.currentimage]
if idx == 1:
duration, self.play_context = player_mci().play(
mp3, globalconfig["ttscommon"]["volume"]
)
self.play_context = playonce(mp3, globalconfig["ttscommon"]["volume"])
self.sigtime = time.time()
def __(ms, tm):
time.sleep(ms / 1000)
def __(tm):
while self.play_context and self.play_context.isplaying:
time.sleep(1)
if self.sigtime == tm:
self.switchstop.emit()
threading.Thread(target=__, args=(duration, self.sigtime)).start()
threading.Thread(target=__, args=(self.sigtime,)).start()
else:
if not self.play_context:
return
player_mci().stop(self.play_context)
self.play_context = None
def startorendrecord(self, idx):

View File

@ -147,27 +147,6 @@ def setTab5lz(self):
"语速_(-10~10)",
D_getspinbox(-10, 10, globalconfig["ttscommon"], "rate"),
],
],
),
0,
"group",
)
],
[
(
dict(
title="音频播放",
grid=[
[
"引擎",
D_getsimplecombobox(
static_data["audioengine_vis"],
globalconfig,
"audioengine",
internal=static_data["audioengine"],
static=True,
),
],
[
"音量_(0~100)",
D_getspinbox(0, 100, globalconfig["ttscommon"], "volume"),
@ -234,7 +213,7 @@ def setTab5lz(self):
self,
globalconfig["ttscommon"]["tts_repair_regex"],
"语音修正",
["正则",'转义', "原文", "替换"],
["正则", "转义", "原文", "替换"],
),
icon="fa.gear",
),

View File

@ -1,69 +1,95 @@
import windows
import os, time
import gobject, uuid
import time
from traceback import print_exc
from myutils.config import globalconfig, static_data
from myutils.config import globalconfig
import threading
import winsharedutils
from ctypes import c_float, pointer, c_void_p
# miniaudio似乎有的时候会莫名崩溃但我没遇到过。没办法只好恢复之前的mci了
# 但miniaudio的好处是不需要写硬盘可以直接在内存里播放mci必须写到文件里才能播放
import gobject
from ctypes.wintypes import BOOL, DWORD, HWND
from ctypes import (
WinDLL,
WINFUNCTYPE,
c_int,
c_ulong,
c_float,
c_int64,
c_void_p,
c_double,
)
class player_miniaudio:
def stop(self, context):
winsharedutils.PlayAudioInMem_Stop(context[0], context[1])
HMUSIC = c_ulong # MOD music handle
HSAMPLE = c_ulong # sample handle
HPLUGIN = c_ulong # Plugin handle
QWORD = c_int64
HSTREAM = c_ulong # sample stream handle
def play(self, binary, volume):
duration = c_float()
device = c_void_p()
decoder = c_void_p()
succ = winsharedutils.PlayAudioInMem(
binary,
len(binary),
volume / 100,
pointer(decoder),
pointer(device),
pointer(duration),
)
if succ != 0:
return 0
context = decoder, device
durationms = duration.value * 1000
return durationms, context
BASS_UNICODE = 0x80000000 # -2147483648
BASS_ATTRIB_VOL = 2
BASS_POS_BYTE = 0 # byte position
bass_module = WinDLL(gobject.GetDllpath("bass.dll"))
BASS_ChannelSetAttribute = WINFUNCTYPE(BOOL, DWORD, DWORD, c_float)(
("BASS_ChannelSetAttribute", bass_module)
)
BASS_ChannelGetLength = WINFUNCTYPE(QWORD, DWORD, DWORD)(
("BASS_ChannelGetLength", bass_module)
)
BASS_ChannelGetPosition = WINFUNCTYPE(QWORD, DWORD, DWORD)(
("BASS_ChannelGetPosition", bass_module)
)
BASS_ChannelPlay = WINFUNCTYPE(BOOL, DWORD, BOOL)(("BASS_ChannelPlay", bass_module))
BASS_StreamFree = WINFUNCTYPE(BOOL, HSTREAM)(("BASS_StreamFree", bass_module))
BASS_Init = WINFUNCTYPE(BOOL, c_int, DWORD, DWORD, HWND, c_void_p)(
("BASS_Init", bass_module)
)
BASS_StreamCreateFile = WINFUNCTYPE(HSTREAM, BOOL, c_void_p, QWORD, QWORD, DWORD)(
("BASS_StreamCreateFile", bass_module)
)
BASS_Free = WINFUNCTYPE(BOOL)(("BASS_Free", bass_module))
class player_mci:
def stop(self, context):
i, lastfile, remove = context
windows.mciSendString(("stop lunatranslator_mci_{}".format(i)))
windows.mciSendString(("close lunatranslator_mci_{}".format(i)))
if remove:
os.remove(lastfile)
class playonce:
def __init__(self, fileormem, volume) -> None:
self.handle = None
self.channel_length = 0
self.__play(fileormem, volume)
def play(self, binaryorfile, volume):
i = str(uuid.uuid4())
if isinstance(binaryorfile, bytes):
tgt = gobject.gettempdir(f"tts/{i}.wav")
with open(tgt, "wb") as ff:
ff.write(binaryorfile)
remove = True
elif isinstance(binaryorfile, str):
tgt = binaryorfile
remove = False
context = (i, tgt, remove)
windows.mciSendString(
'open "{}" type mpegvideo alias lunatranslator_mci_{}'.format(tgt, i)
)
durationms = int(
windows.mciSendString("status lunatranslator_mci_{} length".format(i))
)
windows.mciSendString(
"setaudio lunatranslator_mci_{} volume to {}".format(i, volume * 10)
)
windows.mciSendString(("play lunatranslator_mci_{}".format(i)))
return durationms, context
def __del__(self):
self.__stop()
@property
def isplaying(self):
if not self.handle:
return False
if not self.channel_length:
return False
channel_position = BASS_ChannelGetPosition(self.handle, BASS_POS_BYTE)
return channel_position < self.channel_length
def __play(self, fileormem, volume):
if isinstance(fileormem, bytes):
handle = BASS_StreamCreateFile(True, fileormem, 0, len(fileormem), 0)
else:
handle = BASS_StreamCreateFile(False, fileormem, 0, 0, BASS_UNICODE)
if not handle:
return
BASS_ChannelSetAttribute(handle, BASS_ATTRIB_VOL, volume / 100)
if not BASS_ChannelPlay(handle, False):
return
channel_length = BASS_ChannelGetLength(handle, BASS_POS_BYTE)
self.channel_length = channel_length
self.handle = handle
def __stop(self):
_ = self.handle
if not _:
return
self.handle = None
BASS_StreamFree(_)
BASS_Init(-1, 44100, 0, 0, 0)
class series_audioplayer:
@ -73,8 +99,6 @@ class series_audioplayer:
self.tasks = None
self.lock = threading.Lock()
self.lock.acquire()
self.lastplayer = None
self.lastengine = None
self.lastcontext = None
threading.Thread(target=self.__dotasks).start()
@ -86,36 +110,7 @@ class series_audioplayer:
except:
pass
def __maybeinitengine(self):
using = globalconfig["audioengine"]
supports = static_data["audioengine"]
if using not in supports:
using = supports[0]
if using == self.lastengine:
return
self.lastplayer = {"mci": player_mci, "miniaudio": player_miniaudio}.get(
using
)()
self.lastengine = using
def __maybestoplast(self):
if self.lastplayer and self.lastcontext:
try:
self.lastplayer.stop(self.lastcontext)
except:
print_exc()
self.lastcontext = None
def __playthis(self, binary, volume):
try:
durationms, self.lastcontext = self.lastplayer.play(binary, volume)
except:
durationms = 0
self.lastcontext = None
return durationms
def __dotasks(self):
durationms = 0
try:
while True:
self.lock.acquire()
@ -124,12 +119,10 @@ class series_audioplayer:
if task is None:
continue
binary, volume, force = task
self.__maybestoplast()
self.__maybeinitengine()
durationms = self.__playthis(binary, volume)
if durationms and globalconfig["ttsnointerrupt"]:
while durationms > 0:
durationms -= 100
_playonce = None
_playonce = playonce(binary, volume)
if globalconfig["ttsnointerrupt"]:
while _playonce.isplaying:
time.sleep(0.1)
if self.tasks and self.tasks[-1]:
break

View File

@ -114,9 +114,14 @@ class TTS(TTSbase):
_2 = self.linear_map(rate)
elif voice.endswith("_22"):
_2 = 0
try:
code1 = content.encode("shift-jis")
except:
__ = []
for c in content:
try:
__.append(c.encode("shift-jis"))
except:
pass
code1 = b"".join(__)
if not code1:
return
windows.WriteFile(self.hPipe, voice.encode())
windows.WriteFile(self.hPipe, bytes(c_float(_2)))

View File

@ -304,19 +304,6 @@ Is64bit.restype = c_bool
isDark = utilsdll.isDark
isDark.restype = c_bool
PlayAudioInMem = utilsdll.PlayAudioInMem
PlayAudioInMem.argtypes = (
c_void_p,
c_size_t,
c_float,
c_void_p,
c_void_p,
POINTER(c_float),
)
PlayAudioInMem.restype = c_int
PlayAudioInMem_Stop = utilsdll.PlayAudioInMem_Stop
PlayAudioInMem_Stop.argtypes = c_void_p, c_void_p
_gdi_screenshot = utilsdll.gdi_screenshot
_gdi_screenshot.argtypes = HWND, RECT, c_void_p

View File

@ -328,7 +328,6 @@
"buttonsize2": 18,
"language_setted_2.4.5": false,
"postprocess_rank": [],
"audioengine": "mci",
"fix_translate_rank": false,
"fix_translate_rank_rank": [],
"cishuvisrank": [],

View File

@ -1903,14 +1903,6 @@
"miaobian1"
]
},
"audioengine": [
"mci",
"miniaudio"
],
"audioengine_vis": [
"Windows MCI",
"miniaudio"
],
"main_server": [
"https://lunatranslator.org",
"http://lunatranslator.star.is"

View File

@ -769,7 +769,6 @@
"滚动到最后": "انتقل إلى آخر",
"创建列表": "إنشاء قائمة",
"限制每行字数": "الحد من عدد الكلمات في السطر",
"音频播放": "تشغيل الصوت",
"语速": "سرعة الكلام",
"音量": "حجم",
"固定翻译显示顺序": "ترجمة ثابتة عرض تسلسل",

View File

@ -769,7 +769,6 @@
"滚动到最后": "滾動到最後",
"创建列表": "建立清單",
"限制每行字数": "限制每行字數",
"音频播放": "音訊播放",
"语速": "語速",
"音量": "音量",
"固定翻译显示顺序": "固定翻譯顯示順序",

View File

@ -771,7 +771,6 @@
"修改列表名称": "Změna názvu seznamu",
"滚动到最后": "Přejděte na konec",
"限制每行字数": "Omezení počtu slov na řádek",
"音频播放": "Přehrávání zvuku",
"语速": "Rychlost řeči",
"音量": "objem",
"固定翻译显示顺序": "Pevné pořadí zobrazení překladu",

View File

@ -771,7 +771,6 @@
"修改列表名称": "Ändern des Namens der Liste",
"滚动到最后": "Zum Ende scrollen",
"限制每行字数": "Begrenzung der Wortanzahl pro Zeile",
"音频播放": "Audiowiedergabe",
"语速": "Sprachgeschwindigkeit",
"音量": "Volumen",
"固定翻译显示顺序": "Feste Übersetzungsanzeigereihenfolge",

View File

@ -769,7 +769,6 @@
"指定模块": "Specify Modules",
"创建列表": "Create List",
"限制每行字数": "Limit Number of Words per Line",
"音频播放": "Audio Playback",
"语速": "Speech Speed",
"音量": "Volume",
"固定翻译显示顺序": "Fixed translation display order",

View File

@ -769,7 +769,6 @@
"滚动到最后": "Rodar hasta el final",
"创建列表": "Crear lista",
"限制每行字数": "Limitar el número de palabras por línea",
"音频播放": "Reproducción de audio",
"语速": "Velocidad del habla",
"音量": "Volumen",
"固定翻译显示顺序": "Orden fijo de visualización de la traducción",

View File

@ -769,7 +769,6 @@
"滚动到最后": "Rouler jusqu'à la fin",
"创建列表": "Créer une liste",
"限制每行字数": "Limiter le nombre de mots par ligne",
"音频播放": "Lecture audio",
"语速": "Vitesse de la parole",
"音量": "Volume",
"固定翻译显示顺序": "Ordre fixe d'affichage de la traduction",

View File

@ -769,7 +769,6 @@
"滚动到最后": "Scorri fino alla fine",
"创建列表": "Crea elenco",
"限制每行字数": "Limitare il numero di parole per riga",
"音频播放": "Riproduzione audio",
"语速": "Velocità vocale",
"音量": "volume",
"固定翻译显示顺序": "Ordine fisso di visualizzazione della traduzione",

View File

@ -769,7 +769,6 @@
"滚动到最后": "最後までスクロール",
"创建列表": "リストの作成",
"限制每行字数": "1行あたりの文字数を制限する",
"音频播放": "オーディオ再生",
"语速": "早口",
"音量": "音量",
"固定翻译显示顺序": "固定翻訳表示順序",

View File

@ -769,7 +769,6 @@
"滚动到最后": "끝까지 스크롤",
"创建列表": "목록 만들기",
"限制每行字数": "행당 단어 수 제한",
"音频播放": "오디오 재생",
"语速": "말속도",
"音量": "볼륨",
"固定翻译显示顺序": "고정 번역 표시 순서",

View File

@ -771,7 +771,6 @@
"修改列表名称": "De naam van de lijst wijzigen",
"滚动到最后": "Naar het einde scrollen",
"限制每行字数": "Het aantal woorden per regel beperken",
"音频播放": "Audioweergave",
"语速": "Snelheid van spraak",
"音量": "volume",
"固定翻译显示顺序": "Vaste vertaalvolgorde",

View File

@ -769,7 +769,6 @@
"滚动到最后": "Przewiń do końca",
"创建列表": "Utwórz listę",
"限制每行字数": "Ograniczenie liczby słów na wiersz",
"音频播放": "Odtwarzanie dźwięku",
"语速": "Szybkość mowy",
"音量": "objętość",
"固定翻译显示顺序": "Stała kolejność wyświetlania tłumaczeń",

View File

@ -771,7 +771,6 @@
"修改列表名称": "Alterar o nome da lista",
"滚动到最后": "Deslocar até ao fim",
"限制每行字数": "Limitar a contagem de palavras por linha",
"音频播放": "Reprodução de áudio",
"语速": "Velocidade da fala",
"音量": "volume",
"固定翻译显示顺序": "Ordem fixa de apresentação da tradução",

View File

@ -769,7 +769,6 @@
"滚动到最后": "Прокрутить до конца",
"创建列表": "Создать список",
"限制每行字数": "Ограничение количества слов в строке",
"音频播放": "Звуковое воспроизведение",
"语速": "Скорость речи",
"音量": "Громкость",
"固定翻译显示顺序": "Фиксированный перевод Показать порядок",

View File

@ -771,7 +771,6 @@
"修改列表名称": "Ändra namnet på listan",
"滚动到最后": "Rulla till slutet",
"限制每行字数": "Begränsa antalet ord per rad",
"音频播放": "Ljudspelning",
"语速": "Talhastighet",
"音量": "volym",
"固定翻译显示顺序": "Fast visningsordning för översättning",

View File

@ -769,7 +769,6 @@
"滚动到最后": "เลื่อนไปจนสุด",
"创建列表": "สร้างรายการ",
"限制每行字数": "จำกัดจำนวนคำต่อบรรทัด",
"音频播放": "เล่นเสียง",
"语速": "ความเร็วการพูด",
"音量": "ระดับเสียง",
"固定翻译显示顺序": "ลำดับการแสดงผลการแปลคงที่",

View File

@ -769,7 +769,6 @@
"滚动到最后": "Sonuna doğru yürüt",
"创建列表": "Liste oluştur",
"限制每行字数": "Sırada kelimelerin sayısını sınırla",
"音频播放": "Ses çalması",
"语速": "Konuşma hızı",
"音量": "volume",
"固定翻译显示顺序": "Fikir çeviri gösterme düzeni",

View File

@ -769,7 +769,6 @@
"滚动到最后": "Пересунутися до кінця",
"创建列表": "Створити список",
"限制每行字数": "Обмежити кількість слів на рядок",
"音频播放": "Відтворення звуку",
"语速": "Швидкість мовлення",
"音量": "гучність",
"固定翻译显示顺序": "Визначений порядок показу перекладу",

View File

@ -769,7 +769,6 @@
"滚动到最后": "Cuộn đến cuối",
"创建列表": "Tạo danh sách",
"限制每行字数": "Giới hạn số lượng từ trên mỗi dòng",
"音频播放": "Phát lại âm thanh",
"语速": "Tốc độ nói",
"音量": "Âm lượng",
"固定翻译显示顺序": "Trình tự hiển thị bản dịch cố định",

View File

@ -772,7 +772,6 @@
"修改列表名称": "",
"滚动到最后": "",
"限制每行字数": "",
"音频播放": "",
"语速": "",
"音量": "",
"固定翻译显示顺序": "",

View File

@ -298,6 +298,21 @@ def downloadsomething():
os.chdir(rootDir + "\\temp")
subprocess.run(f"curl -LO {dynalink('Resource/build_req/stylesheets-main.zip')}")
subprocess.run(f"7z x stylesheets-main.zip -oALL")
shutil.move(
"ALL/bass.dll",
f"{rootDir}/LunaTranslator/files/plugins/DLL32",
)
shutil.move(
"ALL/x64/bass.dll",
f"{rootDir}/LunaTranslator/files/plugins/DLL64",
)
def downloadbass():
os.chdir(rootDir + "\\temp")
subprocess.run(f"curl -LO https://www.un4seen.com/files/bass24.zip")
subprocess.run(f"7z x bass24.zip -oALL")
move_directory_contents(
"ALL/stylesheets-main", rootDir + "\\LunaTranslator\\files\\themes"
)
@ -318,6 +333,7 @@ if __name__ == "__main__":
downloadCurl()
downloadOCRModel()
downloadcommon()
downloadbass()
buildLunaHook()
installVCLTL()

View File

@ -28,8 +28,8 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_SOURCE_DIR}/version)
include(generate_product_version)
set(VERSION_MAJOR 5)
set(VERSION_MINOR 23)
set(VERSION_PATCH 9)
set(VERSION_MINOR 25)
set(VERSION_PATCH 0)
add_library(pch pch.cpp)
target_precompile_headers(pch PUBLIC pch.h)

@ -1 +0,0 @@
Subproject commit 4a5b74bef029b3592c54b6048650ee5f972c1a48

View File

@ -11,7 +11,7 @@ generate_product_version(
VERSION_PATCH ${VERSION_PATCH}
)
add_library(winsharedutils MODULE webview2_extra.cpp AreoAcrylic.cpp screenshot.cpp audio.cpp ../implsapi.cpp hwnd.cpp globalmessagelistener.cpp theme.cpp version.cpp otsu.cpp clipboard.cpp lnk.cpp dllmain.cpp levenshtein.cpp muteprocess.cpp sapi_dll.cpp simplemecab.cpp SimpleBrowser.cpp MWebBrowser.cpp icon.cpp ${versioninfo})
add_library(winsharedutils MODULE webview2_extra.cpp AreoAcrylic.cpp screenshot.cpp ../implsapi.cpp hwnd.cpp globalmessagelistener.cpp theme.cpp version.cpp otsu.cpp clipboard.cpp lnk.cpp dllmain.cpp levenshtein.cpp muteprocess.cpp sapi_dll.cpp simplemecab.cpp SimpleBrowser.cpp MWebBrowser.cpp icon.cpp ${versioninfo})
target_precompile_headers(winsharedutils REUSE_FROM pch)
if(${CMAKE_SIZEOF_VOID_P} EQUAL 8)
set_target_properties(winsharedutils PROPERTIES OUTPUT_NAME "winsharedutils64")