Grafika a multimédia v Qt

Z Wikipedie, otevřené encyklopedie

Qt framework v dnešní době představuje komplexní aplikační vývojový framework, který za relativně dlouhou dobu svého vývoje (téměř 21 let) vyrostl do podoby univerzálního nástroje umožňujícího tvorbu sofistikovaných multiplatformních aplikací. Ve své původní podobě to byl pouze tzv. widget toolkit neboli knihovna pro tvorbu grafických uživatelských rozhraní (GUI). Postupně však během vývoje přibývaly funkce a moduly pro podporu multimédií, databází, sítí, webových technologií a mnoho dalších komponent.[1]

Z Qt frameworku se tak stala ucelená vývojářská platforma na jejímž základě lze postavit téměř libovolnou aplikaci, která bude nativně multiplatformní. Navíc při vývoji většinou není potřeba využívat téměř žádné externí knihovny, protože velká většina potřebné bázové funkcionality je už integrována do samotného Qt frameworku. Velkou výhodou je pak to, že pro aplikaci vystačíte pouze s jedinou sadou zdrojových kódu, které stačí pro nasazení na libovolnou další podporovanou platformu pouze jednoduše překompilovat.

Tento článek se však nezabývá celým Qt, které pouze stručně představuje, ale zaměřuje se pouze na možnosti grafiky a multimédií v tomto frameworku.

Historie Qt frameworku[editovat | editovat zdroj]

Vývoj Qt frameworku započal přibližně v roce 1991, kdy jej jeho dva hlavní vývojáři (Haavard Nord a Eirik Chambe-Eng) začali samostatně vyvíjet. První veřejně dostupná verze se pak objevila až v květnu 1995. Původní myšlenky na vytvoření multiplatformního toolkitu pro tvorbu GUI však pocházejí už z roku 1988 a 1990 tedy z dob studií obou jeho hlavních autorů na Norwegian Institute of Technology v Trondheimu.

Poznámka: Zajímavostí ohledně počátku vývoje Qt frameworku je, že tento vývoj sponzorovaly manželky dvou hlavních vývojářů, protože oba zmínění pánové v té době ještě neměli žádné jiné příjmy, kterými by se v té době zajistili. Vskutku se tedy jednalo o originální a unikátní vývojový model.[1]

Původní vývoj tedy zastřešovali pouze dva vývojáři, kteří po relativním úspěchu svého produktu založili společnost Quasar Technologies později Trolltech. Trolltech zajišťoval vývoj Qt od roku 1995 do roku 2008. Poté technologii Qt odkoupila společnost Nokia, která se o jeho vývoj starala až do podzimu 2012. V současné době vývoj spravuje společnost Digia, která Qt zakoupila od Nokie. Digia však není ve vývoji Qt tak úplně nováčkem, protože k němu už předtím několik let poskytovala komerční podporu, vývoj a školení. V poslední době se dokonce starala o prodej komerčních licencí než celou technologii převzala kompletně.

Podporované platformy[editovat | editovat zdroj]

V současné době jsou podporovány tři majoritní desktopové platformy v podobě Microsoft Windows, Apple Mac OS X a UNIX/Linux-like systémy. Kromě nich však Qt podporuje i embedded platformy a mobilní zařízení (Symbian, embedded Linux, …). V blízké budoucnosti (příchod finální verze Qt 5) se chystá také oficiální podpora Android OS, Apple iOS, BlackBerry a QNX.

Podporované programovací jazyky[editovat | editovat zdroj]

Nativním jazykem tohoto frameworku je jazyk C++, který je ovšem rozšířen o možnosti jako je introspekce, podpora mechanismu Signálu & Slotu a několik dalších vylepšení, které usnadňují a urychlují vývoj především aplikací s grafickým uživatelským rozhraním. Dalším nativně podporovaným jazykem je jazyk QML (Qt Markup/Modeling Language) což je v podstatě obdoba webového CSS pomocí kterého ve spolupráci s JavaScriptem lze jednoduše naskriptovat GUI aplikace a jádro poté pro větší efektivitu výsledného kódu napsat v jazyce C++. Kromě těchto dvou nativních možností ještě pro Qt existuje mnoho jazykových vazeb (anglicky language bindings), kde mezi nejvýznamnější patří například podpora pro Python, Ruby, Javu.

