From 3e7f827e9dd6c143772ed063a57209728cea2720 Mon Sep 17 00:00:00 2001 From: Andre de la Rocha Date: Fri, 10 Nov 2017 10:32:53 +0100 Subject: Add ActiveQt Media Player example The Media Player example uses the Microsoft Media Player ActiveX control to implement a functional media player application. This example demonstrates how a Qt application can communicate with embedded ActiveX controls using signals, slots and the dynamicCall() function. Task-number: QTBUG-60636 Change-Id: Ie2f65d3d8796076b2c18d5fa561b709035a53e79 Reviewed-by: Leena Miettinen --- examples/activeqt/activeqt.pro | 5 +- .../doc/images/activeqt-mediaplayer-example.jpg | Bin 0 -> 48753 bytes .../activeqt/mediaplayer/doc/src/mediaplayer.qdoc | 87 ++++++++++ examples/activeqt/mediaplayer/main.cpp | 183 +++++++++++++++++++++ examples/activeqt/mediaplayer/mainwindow.ui | 147 +++++++++++++++++ examples/activeqt/mediaplayer/mediaaxwidget.h | 76 +++++++++ examples/activeqt/mediaplayer/mediaplayer.pro | 11 ++ 7 files changed, 507 insertions(+), 2 deletions(-) create mode 100644 examples/activeqt/mediaplayer/doc/images/activeqt-mediaplayer-example.jpg create mode 100644 examples/activeqt/mediaplayer/doc/src/mediaplayer.qdoc create mode 100644 examples/activeqt/mediaplayer/main.cpp create mode 100644 examples/activeqt/mediaplayer/mainwindow.ui create mode 100644 examples/activeqt/mediaplayer/mediaaxwidget.h create mode 100644 examples/activeqt/mediaplayer/mediaplayer.pro (limited to 'examples') diff --git a/examples/activeqt/activeqt.pro b/examples/activeqt/activeqt.pro index 43ccbeb..6f189bc 100644 --- a/examples/activeqt/activeqt.pro +++ b/examples/activeqt/activeqt.pro @@ -6,8 +6,9 @@ SUBDIRS += comapp \ simple \ wrapper +contains(QT_CONFIG, shared):SUBDIRS += mediaplayer contains(QT_CONFIG, opengl):!contains(QT_CONFIG, opengles2): SUBDIRS += opengl qtHaveModule(quickcontrols2):SUBDIRS += simpleqml -# For now the examples need an IDL compiler -mingw:SUBDIRS = "" +# Other examples need an IDL compiler +mingw:SUBDIRS = mediaplayer diff --git a/examples/activeqt/mediaplayer/doc/images/activeqt-mediaplayer-example.jpg b/examples/activeqt/mediaplayer/doc/images/activeqt-mediaplayer-example.jpg new file mode 100644 index 0000000..4839242 Binary files /dev/null and b/examples/activeqt/mediaplayer/doc/images/activeqt-mediaplayer-example.jpg differ diff --git a/examples/activeqt/mediaplayer/doc/src/mediaplayer.qdoc b/examples/activeqt/mediaplayer/doc/src/mediaplayer.qdoc new file mode 100644 index 0000000..6043a6a --- /dev/null +++ b/examples/activeqt/mediaplayer/doc/src/mediaplayer.qdoc @@ -0,0 +1,87 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: https://www.gnu.org/licenses/fdl-1.3.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \example activeqt/mediaplayer + \title Media Player Example (ActiveQt) + + \brief The Media Player example uses the Microsoft Media Player + ActiveX control to implement a functional media player application. + + \image activeqt-mediaplayer-example.jpg + + \e {Media Player} demonstrates how a Qt application can communicate with + embedded ActiveX controls using signals, slots, and the \c dynamicCall() + function. + + \quotefromfile activeqt/mediaplayer/main.cpp + \skipto class MainWindow + \printuntil /^\}/ + + The \c MainWindow class declares a \c QMainWindow based user interface, + using the \c Ui::MainWindow class created by Qt Designer. A number + of slots are implemented to handle events from user interface elements, + including the \c mediaPlayer object, which is a QAxWidget hosting + the Microsoft Media Player ActiveX control. + + \quotefromfile activeqt/mediaplayer/main.cpp + \skipto MainWindow::MainWindow() + \printuntil /^\}/ + + The constructor initializes the user interface, restores a previously + saved window geometry, and uses the \c dynamicCall() function to invoke + the APIs implemented by the Microsoft Media Player ActiveX control, + to set initial configuration parameters. + + \quotefromfile activeqt/mediaplayer/main.cpp + \skipto MainWindow::on_mediaPlayer_PlayStateChange + \printuntil /^\}/ + + The \c on_mediaPlayer_PlayStateChange slot handles the signal emitted + by the \c mediaPlayer object when its state changes. + + \quotefromfile activeqt/mediaplayer/main.cpp + \skipto MainWindow::openMedia + \printuntil /^\}/ + + The \c openMedia() function allows a media file to be opened by using + the \c dynamicCall() function to set the URL property in the ActiveX + control, which causes the media file to be loaded and played. + + \quotefromfile activeqt/mediaplayer/main.cpp + \skipto int main + \printuntil /^\}/ + + The \c main() function starts the application using standard Qt APIs + and uses an optional command line argument as the name of a media + file to be loaded by the player. + + To build the example, you must first build the QAxContainer + library. Then run your make tool in + \c examples/activeqt/mediaplayer and run the resulting + \c mediaplayer.exe. +*/ diff --git a/examples/activeqt/mediaplayer/main.cpp b/examples/activeqt/mediaplayer/main.cpp new file mode 100644 index 0000000..921279b --- /dev/null +++ b/examples/activeqt/mediaplayer/main.cpp @@ -0,0 +1,183 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ui_mainwindow.h" + +static const char geometryKey[] = "Geometry"; + +class MainWindow : public QMainWindow +{ + Q_OBJECT +public: + MainWindow(); + ~MainWindow(); + void openMedia(const QString &mediaUrl); + +public slots: + void on_mediaPlayer_PlayStateChange(int newState); + void on_actionOpen_triggered(); + void on_actionExit_triggered(); + void on_actionAbout_triggered(); + void on_actionAboutQt_triggered(); + +private: + void updateWindowTitle(const QString &state); + Ui::MainWindow m_ui; +}; + +MainWindow::MainWindow() +{ + m_ui.setupUi(this); + + QSettings settings(QSettings::IniFormat, QSettings::UserScope, + QCoreApplication::organizationName(), QCoreApplication::applicationName()); + + const QByteArray restoredGeometry = settings.value(QLatin1String(geometryKey)).toByteArray(); + if (restoredGeometry.isEmpty() || !restoreGeometry(restoredGeometry)) { + const QRect availableGeometry = QApplication::desktop()->availableGeometry(this); + const QSize size = (availableGeometry.size() * 4) / 5; + resize(size); + move(availableGeometry.center() - QPoint(size.width(), size.height()) / 2); + } + + m_ui.mediaPlayer->dynamicCall("enableContextMenu", false); + m_ui.mediaPlayer->dynamicCall("stretchToFit", true); + updateWindowTitle(""); +} + +MainWindow::~MainWindow() +{ + QSettings settings(QSettings::IniFormat, QSettings::UserScope, + QCoreApplication::organizationName(), QCoreApplication::applicationName()); + settings.setValue(QLatin1String(geometryKey), saveGeometry()); +} + +void MainWindow::on_mediaPlayer_PlayStateChange(int newState) +{ + static const QHash stateMapping { + {1, "Stopped"}, + {2, "Paused"}, + {3, "Playing"}, + {4, "Scanning Forwards"}, + {5, "Scanning Backwards"}, + {6, "Buffering"}, + {7, "Waiting"}, + {8, "Media Ended"}, + {9, "Transitioning"}, + {10, "Ready"}, + {11, "Reconnecting"}, + }; + const char *stateStr = stateMapping.value(newState, ""); + updateWindowTitle(tr(stateStr)); +} + +void MainWindow::on_actionOpen_triggered() +{ + QFileDialog fileDialog(this, tr("Open File")); + fileDialog.setAcceptMode(QFileDialog::AcceptOpen); + fileDialog.setFileMode(QFileDialog::ExistingFile); + fileDialog.setMimeTypeFilters({ "application/octet-stream", "video/x-msvideo", "video/mp4", "audio/mpeg", "audio/mp4" }); + if (fileDialog.exec() == QDialog::Accepted) + openMedia(fileDialog.selectedFiles().first()); +} + +void MainWindow::on_actionExit_triggered() +{ + QCoreApplication::quit(); +} + +void MainWindow::on_actionAbout_triggered() +{ + QMessageBox::about(this, tr("About Media Player"), + tr("This Example has been created using the ActiveQt integration into Qt Designer.\n" + "It demonstrates the use of QAxWidget to embed the Windows Media Player ActiveX\n" + "control into a Qt application.")); +} + +void MainWindow::on_actionAboutQt_triggered() +{ + QMessageBox::aboutQt(this, tr("About Qt")); +} + +void MainWindow::openMedia(const QString &mediaUrl) +{ + if (!mediaUrl.isEmpty()) + m_ui.mediaPlayer->dynamicCall("URL", mediaUrl); +} + +void MainWindow::updateWindowTitle(const QString &state) +{ + QString appName = QCoreApplication::applicationName(); + QString title = state.isEmpty() ? appName : + QString("%1 (%2)").arg(appName, state); + setWindowTitle(title); +} + +#include "main.moc" + +int main(int argc, char *argv[]) +{ + QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); + QApplication app(argc, argv); + QCoreApplication::setApplicationVersion(QT_VERSION_STR); + QCoreApplication::setApplicationName(QLatin1String("Active Qt Media Player")); + QCoreApplication::setOrganizationName(QLatin1String("QtProject")); + + MainWindow w; + QCommandLineParser parser; + parser.setApplicationDescription(QCoreApplication::applicationName()); + parser.addHelpOption(); + parser.addVersionOption(); + parser.addPositionalArgument("file", "The media file to open."); + parser.process(app); + if (!parser.positionalArguments().isEmpty()) + w.openMedia(parser.positionalArguments().constFirst()); + w.show(); + return app.exec(); +} diff --git a/examples/activeqt/mediaplayer/mainwindow.ui b/examples/activeqt/mediaplayer/mainwindow.ui new file mode 100644 index 0000000..b83d392 --- /dev/null +++ b/examples/activeqt/mediaplayer/mainwindow.ui @@ -0,0 +1,147 @@ + + + MainWindow + + + + 0 + 0 + 794 + 599 + + + + true + + + Qt Media Player + + + + + 6 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + QFrame::StyledPanel + + + QFrame::Sunken + + + + 0 + + + 1 + + + 1 + + + 1 + + + 1 + + + + + {6bf52a52-394a-11d3-b153-00c04f79faa6} + + + + 0 + 0 + + + + + + + + + + + + + 0 + 0 + 794 + 21 + + + + + &File + + + + + + + &Help + + + + + + + + + + &Open + + + + + E&xit + + + + + &About + + + + + About &Qt + + + + + + + + QAxWidget + QWidget +
qaxwidget.h
+
+ + MediaAxWidget + QAxWidget +
mediaaxwidget.h
+
+
+ + +
diff --git a/examples/activeqt/mediaplayer/mediaaxwidget.h b/examples/activeqt/mediaplayer/mediaaxwidget.h new file mode 100644 index 0000000..a57ca05 --- /dev/null +++ b/examples/activeqt/mediaplayer/mediaaxwidget.h @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef MEDIAAXWIDGET_H +#define MEDIAAXWIDGET_H + +#include +#include + +// Overrides the translateKeyEvent() function to pass keystrokes +// to the Windows Media Player ActiveX control. +class MediaAxWidget : public QAxWidget +{ +public: + MediaAxWidget(QWidget *parent = nullptr, Qt::WindowFlags f = 0) + : QAxWidget(parent, f) + { + } + +protected: + bool translateKeyEvent(int message, int keycode) const override + { + if (message >= WM_KEYFIRST && message <= WM_KEYLAST) + return true; + return QAxWidget::translateKeyEvent(message, keycode); + } +}; + +#endif // MEDIAAXWIDGET_H diff --git a/examples/activeqt/mediaplayer/mediaplayer.pro b/examples/activeqt/mediaplayer/mediaplayer.pro new file mode 100644 index 0000000..ad787a3 --- /dev/null +++ b/examples/activeqt/mediaplayer/mediaplayer.pro @@ -0,0 +1,11 @@ +TEMPLATE = app + +QT += widgets axcontainer + +HEADERS = mediaaxwidget.h +SOURCES = main.cpp +FORMS = mainwindow.ui + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/activeqt/mediaplayer +INSTALLS += target -- cgit v1.2.3