Commit adb3e0f7 authored by Andreas Cord-Landwehr's avatar Andreas Cord-Landwehr
Browse files

Merge branch 'gstreamer-1.0-port'

parents 2ef93d29 4d2015b8
###
# Copyright 2013 Andreas Cord-Landwehr <cordlandwehr@kde.org>
# Copyright 2013-2014 Andreas Cord-Landwehr <cordlandwehr@kde.org>
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
......@@ -25,11 +25,6 @@
project(artikulate)
set ( CMAKE_MODULE_PATH
${CMAKE_SOURCE_DIR}/cmake/modules
${CMAKE_MODULE_PATH}
)
find_package(KDE4 4.11.1 REQUIRED)
include(KDE4Defaults)
......@@ -44,7 +39,7 @@ add_subdirectory(src)
add_subdirectory(sounds)
add_subdirectory(images)
add_subdirectory(icons)
add_subdirectory(libsound)
add_subdirectory(liblearnerprofile)
# Build Tests if KDE_TEST is on
......
Artikulate is a language learning application that helps improving pronunciation skills for
various languages. This repository maintains the application and language specifications. All course
files are maintained in a separate repository "artikulate-data".
For detailed explanation how to contribute new languages and/or new courses, please refer to the
information at techbase: http://techbase.kde.org/Projects/Edu/Artikulate
PACKAGING:
Libraries:
The following libraries are exclusively used internally in Artikulate.
* liblearnerprofile
* artikulatecore
Dependency Preferences:
If available you should build against QtMultimedia. There are known combinations of PulseAudio,
QtGstreamer0.10 and GStreamer0.10 that lead to deadlocks. This problem will only be solved by the
upcoming port to GStreamer1.x.
BUILDING:
Artikulate has the following build dependencies:
* KDElibs >= 4.10.x
* Qt >= 4.8 (but not Qt 5.x)
* CMake >= 2.8.9
* EITHER QtMobility with component QtMultimedia
OR QtGStreamer
RUNTIME DEPENDENCIES:
* QtQuick plugin: kqtquickcharts (part of KDE Edu)
* KDE-runtime >= 4.11.1
LICENSING:
The whole codebase is licensed as GPL-2+ with the additional KDE e.V. clause.
Packaging and Building Information
==================================
Artikulate is a language learning application that helps improving pronunciation skills for
various languages. This repository maintains the application and language specifications. All course
files are maintained in a separate repository named "artikulate-data" and hosted on the KDE
infrastructure.
For a detailed explanation how to contribute new languages and/or new courses, please refer to the
information at techbase: http://techbase.kde.org/Projects/Edu/Artikulate
# Build Dependencies
Artikulate has the following build dependencies:
* KDElibs >= 4.11.1
* Qt >= 4.8 (but less than Qt 5.x)
* CMake >= 2.8.9
* QtGStreamer >= 1.1.90 (i.e., based on GStreamer-1.x)
# Packaging
Building produces the binary "artikulate" and the following shared libraries, which are only used
internally inside Artikulate:
* artikulatelearnerprofile
* artikuklatesound
* artikulatecore
# Runtime Dependencies
* kqtquickcharts: a KDE Edu library that provides a QtQuick plugin for plotting graphs
* KDE-runtime >= 4.11.1
# GStreamer-Problems
It is important that there is /no/ explicit or implicit linking to any gstreamer-0.10 base library.
Please ensure this, e.g., by executing "ldd artikulate" and by confirming that its output does not
contain any reference to gstreamer-0.10. Mixing both gstreamer-0.10 and gstreamer-1.0 will lead
to crashes and failures of all sound recording and playing functionality of the application.
# Licensing
The major part of the codebase is licensed as GPL-2+ with the additional KDE e.V. clause. If no
license is given, this is the default license (though please report missing licenses asap.)
Main parts of the above named libraries are licenses as LGL-2+ with the additional KDE e.V. clause.
CMake files are BSD licensed.
# Patches and Bug Reports
Please use the bugs.kde.org or the git.reviewboard.kde.org infrastructure for this.
# - Try to find the QtMobility libraries
#
# This module will search for the QtMobility libraries.
#
# It supports both a minimum version and searching for individual
# components. For the minimum version, use
# find_package(QtMobility 1.2.0). For specific components, use
# find_package(QtMobility COMPONENTS ...). See below for a list of known
# components.
#
# Once done this will define
# QTMOBILITY_FOUND - QtMobility and all specified components were found.
# QTMOBILITY_INCLUDE_DIR - Include directory for global QtMobility files.
# QTMOBILITY_INCLUDE_DIRS - All found QtMobility components' include dirs.
# QTMOBILITY_LIBRARIES - All found QtMobility components' libraries.
# QTMOBILITY_VERSION - The version of QtMobility that was found.
#
# For each found component the following will be defined:
# QTMOBILITY_{COMPONENT}_INCLUDE_DIR - The include directory for the component.
# QTMOBILITY_{COMPONENT}_LIBRARY - The location of the library for the component.
#
# Note that searching for components will be limited to the specified components
# if the components option is used.
#
# Copyright (c) 2011 Arjen Hiemstra <ahiemstra@heimr.nl>
# Redistribution and use is allowed according to the terms of the BSD license.
set(QTMOBILITY_COMPONENTS
Bearer
Connectivity
Contacts
Feedback
Gallery
Location
Messaging
MultimediaKit
Organizer
PublishSubscribe
Sensors
ServiceFramework
SystemInfo
Versit
)
if (QtMobility_FIND_COMPONENTS)
foreach (component ${QtMobility_FIND_COMPONENTS})
string(TOUPPER ${component} _COMPONENT)
set(QTMOBILITY_USE_${_COMPONENT} 1)
endforeach (component)
endif (QtMobility_FIND_COMPONENTS)
find_path(QTMOBILITY_INCLUDE_DIR qmobilityglobal.h PATH_SUFFIXES QtMobility)
#Find the mobility version
if(QTMOBILITY_INCLUDE_DIR)
if(EXISTS "${QTMOBILITY_INCLUDE_DIR}/qmobilityglobal.h")
file(READ "${QTMOBILITY_INCLUDE_DIR}/qmobilityglobal.h" _qtmobility_global_header LIMIT 5000)
string(REGEX MATCH "#define QTM_VERSION_STR +\"([0-9.]*)\"" _qtmobility_version_match "${_qtmobility_global_header}")
set(QTMOBILITY_VERSION "${CMAKE_MATCH_1}")
endif()
endif(QTMOBILITY_INCLUDE_DIR)
set(QTMOBILITY_VARIABLES "QTMOBILITY_INCLUDE_DIR")
set(QTMOBILITY_INCLUDE_DIRS ${QTMOBILITY_INCLUDE_DIR})
#A list of files to find for specific components
set(QTMOBILITY_FIND_FILES
QNetworkConfiguration #Bearer
QBluetoothSocket #Connectivity
QContact #Contacts
QFeedbackInterface #Feedback
QAbstractGallery #Gallery
QLandmark #Location
QMessage #Messaging
QMediaPlayer #MultimediaKit
QOrganizerItem #Organizer
QValueSpace #PublishSubscribe
QSensor #Sensors
QService #ServiceFramework
QSystemInfo #SystemInfo
QVersitDocument #Versit
)
list(LENGTH QTMOBILITY_COMPONENTS _component_count)
math(EXPR _component_count "${_component_count} - 1")
foreach (index RANGE ${_component_count})
list(GET QTMOBILITY_COMPONENTS ${index} component)
list(GET QTMOBILITY_FIND_FILES ${index} file)
string(TOUPPER ${component} _COMPONENT)
if (NOT QtMobility_FIND_COMPONENTS OR QTMOBILITY_USE_${_COMPONENT})
find_path(QTMOBILITY_${_COMPONENT}_INCLUDE_DIR ${file} PATH_SUFFIXES Qt${component} qt4/Qt${component})
find_library(QTMOBILITY_${_COMPONENT}_LIBRARY NAMES Qt${component})
list(APPEND QTMOBILITY_VARIABLES "QTMOBILITY_${_COMPONENT}_INCLUDE_DIR" "QTMOBILITY_${_COMPONENT}_LIBRARY")
list(APPEND QTMOBILITY_INCLUDE_DIRS ${QTMOBILITY_${_COMPONENT}_INCLUDE_DIR})
list(APPEND QTMOBILITY_LIBRARIES ${QTMOBILITY_${_COMPONENT}_LIBRARY})
endif (NOT QtMobility_FIND_COMPONENTS OR QTMOBILITY_USE_${_COMPONENT})
endforeach (index)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(QtMobility REQUIRED_VARS ${QTMOBILITY_VARIABLES} VERSION_VAR QTMOBILITY_VERSION)
mark_as_advanced(${QTMOBILITY_VARIABLES})
add_subdirectory(src)
###
# Copyright 2014 Andreas Cord-Landwehr <cordlandwehr@kde.org>
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
###
find_package(QtGStreamer 1.1.90 REQUIRED)
include_directories(
${QTGSTREAMER_INCLUDE_DIR}
)
set(sound_LIB_SRCS
capturedevicecontroller.cpp
outputdevicecontroller.cpp
qtgstreamercapturebackend.cpp
qtgstreameroutputbackend.cpp
)
kde4_add_library(artikulatesound SHARED ${sound_LIB_SRCS})
target_link_libraries(
artikulatesound
LINK_PRIVATE
${QTGLIB_LIBRARIES}
${QTGLIB_LIBRARY}
${QTGSTREAMER_LIBRARIES}
${KDE4_KDECORE_LIBS}
)
set_target_properties(
artikulatesound
PROPERTIES
VERSION ${GENERIC_LIB_VERSION}
SOVERSION ${GENERIC_LIB_SOVERSION}
)
install(
TARGETS artikulatesound
${INSTALL_TARGETS_DEFAULT_ARGS}
)
......@@ -19,18 +19,10 @@
*/
#include "capturedevicecontroller.h"
#include "soundbackends/soundbackendinterface.h"
#include "qtgstreamercapturebackend.h"
#include <config.h>
#if QTMOBILITY_FOUND
#include "soundbackends/qtmultimediabackend.h"
#endif
#if QTGSTREAMER_FOUND
#include "soundbackends/qtgstreamerbackend.h"
#endif
#include <settings.h>
#include <QUrl>
#include <QStringList>
#include <KDebug>
/**
......@@ -53,10 +45,8 @@ public:
~CaptureDeviceControllerPrivate()
{
for (int i = 0; i < m_backends.size(); ++i) {
m_backends.at(i)->deleteLater();
}
m_backends.clear();
delete m_backend;
m_backend = 0;
}
void lazyInit()
......@@ -64,34 +54,18 @@ public:
if (m_initialized) {
return;
}
// add QtMobility as first backend
#if QTMOBILITY_FOUND
kDebug() << "initilaize QtMultimediaBackend";
m_backends.append(new QtMultimediaBackend());
#endif
#if QTGSTREAMER_FOUND
kDebug() << "initilaize QtGStreamerBackend";
m_backends.append(new QtGStreamerBackend());
#endif
m_backend = new QtGStreamerCaptureBackend();
m_initialized = true;
}
SoundBackendInterface * backend() const
QtGStreamerCaptureBackend * backend() const
{
if (m_backends.isEmpty()) {
return 0;
}
foreach (SoundBackendInterface *backend, m_backends) {
if (Settings::recordingBackend() == backend->identifier()) {
return backend;
}
}
kDebug() << "could not understand backend configuration setting, default to first found";
return m_backends.first();
Q_ASSERT(m_backend);
return m_backend;
}
QObject *m_parent;
QList<SoundBackendInterface*> m_backends;
QtGStreamerCaptureBackend *m_backend;
bool m_initialized;
};
......
......@@ -21,7 +21,7 @@
#ifndef CAPTUREDEVICECONTROLLER_H
#define CAPTUREDEVICECONTROLLER_H
#include "artikulatecore_export.h"
#include "libsound_export.h"
#include <QObject>
......@@ -33,7 +33,7 @@ class KUrl;
*
* This singelton class provides a controller for the sound capture device.
*/
class ARTIKULATELIB_EXPORT CaptureDeviceController : public QObject
class LIBSOUND_EXPORT CaptureDeviceController : public QObject
{
Q_OBJECT
......
/*
* Copyright 2014 Andreas Cord-Landwehr <cordlandwehr@kde.org>
*
* This library 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; either
* version 2.1 of the License, or (at your option) version 3, or any
* later version accepted by the membership of KDE e.V. (or its
* successor approved by the membership of KDE e.V.), which shall
* act as a proxy defined in Section 6 of version 3 of the license.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef LIBSOUND_EXPORT_H
#define LIBSOUND_EXPORT_H
// needed for KDE_EXPORT and KDE_IMPORT macros
#include <kdemacros.h>
#ifndef LIBSOUND_EXPORT
# if defined(MAKE_LIBSOUND_LIB)
// We are building this library
# define LIBSOUND_EXPORT KDE_EXPORT
# else
// We are using this library
# define LIBSOUND_EXPORT KDE_IMPORT
# endif
#endif
# ifndef LIBSOUND_EXPORT_DEPRECATED
# define LIBSOUND_EXPORT_DEPRECATED KDE_DEPRECATED LIBSOUND_EXPORT
# endif
#endif
/*
* Copyright 2013 Andreas Cord-Landwehr <cordlandwehr@kde.org>
* Copyright 2013-2014 Andreas Cord-Landwehr <cordlandwehr@kde.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
......@@ -19,9 +19,8 @@
*/
#include "outputdevicecontroller.h"
#include <settings.h>
#include <QUrl>
#include "qtgstreameroutputbackend.h"
#include <KUrl>
#include <KDebug>
/**
......@@ -38,42 +37,38 @@ class OutputDeviceControllerPrivate
public:
OutputDeviceControllerPrivate(OutputDeviceController *parent)
: m_parent(parent)
, m_backend(0)
, m_initialized(false)
, m_volume(0)
{
// use this value only for initialization, will be modified in another thread / another
// static Settings object
m_volume = Settings::audioOutputVolume();
m_backend = new QtGStreamerOutputBackend();
}
~OutputDeviceControllerPrivate()
{
m_mediaObject->disconnect();
m_mediaObject->deleteLater();
m_audioOutput->deleteLater();
delete m_backend;
}
bool lazyInit()
void lazyInit()
{
if (m_initialized) {
return false;
return;
}
m_audioOutput = new Phonon::AudioOutput(Phonon::MusicCategory);
m_mediaObject = new Phonon::MediaObject();
// initialize
Phonon::createPath(m_mediaObject, m_audioOutput);
m_backend = new QtGStreamerOutputBackend();
m_parent->connect(m_backend, SIGNAL(stateChanged()), m_parent, SLOT(emitChangedState()));
m_volume = m_backend->volume();
m_initialized = true;
return true;
}
QtGStreamerOutputBackend * backend() const
{
Q_ASSERT(m_backend);
return m_backend;
}
OutputDeviceController *m_parent;
QtGStreamerOutputBackend *m_backend;
int m_volume; // volume as cubic value
bool m_initialized;
Phonon::AudioOutput *m_audioOutput;
Phonon::MediaObject *m_mediaObject;
int m_volume; // output volume in Db
};
OutputDeviceController::OutputDeviceController()
......@@ -89,51 +84,66 @@ OutputDeviceController::~OutputDeviceController()
OutputDeviceController & OutputDeviceController::self()
{
static OutputDeviceController instance;
if (instance.d->lazyInit()) {
connect(instance.d->m_mediaObject, SIGNAL(stateChanged(Phonon::State,Phonon::State)),
&instance, SLOT(updateState()));
}
instance.d->lazyInit();
return instance;
}
void OutputDeviceController::play(const QString& filePath)
{
play(KUrl::fromLocalFile(filePath));
d->backend()->setUri(filePath);
d->backend()->setVolume(d->m_volume);
d->backend()->play();
emit started();
}
void OutputDeviceController::play(const KUrl &filePath)
{
d->m_mediaObject->setCurrentSource(filePath);
d->m_audioOutput->setVolumeDecibel(d->m_volume);
d->m_mediaObject->play();
play(filePath.toLocalFile());
}
void OutputDeviceController::stop()
{
d->m_mediaObject->stop();
d->backend()->stop();
emit stopped();
}
Phonon::State OutputDeviceController::state() const
OutputDeviceController::State OutputDeviceController::state() const
{
return d->m_mediaObject->state();
switch (d->backend()->state()) {
case QGst::StateNull:
return OutputDeviceController::StoppedState;
break;
case QGst::StatePaused:
return OutputDeviceController::PlayingState;
break;
case QGst::StatePlaying:
return OutputDeviceController::PlayingState;
break;
default:
return OutputDeviceController::StoppedState;
}
}
void OutputDeviceController::setVolume(int volume)
{
// backend only accepts volume, when there is a pipeline
// store value here and set it when playing
d->m_volume = volume;
}
QString OutputDeviceController::currentSource() const
int OutputDeviceController::volume() const
{
return d->m_mediaObject->currentSource().fileName();
return d->backend()->volume();
}
void OutputDeviceController::updateState()
void OutputDeviceController::emitChangedState()
{
if (d->m_mediaObject->state() == Phonon::StoppedState) {
if (state() == OutputDeviceController::StoppedState) {
emit stopped();
return;
}
if (d->m_mediaObject->state() == Phonon::PlayingState) {
if (state() == OutputDeviceController::PlayingState) {
emit started();
return;
}
}
void OutputDeviceController::setVolume(int volumenDb)
{
d->m_volume = volumenDb;
}
......@@ -21,11 +21,8 @@
#ifndef OUTPUTDEVICECONTROLLER_H
#define OUTPUTDEVICECONTROLLER_H
#include "artikulatecore_export.h"
#include "libsound_export.h"
#include <QObject>
#include <Phonon/AudioOutput>
#include <Phonon/MediaObject>
class OutputDeviceControllerPrivate;
class KUrl;
......@@ -35,11 +32,18 @@ class KUrl;
*
* This singelton class provides a controller for the sound output device.
*/
class ARTIKULATELIB_EXPORT OutputDeviceController : public QObject
class LIBSOUND_EXPORT OutputDeviceController : public QObject
{
Q_OBJECT
public:
enum State
{
StoppedState,
PlayingState,
PausedState
};
/**
* Returns self reference to the controller. First call of this method initializes
* output device controller.
......@@ -50,23 +54,19 @@ public:
void play(const QString &filePath);
void play(const KUrl &filePath);
Phonon::State state() const;
OutputDeviceController::State state() const;
void stop();
QString currentSource() const;
/**