Licence a možnosti vývoje[editovat | editovat zdroj]

Qt framework je nabízen ve třech možných licenčních modelech. Nejprve je zde klasická licence, kdy si zakoupíte komerční licenci a můžete vyvíjet své aplikace i modifikovat samotný Qt framework bez jakékoli povinnosti zveřejňovat své kódy či platit nějaké licenční poplatky z prodaných aplikací. Poté je zde možnost možnost využít licence GPL (General Public Licence), kdy je možné zdarma nekomerčně vyvíjet, ale je nutné zveřejnit všechny zdrojové kódy vytvořené aplikace. Třetím typem licence je LGPL (Lesser GPL), která umožňuje uzavřený komerční vývoj aplikací, kdy vývojář je povinen zveřejnit pouze změny, které provedl v kódu samotného Qt frameworku.[2]

Moduly Qt frameworku[editovat | editovat zdroj]

Celý framework je postaven na objektových konceptech a je velmi modulární, to v praxi znamená, že svůj projekt zkompilujete pouze s moduly, které využijete a nemusíte s aplikací přibalovat neužitečný kód. V základu se Qt framework skládá z následujících modulů:

  • QtCore – jádro Qt a jeho základní nevizuální komponenty
  • QtGui – bázový modul všech vizuálních prvků GUI tzv. widgetů
  • QtMultimedia – nízkoúrovňová podpora pro multimédia
  • QtNetwork – síťová podpora
  • QtOpenGL – spolupráce s knihovnou OpenGL
  • QtScript – možnost aplikačního skriptování
  • QtSql – podpora práce s databázemi
  • QtSvg – podpora vektorového grafického formátu SVG
  • QtWebKit – jádro webového prohlížeče WebKit (práce s webem)
  • QtXml – podpora technologie XML
  • QtDeclarative – jádro a rozhraní pro spolupráci nativního kódu s deklarativním QML
  • Phonon – komplexní multimediální framework
  • a několik dalších..

Rastrové 2D kreslení pomocí systému Arthur[editovat | editovat zdroj]

Rastrové kreslení v Qt je v principu obdobné kreslení pomocí standardních Win32 API funkcí respektive grafickému modulu GDI (Graphics Device Interface), kde se pracuje s nejrůznějšími pery, výplňovými štětci a doplňkovými nástroji které modifikují určitý rastr. V systému Arthur je tento přístup zapouzdřen pomocí třech typů tříd. Vystupuje zde třída QPainter (malíř/kreslíř) která umožňuje vlastní kreslení na základě sekvenčních pokynů programátora. Poté je zde přítomno kreslící jádro QPaintEngine které přímo implementuje kreslící metody a abstrahuje QPainter od specifického kreslícího zařízení. Nakonec třída QPaintDevice zapouzdřuje samotné kreslící zařízení na které se bude vykreslovat.

Uživatel typicky přijde do styku pouze se třídami QPainter a QPaintDevice. Na určité kreslící zařízení je totiž třeba inicializovat QPainter a pak už pomocí něj pouze kreslit. Kreslí se v principu jako byste kreslili perem nebo obdobným nástrojem na papír či jiné médium. Tedy řekněme, že nakreslíte čtverec, poté trojúhelník atd. a ve výsledku z toho vznikne například dům. Abyste si vytvořili praktickou představu, podívejte se na ukázku níže. Díky obecnému principu lze takto kreslit na nejrůznější kreslící zařízení zahrnující vlastní widgety (QWidget), rastrové obrázky (QPixmap) a dokonce i tisknout (jako kreslící zařízení se využije třída QPrinter). Tímto systémem pak lze většinou kreslit pouze v kreslící události paintEvent() jednotlivých prvků, výjimkou je zde ale například tisk nebo renderování do rastru které lze provádět téměř v libovolné funkci či metodě.

