qtubuntu-media-0.7.1+14.04.20140304/ 0000755 0000152 0177776 00000000000 12305354221 017052 5 ustar pbuser nogroup 0000000 0000000 qtubuntu-media-0.7.1+14.04.20140304/unittests/ 0000755 0000152 0177776 00000000000 12305354221 021114 5 ustar pbuser nogroup 0000000 0000000 qtubuntu-media-0.7.1+14.04.20140304/unittests/unittests.pro 0000644 0000152 0177776 00000001237 12305353776 023721 0 ustar pbuser nogroup 0000000 0000000 include(../coverage.pri)
CONFIG += testcase
TARGET = tst_mediaplayerplugin
QT += testlib
QT += multimedia opengl
INCLUDEPATH += ../src \
/usr/include/qt5/QtMultimedia \
/usr/include/hybris \
/usr/include/libqtubuntu-media-signals
LIBS += -lqtubuntu-media-signals
HEADERS += \
../src/aalmediaplayercontrol.h \
../src/aalmediaplayerservice.h \
../src/aalmediaplayerserviceplugin.h \
../src/aalvideorenderercontrol.h
SOURCES += \
tst_mediaplayerplugin.cpp \
player.cpp \
../src/aalmediaplayercontrol.cpp \
../src/aalmediaplayerservice.cpp \
../src/aalmediaplayerserviceplugin.cpp \
../src/aalvideorenderercontrol.cpp
qtubuntu-media-0.7.1+14.04.20140304/unittests/media_compatibility_layer.h 0000644 0000152 0177776 00000005464 12305353776 026520 0 ustar pbuser nogroup 0000000 0000000 /*
* Copyright (C) 2013 Canonical Ltd
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 3 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see .
*
*/
#ifndef MEDIA_COMPATIBILITY_LAYER_H_
#define MEDIA_COMPATIBILITY_LAYER_H_
#include
#include
#include
#ifdef __cplusplus
extern "C" {
#endif
// Callback types
typedef void (*on_msg_set_video_size)(int height, int width, void *context);
typedef void (*on_video_texture_needs_update)(void *context);
typedef void (*on_msg_error)(void *context);
typedef void (*on_playback_complete)(void *context);
typedef void (*on_media_prepared)(void *context);
struct MediaPlayerWrapper;
// ----- Start of C API ----- //
// Callback setters
void android_media_set_video_size_cb(MediaPlayerWrapper *mp, on_msg_set_video_size cb, void *context);
void android_media_set_video_texture_needs_update_cb(MediaPlayerWrapper *mp, on_video_texture_needs_update cb, void *context);
void android_media_set_error_cb(MediaPlayerWrapper *mp, on_msg_error cb, void *context);
void android_media_set_playback_complete_cb(MediaPlayerWrapper *mp, on_playback_complete cb, void *context);
void android_media_set_media_prepared_cb(MediaPlayerWrapper *mp, on_media_prepared cb, void *context);
// Main player control API
MediaPlayerWrapper *android_media_new_player();
int android_media_set_data_source(MediaPlayerWrapper *mp, const char* url);
int android_media_set_preview_texture(MediaPlayerWrapper *mp, int texture_id);
void android_media_update_surface_texture(MediaPlayerWrapper *mp);
void android_media_surface_texture_get_transformation_matrix(MediaPlayerWrapper *mp, GLfloat*matrix);
int android_media_play(MediaPlayerWrapper *mp);
int android_media_pause(MediaPlayerWrapper *mp);
int android_media_stop(MediaPlayerWrapper *mp);
bool android_media_is_playing(MediaPlayerWrapper *mp);
int android_media_seek_to(MediaPlayerWrapper *mp, int msec);
int android_media_get_current_position(MediaPlayerWrapper *mp, int *msec);
int android_media_get_duration(MediaPlayerWrapper *mp, int *msec);
int android_media_get_volume(MediaPlayerWrapper *mp, int *volume);
int android_media_set_volume(MediaPlayerWrapper *mp, int volume);
#ifdef __cplusplus
}
#endif
#endif // CAMERA_COMPATIBILITY_LAYER_H_
qtubuntu-media-0.7.1+14.04.20140304/unittests/tst_mediaplayerplugin.cpp 0000644 0000152 0177776 00000005305 12305353776 026246 0 ustar pbuser nogroup 0000000 0000000 /*
* Copyright (C) 2013 Canonical, Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see .
*/
#include "aalmediaplayerservice.h"
#include "media_compatibility_layer.h"
#include
#include
#include
#define private public
struct MediaPlayerWrapper;
class tst_MediaPlayerPlugin : public QObject
{
Q_OBJECT
AalMediaPlayerService m_service;
QMediaControl *m_playerControl;
QMediaControl *m_rendererControl;
private slots:
void initTestCase();
void cleanupTestCase();
void tst_requestRelease();
void tst_newMediaPlayer();
void tst_androidControl();
};
void tst_MediaPlayerPlugin::initTestCase()
{
m_playerControl = m_service.requestControl(QMediaPlayerControl_iid);
QVERIFY(m_playerControl != NULL);
m_rendererControl = m_service.requestControl(QVideoRendererControl_iid);
QVERIFY(m_rendererControl != NULL);
}
void tst_MediaPlayerPlugin::cleanupTestCase()
{
m_service.releaseControl(m_playerControl);
m_service.releaseControl(m_rendererControl);
}
void tst_MediaPlayerPlugin::tst_requestRelease()
{
QMediaControl *mpControl = NULL;
QMediaControl *rendererControl = NULL;
// Request a new reference to the media player control and verify that
// it's the same pointer as the original reference.
mpControl = m_service.requestControl(QMediaPlayerControl_iid);
QVERIFY(mpControl == m_playerControl);
rendererControl = m_service.requestControl(QVideoRendererControl_iid);
QVERIFY(rendererControl == m_rendererControl);
// Now release the reference and make sure that the original media player
// control reference still exists.
m_service.releaseControl(mpControl);
QVERIFY(mpControl == m_playerControl);
m_service.releaseControl(rendererControl);
QVERIFY(rendererControl == m_rendererControl);
}
void tst_MediaPlayerPlugin::tst_newMediaPlayer()
{
bool ret = m_service.newMediaPlayer();
QVERIFY(ret == true);
}
void tst_MediaPlayerPlugin::tst_androidControl()
{
MediaPlayerWrapper *mp = m_service.androidControl();
QVERIFY(mp != NULL);
}
QTEST_MAIN(tst_MediaPlayerPlugin)
#include "tst_mediaplayerplugin.moc"
qtubuntu-media-0.7.1+14.04.20140304/unittests/player.cpp 0000644 0000152 0177776 00000006256 12305353776 023143 0 ustar pbuser nogroup 0000000 0000000 /*
* Copyright (C) 2013 Canonical, Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see .
*/
#include "media_compatibility_layer.h"
#include
// Mock object so that we don't get an incomplete type compiler error
struct MediaPlayerWrapper
{
MediaPlayerWrapper() { }
};
void android_media_set_video_size_cb(MediaPlayerWrapper *mp, on_msg_set_video_size cb, void *context)
{
Q_UNUSED(mp);
Q_UNUSED(cb);
Q_UNUSED(context);
}
void android_media_set_video_texture_needs_update_cb(MediaPlayerWrapper *mp, on_video_texture_needs_update cb, void *context)
{
Q_UNUSED(mp);
Q_UNUSED(cb);
Q_UNUSED(context);
}
void android_media_set_error_cb(MediaPlayerWrapper *mp, on_msg_error cb, void *context)
{
Q_UNUSED(mp);
Q_UNUSED(cb);
Q_UNUSED(context);
}
void android_media_set_playback_complete_cb(MediaPlayerWrapper *mp, on_playback_complete cb, void *context)
{
Q_UNUSED(mp);
Q_UNUSED(cb);
Q_UNUSED(context);
}
void android_media_set_media_prepared_cb(MediaPlayerWrapper *mp, on_media_prepared cb, void *context)
{
Q_UNUSED(mp);
Q_UNUSED(cb);
Q_UNUSED(context);
}
MediaPlayerWrapper *android_media_new_player()
{
return new MediaPlayerWrapper();
}
int android_media_set_data_source(MediaPlayerWrapper *mp, const char* url)
{
Q_UNUSED(mp);
Q_UNUSED(url);
return 0;
}
int android_media_set_preview_texture(MediaPlayerWrapper *mp, int texture_id)
{
Q_UNUSED(mp);
Q_UNUSED(texture_id);
return 0;
}
void android_media_update_surface_texture(MediaPlayerWrapper *mp)
{
Q_UNUSED(mp);
}
void android_media_surface_texture_get_transformation_matrix(MediaPlayerWrapper *mp, GLfloat* matrix)
{
Q_UNUSED(mp);
Q_UNUSED(matrix);
}
int android_media_play(MediaPlayerWrapper *mp)
{
Q_UNUSED(mp);
return 0;
}
int android_media_pause(MediaPlayerWrapper *mp)
{
Q_UNUSED(mp);
return 0;
}
int android_media_stop(MediaPlayerWrapper *mp)
{
Q_UNUSED(mp);
return 0;
}
bool android_media_is_playing(MediaPlayerWrapper *mp)
{
Q_UNUSED(mp);
return true;
}
int android_media_seek_to(MediaPlayerWrapper *mp, int msec)
{
Q_UNUSED(mp);
Q_UNUSED(msec);
return 0;
}
int android_media_get_current_position(MediaPlayerWrapper *mp, int *msec)
{
Q_UNUSED(mp);
Q_UNUSED(msec);
return 0;
}
int android_media_get_duration(MediaPlayerWrapper *mp, int *msec)
{
Q_UNUSED(mp);
Q_UNUSED(msec);
return 0;
}
int android_media_get_volume(MediaPlayerWrapper *mp, int *volume)
{
Q_UNUSED(mp);
Q_UNUSED(volume);
return 0;
}
int android_media_set_volume(MediaPlayerWrapper *mp, int volume)
{
Q_UNUSED(mp);
Q_UNUSED(volume);
return 0;
}
qtubuntu-media-0.7.1+14.04.20140304/aalMediaPlayer.pro 0000644 0000152 0177776 00000000120 12305353776 022455 0 ustar pbuser nogroup 0000000 0000000 include(coverage.pri)
TEMPLATE = subdirs
SUBDIRS += \
src \
unittests
qtubuntu-media-0.7.1+14.04.20140304/coverage.pri 0000644 0000152 0177776 00000003561 12305353776 021404 0 ustar pbuser nogroup 0000000 0000000 # Coverage
CONFIG(coverage) {
OBJECTS_DIR =
MOC_DIR =
TOP_SRC_DIR = $$PWD
LIBS += -lgcov
QMAKE_CXXFLAGS += --coverage
QMAKE_LDFLAGS += --coverage
QMAKE_EXTRA_TARGETS += coverage cov
QMAKE_EXTRA_TARGETS += clean-gcno clean-gcda coverage-html \
generate-coverage-html clean-coverage-html coverage-gcovr \
generate-gcovr generate-coverage-gcovr clean-coverage-gcovr
clean-gcno.commands = \
"@echo Removing old coverage instrumentation"; \
"find -name '*.gcno' -print | xargs -r rm"
clean-gcda.commands = \
"@echo Removing old coverage results"; \
"find -name '*.gcda' -print | xargs -r rm"
coverage-html.depends = clean-gcda check generate-coverage-html
generate-coverage-html.commands = \
"@echo Collecting coverage data"; \
"lcov --directory $${TOP_SRC_DIR} --capture --output-file coverage.info --no-checksum --compat-libtool"; \
"lcov --extract coverage.info \"*/src/*.cpp\" -o coverage.info"; \
"lcov --remove coverage.info \"moc_*.cpp\" -o coverage.info"; \
"LANG=C genhtml --prefix $${TOP_SRC_DIR} --output-directory coverage-html --title \"Code Coverage\" --legend --show-details coverage.info"
clean-coverage-html.depends = clean-gcda
clean-coverage-html.commands = \
"lcov --directory $${TOP_SRC_DIR} -z"; \
"rm -rf coverage.info coverage-html"
coverage-gcovr.depends = clean-gcda check generate-coverage-gcovr
generate-coverage-gcovr.commands = \
"@echo Generating coverage GCOVR report"; \
"gcovr -x -r $${TOP_SRC_DIR} -o $${TOP_SRC_DIR}/coverage.xml -e \".*/moc_.*\" -e \"unittests/.*\" -e \".*\\.h\""
clean-coverage-gcovr.depends = clean-gcda
clean-coverage-gcovr.commands = \
"rm -rf $${TOP_SRC_DIR}/coverage.xml"
QMAKE_CLEAN += *.gcda *.gcno coverage.info coverage.xml
}
qtubuntu-media-0.7.1+14.04.20140304/src/ 0000755 0000152 0177776 00000000000 12305354221 017641 5 ustar pbuser nogroup 0000000 0000000 qtubuntu-media-0.7.1+14.04.20140304/src/aalmediaplayer.json 0000644 0000152 0177776 00000000062 12305353776 023522 0 ustar pbuser nogroup 0000000 0000000 {
"Keys": ["org.qt-project.qt.mediaplayer"]
}
qtubuntu-media-0.7.1+14.04.20140304/src/aalmediaplayercontrol.h 0000644 0000152 0177776 00000004346 12305353776 024412 0 ustar pbuser nogroup 0000000 0000000 /*
* Copyright (C) 2013 Canonical, Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see .
*/
#ifndef AALMEDIAPLAYER_H
#define AALMEDIAPLAYER_H
#include
class AalMediaPlayerService;
class AalMediaPlayerControl : public QMediaPlayerControl
{
Q_OBJECT
public:
AalMediaPlayerControl(AalMediaPlayerService *service, QObject *parent = 0);
~AalMediaPlayerControl();
virtual QMediaPlayer::State state() const;
virtual QMediaPlayer::MediaStatus mediaStatus() const;
virtual qint64 duration() const;
virtual qint64 position() const;
virtual void setPosition(qint64);
virtual int volume() const;
virtual void setVolume(int);
virtual bool isMuted() const;
virtual void setMuted(bool);
virtual int bufferStatus() const;
virtual bool isAudioAvailable() const;
virtual bool isVideoAvailable() const;
virtual bool isSeekable() const;
virtual QMediaTimeRange availablePlaybackRanges() const;
virtual qreal playbackRate() const;
virtual void setPlaybackRate(qreal);
virtual QMediaContent media() const;
virtual const QIODevice* mediaStream() const;
virtual void setMedia(const QMediaContent&, QIODevice*);
virtual void play();
virtual void pause();
virtual void stop();
static void playbackCompleteCb(void *context);
static void mediaPreparedCb(void *context);
private:
AalMediaPlayerService *m_service;
QMediaPlayer::State m_state;
QMediaPlayer::MediaStatus m_status;
QMediaContent m_mediaContent;
int m_cachedVolume;
void playbackComplete();
void mediaPrepared();
void setMediaStatus(QMediaPlayer::MediaStatus status);
void setState(QMediaPlayer::State state);
};
#endif
qtubuntu-media-0.7.1+14.04.20140304/src/aalmediaplayerservice.h 0000644 0000152 0177776 00000004536 12305353776 024373 0 ustar pbuser nogroup 0000000 0000000 /*
* Copyright (C) 2013 Canonical, Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see .
*/
#ifndef AALMEDIAPLAYERSERVICE_H
#define AALMEDIAPLAYERSERVICE_H
#include
#include
class AalMediaPlayerControl;
class QMediaPlayerControl;
class AalVideoRendererControl;
struct MediaPlayerWrapper;
class AalMediaPlayerService : public QMediaService
{
Q_OBJECT
public:
AalMediaPlayerService(QObject *parent = 0);
~AalMediaPlayerService();
QMediaControl* requestControl(const char *name);
void releaseControl(QMediaControl *control);
AalMediaPlayerControl *mediaPlayerControl() const { return m_mediaPlayerControl; }
AalVideoRendererControl *videoOutputControl() const { return m_videoOutput; }
MediaPlayerWrapper *androidControl();
bool newMediaPlayer();
void setupMediaPlayer();
void setMedia(const QUrl &url);
void play();
void pause();
void stop();
int position() const;
void setPosition(int msec);
int duration() const;
int getVolume() const;
void setVolume(int volume);
void setVideoTextureNeedsUpdateCb(on_video_texture_needs_update cb, void *context);
void setVideoSizeCb(on_msg_set_video_size cb, void *context);
void setPlaybackCompleteCb(on_playback_complete cb, void *context);
void setMediaPreparedCb(on_media_prepared cb, void *context);
static AalMediaPlayerService *instance() { return m_service; }
Q_SIGNALS:
void serviceReady();
private:
static AalMediaPlayerService *m_service;
AalMediaPlayerControl *m_mediaPlayerControl;
AalVideoRendererControl *m_videoOutput;
MediaPlayerWrapper *m_androidMediaPlayer;
int m_mediaPlayerControlRef;
int m_videoOutputRef;
on_msg_set_video_size m_setVideoSizeCb;
void *m_setVideoSizeContext;
};
#endif
qtubuntu-media-0.7.1+14.04.20140304/src/aalvideorenderercontrol.cpp 0000644 0000152 0177776 00000013302 12305353776 025276 0 ustar pbuser nogroup 0000000 0000000 /*
* Copyright (C) 2013 Canonical, Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see .
*/
#include "aalvideorenderercontrol.h"
#include "aalmediaplayercontrol.h"
#include "aalmediaplayerservice.h"
#include
#include
#include
#include
#include
#include
#include
#include
class AalGLTextureBuffer : public QAbstractVideoBuffer
{
public:
AalGLTextureBuffer(GLuint textureId) :
QAbstractVideoBuffer(QAbstractVideoBuffer::GLTextureHandle),
m_textureId(textureId)
{
}
MapMode mapMode() const { return NotMapped; }
uchar *map(MapMode mode, int *numBytes, int *bytesPerLine)
{
qDebug() << Q_FUNC_INFO;
Q_UNUSED(mode);
Q_UNUSED(numBytes);
Q_UNUSED(bytesPerLine);
return NULL;
}
void unmap()
{
qDebug() << Q_FUNC_INFO;
}
QVariant handle() const
{
return QVariant::fromValue(m_textureId);
}
GLuint textureId() { return m_textureId; }
private:
GLuint m_textureId;
};
AalVideoRendererControl::AalVideoRendererControl(AalMediaPlayerService *service, QObject *parent)
: QVideoRendererControl(parent),
m_surface(0),
m_service(service),
m_textureBuffer(0),
m_textureId(0),
m_height(720),
m_width(1280),
m_firstFrame(true)
{
m_service->setVideoSizeCb(AalVideoRendererControl::setVideoSizeCb, static_cast(this));
// Get notified when qtvideo-node creates a GL texture
connect(SharedSignal::instance(), SIGNAL(textureCreated(unsigned int)), this, SLOT(onTextureCreated(unsigned int)));
// Get notified when the AalMediaPlayerService is ready to play video
connect(m_service, SIGNAL(serviceReady()), this, SLOT(onServiceReady()));
}
AalVideoRendererControl::~AalVideoRendererControl()
{
if (m_textureBuffer) {
GLuint textureId = m_textureBuffer->handle().toUInt();
glDeleteTextures(1, &textureId);
delete m_textureBuffer;
}
}
QAbstractVideoSurface *AalVideoRendererControl::surface() const
{
return m_surface;
}
void AalVideoRendererControl::setSurface(QAbstractVideoSurface *surface)
{
if (m_surface != surface) {
m_surface = surface;
Q_EMIT surfaceChanged(surface);
}
}
void AalVideoRendererControl::updateVideoTextureCb(void *context)
{
Q_ASSERT(context != NULL);
QMetaObject::invokeMethod(static_cast(context), "updateVideoTexture", Qt::QueuedConnection);
}
void AalVideoRendererControl::setVideoSizeCb(int height, int width, void *data)
{
if (data != NULL)
static_cast(data)->setVideoSize(height, width);
else
qWarning() << "Failed to call setVideoSize() since data is NULL." << endl;
}
void AalVideoRendererControl::setupSurface()
{
if (!m_textureBuffer)
return;
MediaPlayerWrapper *mp = m_service->androidControl();
m_service->setVideoTextureNeedsUpdateCb(AalVideoRendererControl::updateVideoTextureCb, static_cast(this));
android_media_set_preview_texture(mp, m_textureBuffer->handle().toUInt());
}
void AalVideoRendererControl::setVideoSize(int height, int width)
{
m_height = height;
m_width = width;
}
void AalVideoRendererControl::updateVideoTexture()
{
if (!m_surface) {
qWarning() << "m_surface is NULL, can't update video texture" << endl;
return;
}
if (!m_textureBuffer) {
qWarning() << "m_textureBuffer is NULL, can't update video texture" << endl;
return;
}
// If this is the first video frame being rendered, it's ok that m_textureId == 0.
// This is necessary so that a ShaderVideoNode instance from qtvideo-node gets created,
// as it is responsible for creating and returning a new texture and ID respectively.
if (m_textureId == 0 && !m_firstFrame) {
qWarning() << "m_textureId == 0, can't update video texture" << endl;
return;
}
QVideoFrame frame(new AalGLTextureBuffer(m_textureId), QSize(m_width, m_height), QVideoFrame::Format_RGB32);
if (!frame.isValid())
{
qWarning() << "Frame is invalid, not presenting." << endl;
return;
}
MediaPlayerWrapper *mp = m_service->androidControl();
frame.setMetaData("MediaPlayerControl", QVariant::fromValue((void*)mp));
presentVideoFrame(frame);
if (m_firstFrame)
m_firstFrame = false;
}
void AalVideoRendererControl::onTextureCreated(unsigned int textureID)
{
m_textureId = static_cast(textureID);
}
void AalVideoRendererControl::onServiceReady()
{
m_textureBuffer = new AalGLTextureBuffer(m_textureId);
setupSurface();
}
void AalVideoRendererControl::presentVideoFrame(const QVideoFrame &frame, bool empty)
{
Q_ASSERT(m_surface != NULL);
if (!m_surface->isActive()) {
QVideoSurfaceFormat format(frame.size(), frame.pixelFormat(), frame.handleType());
if (!m_surface->start(format)) {
qWarning() << "Failed to start video surface with format:" << format;
}
}
if (m_surface->isActive()) {
m_surface->present(frame);
}
}
qtubuntu-media-0.7.1+14.04.20140304/src/aalmediaplayerserviceplugin.h 0000644 0000152 0177776 00000002513 12305353776 025603 0 ustar pbuser nogroup 0000000 0000000 /*
* Copyright (C) 2013 Canonical, Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see .
*/
#ifndef AALMEDIAPLAYERSERVICEPLUGIN_H
#define AALMEDIAPLAYERSERVICEPLUGIN_H
#include
class AalServicePlugin : public QMediaServiceProviderPlugin,
public QMediaServiceSupportedDevicesInterface
{
Q_OBJECT
Q_INTERFACES(QMediaServiceSupportedDevicesInterface)
Q_PLUGIN_METADATA(IID "org.qt-project.qt.mediaserviceproviderfactory/5.0" FILE "aalmediaplayer.json")
public:
AalServicePlugin();
QMediaService* create(QString const& key);
void release(QMediaService *service);
QList devices(const QByteArray &service) const;
QString deviceDescription(const QByteArray &service, const QByteArray &device);
};
#endif
qtubuntu-media-0.7.1+14.04.20140304/src/aalvideorenderercontrol.h 0000644 0000152 0177776 00000003562 12305353776 024752 0 ustar pbuser nogroup 0000000 0000000 /*
* Copyright (C) 2013 Canonical, Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see .
*/
#ifndef AALVIDEORENDERERCONTROL_H
#define AALVIDEORENDERERCONTROL_H
#include
#include
#include
#include
class AalMediaPlayerService;
class AalGLTextureBuffer;
class AalVideoRendererControl : public QVideoRendererControl
{
Q_OBJECT
public:
AalVideoRendererControl(AalMediaPlayerService *service, QObject *parent = 0);
~AalVideoRendererControl();
QAbstractVideoSurface *surface() const;
void setSurface(QAbstractVideoSurface *surface);
// Callbacks
static void updateVideoTextureCb(void *context);
static void setVideoSizeCb(int height, int width, void *data);
public Q_SLOTS:
void setupSurface();
Q_SIGNALS:
void surfaceChanged(QAbstractVideoSurface *surface);
private Q_SLOTS:
void setVideoSize(int height, int width);
void updateVideoTexture();
void onTextureCreated(unsigned int textureID);
void onServiceReady();
private:
void presentVideoFrame(const QVideoFrame &frame, bool empty = false);
QAbstractVideoSurface *m_surface;
AalMediaPlayerService *m_service;
AalGLTextureBuffer *m_textureBuffer;
GLuint m_textureId;
int m_height;
int m_width;
bool m_firstFrame;
};
#endif
qtubuntu-media-0.7.1+14.04.20140304/src/aalmediaplayerserviceplugin.cpp 0000644 0000152 0177776 00000002627 12305353776 026144 0 ustar pbuser nogroup 0000000 0000000 /*
* Copyright (C) 2013 Canonical, Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see .
*/
#include "aalmediaplayerserviceplugin.h"
#include "aalmediaplayerservice.h"
#include
AalServicePlugin::AalServicePlugin()
{
}
QMediaService* AalServicePlugin::create(QString const& key)
{
if (key == QLatin1String(Q_MEDIASERVICE_MEDIAPLAYER))
return new AalMediaPlayerService;
else
qWarning() << "Key not supported:" << key;
return 0;
}
void AalServicePlugin::release(QMediaService *service)
{
Q_UNUSED(service);
delete service;
}
QList AalServicePlugin::devices(const QByteArray &service) const
{
Q_UNUSED(service);
return QList();
}
QString AalServicePlugin::deviceDescription(const QByteArray &service, const QByteArray &device)
{
Q_UNUSED(service);
Q_UNUSED(device);
return QString();
}
qtubuntu-media-0.7.1+14.04.20140304/src/src.pro 0000644 0000152 0177776 00000001256 12305353776 021174 0 ustar pbuser nogroup 0000000 0000000 include(../coverage.pri)
TARGET = aalmediaplayer
QT += multimedia opengl
TEMPLATE = lib
CONFIG += plugin
PLUGIN_TYPE = mediaservice
target.path += $$[QT_INSTALL_PLUGINS]/$${PLUGIN_TYPE}
INSTALLS = target
INCLUDEPATH += /usr/include/hybris /usr/include/libqtubuntu-media-signals
LIBS += -lhybris-common -lubuntu_application_api -lmedia -lqtubuntu-media-signals
OTHER_FILES += aalmediaplayer.json
HEADERS += \
aalmediaplayercontrol.h \
aalmediaplayerservice.h \
aalmediaplayerserviceplugin.h \
aalvideorenderercontrol.h
SOURCES += \
aalmediaplayercontrol.cpp \
aalmediaplayerservice.cpp \
aalmediaplayerserviceplugin.cpp \
aalvideorenderercontrol.cpp
qtubuntu-media-0.7.1+14.04.20140304/src/aalmediaplayerservice.cpp 0000644 0000152 0177776 00000016644 12305353776 024731 0 ustar pbuser nogroup 0000000 0000000 /*
* Copyright (C) 2013 Canonical, Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see .
*/
#include "aalmediaplayercontrol.h"
#include "aalmediaplayerservice.h"
#include "aalvideorenderercontrol.h"
#include
#include
#include
enum {
OK = 0,
NO_ERROR = 0,
BAD_VALUE = -EINVAL,
};
static void error_msg_cb(void *context)
{
Q_UNUSED(context);
qDebug() << __PRETTY_FUNCTION__ << endl;
}
AalMediaPlayerService *AalMediaPlayerService::m_service = 0;
AalMediaPlayerService::AalMediaPlayerService(QObject *parent):
QMediaService(parent),
m_androidMediaPlayer(NULL),
m_mediaPlayerControlRef(0),
m_videoOutputRef(0),
m_setVideoSizeCb(0),
m_setVideoSizeContext(0)
{
m_service = this;
if (!newMediaPlayer())
qWarning() << "Failed to create a new media player backend. Video playback will not function." << endl;
m_videoOutput = new AalVideoRendererControl(this);
m_mediaPlayerControl = new AalMediaPlayerControl(this);
}
AalMediaPlayerService::~AalMediaPlayerService()
{
if (m_mediaPlayerControl != NULL)
delete m_mediaPlayerControl;
if (m_videoOutput != NULL)
delete m_videoOutput;
if (m_androidMediaPlayer != NULL)
delete m_androidMediaPlayer;
}
QMediaControl *AalMediaPlayerService::requestControl(const char *name)
{
if (qstrcmp(name, QMediaPlayerControl_iid) == 0)
{
if (m_mediaPlayerControlRef == 0 && m_mediaPlayerControl == NULL)
m_mediaPlayerControl = new AalMediaPlayerControl(this);
++m_mediaPlayerControlRef;
return m_mediaPlayerControl;
}
if (qstrcmp(name, QVideoRendererControl_iid) == 0)
{
if (m_videoOutputRef == 0 && m_videoOutput == NULL)
m_videoOutput = new AalVideoRendererControl(this);
++m_videoOutputRef;
return m_videoOutput;
}
return NULL;
}
void AalMediaPlayerService::releaseControl(QMediaControl *control)
{
if (control == m_mediaPlayerControl)
{
if (m_mediaPlayerControlRef > 0)
--m_mediaPlayerControlRef;
if (m_mediaPlayerControlRef == 0)
{
if (m_mediaPlayerControl != NULL)
{
delete m_mediaPlayerControl;
m_mediaPlayerControl = NULL;
control = NULL;
}
}
}
else if (control == m_videoOutput)
{
if (m_videoOutputRef > 0)
--m_videoOutputRef;
if (m_videoOutputRef == 0)
{
if (m_videoOutput != NULL)
{
delete m_videoOutput;
m_videoOutput = NULL;
control = NULL;
}
}
}
}
MediaPlayerWrapper *AalMediaPlayerService::androidControl()
{
return m_androidMediaPlayer;
}
bool AalMediaPlayerService::newMediaPlayer()
{
if (m_androidMediaPlayer)
return true;
m_androidMediaPlayer = android_media_new_player();
if (!m_androidMediaPlayer) {
qWarning() << "Unable to create a new media player instance.";
return false;
}
return true;
}
void AalMediaPlayerService::setupMediaPlayer()
{
assert(m_androidMediaPlayer != NULL);
assert(m_setVideoSizeCb != NULL);
android_media_set_video_size_cb(m_androidMediaPlayer, m_setVideoSizeCb, m_setVideoSizeContext);
m_videoOutput->setupSurface();
// Gets called when there is any type of media playback issue
android_media_set_error_cb(m_androidMediaPlayer, error_msg_cb, static_cast(this));
}
void AalMediaPlayerService::setMedia(const QUrl &url)
{
if (url.isEmpty())
{
qWarning() << "Failed to set media source, url must be set." << endl;
return;
}
int ret = android_media_set_data_source(m_androidMediaPlayer, url.path().toStdString().c_str());
if (ret != OK)
{
qWarning() << "Failed to set media source." << endl;
return;
}
}
void AalMediaPlayerService::play()
{
assert(m_androidMediaPlayer != NULL);
int ret = android_media_play(m_androidMediaPlayer);
if (ret != OK)
{
qWarning() << "Failed to play media." << endl;
return;
}
Q_EMIT serviceReady();
}
void AalMediaPlayerService::pause()
{
assert(m_androidMediaPlayer != NULL);
int ret = android_media_pause(m_androidMediaPlayer);
if (ret != OK)
{
qWarning() << "Failed to pause media playback." << endl;
return;
}
}
void AalMediaPlayerService::stop()
{
assert(m_androidMediaPlayer != NULL);
int ret = android_media_stop(m_androidMediaPlayer);
if (ret != OK)
{
qWarning() << "Failed to stop media playback." << endl;
return;
}
}
int AalMediaPlayerService::position() const
{
assert(m_androidMediaPlayer != NULL);
int pos_msec = 0;
int ret = android_media_get_current_position(m_androidMediaPlayer, &pos_msec);
if (ret != OK)
{
qWarning() << "Failed to get the current playback position." << endl;
}
return pos_msec;
}
void AalMediaPlayerService::setPosition(int msec)
{
assert(m_androidMediaPlayer != NULL);
int ret = android_media_seek_to(m_androidMediaPlayer, msec);
if (ret != OK)
{
qWarning() << "Failed to set the current playback position." << endl;
return;
}
}
int AalMediaPlayerService::duration() const
{
assert(m_androidMediaPlayer != NULL);
int duration_msec = 0;
int ret = android_media_get_duration(m_androidMediaPlayer, &duration_msec);
if (ret != OK)
{
qWarning() << "Failed to get the media duration." << endl;
}
return duration_msec;
}
int AalMediaPlayerService::getVolume() const
{
assert(m_androidMediaPlayer != NULL);
int vol = 0;
int ret = android_media_get_volume(m_androidMediaPlayer, &vol);
if (ret != OK)
{
qWarning() << "Failed to get the volume." << endl;
}
return vol;
}
void AalMediaPlayerService::setVolume(int volume)
{
assert(m_androidMediaPlayer != NULL);
int ret = android_media_set_volume(m_androidMediaPlayer, volume);
if (ret != OK)
{
qWarning() << "Failed to set the volume." << endl;
}
}
void AalMediaPlayerService::setVideoTextureNeedsUpdateCb(on_video_texture_needs_update cb, void *context)
{
assert(m_androidMediaPlayer != NULL);
android_media_set_video_texture_needs_update_cb(m_androidMediaPlayer, cb, context);
}
void AalMediaPlayerService::setVideoSizeCb(on_msg_set_video_size cb, void *context)
{
m_setVideoSizeCb = cb;
m_setVideoSizeContext = context;
}
void AalMediaPlayerService::setPlaybackCompleteCb(on_playback_complete cb, void *context)
{
assert(m_androidMediaPlayer != NULL);
android_media_set_playback_complete_cb(m_androidMediaPlayer, cb, context);
}
void AalMediaPlayerService::setMediaPreparedCb(on_media_prepared cb, void *context)
{
assert(m_androidMediaPlayer != NULL);
android_media_set_media_prepared_cb(m_androidMediaPlayer, cb, context);
}
qtubuntu-media-0.7.1+14.04.20140304/src/aalmediaplayercontrol.cpp 0000644 0000152 0177776 00000014006 12305353776 024737 0 ustar pbuser nogroup 0000000 0000000 /*
* Copyright (C) 2013 Canonical, Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see .
*/
#include "aalmediaplayercontrol.h"
#include "aalmediaplayerservice.h"
#include "aalvideorenderercontrol.h"
#include
#include
AalMediaPlayerControl::AalMediaPlayerControl(AalMediaPlayerService *service, QObject *parent)
: QMediaPlayerControl(parent),
m_service(service),
m_state(QMediaPlayer::StoppedState),
m_status(QMediaPlayer::NoMedia)
{
m_service->setupMediaPlayer();
m_service->setPlaybackCompleteCb(AalMediaPlayerControl::playbackCompleteCb, static_cast(this));
m_service->setMediaPreparedCb(AalMediaPlayerControl::mediaPreparedCb, static_cast(this));
m_cachedVolume = volume();
}
AalMediaPlayerControl::~AalMediaPlayerControl()
{
stop();
m_state = QMediaPlayer::StoppedState;
m_status = QMediaPlayer::NoMedia;
m_cachedVolume = 0;
}
QMediaPlayer::State AalMediaPlayerControl::state() const
{
qDebug() << __PRETTY_FUNCTION__ << endl;
return m_state;
}
QMediaPlayer::MediaStatus AalMediaPlayerControl::mediaStatus() const
{
qDebug() << __PRETTY_FUNCTION__ << endl;
return m_status;
}
qint64 AalMediaPlayerControl::duration() const
{
return static_cast(m_service->duration());
}
qint64 AalMediaPlayerControl::position() const
{
return static_cast(m_service->position());
}
void AalMediaPlayerControl::setPosition(qint64 msec)
{
m_service->setPosition(static_cast(msec));
Q_EMIT positionChanged(msec);
}
int AalMediaPlayerControl::volume() const
{
qDebug() << __PRETTY_FUNCTION__ << endl;
return m_service->getVolume();
}
void AalMediaPlayerControl::setVolume(int volume)
{
qDebug() << __PRETTY_FUNCTION__ << endl;
m_cachedVolume = volume;
m_service->setVolume(volume);
Q_EMIT volumeChanged(m_cachedVolume);
}
bool AalMediaPlayerControl::isMuted() const
{
qDebug() << __PRETTY_FUNCTION__ << endl;
return (volume() == 0);
}
void AalMediaPlayerControl::setMuted(bool muted)
{
qDebug() << __PRETTY_FUNCTION__ << endl;
if (muted)
{
m_cachedVolume = volume();
setVolume(0);
}
else
{
setVolume(m_cachedVolume);
}
Q_EMIT mutedChanged(muted);
}
int AalMediaPlayerControl::bufferStatus() const
{
qDebug() << __PRETTY_FUNCTION__ << endl;
// Until we are playing network streams, there is no buffering necessary
return 100;
}
bool AalMediaPlayerControl::isAudioAvailable() const
{
qDebug() << __PRETTY_FUNCTION__ << endl;
return true;
}
bool AalMediaPlayerControl::isVideoAvailable() const
{
qDebug() << __PRETTY_FUNCTION__ << endl;
return true;
}
bool AalMediaPlayerControl::isSeekable() const
{
qDebug() << __PRETTY_FUNCTION__ << endl;
return true;
}
QMediaTimeRange AalMediaPlayerControl::availablePlaybackRanges() const
{
qDebug() << __PRETTY_FUNCTION__ << endl;
// TODO: this will need to change once we can play networked sources
return QMediaTimeRange(0, duration());
}
qreal AalMediaPlayerControl::playbackRate() const
{
qDebug() << __PRETTY_FUNCTION__ << endl;
return 1.0;
}
void AalMediaPlayerControl::setPlaybackRate(qreal rate)
{
qDebug() << __PRETTY_FUNCTION__ << endl;
Q_UNUSED(rate);
}
QMediaContent AalMediaPlayerControl::media() const
{
qDebug() << __PRETTY_FUNCTION__ << endl;
return m_mediaContent;
}
const QIODevice* AalMediaPlayerControl::mediaStream() const
{
qDebug() << __PRETTY_FUNCTION__ << endl;
// This is only valid if a stream was passed into setMedia()
return NULL;
}
void AalMediaPlayerControl::setMedia(const QMediaContent& media, QIODevice* stream)
{
Q_UNUSED(stream);
qDebug() << __PRETTY_FUNCTION__ << endl;
stop();
m_mediaContent = media;
Q_EMIT mediaChanged(m_mediaContent);
// Make sure we can actually load something valid
if (!media.isNull())
{
setMediaStatus(QMediaPlayer::LoadingMedia);
m_service->setMedia(media.canonicalUrl());
}
}
void AalMediaPlayerControl::play()
{
m_service->play();
setState(QMediaPlayer::PlayingState);
}
void AalMediaPlayerControl::pause()
{
m_service->pause();
setState(QMediaPlayer::PausedState);
}
void AalMediaPlayerControl::stop()
{
m_service->stop();
setState(QMediaPlayer::StoppedState);
}
void AalMediaPlayerControl::playbackCompleteCb(void *context)
{
if (context != NULL)
static_cast(context)->playbackComplete();
else
qWarning() << "Failed to call playbackComplete() since context is NULL." << endl;
}
void AalMediaPlayerControl::playbackComplete()
{
setMediaStatus(QMediaPlayer::EndOfMedia);
setState(QMediaPlayer::StoppedState);
}
void AalMediaPlayerControl::mediaPreparedCb(void *context)
{
if (context != NULL)
static_cast(context)->mediaPrepared();
else
qWarning() << "Failed to call mediaPrepared() since context is NULL." << endl;
}
void AalMediaPlayerControl::mediaPrepared()
{
setMediaStatus(QMediaPlayer::LoadedMedia);
Q_EMIT durationChanged(duration());
Q_EMIT positionChanged(position());
}
void AalMediaPlayerControl::setMediaStatus(QMediaPlayer::MediaStatus status)
{
if (status != m_status)
{
m_status = status;
Q_EMIT mediaStatusChanged(m_status);
}
}
void AalMediaPlayerControl::setState(QMediaPlayer::State state)
{
if (state != m_state)
{
m_state = state;
Q_EMIT stateChanged(m_state);
}
}
qtubuntu-media-0.7.1+14.04.20140304/COPYING 0000644 0000152 0177776 00000016743 12305353776 020136 0 ustar pbuser nogroup 0000000 0000000 GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc.
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
This version of the GNU Lesser General Public License incorporates
the terms and conditions of version 3 of the GNU General Public
License, supplemented by the additional permissions listed below.
0. Additional Definitions.
As used herein, "this License" refers to version 3 of the GNU Lesser
General Public License, and the "GNU GPL" refers to version 3 of the GNU
General Public License.
"The Library" refers to a covered work governed by this License,
other than an Application or a Combined Work as defined below.
An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.
A "Combined Work" is a work produced by combining or linking an
Application with the Library. The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".
The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.
The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.
1. Exception to Section 3 of the GNU GPL.
You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.
2. Conveying Modified Versions.
If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:
a) under this License, provided that you make a good faith effort to
ensure that, in the event an Application does not supply the
function or data, the facility still operates, and performs
whatever part of its purpose remains meaningful, or
b) under the GNU GPL, with none of the additional permissions of
this License applicable to that copy.
3. Object Code Incorporating Material from Library Header Files.
The object code form of an Application may incorporate material from
a header file that is part of the Library. You may convey such object
code under terms of your choice, provided that, if the incorporated
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:
a) Give prominent notice with each copy of the object code that the
Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the object code with a copy of the GNU GPL and this license
document.
4. Combined Works.
You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
engineering for debugging such modifications, if you also do each of
the following:
a) Give prominent notice with each copy of the Combined Work that
the Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the Combined Work with a copy of the GNU GPL and this license
document.
c) For a Combined Work that displays copyright notices during
execution, include the copyright notice for the Library among
these notices, as well as a reference directing the user to the
copies of the GNU GPL and this license document.
d) Do one of the following:
0) Convey the Minimal Corresponding Source under the terms of this
License, and the Corresponding Application Code in a form
suitable for, and under terms that permit, the user to
recombine or relink the Application with a modified version of
the Linked Version to produce a modified Combined Work, in the
manner specified by section 6 of the GNU GPL for conveying
Corresponding Source.
1) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (a) uses at run time
a copy of the Library already present on the user's computer
system, and (b) will operate properly with a modified version
of the Library that is interface-compatible with the Linked
Version.
e) Provide Installation Information, but only if you would otherwise
be required to provide such information under section 6 of the
GNU GPL, and only to the extent that such information is
necessary to install and execute a modified version of the
Combined Work produced by recombining or relinking the
Application with a modified version of the Linked Version. (If
you use option 4d0, the Installation Information must accompany
the Minimal Corresponding Source and Corresponding Application
Code. If you use option 4d1, you must provide the Installation
Information in the manner specified by section 6 of the GNU GPL
for conveying Corresponding Source.)
5. Combined Libraries.
You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:
a) Accompany the combined library with a copy of the same work based
on the Library, uncombined with any other library facilities,
conveyed under the terms of this License.
b) Give prominent notice with the combined library that part of it
is a work based on the Library, and explaining where to find the
accompanying uncombined form of the same work.
6. Revised Versions of the GNU Lesser General Public License.
The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the
Library as you received it specifies that a certain numbered version
of the GNU Lesser General Public License "or any later version"
applies to it, you have the option of following the terms and
conditions either of that published version or of any later version
published by the Free Software Foundation. If the Library as you
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.
If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.