Qt-based media player

This patch implements a simple Qt-based media player which is actually a
graphical user interface for the SDL-based 'avplay' media player from
'libav'. It starts 'avplay' as a child and shows its graphical output in a
'QNitpickerViewWidget'. The widgets for controlling the player state send
the according keyboard and mouse input events to 'avplay'.

The 'qt_avplay' player supports the following configuration options:

<mediafile name="..."/>
-> name of the media file to play

<framebuffer_filter name="..." ram_quota="..."/> (may appear multiple times)
-> name of a framebuffer filter service to filter the video output

Fixes #222.
This commit is contained in:
Christian Prochaska 2012-05-25 18:14:32 +02:00 committed by Christian Helmuth
parent 8f4b3dd4f1
commit 06fdc7b897
21 changed files with 1055 additions and 2 deletions

View File

@ -14,6 +14,7 @@
#ifndef _EVENT_QUEUE_H_
#define _EVENT_QUEUE_H_
#include <base/printf.h>
#include <input/event.h>
#include <os/ring_buffer.h>

View File

@ -15,13 +15,13 @@
#define _PS2_KEYBOARD_H_
#include <base/printf.h>
#include <input/event_queue.h>
#include <input/keycodes.h>
#include "input_driver.h"
#include "serial_interface.h"
#include "scan_code_set_1.h"
#include "scan_code_set_2.h"
#include "event_queue.h"
class Ps2_keyboard : public Input_driver
{

View File

@ -15,9 +15,9 @@
#define _PS2_MOUSE_H_
#include <base/printf.h>
#include <input/event_queue.h>
#include <input/keycodes.h>
#include "event_queue.h"
#include "input_driver.h"
class Ps2_mouse : public Input_driver

160
qt4/run/qt_avplay.run Normal file
View File

@ -0,0 +1,160 @@
#
# Build
#
build {
core
init
drivers/input/ps2
drivers/pci
drivers/framebuffer
drivers/timer
drivers/audio_out
server/nitpicker
app/avplay
app/qt_avplay
}
#
# Download media file
#
set media_url "ftp://ftp.untergrund.net/users/ae/dhstv/escape-chotro.mp4"
if {![file exists bin/mediafile]} {
puts "downloading media file from $media_url"
catch { exec wget -O bin/mediafile $media_url }
}
create_boot_directory
#
# Generate config
#
set config {
<config>
<parent-provides>
<service name="ROM"/>
<service name="RAM"/>
<service name="IRQ"/>
<service name="IO_MEM"/>
<service name="IO_PORT"/>
<service name="CAP"/>
<service name="PD"/>
<service name="RM"/>
<service name="CPU"/>
<service name="LOG"/>
<service name="SIGNAL"/>
</parent-provides>
<default-route>
<any-service> <parent/> <any-child/> </any-service>
</default-route> }
append_if [have_spec sdl] config {
<start name="fb_sdl">
<resource name="RAM" quantum="4M"/>
<provides>
<service name="Input"/>
<service name="Framebuffer"/>
</provides>
</start>}
append_if [have_spec pci] config {
<start name="pci_drv">
<resource name="RAM" quantum="1M"/>
<provides><service name="PCI"/></provides>
</start>}
append_if [have_spec vesa] config {
<start name="vesa_drv">
<resource name="RAM" quantum="1M"/>
<provides><service name="Framebuffer"/></provides>
</start>}
append_if [have_spec pl11x] config {
<start name="pl11x_drv">
<resource name="RAM" quantum="2M"/>
<provides><service name="Framebuffer"/></provides>
</start>}
append_if [have_spec ps2] config {
<start name="ps2_drv">
<resource name="RAM" quantum="1M"/>
<provides><service name="Input"/></provides>
</start> }
append config {
<start name="timer">
<resource name="RAM" quantum="1M"/>
<provides><service name="Timer"/></provides>
</start>
<start name="audio_out_drv">
<resource name="RAM" quantum="2M"/>
<provides><service name="Audio_out"/></provides>
</start>
<start name="nitpicker">
<resource name="RAM" quantum="1M"/>
<provides><service name="Nitpicker"/></provides>
</start>
<start name="qt_avplay">
<resource name="RAM" quantum="2G"/>
<config>
<mediafile name="mediafile"/>
</config>
</start>
</config>
}
install_config $config
#
# Boot modules
#
# generic modules
set boot_modules {
core
init
timer
audio_out_drv
nitpicker
qt_avplay
dejavusans.lib.so
freetype.lib.so
ld.lib.so
libc.lib.so
libc_lock_pipe.lib.so
libm.lib.so
libpng.lib.so
jpeg.lib.so
qnitpickerviewwidget.lib.so
qt_core.lib.so
qt_gui.lib.so
qt_xml.lib.so
zlib.lib.so
avcodec.lib.so
avformat.lib.so
avutil.lib.so
avfilter.lib.so
swscale.lib.so
sdl.lib.so
pthread.lib.so
libc_log.lib.so
libc_rom.lib.so
avplay
mediafile
}
# platform-specific modules
lappend_if [have_spec linux] boot_modules fb_sdl
lappend_if [have_spec pci] boot_modules pci_drv
lappend_if [have_spec vesa] boot_modules vesa_drv
lappend_if [have_spec ps2] boot_modules ps2_drv
lappend_if [have_spec pl11x] boot_modules pl11x_drv
build_boot_image $boot_modules
append qemu_args " -m 512 -soundhw all"
run_genode_until forever

View File

@ -0,0 +1,18 @@
This directory contains a simple Qt-based media player which is actually a
graphical user interface for the SDL-based 'avplay' media player from 'libav'.
It starts 'avplay' as a child and shows its graphical output in a
'QNitpickerViewWidget'. The widgets for controlling the player state send the
according keyboard and mouse input events to 'avplay'.
The 'qt_avplay' player supports the following configuration options:
:'<mediafile name="..."/>:'
name of the media file to play
:'<framebuffer_filter name="..." ram_quota="..."/>':
This node contains the name of a framebuffer filter service to filter the
video output. It may appear multiple times. If specified more than once, it
is possible to build a post-processing pipeline for the video display where
each processing stage is executed by a separate program.

View File

@ -0,0 +1,115 @@
/*
* \brief Avplay policy
* \author Christian Prochaska
* \date 2012-04-05
*/
/*
* Copyright (C) 2012 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _AVPLAY_POLICY_H_
#define _AVPLAY_POLICY_H_
/* Qt4 includes */
#include <QDebug>
#include <QObject>
#include <QDomDocument>
#include <QDomElement>
#include <QDomText>
/* Genode includes */
#include <os/slave.h>
class Avplay_policy : public QObject, public Genode::Slave_policy
{
Q_OBJECT
private:
Genode::Service_registry &_input_in;
Genode::Service_registry &_framebuffer_in;
const char *_mediafile;
int _sdl_audio_volume;
QByteArray _config_byte_array;
const char *_config()
{
QDomDocument config_doc;
QDomElement config_node = config_doc.createElement("config");
config_doc.appendChild(config_node);
QDomElement arg0_node = config_doc.createElement("arg");
arg0_node.setAttribute("value", "avplay");
config_node.appendChild(arg0_node);
QDomElement arg1_node = config_doc.createElement("arg");
arg1_node.setAttribute("value", _mediafile);
config_node.appendChild(arg1_node);
QDomElement sdl_audio_volume_node = config_doc.createElement("sdl_audio_volume");
sdl_audio_volume_node.setAttribute("value", QString::number(_sdl_audio_volume));
config_node.appendChild(sdl_audio_volume_node);
_config_byte_array = config_doc.toByteArray(4);
return _config_byte_array.constData();
}
protected:
const char **_permitted_services() const
{
static const char *permitted_services[] = {
"CAP", "LOG", "RM", "ROM", "SIGNAL",
"Timer", "Audio_out", 0 };
return permitted_services;
};
public:
Avplay_policy(Genode::Rpc_entrypoint &entrypoint,
Genode::Service_registry &input_in,
Genode::Service_registry &framebuffer_in,
const char *mediafile)
: Genode::Slave_policy("avplay", entrypoint, Genode::env()->ram_session()),
_input_in(input_in),
_framebuffer_in(framebuffer_in),
_mediafile(mediafile),
_sdl_audio_volume(100)
{
configure(_config());
}
Genode::Service *resolve_session_request(const char *service_name,
const char *args)
{
if (strcmp(service_name, "Input") == 0)
return _input_in.find(service_name);
if (strcmp(service_name, "Framebuffer") == 0) {
Genode::Client client;
return _framebuffer_in.wait_for_service(service_name, &client, name());
}
return Slave_policy::resolve_session_request(service_name, args);
}
public Q_SLOTS:
void volume_changed(int value)
{
_sdl_audio_volume = value;
configure(_config());
}
};
#endif /* _AVPLAY_POLICY_H_ */

View File

@ -0,0 +1,73 @@
/*
* \brief Control bar
* \author Christian Prochaska
* \date 2012-03-30
*/
/*
* Copyright (C) 2012 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
/* Genode includes */
#include <input/keycodes.h>
/* Qoost includes */
#include <qoost/style.h>
#include "input_service.h"
#include "main_window.h"
void Control_bar::_rewind()
{
/* mouse click at horizontal position 0 */
ev_queue.add(Input::Event(Input::Event::PRESS, Input::BTN_LEFT, 0, 0, 0, 0));
ev_queue.add(Input::Event(Input::Event::RELEASE, Input::BTN_LEFT, 0, 0, 0, 0));
}
void Control_bar::_pause_resume()
{
ev_queue.add(Input::Event(Input::Event::PRESS, Input::KEY_SPACE, 0, 0, 0, 0));
ev_queue.add(Input::Event(Input::Event::RELEASE, Input::KEY_SPACE, 0, 0, 0, 0));
_playing = !_playing;
if (_playing)
update_style_id(_play_pause_button, "play");
else
update_style_id(_play_pause_button, "pause");
}
void Control_bar::_stop()
{
if (_playing)
_pause_resume();
_rewind();
}
Control_bar::Control_bar()
: _playing(true)
{
update_style_id(_play_pause_button, "play");
_volume_slider->setOrientation(Qt::Horizontal);
_volume_slider->setRange(0, 100);
_volume_slider->setTickInterval(10);
_volume_slider->setValue(100);
_layout->addWidget(_play_pause_button);
_layout->addWidget(_stop_button);
_layout->addStretch();
_layout->addWidget(_volume_label);
_layout->addWidget(_volume_slider);
connect(_play_pause_button, SIGNAL(clicked()), this, SLOT(_pause_resume()));
connect(_stop_button, SIGNAL(clicked()), this, SLOT(_stop()));
connect(_volume_slider, SIGNAL(valueChanged(int)), this, SIGNAL(volume_changed(int)));
}

View File

@ -0,0 +1,58 @@
/*
* \brief Control bar
* \author Christian Prochaska
* \date 2012-03-30
*/
/*
* Copyright (C) 2012 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _CONTROL_BAR_H_
#define _CONTROL_BAR_H_
/* Qt includes */
#include <QtGui>
/* Qoost includes */
#include <qoost/compound_widget.h>
#include <qoost/qmember.h>
struct Play_pause_button : QPushButton { Q_OBJECT };
struct Stop_button : QPushButton { Q_OBJECT };
struct Volume_label : QLabel { Q_OBJECT };
struct Volume_slider : QSlider { Q_OBJECT };
class Control_bar : public Compound_widget<QWidget, QHBoxLayout>
{
Q_OBJECT
private:
QMember<Play_pause_button> _play_pause_button;
QMember<Stop_button> _stop_button;
QMember<Volume_label> _volume_label;
QMember<Volume_slider> _volume_slider;
bool _playing;
void _rewind();
private Q_SLOTS:
void _pause_resume();
void _stop();
public:
Control_bar();
Q_SIGNALS:
void volume_changed(int value);
};
#endif /* _CONTROL_BAR_H_ */

View File

@ -0,0 +1,77 @@
/*
* \brief Filter framebuffer policy
* \author Christian Prochaska
* \date 2012-04-11
*/
/*
* Copyright (C) 2012 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _FILTER_FRAMEBUFFER_POLICY_H_
#define _FILTER_FRAMEBUFFER_POLICY_H_
/* Genode includes */
#include <base/service.h>
#include <os/slave.h>
class Filter_framebuffer_policy : public Genode::Slave_policy
{
private:
Genode::Service_registry &_framebuffer_in;
Genode::Service_registry &_framebuffer_out;
protected:
const char **_permitted_services() const
{
static const char *permitted_services[] = {
"CAP", "LOG", "RM", "ROM", "SIGNAL",
"Timer", 0 };
return permitted_services;
};
public:
Filter_framebuffer_policy(const char *name,
Genode::Rpc_entrypoint &entrypoint,
Genode::Service_registry &framebuffer_in,
Genode::Service_registry &framebuffer_out)
: Genode::Slave_policy(name, entrypoint, Genode::env()->ram_session()),
_framebuffer_in(framebuffer_in),
_framebuffer_out(framebuffer_out) { }
Genode::Service *resolve_session_request(const char *service_name,
const char *args)
{
if (strcmp(service_name, "Framebuffer") == 0) {
Genode::Client client;
return _framebuffer_in.wait_for_service(service_name, &client, name());
}
return Slave_policy::resolve_session_request(service_name, args);
}
bool announce_service(const char *name,
Genode::Root_capability root,
Genode::Allocator *alloc,
Genode::Server *server)
{
if (strcmp(name, "Framebuffer") == 0) {
_framebuffer_out.insert(new (alloc) Genode::Child_service(name, root, server));
return true;
}
return Slave_policy::announce_service(name, root, alloc, server);
}
};
#endif /* _FILTER_FRAMEBUFFER_POLICY_H_ */

View File

@ -0,0 +1,64 @@
/*
* \brief Framebuffer root
* \author Christian Prochaska
* \date 2012-04-02
*/
/*
* Copyright (C) 2012 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _FRAMEBUFFER_ROOT_H_
#define _FRAMEBUFFER_ROOT_H_
/* Genode includes */
#include <root/component.h>
#include "framebuffer_session_component.h"
namespace Framebuffer {
/**
* Shortcut for single-client root component
*/
typedef Genode::Root_component<Session_component, Genode::Single_client> Root_component;
class Root : public Root_component
{
private:
QNitpickerViewWidget &_nitpicker_view_widget;
int _max_width;
int _max_height;
protected:
Session_component *_create_session(const char *args)
{
return new (md_alloc())
Session_component(args, _nitpicker_view_widget,
_max_width, _max_height);
}
public:
Root(Genode::Rpc_entrypoint *session_ep,
Genode::Allocator *md_alloc,
QNitpickerViewWidget &nitpicker_view_widget,
int max_width = 0,
int max_height = 0)
: Root_component(session_ep, md_alloc),
_nitpicker_view_widget(nitpicker_view_widget),
_max_width(max_width),
_max_height(max_height) { }
};
}
#endif /* _FRAMEBUFFER_ROOT_H_ */

View File

@ -0,0 +1,86 @@
/*
* \brief Framebuffer session component
* \author Christian Prochaska
* \date 2012-04-02
*/
/*
* Copyright (C) 2012 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
/* Genode includes */
#include <base/env.h>
#include <nitpicker_view/client.h>
#include <util/arg_string.h>
#include <util/misc_math.h>
#include "framebuffer_session_component.h"
namespace Framebuffer {
int Session_component::_limited_size(int requested_size, int max_size)
{
if (requested_size == 0)
return max_size;
else
return (max_size > 0) ? Genode::min(requested_size, max_size) : requested_size;
}
static inline long session_arg(const char *arg, const char *key)
{
return Genode::Arg_string::find_arg(arg, key).long_value(0);
}
Session_component::Session_component(const char *args,
QNitpickerViewWidget &nitpicker_view_widget,
int max_width,
int max_height)
: _nitpicker(Nitpicker::Connection(
_limited_size(session_arg(args, "fb_width"), max_width),
_limited_size(session_arg(args, "fb_height"), max_height))),
_framebuffer(_nitpicker.framebuffer_session())
{
Nitpicker::View_capability nitpicker_view_cap = _nitpicker.create_view();
Mode _mode = _framebuffer.mode();
nitpicker_view_widget.setNitpickerView(nitpicker_view_cap,
0, 0,
_mode.width(),
_mode.height());
}
Genode::Dataspace_capability Session_component::dataspace()
{
return _framebuffer.dataspace();
}
void Session_component::release()
{
_framebuffer.release();
}
Mode Session_component::mode() const
{
return _framebuffer.mode();
}
void Session_component::mode_sigh(Genode::Signal_context_capability sigh_cap)
{
_framebuffer.mode_sigh(sigh_cap);
}
void Session_component::refresh(int x, int y, int w, int h)
{
_framebuffer.refresh(x, y, w, h);
}
}

View File

@ -0,0 +1,57 @@
/*
* \brief Framebuffer session component
* \author Christian Prochaska
* \date 2012-04-02
*/
/*
* Copyright (C) 2012 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _FRAMEBUFFER_SESSION_COMPONENT_H_
#define _FRAMEBUFFER_SESSION_COMPONENT_H_
/* Genode includes */
#include <base/rpc_server.h>
#include <framebuffer_session/client.h>
#include <nitpicker_session/connection.h>
/* Qt4 includes */
#include <qnitpickerviewwidget/qnitpickerviewwidget.h>
namespace Framebuffer {
class Session_component : public Genode::Rpc_object<Session>
{
private:
Nitpicker::Connection _nitpicker;
Session_client _framebuffer;
int _limited_size(int requested_size, int max_size);
public:
/**
* Constructor
*/
Session_component(const char *args,
QNitpickerViewWidget &nitpicker_view_widget,
int max_width = 0,
int max_height = 0);
Genode::Dataspace_capability dataspace();
void release();
Mode mode() const;
void mode_sigh(Genode::Signal_context_capability sigh_cap);
void refresh(int x, int y, int w, int h);
};
}
#endif /* _FRAMEBUFFER_SESSION_COMPONENT_H_ */

View File

@ -0,0 +1,40 @@
/*
* \brief Input service
* \author Christian Prochaska
* \date 2012-03-29
*/
/*
* Copyright (C) 2012 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
/* Genode includes */
#include <input/component.h>
#include "input_service.h"
using namespace Genode;
Event_queue ev_queue;
namespace Input {
/*
* Event handling is disabled on queue creation and will be enabled later if a
* session is created.
*/
void event_handling(bool enable)
{
if (enable)
ev_queue.enable();
else
ev_queue.disable();
}
bool event_pending() { return !ev_queue.empty(); }
Event get_event() { return ev_queue.get(); }
}

View File

@ -0,0 +1,24 @@
/*
* \brief Input service
* \author Christian Prochaska
* \date 2012-03-29
*/
/*
* Copyright (C) 2012 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _INPUT_SERVICE_H_
#define _INPUT_SERVICE_H_
/* Genode includes */
#include <input/event_queue.h>
extern Event_queue ev_queue;
extern void create_input_service();
#endif /* _INPUT_SERVICE_H_ */

View File

@ -0,0 +1,45 @@
/*
* \brief Simple Qt interface for 'avplay' media player
* \author Christian Prochaska
* \date 2012-03-21
*/
/*
* Copyright (C) 2012 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
/* Qt includes */
#include <QApplication>
/* qt_avplay includes */
#include "main_window.h"
static inline void load_stylesheet()
{
QFile file(":style.qss");
if (!file.open(QFile::ReadOnly)) {
qWarning() << "Warning:" << file.errorString()
<< "opening file" << file.fileName();
return;
}
qApp->setStyleSheet(QLatin1String(file.readAll()));
}
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
load_stylesheet();
QMember<Main_window> main_window;
main_window->show();
return app.exec();
}