void VlastniWidget::paintEvent(QPaintEvent *udalost) 
{ 
  QPainter painter(this); // instance QPainteru pro kreslení na vlastní widget 
  painter.setRenderHint(QPainter::Antialiasing); // s vyhlazováním 
  painter.setFont(QFont("Arial", 13, QFont::Normal, true)); // typ a styl písma

  // vykreslení textu
  painter.drawText(10, 10, QString::fromUtf8("Můj dům:"));

  // nastaveni stylu pera
  painter.setPen(QPen(QBrush(Qt::darkGreen), 6, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin)); 
  painter.drawRect(QRect(1, 10, 5, 4)); // vykreslení obdélníku

  painter.setPen(Qt::black); painter.setPen(Qt::DotLine);
  for (int i = 0; (i < pocet_pi - 1); i++) { painter.drawLine(pi[i], pi[i + 1]); } }

  // vykreslení čáry
  painter.drawLine(px, py); // atd..

  udalost->accept();
}

Mezi kreslícími instrukcemi je k dispozici velké množství metod od těch elementárních pro kreslení čar (drawLine()), obdélníku (drawRect()) nebo elips (drawEllipse()) až po metody pro kreslení komplexnějších tvarů (drawPath()). Jako parametry jednotlivých entit lze kompletně nastavit jejich obrys (setPen()) a vyplň (setBrush()). Protože vykreslování pracuje stavově, jsou dané atributy aplikovány na další entity dokud nejsou jejich hodnoty přepsány jiným nastavením tedy voláním metody typu set*().

Při rastrovém kreslení se také hodí uchovávat si různé datové struktury typu bod (QPoint/F), čára (QLine/F), obdélník (QRect/F) či QPainterPath (obecná cesta) a QPainterPathStroker (parametry obecné cesty) apod. pro které Qt nabízí své vestavěné datové struktury. Postfix /F pak znamená, že například třída QRect představující parametry obdélníka existuje i ve variantě QRectF, která takovéto parametry uchovává v desetinné reprezentaci.

Vektorové 2D kreslení pomocí modulu Graphics View Framework[editovat | editovat zdroj]

Qt nabízí kromě rastrového kreslícího mechanismu také pokročilejší modelování 2D scény na základě vzoru model/pohled. V tomto případě nepracujete s kreslícími nástroji a rastrem ale s modelem scény, jejími entitami a pohledem či pohledy na takovouto scénu. Díky tomu, že dané entity scény vystupují samostatně a relativně nezávisle, je zde možnost selekce a interakce s prvky takovéto scény díky zabudovanému výběrovému a notifikačnímu mechanismu (ten je založen na implementaci BSP stromu). Princip práce s Graphics View Frameworkem je obecně takový, že si nejprve vytvoříte grafickou scénu (QGraphicsScene), která bude představovat model. Do této scény přidáte požadované entity (QGraphicsItem) jako jsou čáry (QGraphicsLineItem), obdélníky (QGraphicsRectItem), obrázky (QGraphicsPixmapItem a QGraphicsSvgItem) nebo vlastní komplexnější entity odvozené například ze třídy QGraphicsItem. A nakonec pouze vytvoříte pohled (QGraphicsView) který bude sloužit k vizualizaci daného výseku scény. Pohled je tedy obyčejný widget představující jakési plátno, které zobrazuje specifický výřez modelu scény. Pohledů může být samozřejmě i více a můžete takto sledovat současně více lokací ve scéně.

