1

During the testing of QSound for one of my programs, I encountered an issue I can't get my head around. Whenever I'm implementing QSound objects inside another object, the play() function doesn't seem to be able to call the member variables of the QSound object.

Here are the examples, I used to analyze the problem:

  1. Example with QSound in Script (Works as expected with 2 repetitions of the sound)
from PyQt5.Qt import QApplication
from PyQt5.QtMultimedia import QSound
import sys

app=QApplication(sys.argv)

SoundObject=QSound("./path/sound.wav")

SoundObject.play()
SoundObject.play("./path/sound.wav")

sys.exit(app.exec())
  1. Example QSound inside another object (Only one repetition of the sound)
from PyQt5.Qt import QApplication
from PyQt5.QtMultimedia import QSound
import sys

app=QApplication(sys.argv)

class SoundClass:

   def __init__(self):

        SoundObject = QSound("./path/sound.wav")

        print(SoundObject.fileName())  # output= "./path/sound.wav"

        SoundObject.play()  # this doesn't do anything
        SoundObject.play("./path/sound.wav") 

SoundClass()

sys.exit(app.exec())

In both cases I would expect, that the sound gets played 2 times in a row. However as soon as I use an QSound object inside another object, it seems like the ".play()" function ignores the settings of my object and instead calls the static function QSound.play(). The same behavior appears with other member variables of the QSound object (e.g. setLoops/loops).

While searching for an answer to my problem, I found a thread about the same issue with C++ and Qt. Although someone mentioned that QSound might be deprecated, there wasn't a definite answer. (And I'm wondering why it would 4 years later still be part of the documentation.)

Link to the Thread: QSound::play("soundpath") call works but a QSound object doesn't

I used the following documentation: https://www.riverbankcomputing.com/static/Docs/PyQt5/api/qtmultimedia/qsound.html?highlight=qsound#PyQt5.QtMultimedia.QSound

My specs:

  • Windows 10.0.17134.706
  • Python 3.7
  • PyQt 5.12

Am I missing something crucial or is this simply a bug?

halfer
  • 19,824
  • 17
  • 99
  • 186
eNceo1423
  • 23
  • 4

1 Answers1

0

In the second code, the SoundObject variable is a local variable that will be deleted when the constructor finishes executing so the first play will not be executed instead the second play if it is a static method that does not depend on any object.

  In the first code, the SoundObject variable will be deleted when the script finishes, since its scope is larger.

The solution is to increase the scope of SoundObject by making it a member of the class:

from PyQt5.Qt import QApplication
from PyQt5.QtMultimedia import QSound
import sys

app = QApplication(sys.argv)


class SoundClass:
    def __init__(self):
        self.SoundObject = QSound("./path/sound.wav")
        print(self.SoundObject.fileName())  # output= "./path/sound.wav"
        self.SoundObject.play()  # this doesn't do anything
        self.SoundObject.play("./path/sound.wav")


SoundClass()
sys.exit(app.exec())
eyllanesc
  • 235,170
  • 19
  • 170
  • 241
  • Thanks for your answer. I think we might are talking past each other. The SoundObject.play() function isn't a static function, it just behaves like the static function QSound.play() by ignoring it's own member variables. This behavior only appears with QSound objects that are members of another object. Furthermore I'm uncertain how the .play() function can be out of scope, if it is inside the constructor. I copy and pasted your solution and the sound still only appears once. If you tested the same code on your system as well, it could be just a platform specific problem on my side. – eNceo1423 Apr 23 '19 at 17:03
  • @eNceo1423 There are 2 play methods: if you do not pass arguments this must be through an object https://doc.qt.io/qt-5/qsound.html#play-1, but if you do not pass any arguments even when you use an object it will use the static method https://doc.qt.io/qt-5/qsound.html#play – eyllanesc Apr 23 '19 at 18:10
  • Maybe I should read the documentation properly^^. However, I still don't understand why your solution doesn't play the sound twice, whenever the code get's executed. After all the method of the object should get the file-path through the string passed to the constructor. – eNceo1423 Apr 25 '19 at 17:01