QMediaPlayer::metaData always returns QVariant(Invalid) - qt

I used Qt on MAC OS and try to retrieve the metadata of media. So i took the Qt's Media Player Example (Qt 5.8.0) and modified a little bit:
Instead of:
connect(controls, SIGNAL(play()), player, SLOT(play()));
i used:
connect(controls, &PlayerControls::play, player,
[this]{
qDebug() << player->isMetaDataAvailable();
qDebug() << player->metaData(QMediaMetaData::Size);
player->play();
qDebug() << player->isMetaDataAvailable();
qDebug() << player->metaData(QMediaMetaData::Resolution);
});
The results are:
false
QVariant(Invalid)
false
QVariant(Invalid)
1st question: why is the metadata not available even after the media started playing?
2nd question: i added some codes in the destructor:
Player::~Player()
{
qDebug() << player->isMetaDataAvailable();
qDebug() << player->metaData(QMediaMetaData::Duration);
}
Now the metadata is available, but no data is returned:
true
QVariant(Invalid)
Can anyone help me please?
Update Question 1:
Instead of
connect(controls, SIGNAL(pause()), player, SLOT(pause()));
i used:
connect(controls, &PlayerControls::pause, player,
[this]{
qDebug() << player->isMetaDataAvailable();
qDebug() << player->metaData(QMediaMetaData::Resolution);
});
And after about 3-5 seconds of playing, the metadata is already available, but it also returns nothing:
true
QVariant(Invalid)

This is not the exact answer for your question but this may help you. You can check which metadata available with this code:
QMetaDataReaderControl *c = qobject_cast<QMetaDataReaderControl*>(player_->service()->requestControl(QMetaDataReaderControl_iid));
if(c) {
connect(c, &QMetaDataReaderControl::metaDataAvailableChanged, [c](bool) {
qDebug() << c->availableMetaData();
});
}

I', not sure, but I think that qDebug cannot handle QVariant, you should use for example:
qDebug() << (player->metaData(QMediaMetaData::Title)).toString();

Related

Generically getting the date and time

