diff options
author | Andre de la Rocha <andre.rocha@qt.io> | 2017-11-10 10:32:53 +0100 |
---|---|---|
committer | Andre de la Rocha <andre.rocha@qt.io> | 2017-11-23 15:50:32 +0000 |
commit | 3e7f827e9dd6c143772ed063a57209728cea2720 (patch) | |
tree | 62ba83965b6a8e09a97026e617e221cd468e70c4 /examples/activeqt | |
parent | 616207ec9783cf58661f35782fee6f8c825f205f (diff) | |
download | qtactiveqt-3e7f827e9dd6c143772ed063a57209728cea2720.tar.gz |
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 <riitta-leena.miettinen@qt.io>
Diffstat (limited to 'examples/activeqt')
-rw-r--r-- | examples/activeqt/activeqt.pro | 5 | ||||
-rw-r--r-- | examples/activeqt/mediaplayer/doc/images/activeqt-mediaplayer-example.jpg | bin | 0 -> 48753 bytes | |||
-rw-r--r-- | examples/activeqt/mediaplayer/doc/src/mediaplayer.qdoc | 87 | ||||
-rw-r--r-- | examples/activeqt/mediaplayer/main.cpp | 183 | ||||
-rw-r--r-- | examples/activeqt/mediaplayer/mainwindow.ui | 147 | ||||
-rw-r--r-- | examples/activeqt/mediaplayer/mediaaxwidget.h | 76 | ||||
-rw-r--r-- | examples/activeqt/mediaplayer/mediaplayer.pro | 11 |
7 files changed, 507 insertions, 2 deletions
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 Binary files differnew file mode 100644 index 0000000..4839242 --- /dev/null +++ b/examples/activeqt/mediaplayer/doc/images/activeqt-mediaplayer-example.jpg 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 <QApplication> +#include <QMessageBox> +#include <QMainWindow> +#include <QDesktopWidget> +#include <QVariant> +#include <QSettings> +#include <QFileDialog> +#include <QCommandLineParser> + +#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<int, const char *> 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 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>MainWindow</class> + <widget class="QMainWindow" name="MainWindow"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>794</width> + <height>599</height> + </rect> + </property> + <property name="acceptDrops"> + <bool>true</bool> + </property> + <property name="windowTitle"> + <string>Qt Media Player</string> + </property> + <widget class="QWidget" name="centralWidget"> + <layout class="QHBoxLayout" name="unnamed"> + <property name="spacing"> + <number>6</number> + </property> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <widget class="QFrame" name="Frame"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="frameShape"> + <enum>QFrame::StyledPanel</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Sunken</enum> + </property> + <layout class="QVBoxLayout" name="unnamed"> + <property name="spacing"> + <number>0</number> + </property> + <property name="leftMargin"> + <number>1</number> + </property> + <property name="topMargin"> + <number>1</number> + </property> + <property name="rightMargin"> + <number>1</number> + </property> + <property name="bottomMargin"> + <number>1</number> + </property> + <item> + <widget class="MediaAxWidget" name="mediaPlayer"> + <property name="control" stdset="0"> + <string>{6bf52a52-394a-11d3-b153-00c04f79faa6}</string> + </property> + <property name="sizePolicy" stdset="0"> + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + </widget> + </item> + </layout> + </widget> + </item> + </layout> + </widget> + <widget class="QMenuBar" name="menubar"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>794</width> + <height>21</height> + </rect> + </property> + <widget class="QMenu" name="PopupMenu"> + <property name="title"> + <string>&File</string> + </property> + <addaction name="actionOpen"/> + <addaction name="actionExit"/> + </widget> + <widget class="QMenu" name="menuHelp"> + <property name="title"> + <string>&Help</string> + </property> + <addaction name="actionAbout"/> + <addaction name="actionAboutQt"/> + </widget> + <addaction name="PopupMenu"/> + <addaction name="menuHelp"/> + </widget> + <action name="actionOpen"> + <property name="text"> + <string>&Open</string> + </property> + </action> + <action name="actionExit"> + <property name="text"> + <string>E&xit</string> + </property> + </action> + <action name="actionAbout"> + <property name="text"> + <string>&About</string> + </property> + </action> + <action name="actionAboutQt"> + <property name="text"> + <string>About &Qt</string> + </property> + </action> + <actiongroup name="FileNewGroup"/> + </widget> + <layoutdefault spacing="6" margin="11"/> + <customwidgets> + <customwidget> + <class>QAxWidget</class> + <extends>QWidget</extends> + <header>qaxwidget.h</header> + </customwidget> + <customwidget> + <class>MediaAxWidget</class> + <extends>QAxWidget</extends> + <header>mediaaxwidget.h</header> + </customwidget> + </customwidgets> + <resources/> + <connections/> +</ui> 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 <ActiveQt/QAxWidget> +#include <qt_windows.h> + +// 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 |