Z výše uvedeného je vidět, že se se scénou pracuje v principu vektorově, kdy máme k dispozici matematický popis scény (seznam entit s parametry) a nové entity zadáváme pouze parametricky, tedy neřešíme jak je vykreslit. Pokud se změní měřítko scény, entity se automatický přeškálují a jsou opět vykresleny v maximální možné kvalitě. Zde zmiňme dvě výjimky. Neomezeně a bezchybně nelze škálovat pouze obrázky typu QGraphicsPixmapItem, což plyne z jejich diskrétní povahy. A pak u vlastních entit je třeba napsat jejich vykreslovací metodu (realizovanou přes QPainter) tak, aby brala v potaz možnou změnu rozměrů dané entity vyvolanou změnou měřítka scény respektive jejího pohledu. Při vlastní práci s entitami a scénou je třeba myslet na vztahy různých souřadnicových systému a ty dle potřeby přemapovat. V základu je obecné schéma těchto vztahů následující: entita → rodičovská entita → scéna → pohled a zpět. K přemapování slouží metody s prefixem mapFrom/To*(). Vzhledem k obecné reprezentaci entit scény jsou pak umožněny efekty jako animace jednotlivých entit a jejich pokročilejší transformace, aplikace grafických efektů (rozmazání, vržený stín, …) apod. Díky zabudované podpoře mechanismu Signálu & Slotu lze takto komunikovat mezi jednotlivými entitami ale i mezi klasickými widgety a prvky scény, což velmi zjednodušuje například psaní grafických aplikací, kdy nemusíme provádět vlastní přepočty z kurzoru na entity a složitě využívat různých callbacků (ukazatelů na funkce) pro komunikaci apod.

// vytvoření scény
scena = new QGraphicsScene;                   // vytvoření modelu scény 
scena->setSceneRect(QRectF(0, 0, 200, 200));  // nastavení velikosti 
scena->setBackgroundBrush(QBrush(Qt::white)); // barva pozadí

// instalace pohledu
pohled = new QGraphicsView(scena); // vytvoření pohledu 
pohled->setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);
pohled->setDragMode(QGraphicsView::RubberBandDrag); // povolení výběru oramováním

// přidání entit
scena.addItem(new GraphicsLineItem(10, 10));
// stejně pro další entity..

OpenGL v Qt (3D grafika v Qt I.)[editovat | editovat zdroj]

Grafická knihovna OpenGL je dnes v podstatě standardem na poli otevřených grafických akcelerovaných knihoven pro 2D i 3D grafiku, která umožňuje efektivní nízkoúrovňové vykreslení s využitím dostupného grafického hardware. V Qt je tato knihovna integrována a podporována hned třemi možnými způsoby využití. V základu je umožněno akcelerovat kreslení pomocí painteru, poté lze využít urychlení vykreslování grafické scény do QGraphicsView a nakonec lze vytvořit vlastní widget, který bude představovat kreslící plochu OpenGL jež bude kompletně vykreslena s využitím této knihovny. Nejjednodušším příkladem použití je tedy zmíněné využití přes QPainter, kdy například v kreslící události zavoláte metodu beginNativePainting() a poté můžete volat standardní kreslící funkce OpenGL. Toto kreslení je však třeba nakonec ukončit voláním endNativePainting().

void VlastniWidget::paintEvent(QPaintEvent *udalost) 
{ 
  QPainter painter(this); // instance QPainteru pro kreslení na vlastní widget 
  painter.setRenderHint(QPainter::Antialiasing); // s vyhlazováním 
  painter.setFont(QFont("Arial", 13, QFont::Normal, true)); // typ a styl písma

  painter.beginNativePainting();

    // vlastní OpenGL kód..

  painter.endNativePainting();

  // standardní neakcelerované vykreslení čáry
  painter.drawLine(px, py); // atd..

  udalost->accept();
}

Dalším příkladem využití OpenGL je akcelerace vykreslování pohledu do grafické scény. U této techniky se jedná pouze o to, že vytvoříte výchozí QGLWidget a přesměrujete do něho vykreslování celé scény respektive jejího konkrétního pohledu. Jednoduše řečeno: plátno pohledu bude vykreslováno pomocí OpenGL. Ukázkový kód pak demonstruje provedení tohoto přepnutí.

pohled = new QGraphicsView(scena); // vytvoření a inicializace pohledu

QGLWidget *glWidget = new QGLWidget(QGLFormat(QGL::SampleBuffers)); // widget OpenGL 
pohled->setViewport(glWidget); // přepnutí kreslení na OpenGL rendering

pohled->setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);
// ...