I know that this question may have been asked before, but this is a follow up of one of my previous questions found here. What makes this unique from the other questions is that I'm looking for something that is current and relevant to my compiler: Visual Studio 2017 using C++17 - latest draft standard.
I know that in time C++20 will be released and available for Visual Studio 2019 in which I'm looking forward to. However at the time being; I'm still using Visual Studio 2017 on Windows 7, and I'm currently bounded to C++17. I have found this Q/A that is similar to this that had offered great answers, however when I started to use <ctime> or <time.h> functions such as:
std::gmtime()
std::localtime()
My compiler is yelling at me that these functions are marked as unsafe and deprecated. I was attempting to write a function like this:
-DateAndTime.h-
#pragma once
#include <ctime>
#include <iomanip>
#include <iostream>
#include <sstream>
namespace util {
enum class TimeLocale {
LOCAL = 0x01,
GMT = 0x02,
BOTH = (LOCAL | GMT)
};
inline TimeLocale operator|(TimeLocale a, TimeLocale b) {
return static_cast<TimeLocale>(static_cast<int>(a) | static_cast<int>(b));
}
#pragma warning( push )
#pragma warning( disable : 4996 )
inline void currentDateAndTime(std::stringstream& stream, TimeLocale locale) {
std::time_t t = std::time(nullptr);
if (locale == TimeLocale::GMT) {
stream << "UTC: " << std::put_time( std::gmtime(&t), "%c, %Z") << '\n';
}
if (locale == TimeLocale::LOCAL) {
stream << "LOCAL: " << std::put_time(std::localtime(&t), "%c, %Z") << '\n';
}
if (locale == TimeLocale::BOTH) {
stream << "UTC: " << std::put_time(std::gmtime(&t), "%c, %Z") << '\n'
<< "LOCAL: " << std::put_time(std::localtime(&t), "%c, %Z") << '\n';
}
}
#pragma warning( pop )
} // namespace util
-main.cpp-
#include "DateAndTime.h"
#include <iostream>
#include <sstream>
using namespace util;
int main() {
try {
std::stringstream stream1;
getCurrentTime(stream1, TimeLocale::GMT);
std::cout << stream1.str() << '\n';
std::stringstream stream2;
getCurrentTime(stream2, TimeLocale::LOCAL);
std::cout << stream2.str() << '\n';
std::stringstream stream3;
getCurrentTime(stream3, TimeLocale::BOTH);
std::cout << stream3.str() << '\n';
std::stringstream stream4;
getCurrentTime(stream4, TimeLocale::GMT | TimeLocale::LOCAL);
std::cout << stream4.str() << '\n';
// ExceptionHandler is one of my class's and can be ignored in this context
// You can replace this with std::exception, std::cerr, etc...
} catch ( ExceptionHandler& e ) {
std::cout << "Exception Thrown: " << e.getMessage() << std::endl;
return EXIT_FAILURE;
} catch (...) {
std::cout << __FUNCTION__ << " Caught Unknown Exception" << std::endl;
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
This works fine if I use #pragma warning( disable : 4996 )
And I am getting a nice output like this:
UTC: 02/20/19 05:44:38, Eastern Standard Time
Local: 02/20/19 00:44:38, Eastern Standard Time
UTC: 02/20/19 05:44:38, Eastern Standard Time
Local: 02/20/19 00:44:38, Eastern Standard Time
UTC: 02/20/19 05:44:38, Eastern Standard Time
Local: 02/20/19 00:44:38, Eastern Standard Time
Which looks great. However, I'd prefer to not use any functions that are marked deprecated, that are not platform specific, that are generic, portable and cross platform as possible that is currently available in C++17. Preferably something from the standard library. I don't want to use a third party library nor boost. std::chrono would be a nice option however their calendar section won't be available until the full release of C++20. What kind of options am I left with?
The functions gmtime and localtime aren't deprecated.
Only for Visual Studio they are deprecated because Visual Studio offer the alternative gmtime_s and localtime_s, so I would use those functions.
And under Unix you have gmtime_r and localtime_r if you want to be thread-safe. See also this answer
Write an inline gmtime_r and localtime_r under Windows that calls gmtime_s and localtime_s and you have an almost standard cross plattform solution until C++20.

QtCreator semantic issue warning code will never be executed

I have following chunk of Qt code:
if(this->ueCommunicationsSocket()->bind(QHostAddress(data[0].toString()),
static_cast<quint16>(data[1].toInt())),
QAbstractSocket::ShareAddress)
{
qDebug() << Q_FUNC_INFO
<< "TCP socket bind succesfull";
}
else
{
qDebug() << Q_FUNC_INFO
<< QString::number(this->ueCommunicationsSocket()->error())
<< this->ueCommunicationsSocket()->errorString(); // here i get semantic issue
} // if
and I am getting semantic issue warning code will never be executed. I am aware this is some dumb mistake and I am ready to get downvote(s), however, I cannot find mistake! Here is also a screenshot:
if(this->ueCommunicationsSocket()->bind(QHostAddress(data[0].toString()),
static_cast<quint16>(data[1].toInt())),
QAbstractSocket::ShareAddress)
is
if ( /*something */, QAbstractSocket::ShareAddress)
since AbstractSocket::SharedAddress is 0x1, this condition with a comma operator ! is always true, i.e. the else branch will never be executed.

QDesktopWidget::screenGeometry returning incorrect value

I have Qt 5.3 running on top of DirectFB 1.7.4 (along with a tiny patch to qdirectfbintegration because platformNativeInterface was not implemented).
I come up in 3840x2160 resolution, then change to 1920x1080 resolution using the code below. The resolution changes and I can confirm looking at fbset output. The problem I am seeing is that after changing the resolution to 1920x1080 Qt still reports it as 3840x2160.
Does anyone know how to force Qt to recheck/update the resolution it is reporting? Or what might be missing from the directfb plugin to notify Qt that something has changed under the hood?
Thanks.
IDirectFB * dfb = (IDirectFB*)m_app->platformNativeInterface();
if(dfb){
std::cerr << "######## New resolution is " << width << "x" << height << std::endl;
IDirectFBDisplayLayer *layer;
DFBDisplayLayerConfig config;
std::cerr << "######## Getting primary IDirectFBDisplayLayer" << std::endl;
/* Get an interface to the primary layer. */
dfb->GetDisplayLayer(dfb, DLID_PRIMARY, &layer);
if(layer){
DFBResult dres;
std::cerr << "######## Got the primary display layer, setting admin" << std::endl;
// This level allows window stack mode switches
dres = layer->SetCooperativeLevel(layer, DLSCL_ADMINISTRATIVE);
if(dres != DFB_OK){
std::cerr << "######## Error: " << DirectFBErrorString(dres) << std::endl;
}
std::cerr << "######## Getting layer configuration" << std::endl;
// Get layer configuration
dres = layer->GetConfiguration(layer, &config);
if(dres != DFB_OK){
std::cerr << "######## Error: " << DirectFBErrorString(dres) << std::endl;
}
// Set the new resolution
std::cerr << "######## Setting layer resolution" << std::endl;
config.width = width;
config.height = height;
dres = layer->SetConfiguration(layer, &config);
if(dres != DFB_OK){
std::cerr << "######## Error: " << DirectFBErrorString(dres) << std::endl;
}
}
// Print out resolution from Qt
QRect res = QApplication::desktop()->screenGeometry();
std::cerr << "######## QApplication resolution is now " << res.width() << "x" << res.height() << std::endl;
The output I see from the console is:
######## New resolution is 1920x1080
######## Getting primary IDirectFBDisplayLayer
######## Got the primary display layer, setting admin
######## Getting layer configuration
######## Setting layer resolution
(*) FBDev/Mode: Setting 1920x1080 ARGB
(*) FBDev/Mode: Switched to 1920x1080 (virtual 1920x2160) at 32 bit (ARGB), pitch 7680
######## QApplication resolution is now 3840x2160
root#output:~# fbset
mode "1920x1080-24"
# D: 74.250 MHz, H: 27.000 kHz, V: 24.000 Hz
geometry 1920 1080 1920 2160 32
timings 13468 148 638 36 4 44 5
accel false
rgba 8/16,8/8,8/0,8/24
endmode
The directfb qpa plugin is lacking several features. I'm working on some updates to the plugin, I'll post a link here when I submit them.
For a temporary workaround calling:
WindowSystemInterface::handleScreenGeometryChange(m_app->screens().first(), QRect(0,0,width,height));
is working to update the resolution in Qt.

QCamera automatically reset my settings

I'm trying to set a few settings in the camera example
Declaration
QCamera *camera;
QMediaRecorder* mediaRecorder;
QVideoEncoderSettings videoSettings;
Code
videoSettings.setFrameRate(10);
qDebug() << videoSettings.frameRate();
videoSettings.setQuality(QMultimedia::VeryLowQuality);
videoSettings.setResolution(200, 300);
qDebug() << videoSettings.resolution();
mediaRecorder->setVideoSettings(videoSettings);
qDebug() << mediaRecorder->videoSettings().resolution();
And it's not working, as you can see the debug log:
10
QSize(200, 300)
QSize(-1, -1) 0 // should be 200*300 an 10fps, isn't it ?
I don't understand why it's not working...

Qt: QUrl::fromUserInput intepretes FTP Url wrong

I have some issue in passing a FTP string into QUrl:
std::cout << QUrl::fromUserInput("ftp://user#host.com:password#ftphost:21/path/file.ext").toString().toStdString().c_str() << std::endl;
Is always resulting in
http://ftp//user#host.com:password#ftphost:21/path/file.ext
which is obviously wrong. What's the problem with the above FTP Url? Or is that a known issue within Qt4?
I am working on Linux, using Qt 4.8.1.
Even following code
if(QUrl("ftp://user#host.com:password#ftphost:21/path/file.ext").isValid())
std::cout << "is valid" << std::endl;
else
std::cout << "is not valid" << std::endl;
Is resulting in "is not valid"
Thanks in advance
You need manually replace # in username with %40. That's what QUrl does internally if QUrl::setUserName() is called with user#domain.tld.

Resources