BMSTU/03-mmt-lab-03-report.tex

405 lines
19 KiB
TeX
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

\documentclass[a4paper]{article}
\input{../common-preamble}
\input{../bmstu-preamble}
\input{../fancy-listings-preamble}
\numerationTop
\begin{document}
\fontsize{14pt}{14pt}\selectfont % Вполне очевидно, что мы хотим 14й шрифт, все его хотят
\thispagestyle{empty}
\makeBMSTUHeader
\makeReportTitle{лабораторной}{3}{Разработка мультимедийного приложения}{Мультимедиа технологии}{}{Д.А. Видьманов}
\newpage
\pagestyle{fancy}
\sloppy
\section{Цель}
Целью работы является приобретение навыков создания мультимедийных приложений. Создать мультимедийное приложение.
\section{Задачи}
\begin{enumerate}
\item Установить среду разработки;
\item Описать критерии создания приложения;
\item Написать код и отладить работу приложения.
\end{enumerate}
\section{Выполнение работы}
Для написания мультимедйного приложения был выбран Qt Framework версии 5.12, и язык C++. Разрабатываемое приложение - это единый мультимедийный просмотрщик файлов (офисные документы, pdf, видео). Для реализации мультимедийности были выбраны несколько компонентов и создан экран, основной частью которого является область просмотра.
\begin{figure}[H]
\centering
\includegraphics[width=12cm]{03-mmt-lab-03-main.png}
\caption{Основное окно приложения}
\end{figure}
\subsection{Функции. Открытие MPEG}
\begin{figure}[H]
\centering
\includegraphics[width=12cm]{03-mmt-lab-03-video.png}
\caption{Видео в приложении}
\end{figure}
Для открытия, воспроизведения и перемотки видеофайлов используются компоненты \code{QMediaPlayer} и \code{QVideoWidget}. Для работы с компонентами были описаны следующие слоты и функции:
\begin{itemize}
\item \code{void openMPEG(QString&)}. Достраивает в главном окне необходимые области, добавляет кнопки, инициализирует слайдеры, связывает слоты.
\item \code{void closeMPEG()}. Отвязывает слоты, удаляет динамические объекты, очищает окно от элементов управления.
\item \code{void playVideo()}. Начинает/продолжает проигрывание медиафайла.
\item \code{void stopVideo()}. Завершает проигрывание файла. Позиция проигрывания перемещается в начало. Если после вызова этой функции вызвать \code{playVideo()}, то видео начнется сначала.
\item \code{void pauseVideo()}. Приостанавливает проигрывание медиа. Позиция сохраняется. Если после вызова этой вызвать \code{playVideo()}, то видео продолжится с момента приостановки видео.
\item \code{void changeVolume(int)}. Изменяет громкость звука. Слот вызывается сигналом \code{&QSlider::valueChanged} с передачей значения из компонента.
\item \code{void changePosition()}. Принудительно перематывает видео ползунком. При вызове слота позиции видео присваивается значение с ползунка, отвечающего за перемотку видео.
\item \code{void updatePosition(qint64)}. Слот реагирует на текущее положение курсора в проигрывателе и передает относительное положение ползунку перемотки видео, чтобы положение ползунка менялось в ходе проигрывания видео.
\item \code{void updateDuration(qint64)}. При старте видеопотока общая продолжительность видео считается некоторое время, поэтому сразу идентифицировать не удастся. Слот привязан к сигналу о том, что для данного видеофайла изменилось (вычислилось) значение продолжительности.
\item \code{void updateState(int)}. Справочный слот. Реагирует на Старт, Стоп и Паузу видео. Если необходимо в процессе работы выдавать еще какие-то команды - слот «узнаёт», в каком состоянии проигрывания медиафайл.
\end{itemize}
\subsection{Функции. Открытие офисных документов (XLSX, DOCX, PPTX)}
Функции офиса используют компонент ActiveX и отображают содержимое, фактически открытое в приложениях офисного пакета.
\begin{figure}[H]
\centering
\includegraphics[width=12cm]{03-mmt-lab-03-open.png}
\caption{Окно открытия файла}
\end{figure}
\begin{itemize}
\item \code{void openXLSX(QString&)}. Открывает XLSX файл и передает управление файлом приложению MS Excel. Отображение размещается внутри виджета.
\item \code{void openDOCX(QString&)}. Открывает DOCX файл и передает управление файлом приложению MS Word. Отображение размещается внутри виджета.
\item \code{void openPPTX(QString&)}. Открывает PPTX файл и передает управление файлом приложению MS PowerPoint. Отображение размещается внутри виджета. Дополнительно, здесь происходит подключение к слоту, вызывющему проигрывание в режиме презентации.
\end{itemize}
\subsection{Функции. Открытие документов PDF}
\code{void openPDF(QString&)}. Открывает PDF файл и передает управление файлом приложению Adobe Acrobat. Отображение размещается внутри виджета.
\begin{figure}[H]
\centering
\includegraphics[width=12cm]{03-mmt-lab-03-pdf.png}
\caption{Просмотр PDF документа}
\end{figure}
\subsection{Закрытие документа}
\code{void closeFile()} - Закрывает открытый документ.
\section{Выводы}
Для разработки мультимедийного приложения необходимо изучить разнообразный инструментарий, позволяющий манипулировать мультимедийными данными. Написание мультимедийнх приложений тесно связано с обработкой больших объёмов данных или использованием внешних библиотек и приложений. Мультимедийные приложения возможно написать для любых платформ и внедрить для любых категорий пользователей.
\newpage
\appendix
\setcounter{secnumdepth}{0}
\section{Приложения}
\renewcommand{\thesubsection}{\Asbuk{subsection}}
\subsection{Полный листинг главного окна приложения}
\begin{lstlisting}[language=C++,style=CCodeStyle]
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QMenuBar *menuBar = new QMenuBar();
m_menuFile = menuBar->addMenu("&File");
m_openAction = new QAction("&Open");
m_openAction->setStatusTip(tr("Open a document"));
m_menuFile->addAction(m_openAction);
m_menuFile->addSeparator();
m_quitAction = new QAction("&Quit");
m_quitAction->setShortcut(tr("CTRL+Q"));
m_quitAction->setStatusTip(tr("Quit application"));
m_menuFile->addAction(m_quitAction);
connect(this->m_openAction, &QAction::triggered, this, &MainWindow::slotOpenAction);
connect(this->m_quitAction, &QAction::triggered, qApp, &QApplication::quit);
this->setMenuBar(menuBar);
this->resize(800, 600);
show();
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::delay(int delay) {
QTime dieTime= QTime::currentTime().addSecs(delay);
while (QTime::currentTime() < dieTime)
QCoreApplication::processEvents(QEventLoop::AllEvents, 100);
}
void MainWindow::slotOpenAction() {
m_filename = QFileDialog::getOpenFileName(
this, tr("Выберите файл"), "../", tr("MPEG (*.mpeg) ;; PDF (*.pdf) ;; DOCX (*.docx) ;; XLSX (*.xlsx) ;; PPTX (*.pptx)"));
if (m_filename != "") {
if (axObj) {
qDebug() << "Close file!\n";
closeFile();
}
if (m_videoWidget) {
qDebug() << "Close MPEG!\n";
closeMPEG();
}
if (m_filename.endsWith(".pdf")) {
openPDF(m_filename);
} else if (m_filename.endsWith(".pptx")) {
openPPTX(m_filename);
} else if (m_filename.endsWith(".docx")) {
openDOCX(m_filename);
} else if (m_filename.endsWith(".xlsx")) {
openXLSX(m_filename);
} else if (m_filename.endsWith(".mpeg")) {
openMPEG(m_filename);
}
}
}
void MainWindow::closeFile() {
if (axObj != nullptr) {
QProcess process;
QString strCmd;
strCmd = "taskkill /im winword.exe /f";
process.execute(strCmd);
strCmd = "taskkill /im EXCEL.exe /f";
process.execute(strCmd);
strCmd = "taskkill /im POWERPNT.exe /f";
process.execute(strCmd);
strCmd = "taskkill /im AcroRd32.exe /f";
process.execute(strCmd);
process.close();
axObj->close();
axObj->clear();
delete axObj;
axObj = nullptr;
qDebug() << "file closed!";
}
}
void MainWindow::openPDF(QString &filename) {
axObj = new QAxWidget(this);
setCentralWidget(axObj);
if(!axObj->setControl("Adobe PDF Reader"))
QMessageBox::critical(this, "Error", "Make sure you have Adobe Reader (and its ActiveX) installed!");
axObj->dynamicCall("LoadFile(QString)", filename);
}
/* run slideshow */
void MainWindow::playPPTX() {
// Open parameter
QList<QVariant> param_list;
axObj->setControl("PowerPoint.Application");
param_list.append(m_filename);
param_list.append(1);
param_list.append(1);
param_list.append(0);
// Open a template file
QAxObject *presentations = axObj->querySubObject("Presentations");
QAxObject *presentation = presentations->querySubObject("Open(const QString&,int,int,int)", param_list);
// Start the slides
QAxObject *slideshow = presentation->querySubObject("SlideShowSettings");
slideshow->setProperty("RangeType", "ppShowAll");
slideshow->dynamicCall("run()");
}
void MainWindow::openPPTX(QString &filename) {
/* инициализация окна виджетом */
m_wideWidget = new QWidget;
setCentralWidget(m_wideWidget);
qDebug() << "1";
/* здесь будут элементы управления и окно проигрывателя (выравнивание по горизонтали) */
m_qvBoxLayout = new QVBoxLayout(m_wideWidget);
axObj = new QAxWidget("PowerPoint.Application", m_wideWidget);
m_btnPlay = new QPushButton("Начать презентацию");
qDebug() << "2";
m_qvBoxLayout->addWidget(axObj);
m_qvBoxLayout->addWidget(m_btnPlay);
if (axObj == nullptr) {
return;
}
if (!axObj->setControl(filename)) {
return;
}
axObj->dynamicCall("LoadFile(const QString&)", filename);
axObj->dynamicCall("SetVisible (bool Visible)", "false");
axObj->setProperty("DisplayAlerts", false);
axObj->setProperty("DisplayScrollBars", true);
delay(1);
axObj->show();
axObj->raise();
qDebug() << "3";
connect(this->m_btnPlay, &QPushButton::clicked, this, &MainWindow::playPPTX);
}
void MainWindow::openXLSX(QString &filename) {
axObj = new QAxWidget("Excel.Application", this);
setCentralWidget(axObj);
if (axObj == nullptr) {
return;
}
axObj->dynamicCall("SetVisible (bool Visible)", "false");
axObj->setProperty("DisplayAlerts", false);
axObj->setProperty("DisplayScrollBars", true); // Show scroll bar
axObj->setGeometry(this->geometry());
axObj->setControl(filename);
axObj->show();
}
void MainWindow::openDOCX(QString &filename) {
axObj = new QAxWidget("Word.Application", this);
setCentralWidget(axObj);
if (axObj == nullptr) {
return;
}
axObj->dynamicCall("SetVisible (bool Visible)", "false");
axObj->setFocusPolicy(Qt::StrongFocus);
axObj->setProperty("DisplayAlerts", false);
axObj->setProperty("DisplayHorizontalScrollBar", true); // Show scroll bar
axObj->setGeometry(this->geometry());
axObj->setControl(filename);
axObj->show();
}
/* продолжить проигрывать видео */
void MainWindow::playVideo() {
m_player->setPosition(m_position);
m_player->play();
}
/* остановка видео */
void MainWindow::stopVideo() {
m_player->stop();
}
/* пауза видео */
void MainWindow::pauseVideo() {
m_player->pause();
}
/* событие при изменении состояния видеопроигрывателя */
void MainWindow::updateState(int state) {
switch (state) {
case QMediaPlayer::PlayingState:
/* media is played */
break;
case QMediaPlayer::PausedState:
/* media paused */
break;
case QMediaPlayer::StoppedState:
/* media is stopped */
break;
}
}
/* принудительно изменить время проигрывания */
void MainWindow::changePosition() {
m_position = m_sliderVideo->value();
m_player->setPosition(m_position);
}
/* принудительно изменить время проигрывания */
void MainWindow::updatePosition(qint64 position) {
m_position = position;
m_sliderVideo->setValue(m_position);
}
/* изменить величину звука */
void MainWindow::changeVolume(int volume) {
m_player->setVolume(volume);
}
/* слот для иницализации значением слайдера видео */
void MainWindow::updateDuration(qint64 duration) {
m_sliderVideo->setRange(0, m_player->duration());
m_sliderVideo->setEnabled(duration > 0);
m_sliderVideo->setPageStep(duration / 10);
}
/* инициализация медиа файла */
void MainWindow::openMPEG(QString &filename) {
/* инициализация окна виджетом */
m_wideWidget = new QWidget;
setCentralWidget(m_wideWidget);
/* здесь будут элементы управления и окно проигрывателя (выравнивание по горизонтали) */
m_qvBoxLayout = new QVBoxLayout(m_wideWidget);
/* область для отображения видео */
m_videoWidget = new QVideoWidget;
m_player = new QMediaPlayer(m_videoWidget);
m_player->setVideoOutput(m_videoWidget);
m_player->setMedia(QUrl::fromLocalFile(filename));
/* область размещения кнопок управления видео */
m_hBtnsLayout = new QHBoxLayout;
m_play = new QPushButton("Play");
m_stop = new QPushButton("Stop");
m_pause = new QPushButton("Pause");
m_sliderVolume = new QSlider(Qt::Horizontal);
m_sliderVolume->setRange(0, 100); // диапазон значений громкости
m_sliderVolume->setValue(50); // текущая громкость 50%
m_sliderVideo = new QSlider(Qt::Horizontal);
m_hBtnsLayout->addWidget(m_play, 1);
m_hBtnsLayout->addWidget(m_stop, 1);
m_hBtnsLayout->addWidget(m_pause, 1);
m_hBtnsLayout->addWidget(&m_labelVolume);
m_hBtnsLayout->addWidget(m_sliderVolume, 1);
m_hBtnsLayout->addWidget(&m_labelScroll);
m_hBtnsLayout->addWidget(m_sliderVideo, 5);
/* поместить настроенные объекты в центральный виджет */
m_qvBoxLayout->addWidget(m_videoWidget);
m_qvBoxLayout->addLayout(m_hBtnsLayout);
/* связать слоты */
connect(this->m_play, &QPushButton::clicked, this, &MainWindow::playVideo);
connect(this->m_stop, &QPushButton::clicked, this, &MainWindow::stopVideo);
connect(this->m_pause, &QPushButton::clicked, this, &MainWindow::pauseVideo);
connect(this->m_sliderVolume, &QSlider::sliderMoved, this, &MainWindow::changeVolume);
connect(this->m_sliderVideo, &QSlider::sliderMoved, this, &MainWindow::changePosition);
connect(this->m_sliderVideo, &QSlider::valueChanged, this, &MainWindow::changePosition);
connect(this->m_player, &QMediaPlayer::durationChanged, this, &MainWindow::updateDuration);
connect(this->m_player, &QMediaPlayer::positionChanged, this, &MainWindow::updatePosition);
connect(this->m_player, &QMediaPlayer::stateChanged, this, &MainWindow::updateState);
/* начать проигрывать видео */
playVideo();
}
void MainWindow::closeMPEG() {
/* отключение всех слотов */
disconnect(this->m_play, &QPushButton::clicked, this, &MainWindow::playVideo);
disconnect(this->m_stop, &QPushButton::clicked, this, &MainWindow::stopVideo);
disconnect(this->m_pause, &QPushButton::clicked, this, &MainWindow::pauseVideo);
disconnect(this->m_sliderVolume, &QSlider::sliderMoved, this, &MainWindow::changeVolume);
disconnect(this->m_sliderVideo, &QSlider::sliderMoved, this, &MainWindow::changePosition);
disconnect(this->m_sliderVideo, &QSlider::sliderPressed, this, &MainWindow::changePosition);
disconnect(this->m_player, &QMediaPlayer::durationChanged, this, &MainWindow::updateDuration);
disconnect(this->m_player, &QMediaPlayer::positionChanged, this, &MainWindow::updatePosition);
disconnect(this->m_player, &QMediaPlayer::stateChanged, this, &MainWindow::updateState);
/* удаление динамических объектов */
delete m_sliderVideo;
delete m_sliderVolume;
delete m_play;
delete m_stop;
delete m_pause;
delete m_hBtnsLayout;
delete m_player;
delete m_videoWidget;
delete m_qvBoxLayout;
}
\end{lstlisting}
\end{document}