From c8b287bdac7fb274ead0fe9e5f924c0c1a3be271 Mon Sep 17 00:00:00 2001 From: Mohammed Sameer Date: Wed, 26 Sep 2012 23:26:59 +0300 Subject: [PATCH] Added a sounds component that implements the Notifications interface and is used to play platform predefined sounds. --- data/n9/qtcamera.ini | 7 ++ imports/camera.cpp | 7 ++ imports/imports.pro | 8 ++- imports/plugin.cpp | 2 + imports/sounds.cpp | 154 +++++++++++++++++++++++++++++++++++++++++++ imports/sounds.h | 65 ++++++++++++++++++ lib/qtcamconfig.cpp | 16 +++++ lib/qtcamconfig.h | 5 ++ qml/main.qml | 5 +- src/src.pro | 1 - 10 files changed, 265 insertions(+), 5 deletions(-) create mode 100644 imports/sounds.cpp create mode 100644 imports/sounds.h diff --git a/data/n9/qtcamera.ini b/data/n9/qtcamera.ini index dd3a028..95d5d9d 100644 --- a/data/n9/qtcamera.ini +++ b/data/n9/qtcamera.ini @@ -164,3 +164,10 @@ fps = 30 night = 10 aspectratio=16:9 resolution=720p + + +[sounds] +imageCaptureStarted = /usr/share/sounds/ui-tones//snd_camera_shutter.wav +imageCaptureEnded = +videoRecordingStarted = /usr/share/sounds/ui-tones//snd_camera_video_record_start.wav +videoRecordingEnded = /usr/share/sounds/ui-tones//snd_camera_video_record_stop.wav diff --git a/imports/camera.cpp b/imports/camera.cpp index eac909e..14b1cf5 100644 --- a/imports/camera.cpp +++ b/imports/camera.cpp @@ -28,6 +28,7 @@ #include "qtcamconfig.h" #include "notifications.h" #include "notificationscontainer.h" +#include "sounds.h" // TODO: a viewfinder class that inherits QDeclarativeItem @@ -192,6 +193,12 @@ Notifications *Camera::notifications() const { void Camera::setNotifications(Notifications *notifications) { if (m_notifications->setNotifications(notifications)) { + + if (Sounds *s = dynamic_cast(notifications)) { + s->setConfig(m_cam->config()); + s->reload(); + } + emit notificationsChanged(); } } diff --git a/imports/imports.pro b/imports/imports.pro index 39cda15..b55a8d0 100644 --- a/imports/imports.pro +++ b/imports/imports.pro @@ -6,7 +6,7 @@ INCLUDEPATH += . ../lib/ CONFIG += link_pkgconfig debug PKGCONFIG = gstreamer-0.10 gstreamer-interfaces-0.10 gstreamer-video-0.10 gstreamer-tag-0.10 \ - gstreamer-pbutils-0.10 meego-gstreamer-interfaces-0.10 + gstreamer-pbutils-0.10 meego-gstreamer-interfaces-0.10 libcanberra QT += declarative @@ -14,10 +14,12 @@ HEADERS += plugin.h previewprovider.h camera.h mode.h imagemode.h videomode.h \ capability.h zoom.h flash.h scene.h evcomp.h videotorch.h whitebalance.h \ colortone.h exposure.h aperture.h iso.h noisereduction.h \ flickerreduction.h mute.h metadata.h imagesettings.h imageresolutionmodel.h \ - videosettings.h videoresolutionmodel.h notifications.h notificationscontainer.h + videosettings.h videoresolutionmodel.h notifications.h \ + notificationscontainer.h sounds.h SOURCES += plugin.cpp previewprovider.cpp camera.cpp mode.cpp imagemode.cpp videomode.cpp \ capability.cpp zoom.cpp flash.cpp scene.cpp evcomp.cpp videotorch.cpp whitebalance.cpp \ colortone.cpp exposure.cpp aperture.cpp iso.cpp noisereduction.cpp \ flickerreduction.cpp mute.cpp metadata.cpp imagesettings.cpp imageresolutionmodel.cpp \ - videosettings.cpp videoresolutionmodel.cpp notifications.cpp notificationscontainer.cpp + videosettings.cpp videoresolutionmodel.cpp notifications.cpp \ + notificationscontainer.cpp sounds.cpp diff --git a/imports/plugin.cpp b/imports/plugin.cpp index 80f13e0..1046c12 100644 --- a/imports/plugin.cpp +++ b/imports/plugin.cpp @@ -43,6 +43,7 @@ #include "videosettings.h" #include "videoresolutionmodel.h" #include "notifications.h" +#include "sounds.h" #include @@ -70,6 +71,7 @@ void Plugin::registerTypes(QDeclarativeEngine *engine) { qmlRegisterType(URI, MAJOR, MINOR, "MetaData"); qmlRegisterType(URI, MAJOR, MINOR, "ImageSettings"); qmlRegisterType(URI, MAJOR, MINOR, "VideoSettings"); + qmlRegisterType(URI, MAJOR, MINOR, "Sounds"); qmlRegisterInterface("Notifications"); qmlRegisterUncreatableType(URI, MAJOR, MINOR, "ImageResolutionModel", diff --git a/imports/sounds.cpp b/imports/sounds.cpp new file mode 100644 index 0000000..65ed983 --- /dev/null +++ b/imports/sounds.cpp @@ -0,0 +1,154 @@ +/*! + * This file is part of CameraPlus. + * + * Copyright (C) 2012 Mohammed Sameer + * + * 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) any later version. + * + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "sounds.h" +#include +#include "qtcamconfig.h" + +#define CAMERA_IMAGE_START_SOUND_ID "camera-image-start" +#define CAMERA_IMAGE_END_SOUND_ID "camera-image-end" +#define CAMERA_VIDEO_START_SOUND_ID "camera-video-start" +#define CAMERA_VIDEO_STOP_SOUND_ID "camera-video-stop" + +// TODO: video start sound should block +// TODO: video end sound should not appear in the video +// TODO: monitor pulse audio death and re-upload our samples +// TODO: if we are using headphones then sound volume might be loud. Detect and lower it. +Sounds::Sounds(QObject *parent) : + QObject(parent), + m_muted(false), + m_ctx(0), + m_conf(0) { + + // No idea why but canberra will not cache without that!!! + setenv("CANBERRA_EVENT_LOOKUP", "1", 1); +} + +Sounds::~Sounds() { + if (m_ctx) { + ca_context_destroy(m_ctx); + m_ctx = 0; + } +} + +void Sounds::setConfig(QtCamConfig *conf) { + m_conf = conf; +} + +void Sounds::imageCaptureStarted() { + if (isMuted() || !m_ctx) { + return; + } + + play(CAMERA_IMAGE_START_SOUND_ID); +} + +void Sounds::imageCaptureEnded() { + if (isMuted() || !m_ctx) { + return; + } + + play(CAMERA_IMAGE_END_SOUND_ID); +} + +void Sounds::videoRecordingStarted() { + if (isMuted() || !m_ctx) { + return; + } + + play(CAMERA_VIDEO_START_SOUND_ID); +} + +void Sounds::videoRecordingEnded() { + if (isMuted() || !m_ctx) { + return; + } + + play(CAMERA_VIDEO_STOP_SOUND_ID); +} + +bool Sounds::isMuted() const { + return m_muted; +} + +void Sounds::setMuted(bool mute) { + if (mute != m_muted) { + m_muted = mute; + emit muteChanged(); + } +} + +void Sounds::reload() { + if (m_ctx) { + ca_context_destroy(m_ctx); + m_ctx = 0; + } + + if (int code = ca_context_create(&m_ctx) != CA_SUCCESS) { + qWarning() << "Failed to create canberra context" << ca_strerror(code) << code; + return; + } + + if (int code = ca_context_set_driver(m_ctx, "pulse") != CA_SUCCESS) { + qWarning() << "Failed to set canberra driver to pulse audio" << ca_strerror(code) << code; + } + + if (int code = ca_context_change_props(m_ctx, + CA_PROP_MEDIA_ROLE, "camera-sound-effect", + NULL) != CA_SUCCESS) { + qWarning() << "Failed to set context properties" << ca_strerror(code) << code; + } + + if (int code = ca_context_open(m_ctx) != CA_SUCCESS) { + qWarning() << "Failed to open canberra context" << ca_strerror(code) << code; + ca_context_destroy(m_ctx); + m_ctx = 0; + return; + } + + cache(m_conf->imageCaptureStartedSound(), CAMERA_IMAGE_START_SOUND_ID); + cache(m_conf->imageCaptureEndedSound(), CAMERA_IMAGE_END_SOUND_ID); + cache(m_conf->videoRecordingStartedSound(), CAMERA_VIDEO_START_SOUND_ID); + cache(m_conf->videoRecordingEndedSound(), CAMERA_VIDEO_STOP_SOUND_ID); +} + +void Sounds::cache(const QString& path, const char *id) { + if (path.isEmpty()) { + return; + } + + if (int code = ca_context_cache(m_ctx, + CA_PROP_EVENT_ID, id, + CA_PROP_MEDIA_FILENAME, path.toLocal8Bit().data(), + CA_PROP_CANBERRA_CACHE_CONTROL, "permanent", + NULL) != CA_SUCCESS) { + qWarning() << "Failed to cache" << path << ca_strerror(code) << code; + } +} + +void Sounds::play(const char *id) { + if (int code = ca_context_play(m_ctx, 0, + CA_PROP_CANBERRA_VOLUME, "0.0", // Odd, volume has to be a char * + CA_PROP_EVENT_ID, id, + CA_PROP_MEDIA_ROLE, "camera-sound-effect", + NULL) != CA_SUCCESS) { + qDebug() << "Failed to play sound" << ca_strerror(code) << code; + } +} diff --git a/imports/sounds.h b/imports/sounds.h new file mode 100644 index 0000000..f443784 --- /dev/null +++ b/imports/sounds.h @@ -0,0 +1,65 @@ +// -*- c++ -*- + +/*! + * This file is part of CameraPlus. + * + * Copyright (C) 2012 Mohammed Sameer + * + * 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) any later version. + * + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef SOUNDS_H +#define SOUNDS_H + +#include +#include "notifications.h" +#include + +class QtCamConfig; + +class Sounds : public QObject, public Notifications { + Q_OBJECT + Q_INTERFACES(Notifications); + + Q_PROPERTY(bool mute READ isMuted WRITE setMuted NOTIFY muteChanged); + +public: + Sounds(QObject *parent = 0); + ~Sounds(); + + void imageCaptureStarted(); + void imageCaptureEnded(); + void videoRecordingStarted(); + void videoRecordingEnded(); + + bool isMuted() const; + void setMuted(bool mute); + + void setConfig(QtCamConfig *conf); + void reload(); + +signals: + void muteChanged(); + +private: + void cache(const QString& path, const char *id); + void play(const char *id); + + bool m_muted; + ca_context *m_ctx; + QtCamConfig *m_conf; +}; + +#endif /* SOUNDS_H */ diff --git a/lib/qtcamconfig.cpp b/lib/qtcamconfig.cpp index b94a1c0..31afe41 100644 --- a/lib/qtcamconfig.cpp +++ b/lib/qtcamconfig.cpp @@ -191,3 +191,19 @@ QString QtCamConfig::imageSuffix() const { QString QtCamConfig::videoSuffix() const { return d_ptr->conf->value("video/extension").toString(); } + +QString QtCamConfig::imageCaptureStartedSound() const { + return d_ptr->conf->value("sounds/imageCaptureStarted").toString(); +} + +QString QtCamConfig::imageCaptureEndedSound() const { + return d_ptr->conf->value("sounds/imageCaptureEnded").toString(); +} + +QString QtCamConfig::videoRecordingStartedSound() const { + return d_ptr->conf->value("sounds/videoRecordingStarted").toString(); +} + +QString QtCamConfig::videoRecordingEndedSound() const { + return d_ptr->conf->value("sounds/videoRecordingEnded").toString(); +} diff --git a/lib/qtcamconfig.h b/lib/qtcamconfig.h index 7d06a82..ec9b8f6 100644 --- a/lib/qtcamconfig.h +++ b/lib/qtcamconfig.h @@ -70,6 +70,11 @@ public: QString audioCaptureCaps() const; + QString imageCaptureStartedSound() const; + QString imageCaptureEndedSound() const; + QString videoRecordingStartedSound() const; + QString videoRecordingEndedSound() const; + private: QtCamConfigPrivate *d_ptr; }; diff --git a/qml/main.qml b/qml/main.qml index 27c686f..4e0592d 100644 --- a/qml/main.qml +++ b/qml/main.qml @@ -37,7 +37,6 @@ import QtMobility.location 1.2 // TODO: record video in a hidden directory and then copy the video to avoid tracker indexing it. // TODO: stop viewfinder in settings pages ? // TODO: prevent going to mass storage while recording and capturing -// TODO: sounds // TODO: grid lines, face tracking, ambr // TODO: complete settings pages // TODO: stop camera properly when we get closed. @@ -245,6 +244,10 @@ PageStackWindow { opacity: 0 color: "black" } + + notifications: Sounds { + id: sounds + } } Scene { diff --git a/src/src.pro b/src/src.pro index 0a5f2e8..81dd0cc 100644 --- a/src/src.pro +++ b/src/src.pro @@ -12,7 +12,6 @@ MOBILITY += location PKGCONFIG = gstreamer-0.10 gstreamer-interfaces-0.10 gstreamer-video-0.10 gstreamer-tag-0.10 \ gstreamer-pbutils-0.10 meego-gstreamer-interfaces-0.10 quill qmsystem2 libresourceqt1 - LIBS += -L../imports/ -limports -L../lib/ -lqtcamera SOURCES += main.cpp settings.cpp filenaming.cpp quillitem.cpp displaystate.cpp fsmonitor.cpp \ -- 2.25.1