diff --git a/README.md b/README.md index 98ae575..92b91dc 100644 --- a/README.md +++ b/README.md @@ -88,8 +88,6 @@ Pesterchum is a Python script. This means that as long as you have Python instal - [PyQt6] (prefered) or [PyQt5] (legacy) - Qt6 only supports maintained 64 bit operating systems, like Windows 10 or later for Windows. ([Qt 6.3 Supported Platforms](https://doc.qt.io/qt-6/supported-platforms.html)) - Qt5 supports Windows 7 or later, but is past its EOL for non-commercial use. ([Qt 5.15 Supported Platforms](https://doc.qt.io/qt-6/supported-platforms.html)) - - (Optional) [pygame-ce] or [pygame] can provide an alternative audio backend for certain systems. - - Useful for Linux systems that don't meet the Qt6 requirements, as Qt5 Multimedia has a GStreamer dependency. - (Optional) [certifi] can provide alternative root certificates for TLS certificate validation. - Useful for MacOS, as Python doesn't use the system-provided certificates because of MacOS' outdated SSL library. Also miscellaneous systems without usable root certificates. @@ -102,9 +100,9 @@ Pesterchum is a Python script. This means that as long as you have Python instal - On macOS it's also possible to install (a more recent version of) Python via [Brew](https://brew.sh/). 2. Install Pesterchum's dependencies with pip, run: ``python -m pip install -r requirements.txt`` - If this fails, try running ``python -m pip install -U pip setuptools wheel`` to update pip, setuptools & wheel and then trying again. - - Alternatively, many linux distros also have packages for pyqt and pygame. - - Debian: [python3-pyqt6](https://packages.debian.org/testing/python/python3-pyqt6), [python3-pygame](https://packages.debian.org/testing/python/python3-pygame) - - Arch: [python-pyqt6](https://archlinux.org/packages/extra/x86_64/python-pyqt6/), [python-pygame](https://archlinux.org/packages/community/x86_64/python-pygame/) + - Alternatively, many linux distros also have packages for PyQt6. + - Debian: [python3-pyqt6](https://packages.debian.org/testing/python/python3-pyqt6) + - Arch: [python-pyqt6](https://archlinux.org/packages/extra/x86_64/python-pyqt6/) 3. Download [this repository's source](https://github.com/Dpeta/pesterchum-alt-servers/archive/refs/heads/main.zip), or choose the "Source Code" option on any release, and extract the archive to a folder of your choice. - Alternatively, clone the repository with git. 4. Navigate your terminal to the folder you chose with ``cd /folder/you/chose``. @@ -116,8 +114,6 @@ Pesterchum is a Python script. This means that as long as you have Python instal [pip]: https://pypi.org/project/pip/ [PyQt5]: https://pypi.org/project/PyQt5/ [PyQt6]: https://pypi.org/project/PyQt6/ -[pygame]: https://pypi.org/project/pygame/ -[pygame-ce]: https://pypi.org/project/pygame-ce/ [certifi]: https://pypi.org/project/certifi/ [GStreamer]: https://gstreamer.freedesktop.org/ diff --git a/generic.py b/generic.py index 99316a4..5171129 100644 --- a/generic.py +++ b/generic.py @@ -160,20 +160,6 @@ class MovingWindow(QtWidgets.QFrame): self.moving = None -class NoneSound: - def __init__(self, *args, **kwargs): - pass - - def play(self): - pass - - def setVolume(self, v): - pass - - def set_volume(self, v): - pass - - class WMButton(QtWidgets.QPushButton): def __init__(self, icon, parent=None): super().__init__(icon, "", parent) diff --git a/menus.py b/menus.py index 69fc8e2..6e3949f 100644 --- a/menus.py +++ b/menus.py @@ -1567,15 +1567,19 @@ class PesterOptions(QtWidgets.QDialog): self.audioDeviceBox = QtWidgets.QComboBox(self) current_audio_device = self.config.audioDevice() active_index = None - try: - for i, output in enumerate(QtMultimedia.QMediaDevices.audioOutputs()): - self.audioDeviceBox.addItem(f"{output.description()}", output.id()) - if output.id() == current_audio_device: - active_index = i - if active_index is not None: - self.audioDeviceBox.setCurrentIndex(active_index) - except AttributeError: - PchumLog.warning("Can't get audio devices, not using PyQt6 QtMultimedia?") + if hasattr(QtMultimedia, "QMediaDevices"): + # PyQt6 + try: + for i, output in enumerate(QtMultimedia.QMediaDevices.audioOutputs()): + self.audioDeviceBox.addItem(f"{output.description()}", output.id()) + if output.id() == current_audio_device: + active_index = i + if active_index is not None: + self.audioDeviceBox.setCurrentIndex(active_index) + except AttributeError: + PchumLog.warning( + "Can't get audio devices, not using PyQt6 QtMultimedia?" + ) layout_sound = QtWidgets.QVBoxLayout(widget) layout_sound.setAlignment(QtCore.Qt.AlignmentFlag.AlignTop) diff --git a/pesterchum.py b/pesterchum.py index 9fb6233..af846b5 100755 --- a/pesterchum.py +++ b/pesterchum.py @@ -46,7 +46,6 @@ from generic import ( PesterList, CaseInsensitiveDict, MovingWindow, - NoneSound, WMButton, ) from convo import PesterTabWindow, PesterConvo @@ -64,11 +63,20 @@ from randomer import RandomHandler, RANDNICK from toast import PesterToastMachine, PesterToast try: - from PyQt6 import QtCore, QtGui, QtWidgets + from PyQt6 import QtCore, QtGui, QtWidgets, QtMultimedia from PyQt6.QtGui import QAction, QActionGroup + + # Give Linux QtMultimedia warning. + if ostools.isLinux(): + print( + "QtMultimedia audio is a bit silly/goofy on Linux and relies on an appropriate" + " backend being availible." + "\nIf it doesn't work, try installing your distro's equivalent" + " of the qt6-multimedia-backend/qt6-multimedia/gstreamer packages." + ) except ImportError: print("PyQt5 fallback (pesterchum.py)") - from PyQt5 import QtCore, QtGui, QtWidgets + from PyQt5 import QtCore, QtGui, QtWidgets, QtMultimedia from PyQt5.QtWidgets import QAction, QActionGroup # Data directory @@ -142,60 +150,6 @@ BOTNAMES.extend(SERVICES) # Command line arguments _ARGUMENTS = parser.parse_args() -# Import audio module -# Qt6.4's ffmpeg audio backend makes using QtMultimedia on linux less risky -try: - # PyQt6, QtMultimedia is prefered. - from PyQt6 import QtMultimedia - - print("Audio module is PyQt6 QtMultimedia.") -except ImportError: - if ostools.isWin32() or ostools.isOSX(): - # PyQt5 QtMultimedia has native backends for MacOS and Windows - try: - from PyQt5 import QtMultimedia - - print( - "Using PyQt5 QtMultimedia as sound module. (fallback, PyQt6 QtMultimedia not availible)" - ) - except ImportError: - try: - import pygame - - print( - "Using pygame as sound module. (fallback, PyQt6 QtMultimedia and PyQt5 QtMultimedia not availible)" - ) - except ImportError: - print( - "All possible audio modules failed to import." - "\nPossible audio modules in order of preference (Windows/MacOS): PyQt6 QtMultimedia > PyQt5 QtMultimedia > pygame" - ) - # Linux or misc. - else: - # PyQt5 QtMultimedia needs gstreamer on linux, so pygame is prefered. - try: - import pygame - - print( - "Using pygame as sound module. (fallback, PyQt6 QtMultimedia not availible)" - ) - except ImportError: - try: - from PyQt5 import QtMultimedia - - print( - "Using PyQt5 QtMultimedia as sound module. (fallback, PyQt6 QtMultimedia and pygame not availible)" - ) - print( - "PyQt5 Multimedia will silently fail without GStreamer with relevant" - " plugins on Linux, pygame is prefered when using PyQt5." - ) - except ImportError: - print( - "All possible audio modules failed to import." - "\nLPossible audio modules in order of preference (Linux/Unknown): PyQt6 QtMultimedia > pygame > PyQt5 QtMultimedia" - ) - class waitingMessageHolder: def __init__(self, mainwindow, **msgfuncs): @@ -1372,8 +1326,6 @@ class PesterWindow(MovingWindow): self.honk = True self.modes = "" - self.sound_type = None - self.randhandler = RandomHandler(self) try: @@ -2202,69 +2154,28 @@ class PesterWindow(MovingWindow): self._setup_sounds() self.setVolume(self.config.volume()) - def _setup_sounds(self, soundclass=None): + def _setup_sounds(self): """Set up the event sounds for later use.""" - # Set up the sounds we're using. + # Define and load sounds try: - # Pygame - soundclass = pygame.mixer.Sound # pylint: disable=used-before-assignment - except (NameError, AttributeError): - try: - # QtMultimedia - soundclass = QtMultimedia.QSoundEffect - except (NameError, AttributeError): - # death - soundclass = NoneSound - PchumLog.warning("No sound module loaded?") - - self.sound_type = soundclass - - # These get redefined if sound works - self.alarm = NoneSound() - self.memosound = NoneSound() - self.namesound = NoneSound() - self.ceasesound = NoneSound() - self.honksound = NoneSound() - - # Use the class we chose to build the sound set. - try: - if "pygame" in globals(): - if soundclass == pygame.mixer.Sound: - self.alarm = soundclass(self.theme["main/sounds/alertsound"]) - self.memosound = soundclass(self.theme["main/sounds/memosound"]) - self.namesound = soundclass("themes/namealarm.wav") - self.ceasesound = soundclass(self.theme["main/sounds/ceasesound"]) - self.honksound = soundclass("themes/honk.wav") - if "QtMultimedia" in globals(): - if soundclass == QtMultimedia.QSoundEffect: - self.alarm = soundclass() - self.memosound = soundclass() - self.namesound = soundclass() - self.ceasesound = soundclass() - self.honksound = soundclass() - - self.alarm.setSource( - QtCore.QUrl.fromLocalFile(self.theme["main/sounds/alertsound"]) - ) - self.memosound.setSource( - QtCore.QUrl.fromLocalFile(self.theme["main/sounds/memosound"]) - ) - self.namesound.setSource( - QtCore.QUrl.fromLocalFile("themes/namealarm.wav") - ) - self.ceasesound.setSource( - QtCore.QUrl.fromLocalFile(self.theme["main/sounds/ceasesound"]) - ) - self.honksound.setSource( - QtCore.QUrl.fromLocalFile("themes/honk.wav") - ) + self.alarm = QtMultimedia.QSoundEffect() + self.alarm.setSource( + QtCore.QUrl.fromLocalFile(self.theme["main/sounds/alertsound"]) + ) + self.memosound = QtMultimedia.QSoundEffect() + self.memosound.setSource( + QtCore.QUrl.fromLocalFile(self.theme["main/sounds/memosound"]) + ) + self.namesound = QtMultimedia.QSoundEffect() + self.namesound.setSource(QtCore.QUrl.fromLocalFile("themes/namealarm.wav")) + self.ceasesound = QtMultimedia.QSoundEffect() + self.ceasesound.setSource( + QtCore.QUrl.fromLocalFile(self.theme["main/sounds/ceasesound"]) + ) + self.honksound = QtMultimedia.QSoundEffect() + self.honksound.setSource(QtCore.QUrl.fromLocalFile("themes/honk.wav")) except: PchumLog.exception("Warning: Error loading sounds!") - self.alarm = NoneSound() - self.memosound = NoneSound() - self.namesound = NoneSound() - self.ceasesound = NoneSound() - self.honksound = NoneSound() self.sounds = [ self.alarm, @@ -2282,12 +2193,7 @@ class PesterWindow(MovingWindow): vol = vol_percent / 100.0 for sound in self.sounds: try: - if "pygame" in globals(): - if self.sound_type == pygame.mixer.Sound: - sound.set_volume(vol) - if "QtMultimedia" in globals(): - if self.sound_type == QtMultimedia.QSoundEffect: - sound.setVolume(vol) + sound.setVolume(vol) except Exception as err: PchumLog.warning("Couldn't set volume: %s", err) @@ -2298,23 +2204,21 @@ class PesterWindow(MovingWindow): if "QtMultimedia" not in globals(): PchumLog.warning("Not using QtMultimedia, can't set audio device.") return - for output in QtMultimedia.QMediaDevices.audioOutputs(): - if device_id == output.id(): - for sound in self.sounds: - sound.setAudioDevice(output) + if hasattr(QtMultimedia, "QMediaDevices"): + # PyQt6 + for output in QtMultimedia.QMediaDevices.audioOutputs(): + if device_id == output.id(): + for sound in self.sounds: + if sound: + sound.setAudioDevice(output) def canSetVolume(self): """Returns the state of volume setting capabilities.""" # If the volume can be changed by Pesterchum. - if self.sound_type is None: - # We haven't initialized yet. - return False - elif self.sound_type == NoneSound: - # Sound is dead - return False - else: - # We can set volume - return True + for sound in self.sounds: + if sound: + return True + return False # All None. . . def changeTheme(self, theme): # check theme @@ -4113,14 +4017,6 @@ class MainProgram(QtCore.QObject): msgbox.setIcon(QtWidgets.QMessageBox.Icon.Critical) msgbox.exec() - # If we're using pygame for sound we need to init - if "pygame" in globals(): - # we could set the frequency higher but i love how cheesy it sounds - try: - pygame.mixer.init() - except Exception as err: - print("Warning: No sound! (pygame error: %s)" % err) - self.widget = PesterWindow(options, parent=self, app=self.app) # self.widget.show() <== Already called in showLoading() diff --git a/pyinst.py b/pyinst.py index ca5847e..59674fc 100644 --- a/pyinst.py +++ b/pyinst.py @@ -9,9 +9,6 @@ import PyInstaller.__main__ is_64bit = sys.maxsize > 2**32 # is_linux = sys.platform.startswith("linux") exclude_modules = [] -# if is_linux == False: -# print("Not Linux, excluding pygame.") -# exclude_modules.append('pygame') add_data = [ "quirks;quirks", "smilies;smilies", diff --git a/requirements-qt5.txt b/requirements-qt5.txt index dc36024..f8110a3 100644 --- a/requirements-qt5.txt +++ b/requirements-qt5.txt @@ -1,5 +1,4 @@ certifi==2022.12.7 -pygame-ce PyQt5==5.15.7 PyQt5-Qt5==5.15.2 PyQt5-sip==12.11.0