Added a sounds component that implements the Notifications interface and is used to
authorMohammed Sameer <msameer@foolab.org>
Wed, 26 Sep 2012 20:26:59 +0000 (23:26 +0300)
committerMohammed Sameer <msameer@foolab.org>
Wed, 26 Sep 2012 23:48:31 +0000 (02:48 +0300)
play platform predefined sounds.

data/n9/qtcamera.ini
imports/camera.cpp
imports/imports.pro
imports/plugin.cpp
imports/sounds.cpp [new file with mode: 0644]
imports/sounds.h [new file with mode: 0644]
lib/qtcamconfig.cpp
lib/qtcamconfig.h
qml/main.qml
src/src.pro

index dd3a028..95d5d9d 100644 (file)
@@ -164,3 +164,10 @@ fps = 30
 night = 10
 aspectratio=16:9
 resolution=720p
 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
index eac909e..14b1cf5 100644 (file)
@@ -28,6 +28,7 @@
 #include "qtcamconfig.h"
 #include "notifications.h"
 #include "notificationscontainer.h"
 #include "qtcamconfig.h"
 #include "notifications.h"
 #include "notificationscontainer.h"
+#include "sounds.h"
 
 // TODO: a viewfinder class that inherits QDeclarativeItem
 
 
 // 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)) {
 
 void Camera::setNotifications(Notifications *notifications) {
   if (m_notifications->setNotifications(notifications)) {
+
+    if (Sounds *s = dynamic_cast<Sounds *>(notifications)) {
+      s->setConfig(m_cam->config());
+      s->reload();
+    }
+
     emit notificationsChanged();
   }
 }
     emit notificationsChanged();
   }
 }
index 39cda15..b55a8d0 100644 (file)
@@ -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 \
 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
 
 
 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 \
            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 \
 
 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
index 80f13e0..1046c12 100644 (file)
@@ -43,6 +43,7 @@
 #include "videosettings.h"
 #include "videoresolutionmodel.h"
 #include "notifications.h"
 #include "videosettings.h"
 #include "videoresolutionmodel.h"
 #include "notifications.h"
+#include "sounds.h"
 
 #include <QtDeclarative>
 
 
 #include <QtDeclarative>
 
@@ -70,6 +71,7 @@ void Plugin::registerTypes(QDeclarativeEngine *engine) {
   qmlRegisterType<MetaData>(URI, MAJOR, MINOR, "MetaData");
   qmlRegisterType<ImageSettings>(URI, MAJOR, MINOR, "ImageSettings");
   qmlRegisterType<VideoSettings>(URI, MAJOR, MINOR, "VideoSettings");
   qmlRegisterType<MetaData>(URI, MAJOR, MINOR, "MetaData");
   qmlRegisterType<ImageSettings>(URI, MAJOR, MINOR, "ImageSettings");
   qmlRegisterType<VideoSettings>(URI, MAJOR, MINOR, "VideoSettings");
+  qmlRegisterType<Sounds>(URI, MAJOR, MINOR, "Sounds");
   qmlRegisterInterface<Notifications>("Notifications");
 
   qmlRegisterUncreatableType<ImageResolutionModel>(URI, MAJOR, MINOR, "ImageResolutionModel",
   qmlRegisterInterface<Notifications>("Notifications");
 
   qmlRegisterUncreatableType<ImageResolutionModel>(URI, MAJOR, MINOR, "ImageResolutionModel",
diff --git a/imports/sounds.cpp b/imports/sounds.cpp
new file mode 100644 (file)
index 0000000..65ed983
--- /dev/null
@@ -0,0 +1,154 @@
+/*!
+ * This file is part of CameraPlus.
+ *
+ * Copyright (C) 2012 Mohammed Sameer <msameer@foolab.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) 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 <QDebug>
+#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 (file)
index 0000000..f443784
--- /dev/null
@@ -0,0 +1,65 @@
+// -*- c++ -*-
+
+/*!
+ * This file is part of CameraPlus.
+ *
+ * Copyright (C) 2012 Mohammed Sameer <msameer@foolab.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) 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 <QObject>
+#include "notifications.h"
+#include <canberra.h>
+
+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 */
index b94a1c0..31afe41 100644 (file)
@@ -191,3 +191,19 @@ QString QtCamConfig::imageSuffix() const {
 QString QtCamConfig::videoSuffix() const {
   return d_ptr->conf->value("video/extension").toString();
 }
 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();
+}
index 7d06a82..ec9b8f6 100644 (file)
@@ -70,6 +70,11 @@ public:
 
   QString audioCaptureCaps() const;
 
 
   QString audioCaptureCaps() const;
 
+  QString imageCaptureStartedSound() const;
+  QString imageCaptureEndedSound() const;
+  QString videoRecordingStartedSound() const;
+  QString videoRecordingEndedSound() const;
+
 private:
   QtCamConfigPrivate *d_ptr;
 };
 private:
   QtCamConfigPrivate *d_ptr;
 };
index 27c686f..4e0592d 100644 (file)
@@ -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: 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.
 // 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"
                 }
                         opacity: 0
                         color: "black"
                 }
+
+                notifications: Sounds {
+                        id: sounds
+                }
         }
 
         Scene {
         }
 
         Scene {
index 0a5f2e8..81dd0cc 100644 (file)
@@ -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
 
 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 \
 LIBS +=  -L../imports/ -limports -L../lib/ -lqtcamera
 
 SOURCES += main.cpp settings.cpp filenaming.cpp quillitem.cpp displaystate.cpp fsmonitor.cpp \