View File

@ -0,0 +1,129 @@
/*
* \brief Main window of the media player
* \author Christian Prochaska
* \date 2012-03-29
*/
/*
* Copyright (C) 2012 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
/* Genode includes */
#include <cap_session/connection.h>
#include <input/component.h>
#include <os/config.h>
#include <rom_session/connection.h>
/* qt_avplay includes */
#include "avplay_policy.h"
#include "filter_framebuffer_policy.h"
#include "framebuffer_root.h"
#include "input_service.h"
#include "main_window.h"
using namespace Genode;
struct Framebuffer_filter
{
enum { MAX_FILTER_NAME_SIZE = 32 };
char name[MAX_FILTER_NAME_SIZE];
Genode::Number_of_bytes ram_quota;
Service_registry *framebuffer_out_registry;
Rpc_entrypoint *ep;
Filter_framebuffer_policy *policy;
Slave *slave;
};
Main_window::Main_window()
{
/* look for dynamic linker */
try {
static Rom_connection ldso_rom("ld.lib.so");
Process::dynamic_linker(ldso_rom.dataspace());
} catch (...) {
PERR("ld.lib.so not found");
}
/* get the name of the media file from the config file */
enum { MAX_LEN_MEDIAFILE_NAME = 256 };
static char mediafile[MAX_LEN_MEDIAFILE_NAME] = "mediafile";
try {
config()->xml_node().sub_node("mediafile").attribute("name").value(mediafile, sizeof(mediafile));
} catch(...) {
PWRN("no <mediafile> config node found, using \"mediafile\"");
}
/* create local services */
enum { STACK_SIZE = 2*sizeof(addr_t)*1024 };
static Cap_connection cap;
static Rpc_entrypoint avplay_ep(&cap, STACK_SIZE, "avplay_ep");
static Service_registry input_registry;
static Service_registry nitpicker_framebuffer_registry;
static Input::Root input_root(&avplay_ep, env()->heap());
static Local_service input_service(Input::Session::service_name(), &input_root);
input_registry.insert(&input_service);
avplay_ep.manage(&input_root);
/* find out which filtering framebuffer services to start and sort them in reverse order */
static QList<Framebuffer_filter*> framebuffer_filters;
try {
Xml_node node = config()->xml_node().sub_node("framebuffer_filter");
for (; ; node = node.next("framebuffer_filter")) {
Framebuffer_filter *framebuffer_filter = new Framebuffer_filter;
node.attribute("name").value(framebuffer_filter->name, sizeof(framebuffer_filter->name));
node.attribute("ram_quota").value(&framebuffer_filter->ram_quota);
qDebug() << "filter:" << framebuffer_filter->name << "," << framebuffer_filter->ram_quota;
framebuffer_filters.prepend(framebuffer_filter);
}
} catch (Config::Invalid) {
} catch (Xml_node::Nonexistent_sub_node) {
}
/* start the filtering framebuffer services */
Service_registry *framebuffer_in_registry = &nitpicker_framebuffer_registry;
Q_FOREACH(Framebuffer_filter *framebuffer_filter, framebuffer_filters) {
framebuffer_filter->framebuffer_out_registry = new Service_registry;
framebuffer_filter->ep = new Rpc_entrypoint(&cap, STACK_SIZE, "filter_fb_ep");
framebuffer_filter->policy = new Filter_framebuffer_policy(framebuffer_filter->name,
*framebuffer_filter->ep,
*framebuffer_in_registry,
*framebuffer_filter->framebuffer_out_registry);
framebuffer_filter->slave = new Slave(*framebuffer_filter->ep,
*framebuffer_filter->policy,
framebuffer_filter->ram_quota);
framebuffer_in_registry = framebuffer_filter->framebuffer_out_registry;
}
Rpc_entrypoint *local_framebuffer_ep = framebuffer_filters.isEmpty() ?
&avplay_ep :
framebuffer_filters.at(0)->ep;
static Framebuffer::Root framebuffer_root(local_framebuffer_ep, env()->heap(), *_avplay_widget, 640, 480);
static Local_service framebuffer_service(Framebuffer::Session::service_name(), &framebuffer_root);
nitpicker_framebuffer_registry.insert(&framebuffer_service);
/* start avplay */
static Avplay_policy avplay_policy(avplay_ep, input_registry, *framebuffer_in_registry, mediafile);
static Genode::Slave avplay_slave(avplay_ep, avplay_policy, 32*1024*1024);
/* add widgets to layout */
_layout->addWidget(_avplay_widget);
_layout->addWidget(_control_bar);
connect(_control_bar, SIGNAL(volume_changed(int)), &avplay_policy, SLOT(volume_changed(int)));
}