Poslední a možná nejzajímavější možností využití OpenGL v Qt frameworku je tvorba vlastního widgetu na jehož plochu se bude vykreslovat čistě pomocí této knihovny. Samozřejmě lze i tento postup kombinovat s painterem v události paintEvent(). Vlastní OpenGL widget stačí odvodit z třídy QGLWidget z ukázky výše a reimplementovat tři její metody. Nejprve metody initializeGL() pro inicializaci OpenGL, poté resizeGL() pro aktualizaci parametrů vykreslování při změně velikosti viewportu a nakonec samotnou metodu paintGL() pro vlastní kreslení. Kostru takovéhoto využití představuje ukázka níže.

class VlastniGLWidget: public QGLWidget 
{ Q_OBJECT

  public: 
    VlastniGLWidget(QWidget *rodic = 0);

  protected:

    // esenciální metody pro práci s OpenGL
    void initializeGL(); 
    void resizeGL(int sirka, int vyska); 
    void paintGL();

    // ošetření událostí
    void mousePressEvent(QMouseEvent *udalost); 
    void mouseMoveEvent(QMouseEvent *udalost); 
    void mouseDoubleClickEvent(QMouseEvent *udalost);

  private: 
    // privátní proměnné a členské metody..
};
void VlastniGLWidget::initializeGL()
{
  qglClearColor(Qt::green);

  glShadeModel(GL_FLAT); // stínování
  glEnable(GL_DEPTH_TEST); // hloubkový test
  glEnable(GL_CULL_FACE); // zahazování odvrácených polygonů

  // a další parametry.. 
}

void VlastniGLWidget::resizeGL(int sirka, int vyska)
{
  glViewport(0, 0, vyska, sirka); 
  glMatrixMode(GL_PROJECTION); 
  
  glLoadIdentity(); 
  GLfloat x = GLfloat(sirka) / vyska; 
  glFrustum(-x, +x, -1.0, +1.0, 5.0, 20.0); 
  glMatrixMode(GL_MODELVIEW);

  // plus vlastní kód..
}

void VlastniGLWidget::paintGL()
{
  // smazání původního obsahu
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
  
  // vlastní kreslící metoda s příkazy OpenGL
  neco_nakresli();
}

// reimplementace handlerů událostí a další kód..

V souvislosti s OpenGL lze ještě zmínit možnost přepnutí vykreslování klasických aplikací pomocí této knihovny. To v praxi znamená, že místo softwarového QPainteru se využije pro jejich vykreslení OpenGL. Toto chování u téměř jakékoli Qt aplikace lze dosáhnout předáním parametru nazev_aplikace -graphicssystem opengl při spouštění aplikace přes konzoli nebo zástupce. Tato možnost je však spíše experimentální. Pro přepnutí zpět na softwarové vykreslování pak slouží komplementární příkaz nazev_aplikace -graphicssystem raster.

Modul Qt3D (3D grafika v Qt II.)[editovat | editovat zdroj]

Qt3D je nový modul pro práci s trojrozměrnou grafikou. Jedná se de facto o jakousi skromnější obdobu OpenSceneGraphu pro Qt, tedy o jakýsi nízkoúrovňový multiplatformní engine založený na OpenGL ke kterému tvoří vrstvu vyšší úrovně se kterou se pohodlněji pracuje. Jeho implicitní integrace se plánuje do Qt verze 5, která v brzké době vyjde. Zatím je však dostupný jako doplněk v QtLabs. Tento modul umožňuje rendering, správu (grafu) scény a jejich zdrojů (pole objektů, vertex buffery, geometrie, materiály atd.), práci s shadery a další činnosti. Do budoucna se chystá například podpora stereoskopie a dalších pokročilejších technologií. Qt3D obsahuje nativně podporu jak pro jazyk C++ tak i pro nové QML, což v praxi znamená, že 3D aplikace lze i jednoduše skriptovat aniž byste museli psát nativní kód. Jako doplněk Qt3D je k dispozici aplikace Qt 3D Asset Viewer pro vizuální konfiguraci 3D modelů, ta bude v budoucnu zřejmě integrována přímo do prostředí Qt Creator. Pro představu jak se s Qt3D pracuje jsou níže uvedeny dvě oficiální ukázky,[3] jedna pro C++ a ta stejná realizovaná přes QML.

