play platform predefined sounds.
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
#include "qtcamconfig.h"
#include "notifications.h"
#include "notificationscontainer.h"
+#include "sounds.h"
// TODO: a viewfinder class that inherits QDeclarativeItem
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();
}
}
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
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
#include "videosettings.h"
#include "videoresolutionmodel.h"
#include "notifications.h"
+#include "sounds.h"
#include <QtDeclarative>
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",
--- /dev/null
+/*!
+ * 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;
+ }
+}
--- /dev/null
+// -*- 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 */
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();
+}
QString audioCaptureCaps() const;
+ QString imageCaptureStartedSound() const;
+ QString imageCaptureEndedSound() const;
+ QString videoRecordingStartedSound() const;
+ QString videoRecordingEndedSound() const;
+
private:
QtCamConfigPrivate *d_ptr;
};
// 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.
opacity: 0
color: "black"
}
+
+ notifications: Sounds {
+ id: sounds
+ }
}
Scene {
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 \