From 5b1c2fd9100b32361ffacbb69a6d0ce3dbd664fe Mon Sep 17 00:00:00 2001 From: "Christopher T. Johnson" Date: Mon, 1 Apr 2024 10:06:24 -0400 Subject: [PATCH] Move to QNetwork --- lib/sounds.py | 71 ++++++++++++++++++++++++++++++++++++++++++--------- lib/words.py | 23 ++++++++++++----- 2 files changed, 76 insertions(+), 18 deletions(-) diff --git a/lib/sounds.py b/lib/sounds.py index 3cfb4f1..ac1d21f 100644 --- a/lib/sounds.py +++ b/lib/sounds.py @@ -1,13 +1,25 @@ from typing import Optional, Self, Type, cast -from PyQt6.QtCore import QObject, Qt, QUrl, pyqtSlot +from PyQt6.QtCore import ( + QBuffer, + QByteArray, + QDir, + QObject, + QStandardPaths, + QUrl, + pyqtSlot, +) from PyQt6.QtMultimedia import ( - QAudioDevice, QAudioOutput, QMediaDevices, QMediaPlayer, QSoundEffect, ) +from PyQt6.QtNetwork import ( + QNetworkAccessManager, + QNetworkDiskCache, + QNetworkRequest, +) # from PyQt6.QtWidgets import QWidget @@ -62,20 +74,28 @@ class SoundOff(QObject): self.virtualPlayer.errorOccurred.connect(self.mediaError) self.virtualPlayer.mediaStatusChanged.connect(self.mediaStatus) self.virtualPlayer.playbackStateChanged.connect(self.playbackState) - - @pyqtSlot() - def alert(self) -> None: - self.alertEffect.play() + cacheDir = QDir( + QStandardPaths.writableLocation( + QStandardPaths.StandardLocation.GenericCacheLocation + ) + ) + cacheDir.mkdir("Troglodite") + cacheDir = QDir(cacheDir.path() + QDir.separator() + "Troglodite") + netCache = QNetworkDiskCache() + netCache.setCacheDirectory(cacheDir.path()) + self.nam = QNetworkAccessManager() + self.nam.setCache(netCache) return @pyqtSlot(QMediaPlayer.Error, str) - def mediaError(self, error: QMediaPlayer.Error, string: str) -> None: + def mediaError(self, error: QMediaPlayer.Error, msg: str) -> None: print(error) - print(str) + print(msg) return @pyqtSlot(QMediaPlayer.MediaStatus) def mediaStatus(self, status: QMediaPlayer.MediaStatus) -> None: + print(f"mediaStatus: {status}") if status == QMediaPlayer.MediaStatus.LoadedMedia: player: Optional[QMediaPlayer] = cast(QMediaPlayer, self.sender()) assert player is not None @@ -84,6 +104,7 @@ class SoundOff(QObject): @pyqtSlot(QMediaPlayer.PlaybackState) def playbackState(self, state: QMediaPlayer.PlaybackState) -> None: + print(f"playbackState: {state}") return # @@ -95,20 +116,46 @@ class SoundOff(QObject): return @pyqtSlot(str) - def playSound(self, url: str) -> None: - src = QUrl(url) + def playSound(self, url: str | QUrl) -> None: + if isinstance(url, str): + url = QUrl(url) if not self.localPlayer.audioOutput(): self.localPlayer.setAudioOutput(self.localOutput) - self.localPlayer.setSource(src) + request = QNetworkRequest(url) + self.reply = self.nam.get(request) + assert self.reply is not None + self.reply.finished.connect(self.finished) + return + + @pyqtSlot() + def alert(self) -> None: + self.alertEffect.play() + return + + # + # Network slots + # + _buffer = QBuffer() + _storage = QByteArray() + + @pyqtSlot() + def finished(self) -> None: + assert self.reply is not None + self._storage = self.reply.readAll() + if self.localPlayer.sourceDevice() != self._buffer: + self._buffer.setBuffer(self._storage) + self.localPlayer.setSourceDevice(self._buffer) self.localPlayer.setPosition(0) if ( self.localPlayer.mediaStatus() == QMediaPlayer.MediaStatus.LoadedMedia ): self.localPlayer.play() + print("play") if not self.virtualDevice: return - self.virtualPlayer.setSource(src) + if self.virtualPlayer.sourceDevice() != self._buffer: + self.virtualPlayer.setSourceDevice(self._buffer) self.virtualPlayer.setPosition(0) if not self.virtualPlayer.audioOutput(): self.virtualPlayer.setAudioOutput(self.virtualOutput) diff --git a/lib/words.py b/lib/words.py index 97b4d85..dae3d6b 100644 --- a/lib/words.py +++ b/lib/words.py @@ -18,6 +18,11 @@ from PyQt6.QtGui import ( QTextOption, QTransform, ) +from PyQt6.QtNetwork import ( + QNetworkAccessManager, + QNetworkReply, + QNetworkRequest, +) from PyQt6.QtSql import QSqlQuery from PyQt6.QtWidgets import QScrollArea, QWidget @@ -537,12 +542,18 @@ class Word: # The code should look at our settings to see if we have an API # key for MW to decide on the source to use. # - source = 'mw' - response = requests.get(MWAPI.format(word=word)) - if response.status_code != 200: - self.current = {} - return - data = json.loads(response.content.decode("utf-8")) + source = "mw" + manager = QNetworkAccessManager() + request = QNetworkRequest() + url = QUrl(MWAPI.format(word=word)) + request.setUrl(url) + reply = manager.get(request) + assert reply is not None + loop = QEventLoop() + reply.finished.connect(loop.quit) + loop.exec() + content = reply.readAll() + data = json.loads(content.data().decode("utf-8")) print(data) self._words[word] = { 'word': word,