View File

@ -0,0 +1,43 @@
/*
* \brief Main window of the media player
* \author Christian Prochaska
* \date 2012-03-29
*/
/*
* Copyright (C) 2012 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _MAIN_WINDOW_H_
#define _MAIN_WINDOW_H_
/* Qt includes */
#include <QVBoxLayout>
#include <QWidget>
#include <qnitpickerviewwidget/qnitpickerviewwidget.h>
/* Qoost includes */
#include <qoost/compound_widget.h>
#include <qoost/qmember.h>
#include "control_bar.h"
class Main_window : public Compound_widget<QWidget, QVBoxLayout>
{
Q_OBJECT
private:
QMember<QNitpickerViewWidget> _avplay_widget;
QMember<Control_bar> _control_bar;
public:
Main_window();
};
#endif /* _MAIN_WINDOW_H_ */

View File

@ -0,0 +1,12 @@
TEMPLATE = app
TARGET = qt_avplay
QT = core gui xml
HEADERS = avplay_policy.h \
control_bar.h \
main_window.h
SOURCES = control_bar.cpp \
framebuffer_session_component.cc \
input_service.cpp \
main.cpp \
main_window.cpp
RESOURCES = style.qrc

View File

@ -0,0 +1,10 @@
<!DOCTYPE RCC>
<RCC version="1.0">
<qresource prefix="/">
<file>style.qss</file>
<file alias="player_play.png">../../../contrib/qt-everywhere-opensource-src-4.7.4/examples/network/torrent/icons/player_play.png</file>
<file alias="player_pause.png">../../../contrib/qt-everywhere-opensource-src-4.7.4/examples/network/torrent/icons/player_pause.png</file>
<file alias="player_stop.png">../../../contrib/qt-everywhere-opensource-src-4.7.4/examples/network/torrent/icons/player_stop.png</file>
<file alias="volume.png">../../../contrib/qt-everywhere-opensource-src-4.7.4/demos/mobile/guitartuner/src/mycomponents/images/volume.png</file>
</qresource>
</RCC>

View File

@ -0,0 +1,32 @@
Main_window {
max-width: 640px;
max-height: 512px;
}
Play_pause_button, Stop_button {
width: 32px;
height: 32px;
}
Play_pause_button#play {
border-image: url(:player_pause.png);
}
Play_pause_button#pause {
border-image: url(:player_play.png);
}
Stop_button {
border-image: url(:player_stop.png);
}
Volume_label {
background-image: url(:volume.png);
min-width: 16px;
max-width: 32px;
min-height: 16px;
max-height: 32px;
margin-right: 5px;
}

View File

@ -0,0 +1,9 @@
# identify the qt4 repository by searching for a file that is unique for qt4
QT4_REP_DIR := $(call select_from_repositories,lib/import/import-qt4.inc)
QT4_REP_DIR := $(realpath $(dir $(QT4_REP_DIR))../..)
include $(QT4_REP_DIR)/src/app/tmpl/target_defaults.inc
include $(QT4_REP_DIR)/src/app/tmpl/target_final.inc
LIBS += qnitpickerviewwidget