How do I wait for QMediaPlayer::setMedia(.. to finish?
Title summarizes my question. I'm using Qt 5.15 in MinGW, gcc 10.2, C++17.
I have a UI with a QVideoWidget with video output to a QMediaPlayer. The UI layout/size automatically rescales to the loaded media, i.e. it depends on the size of that media.
Because of this, I need to finish loading the media set with QMediaPlayer::setMedia(.. to avoid unneccessary layout/resize calls.
However QMediaPlayer::setMedia(.. returns immediately and I can only check if loading is finished by inspecting QMediaPlayer::MediaStatus with the appropriate slot.
Currently, on my load call, I put all size-dependent arguments in a buffer struct and then call the actual layout/resize function either if loading is already finished, or whenever
Code:
QMediaPlayer::MediaStatus == QMediaPlayer::LoadedMedia
But this a bit messy and still means I have to return from my loading function possibly before loading is finished, thus doing all layout/resizing twice..
So: is there any way to specifically wait for loading of the media to finish after calling QMediaPlayer::setMedia(..? As far as I understand, everything is handled by events, not threads, so doing something like would simply lock forever. Do I need to somehow request for a specific event to be processed immediately? Or do I call QMediaPlayer::setMedia(.. itself on a new thread and then lock the main thread with a mutex, would this be defined behavior to do in Qt? Or something else entirely?
Re: How do I wait for QMediaPlayer::setMedia(.. to finish?
And why don't / can't you connect to QMediaPlayer::mediaStatusChanged() signal and do the stuff you want to in there?
Re: How do I wait for QMediaPlayer::setMedia(.. to finish?
That is what I am doing right now, but my problem is that this is not guaranteed to be called when I want it to. My problem is that I do not want to call QMediaPlayer::setMedia(.., then return from the function making that call, and then only sometime later have QMediaPlayer::mediaStatusChanged(.. called with QMediaPlayer::MediaStatus == QMediaPlayer::LoadedMedia.
Currently, this first makes the UI initialize in a weird unusable (but responsive) state exactly because setMedia immediately returns. I do not want this, and I cannot put the UI in a useable state without the media having finished loading, because I need some data from it to do so. Only after some waiting, once QMediaPlayer::mediaStatusChanged(.. is called after loading has finished, I update the UI a second time, in a proper state.
Instead, it would be much easier if I can guarantee that when I return from the function that calls QMediaPlayer::setMedia(.., the media has definitely finished loading. But I cannot sleep, because that will block the main thread, so the call to QMediaPlayer::mediaStatusChanged(.. will never happen to begin with.. unless I'm mistaken somewhere?
I have some "solutions" in mind, but they feel somewhat convoluted and hard to understand in code to me:
- 1. Emit another signal from inside QMediaPlayer::mediaStatusChanged(.. to call a slot in the caller that finishes the remaining UI layout.
My problem with this is that the UI will still be responsive in a bad state until loading is finished. I could hide the window, or copy it to a temporary, or something along those lines, to get around this - but that is quite complicated for such a simple task, not to mention the additional needed signal / slot. - 2. Use a different library to load the media, extract the needed data, use that to do the layout. QMediaPlayer can then load its own seperate media and I don't need to wait for it. This seems a little more sane, but in my use case the loading is generally fast enough that having to double the memory usage for a minor speedup is questionable. Though it would only be for a short time, I guess.
Maybe one of these is fine, but simply waiting for the loading to finish would surely be the simplest and more maintainable way, I just don't know if this is possible..