// header:

#ifndef CUBEVIEW_H 
#define CUBEVIEW_H

#include "qglview.h" 
#include "qgltexture2d.h"

class QGLSceneNode;

class CubeView: public QGLView 
{ Q_OBJECT

  public: 
    CubeView(QWidget *parent = 0); 
    ~CubeView();

  protected: 
    void paintGL(QGLPainter *painter);

  private: 
    QGLSceneNode *cube; 
    QGLTexture2D logo; 
 };

#endif

// source:

#include "cubeview.h" 
#include "qglbuilder.h" 
#include "qglcube.h"

CubeView::CubeView(QWidget *parent) : QGLView(parent) 
{ 
  QGLBuilder builder; 
  builder << QGL::Faceted; 
  builder << QGLCube();

  cube = builder.finalizedSceneNode(); 
 logo.setImage(QImage(QLatin1String(":/qtlogo.png"))); 
}

CubeView::~CubeView() 
{ delete cube; } 
void CubeView::paintGL(QGLPainter *painter) 
{ 
  painter->setStandardEffect(QGL::LitDecalTexture2D); 
  painter->setFaceColor(QGL::AllFaces, QColor(170, 202, 0)); 
  logo.bind();

  painter->modelViewMatrix().rotate(45.0f, 1.0f, 1.0f, 1.0f); 
  cube->draw(painter); 
}

To samé v QML:

import QtQuick 1.0 
import Qt3D 1.0 
import Qt3D.Shapes 1.0

Viewport
{ width: 640; height: 480

  Cube
  { scale: 1.5

   transform:
      Rotation3D
      { angle: 45 
        axis: Qt.vector3d(1, 1, 1) }

    effect:
      Effect
      { color: "#aaca00" 
        texture: "qtlogo.png" 
        decal: true } } 
}

Deklarativní tvorba 2D a 3D uživatelských rozhraní v jazyce QML[editovat | editovat zdroj]

Je to obdoba tvorby rozhraní na webu pomocí CSS a JavaScriptu, která nabízí možnost konstrukce 2D i 3D dynamických uživatelských rozhraní a výstupů. Obecně se tato technologie v Qt frameworku nazývá QtQuick. QtQuick je framework, který je součástí Qt frameworku od verze 4.7. Byl vyvinut hlavně pro použití na mobilních zařízeních a práce v něm je rychlejší a jednodušší než při použití nativního C++.[4]

QtQuick zahrnuje jazyk QML (Qt Markup/Modeling Language), modul QtDeclarative a QML Viewer. QML je deklarativní jazyk, který umožňuje deklarovat elementy následujícím způsobem:

Rectangle
{ id: button 
  ...

  property color buttonColor: "lightblue" 
  property color onHoverColor: "gold" 
  property color borderColor: "white"

  signal buttonClick() 
  onButtonClick:
  { console.log(buttonLabel.text + " clicked" ) } 
   MouseArea{
  { onClicked: buttonClick() 
    hoverEnabled: true 
    onEntered: parent.border.color = onHoverColor 
    onExited:  parent.border.color = borderColor }

    // determines the color of the button by using the conditional operator 
    color: buttonMouseArea.pressed ? Qt.darker(buttonColor, 1.5) : buttonColor 
}

K definici chování elementů je použit JavaScript, pro začlenění do Qt aplikace se pak využije widget QDeclarativeView do kterého se pouze načte obsah definovaný v QML. QML a QDeclarativeView je vystavěno nad standardními Qt třídami a lze tedy použít mechanismus Signálu & Slotu pro zasílání zpráv a využít dalších vlastností meta-object systému. V QML pak lze přistupovat k nativním datům z jazyka C++ a naopak QML objekty jsou přístupné z C++ kódu. QtQuick se tedy využívá hlavně pro definici vzhledu jednotlivých prvků uživatelského rozhraní, zatímco pro ostatní logiku a hlavně jádro aplikace se kvůli výpočetní efektivitě používá backend napsaný v jazyce C++.

Třída QSound (základní možnosti zvuku v Qt)[editovat | editovat zdroj]

QSound poskytuje základní možnosti asynchronního přehrávání zvuku. Jeho hlavní výhodou je jednoduchost použití – přehrání zvuku lze zapsat na jednom řádku viz ukázka. Nevýhodou jsou naopak jeho velmi omezené možnosti. Tato třída nabízí pouze spuštění zvuku, jeho zastavení, nastavení počtu opakování a kontrolu, zda už přehrávání skončilo. Navíc při použití na linuxových systémech vyžaduje dodatečnou instalaci Network Audio System (NAS) a NAS development packages.[5]

QSound::play("sound.wav");

Modul QtMultimedia[editovat | editovat zdroj]

Další možností přehrávání zvuku (a videa) je využití modulu QtMultimedia. Oproti QSound poskytuje mnohem více možností a dává větší kontrolu nad přehráváním zvuků. Lze například zjistit čas přehrávání, zaslat signál po určité době přehrávání, pozastavení přehrávání atd. Nevýhodou může být obtížnější programový zápis, protože modul je poměrně nízkoúrovňový. Pro přehrání zvuku je potřeba nastavit jeho formát (vzorkovací frekvenci, kodek, počet kanálů, …). Podobné rozhraní je dostupné také pro nahrávání vstupního audia.

QFile inputFile;     // class member. 
QAudioOutput* audio; // class member.

inputFile.setFileName("/tmp/test.raw"); 
inputFile.open(QIODevice::ReadOnly);

// set up the format
QAudioFormat format; 
format.setFrequency(8000); 
format.setChannels(1); 
format.setSampleSize(8); 
format.setCodec("audio/pcm"); 
format.setByteOrder(QAudioFormat::LittleEndian); 
format.setSampleType(QAudioFormat::UnSignedInt);

QAudioDeviceInfo info(QAudioDeviceInfo::defaultOutputDevice()); 
if (!info.isFormatSupported(format))
{ qWarning()<<"raw audio format not supported by backend, cannot play audio."; 
  return; }

audio = new QAudioOutput(format, this); 
connect(audio, SIGNAL(stateChanged(QAudio::State)), SLOT(finishedPlaying(QAudio::State))); 
audio->start(&inputFile);

Tento modul umožňuje také práci s videem, například s jeho jednotlivými snímky, streamem snímků a také prezentaci jednotlivých snímků (tedy přehrávání videa).

Modul Phonon (pokročilejší možnosti multimédií v Qt)[editovat | editovat zdroj]

Phonon byl původně vyvinut pro KDE a později se stal součástí Qt. V porovnání s výše uvedenými moduly nabízí nejvíce možností pro přehrávání zvuku a videa. Nekomunikuje přímo s hardware, ale je to API nad multimediálními enginy (backendy) (DirectShow, GSreamer, xine, …). S tím souvisí například podpora různých formátů audia a videa, která je závislá právě na použitém backendu a může se na různých systémech lišit. [6]

Práce s tímto modulem je založena na třech základních entitách (konceptech):

  • media object – zapouzdřuje zdroj (například hudební soubor), řídí přehrávání a umožňuje spuštění, zastavení či pozastavení přehrávání
  • sink – je jakýsi funkční objekt, který zaopatřuje například renderování videa či transfer zvuku na zvukovou kartu; dále může sloužit k nastavení hlasitosti, u videa může třeba upravovat jas či rozměry
  • paths – spojuje objekty (media objekty a sinky) do výsledného mediálního grafu

Phonon dále nabízí také pokročilé možnosti práce se zvukem, například seekování, prolínání zvukových stop nebo nastavovaní hlasitosti. Jeho součástí je třída MediaController, která umožňuje pracovat například s kapitolami, nabídkami a nebo tituly u VOB souborů. Modul také umožňuje přepínání mezi audio zařízeními jako jsou sluchátka či reproduktory.

Doplňkovou entitou tohoto frameworku jsou tzv. processors, což jsou uzly, které se vkládají do grafu mezi media object a sink a umožňují aplikovat na audio nebo video různé efekty.

Ne vždy je ale nutné vytvářet graf ručně. Například pro přehrání audia lze použít funkci createPlayer(), která sestaví graf za nás a vrátí media object. Graf je spuštěn voláním funkce play() viz následující kód:

Phonon::MediaObject *music = 
  Phonon::createPlayer(Phonon::MusicCategory, Phonon::MediaSource("/path/mysong.wav")); 
music->play();

Obdobně lze přehrát i video:

 
Phonon::VideoPlayer *player = new Phonon::VideoPlayer(Phonon::VideoCategory, parentWidget); 
player->play(url);

Pokud soubor obsahuje jak video tak audio stopu, graf bude obsahovat dva výstupní uzly. V případě, že nám ale nestačí základní nabízené možnosti, můžeme si sestrojit graf vlastní. Do takového grafu můžeme například vkládat různé efekty upravující audio nebo video stream. Efekt je aktivován vložením do grafu a deaktivován odebráním.

Následující kód ukazuje vytvoření grafu pro přehrávání audia a videa..

Phonon::MediaObject *mediaObject = new Phonon::MediaObject(this);

Phonon::VideoWidget *videoWidget = new Phonon::VideoWidget(this); 
Phonon::createPath(mediaObject, videoWidget);

Phonon::AudioOutput *audioOutput = new Phonon::AudioOutput(Phonon::VideoCategory, this); 
Phonon::Path path = Phonon::createPath(mediaObject, audioOutput); 
Do grafu můžeme vložit efekt následujícím způsobem: 
Phonon::Effect *effect = new Phonon::Effect( 
  Phonon::BackendCapabilities::availableAudioEffects()[0], this); 
path.insertEffect(effect);

Ve výše uvedeném kódu máme následující uzly:

  • mediaObject – určí jaká data požadují uzly k němu připojené, a podle toho jim pošle požadovaný stream ze vstupního souboru
  • audioOutput – posílá audio na zvukovou kartu
  • videoWidget – kromě toho, že se jedná o uzel v grafu, je to také widget na který se vykresluje video stream. Zařízení pro přehrání videa je vybráno automaticky (například DirectShow pro Windows)

Reference[editovat | editovat zdroj]

  1. a b Jasmin Blanchette, Mark Summerfield. C++ GUI Programming with Qt 4, Second Edition. [s.l.]: Prentice Hall, 2008. ISBN 0-13-235416-0. (anglicky) 
  2. Qt Licensing [online]. Digia [cit. 2012-11-29]. Dostupné online. (anglicky) 
  3. Qt Reference Documentacion [online]. Digia [cit. 2012-11-30]. Dostupné v archivu pořízeném dne 2013-02-22. (anglicky) 
  4. QtQuick [online]. Digia [cit. 2012-11-30]. Dostupné v archivu pořízeném dne 2012-12-08. (anglicky) 
  5. QSound Class Reference [online]. Digia [cit. 2012-11-30]. Dostupné online. (anglicky) [nedostupný zdroj]
  6. Troy Unrau. The Road to KDE 4: Phonon Makes Multimedia Easier [online]. [cit. 2012-11-30]. Dostupné online. (anglicky) 

Literatura[editovat | editovat zdroj]

  • Jasmin Blanchette, Mark Summerfield: C++ GUI Programming with Qt 4, Second Edition, Prentice Hall, 2008, ISBN 0-13-235416-0
  • Johan Thelin: Foundations of Qt Development, Apress, 2007, ISBN 1-59059-831-8
  • Alan Ezust, Paul Ezust: An Introduction to Design Patterns in C++ with Qt 4, Prentice Hall, 2007, ISBN 0-13-187905-7
  • Mark Summerfield: Advanced Qt Programming, Prentice Hall, 2011, ISBN 0-321-63590-6
  • Martin Chroboczek: Grafická uživatelská rozhraní v Qt a C++, Computer Press, 2013, ISBN 978-80-251-4124-3

Související články[editovat | editovat zdroj]

Externí odkazy[editovat | editovat zdroj]