--- /dev/null
+/* XPM */
+static char * flashstrobe_xpm[] = {
+"26 26 262 2",
+" c None",
+". c #4878D4",
+"+ c #4475CF",
+"@ c #4474D0",
+"# c #4071CD",
+"$ c #396BC4",
+"% c #3667C0",
+"& c #4F7FDB",
+"* c #4778D4",
+"= c #4476D5",
+"- c #477ADB",
+"; c #5E8DEB",
+"> c #8AAEFA",
+", c #8EB1FF",
+"' c #6997F9",
+") c #5284E9",
+"! c #4779DA",
+"~ c #396BC7",
+"{ c #275AB0",
+"] c #497AD5",
+"^ c #3265BE",
+"/ c #85A3DA",
+"( c #BFD0EE",
+"_ c #E9EFFA",
+": c #FFFFFF",
+"< c #ECF2FF",
+"[ c #CDDDFF",
+"} c #A3C0FF",
+"| c #5283E7",
+"1 c #275AB2",
+"2 c #5382DF",
+"3 c #3567BF",
+"4 c #3966AD",
+"5 c #CDD9EC",
+"6 c #F6F9FE",
+"7 c #EFF4FE",
+"8 c #DCE7FF",
+"9 c #75A0FB",
+"0 c #3467C4",
+"a c #15499C",
+"b c #1F53A6",
+"c c #6E8DBA",
+"d c #F6F8FB",
+"e c #DEE6F2",
+"f c #6D90CC",
+"g c #8BA8DC",
+"h c #BACEF4",
+"i c #5285ED",
+"j c #6D9AF9",
+"k c #95B7FF",
+"l c #E8EFFF",
+"m c #F9FBFF",
+"n c #A5C2FF",
+"o c #4679DB",
+"p c #0E4394",
+"q c #3668C0",
+"r c #7391BF",
+"s c #FEFEFF",
+"t c #94ABCF",
+"u c #1B4E9F",
+"v c #1C51A8",
+"w c #A9BDE1",
+"x c #A8C0EC",
+"y c #4F80E2",
+"z c #5C8EF8",
+"A c #6797FF",
+"B c #BAD0FF",
+"C c #FEFFFF",
+"D c #2B5FBA",
+"E c #4879D4",
+"F c #3764AB",
+"G c #4E74AC",
+"H c #003685",
+"I c #093F91",
+"J c #5F83BC",
+"K c #F8FAFC",
+"L c #FCFDFE",
+"M c #DDE7F9",
+"N c #8AACF3",
+"O c #6193FF",
+"P c #8FB3FF",
+"Q c #749FF9",
+"R c #0E4396",
+"S c #2B5DB2",
+"T c #CCD7E9",
+"U c #96ADD0",
+"V c #083E8E",
+"W c #134691",
+"X c #A8BAD5",
+"Y c #8EAADC",
+"Z c #B8CAEC",
+"` c #F0F4FC",
+" . c #C4D5F9",
+".. c #6695F8",
+"+. c #477ADC",
+"@. c #4272CC",
+"#. c #7C9ACB",
+"$. c #DDE5F1",
+"%. c #194D9C",
+"&. c #0D4293",
+"*. c #ABBDD8",
+"=. c #C0CDE1",
+"-. c #D3DEEE",
+";. c #2559B3",
+">. c #2E62BF",
+",. c #4777CE",
+"'. c #BFD0F1",
+"). c #C3D5F9",
+"!. c #194EA4",
+"~. c #386AC3",
+"{. c #B9C9E4",
+"]. c #6588C1",
+"^. c #164A9D",
+"/. c #5E81B9",
+"(. c #ACBED9",
+"_. c #7F9BC3",
+":. c #A2B7D8",
+"<. c #376BCA",
+"[. c #3465BD",
+"}. c #E6ECF6",
+"|. c #3664AF",
+"1. c #1A4EA2",
+"2. c #D4DEED",
+"3. c #ECF0F7",
+"4. c #20519B",
+"5. c #B8C8DF",
+"6. c #7B9DDC",
+"7. c #4376D9",
+"8. c #0A4092",
+"9. c #4371C2",
+"0. c #EAEFF7",
+"a. c #2356AB",
+"b. c #2657A9",
+"c. c #FBFCFE",
+"d. c #ACBEDC",
+"e. c #124798",
+"f. c #EFF2F8",
+"g. c #4573C6",
+"h. c #6593F3",
+"i. c #12479B",
+"j. c #4070CA",
+"k. c #6E92D0",
+"l. c #BFCEE9",
+"m. c #527ABD",
+"n. c #7F9CCB",
+"o. c #194C9E",
+"p. c #456FAF",
+"q. c #426CAB",
+"r. c #3E68A7",
+"s. c #3B65A4",
+"t. c #A2B6D3",
+"u. c #F1F4FA",
+"v. c #8BA8DB",
+"w. c #6992DF",
+"x. c #497CE1",
+"y. c #CBDAFA",
+"z. c #1F54AD",
+"A. c #3D6EC8",
+"B. c #7195D4",
+"C. c #C0D0EA",
+"D. c #2C5EB5",
+"E. c #567EC1",
+"F. c #829FCD",
+"G. c #114698",
+"H. c #AEC0D9",
+"I. c #C7D3E7",
+"J. c #86A3D5",
+"K. c #628BD5",
+"L. c #4074D6",
+"M. c #C8D7F6",
+"N. c #275BB5",
+"O. c #4D7ACC",
+"P. c #EBF0F9",
+"Q. c #3062BA",
+"R. c #3363B7",
+"S. c #FCFCFE",
+"T. c #B0C3E1",
+"U. c #1F52A6",
+"V. c #D8E1ED",
+"W. c #99AFD1",
+"X. c #13489C",
+"Y. c #AEC1E0",
+"Z. c #3567C1",
+"`. c #ECF1FB",
+" + c #5B8AE8",
+".+ c #285DB8",
+"++ c #E8EEF9",
+"@+ c #4A76C5",
+"#+ c #D8E1F1",
+"$+ c #EEF2F9",
+"%+ c #3463B2",
+"&+ c #174A9A",
+"*+ c #FBFCFD",
+"=+ c #6888B7",
+"-+ c #1C4E9A",
+";+ c #ECF1F7",
+">+ c #D5DFEF",
+",+ c #4372C6",
+"'+ c #3E72D4",
+")+ c #3064C1",
+"!+ c #3A6BC4",
+"~+ c #C3D3EF",
+"{+ c #7A9CD7",
+"]+ c #3567BE",
+"^+ c #7394D0",
+"/+ c #B6C7E4",
+"(+ c #5C81BE",
+"_+ c #A3B8D9",
+":+ c #B6C6DD",
+"<+ c #DCE3EE",
+"[+ c #386CCB",
+"}+ c #3365BD",
+"|+ c #93B0E5",
+"1+ c #E3EAF7",
+"2+ c #4070C5",
+"3+ c #B8C9E7",
+"4+ c #5D82C1",
+"5+ c #A7BAD5",
+"6+ c #4273CC",
+"7+ c #D6E1F5",
+"8+ c #ABC0E7",
+"9+ c #396BC3",
+"0+ c #4170C2",
+"a+ c #F5F7FB",
+"b+ c #ADBFD9",
+"c+ c #2D60BB",
+"d+ c #3F72D4",
+"e+ c #2558AE",
+"f+ c #638CDA",
+"g+ c #F8FAFD",
+"h+ c #7799D8",
+"i+ c #FDFEFE",
+"j+ c #7191C2",
+"k+ c #3865AD",
+"l+ c #3B6ECF",
+"m+ c #2D60B6",
+"n+ c #99B4E8",
+"o+ c #5C83C6",
+"p+ c #5C81BD",
+"q+ c #2B5FBB",
+"r+ c #3A6CC4",
+"s+ c #E4EAF5",
+"t+ c #92ABD5",
+"u+ c #1A4FA4",
+"v+ c #4679DD",
+"w+ c #2457AC",
+"x+ c #628BDA",
+"y+ c #E3E9F6",
+"z+ c #3663AA",
+"A+ c #2C60BC",
+"B+ c #0C4191",
+"C+ c #3869C1",
+"D+ c #3A6DCE",
+"E+ c #13489A",
+"F+ c #2155AA",
+"G+ c #2E60B7",
+"H+ c #4875C7",
+"I+ c #3F6DBF",
+"J+ c #2B5EB6",
+"K+ c #2C5FB9",
+"L+ c #3266C2",
+"M+ c #2357B0",
+" . + @ # $ % ",
+" & * = - ; > , ' ) ! ~ { ",
+" ] ^ / ( _ : : : : < [ } | 1 ",
+" 2 3 4 5 : : : : : 6 7 : : : 8 9 0 a ",
+" 2 b c d : e f g : : h i j k l : m n o p ",
+" q r : s t u v w : : x y i z A B C : n D ",
+" E F d s G H I J K : : : L M N z O P C m Q R ",
+" & S T : U V W X : : : L Y Z ` : ...O B : 8 +.H ",
+" @.#.: $.%.&.*.: =.: : -.;.>.,.'.: ).z A l : } !. ",
+" ~.{.: ].^./.: (._.: : :.v ;.>.<.'.: N z k : [ >. ",
+". [.}.: |.1.2.3.4.5.: : : : : : : 6.` M i j : < 7.8.",
+"+ 9.: 0.a.b.c.d.e.f.: : : : : : : g.Z L y i 7 : h.i.",
+"j.k.: l.{ m.: n.o.p.q.r.s.t.: : u.;.v.: w.x.y.: , z.",
+"A.B.: C.D.E.: F.1.^.G.&.V H.: : I.v J.: K.L.M.: > N.",
+"$ O.: P.Q.R.S.T.U.1.^.G.&.V.: : W.X.Y.S.Z.<.`.: +.+",
+"% A.++: @+Q.#+$+%+U.1.^.&+*+: : =+-+;+>+;.,+: _ '+)+",
+" !+~+: {+]+^+: /+a.(+_+d.: : : :+<+: J v f : ( [+ ",
+" }+|+: 1+2+]+3+: /+4+: : : : : : : 5+I u e : / <. ",
+" { 6+7+: 8+9+0+3+: $+a+: : : : : b+W H t : 5 c+d+ ",
+" e+f+g+s h+9+]+^+#+i+: : : L j+&.V G s d k+l+ ",
+" m+n+: s 8+2+]+Q.o+: : s p+^.%.U s : c q+ ",
+" a r+n+g+: 1+{+@+Q.s+: t+|.].$.: d r u+v+ ",
+" p w+x+7+: : : P.y+$+0.: : : T z+A+v+ ",
+" B+C+|+~+++: : : : }.{.#.e+D+ ",
+" H E+F+G+H+B.k.I+J+K+L+d+ ",
+" 8.i.v M+.+)+ "};
--- /dev/null
+flashstrobe (1.0-1) unstable; urgency=low
+
+ * Initial packaging
+
+ -- Juan Carlos Torres <jucato@kdemail.net> Wed, 11 Aug 2010 15:48:56 +0800
+
--- /dev/null
+Source: flashstrobe
+Section: user/other
+Priority: extra
+Maintainer: Juan Carlos Torres <jucato@kdemail.net>
+Build-Depends: debhelper (>= 5), libqt4-dev
+Standards-Version: 3.7.2
+
+Package: flashstrobe
+Architecture: any
+Depends: ${shlibs:Depends}, ${misc:Depends}
+XB-Description: Strobe light program for the N900
+ Use the N900's flash LEDs as a strobe light. The user can set the
+ frequency of the strobing in beats per minute (bpm). Additionally,
+ the user can open any audio file to play in the background. The
+ camera shutter need to be kept open to use this program. And for
+ best results, please close any program using the camera.
+ .
+ Do not point the flash at anyone's eyes.
+XB-Maemo-Display-Name: Flash Strobe
+XB-Maemo-Icon-26:
+ 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
+ psNh8q7VqXD85IgA0DB0ZlVkkOFKnUBzcJCEoYNlJk/AEu8I00QIk/2n0tJN
+ ls0pSAsDdhwKOn0r5hZz67KKDwUxZULK9H6QTjZ2Yhg6n7u2ihsWT3Tat77T
+ nBY7La3JTpu3p76PWLwPWdFQVe0dVQixUwizf0jXvU0dOh0hnXG5tmItnZ3H
+ 5lfOM1zj29sQ4g9727hxsR06fP+OGvbVd9Lebbv+u1ZPZWF1oeMD8rMyuBxt
+ +vZKXKrM8rnlTtuLO87w+r5mR7ElCZbNSYlge88Qp1siSfnX+lVV2ykffnbF
+ gBBix+BAP7KisO9USkyKctysnFfoyLQsK2x66QzBsJ1hBTI1Nt+7gOL8TGRZ
+ JhwzWDV/PNctmMD1C8uYN73wsgDWXFXJqgUVaKotHq1dUe57ancqYjV0Vs0r
+ pDgvtQlvHQ9hGHakqqrajn1PzR1I5gNim57QEWaCN470YlmpD33txnLcLtUB
+ ER+0eOiF007/3Km5bH98Jbcuq2DXkXZ0Y3Ri81Ho7o1/ojscdURHshJ85wsz
+ nX7LglffbsUwDRRFRVW1rTCc0FhiqxAiFu4L0xzUeet4KjYpyXPz2WUlTggs
+ yzIHTvfyqz81OWMCmRqPf30uP/7mAhqawn8184/+Zj87DjSl5Q53rp5MeVEq
+ SPzj3lbqG3tsB6ZqMVXVtkEyJ+46/tuBvOrbXIOD/cv8mQGaOw1umJ9SwE9N
+ DnD0XJTOXt2ppBx8L8zxxl7mTc3B57HN3KQSP8V5Xj4qtXXH+OKG7Ty/7QR2
+ zmVXOxZVl/Dcv9c6zlI3BPc8vpd+HbICeaiq9sibT0yvg7SqhLlJCBEMdrXT
+ 1SfYti/kfEhVJDbeNZni3IxRJ3Hbg/v5w962v3rXt719noVffZFdRy6mWbGy
+ cQFeevhGXGoqVHl22yma2nqHQ+igqmibhvucUaH6l/XsGev6B4cGV3szMjnb
+ Lpg9yUNBll2g8bgV5k3NZv+pXuJDwjkJ3bB482gn9ed7SSQEsiyR63dftuxu
+ WfDYfx3mgZ/vYVBP2DWOZLVjQqGfbU9+hkmlKdP5bkM76x97E483m8LCUlRF
+ e2DHo1V7RgEAyJr+maNCiLW9kd5x2Vk5HDk3xNWz/GRm2MNy/Bq1c/M51RJP
+ EyeQuNDZz64jQV7a2UJHaIDlVxSNCeCJ3x7jJy8ehxHVUgmJBdXF1P1kHRUl
+ KeYvBiNc9+1XGDIVJlfW4NLcx1RVW3/uz5vHLi32nd4i/FNved00E1/sjfRm
+ +v0F1DcPsGx2AC1ZUve4Fa67Mh89YfH+xfiIeqfk7PrFzn7uuL5ilBPbdbiN
+ f/vPAyNaJNyqzNdvreGZ79Wm1ZhiAzrX3/sSja0RZs1cgNfj71JVbUXdxvI0
+ KzEqJo6+/2pf5uS17+rG0JfiA3FFdedx+EyMeVMynZOQZYkrp2Wx6soCwrEE
+ zR0DWCNA6IaguiKLieNSBYJLnXG+8vDbDOkmICHLsHZJBS9sqOWWa6rSottL
+ nVFW/+sWjp3rYsb0eeTmFBmqqq2p21h+4oP8jhnUx89ubfFUrumK98fWxGIx
+ FFcOfz4ZY3pZhqMTAH6vyvI5eaxZVERpvgfDtAiGdSxAkeHapBgNGYK7H91L
+ W08/C2cW8tUbp/Gj9Qv4wqopZPvSK3vvNnSw5v5XaemIM3XKpygqmICqav9S
+ t7F8y1i8fugVU/bKX6wXQvzU483UZk2fg8/r5Usr8li7KBdNHXvqwJBJV+8Q
+ vTGD6kkBZEmiuSMOWBTlePC4x06EdMPkma31/PBX+7HQqKqswefLMVRVu7du
+ Y/llr5j+4hWdb/lPlwphviLLSkH1tDnk5xVSkCXz5ZUFLJud/ckv+Sx47e0m
+ HnnhEC3tETIzsygrm4bb5elSVW1d3cbyj3/JN0wZV29yrllzcvKZVjUTv8/P
+ xCIXK6/IZtGMgBMAflS61BVnx8E2frerkZONPaiqi7y8EgKBPFRFO6aq2s11
+ G8s/+TXrMKmLHlOFZV90A0WlxROoLJ+Mx+tDmCYV41wsnJFFWaGbvCyNgiwX
+ BVk2qM7eIYLhQbrCg5xrjbLzcDunmkKYpokkq/h8Ofj9ucNO6iFV1Z6p21j+
+ t7voTqP5D/uw6/P3Az6vx0tBfjH5uQUE/FlYluVUJIRpOtUKIUxMM/lugaxo
+ uFweXC7PcGzzpKpom3Y8WvX3+anBGEDysCvEa0Gq1VTNq7nceD2ZZLg9uF1u
+ NJfb+YCFhCxrKIqCqrqG4/kdqqptU1Vt65tPTP/H/NhjLNIWP+FRVG2FpmpL
+ VFUrVVWtxHnamVObqrpaVVVNPrV3VFXbue+puZ/45zb/D69n+b2nYzkjAAAA
+ AElFTkSuQmCC
--- /dev/null
+This package was debianized by Juan Carlos Torres <jucato@kdemail.net> on
+Sat, 31 Jul 2010 16:36:41 +0800.
+
+Upstream Author: Juan Carlos Torres <jucato@kdemail.net>
+
+Copyright: 2010 by Juan Carlos Torres <jucato@kdemail.net>
+
+License:
+
+ This package is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This package 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 General Public License
+ along with this package; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+On Debian systems, the complete text of the GNU General
+Public License can be found in `/usr/share/common-licenses/GPL'.
+
+The Debian packaging is (C) 2010, Juan Carlos Torres <jucato@kdemail.net> and
+is licensed under the GPL, see above.
--- /dev/null
+#!/bin/sh
+
+gtk-update-icon-cache -f /usr/share/icons/hicolor
+
+exit 0
--- /dev/null
+#!/usr/bin/make -f
+# -*- makefile -*-
+# Sample debian/rules that uses debhelper.
+# This file was originally written by Joey Hess and Craig Small.
+# As a special exception, when this file is copied by dh-make into a
+# dh-make output file, you may use that output file without restriction.
+# This special exception was added by Craig Small in version 0.37 of dh-make.
+
+# Uncomment this to turn on verbose mode.
+#export DH_VERBOSE=1
+
+APPNAME = flashstrobe
+
+builddir:
+ mkdir -p builddir
+
+builddir/Makefile: builddir
+ cd builddir && qmake-qt4 PREFIX=/usr ../$(APPNAME).pro
+
+build: build-stamp
+
+build-stamp: builddir/Makefile
+ dh_testdir
+ # Add here commands to compile the package.
+ #$(MAKE)
+ #docbook-to-man debian/flashstrobe.sgml > flashstrobe.1
+ cd builddir && $(MAKE)
+ touch $@
+
+clean:
+ dh_testdir
+ dh_testroot
+ rm -f build-stamp
+ # Add here commands to clean up after the build process.
+ # -$(MAKE) clean
+ rm -rf builddir
+ dh_clean
+
+install: build
+ dh_testdir
+ dh_testroot
+ dh_clean -k
+ dh_installdirs
+
+ # Add here commands to install the package into debian/flashstrobe.
+ cd builddir && $(MAKE) INSTALL_ROOT=$(CURDIR)/debian/$(APPNAME) install
+
+
+# Build architecture-independent files here.
+binary-indep: build install
+# We have nothing to do by default.
+
+# Build architecture-dependent files here.
+binary-arch: build install
+ dh_testdir
+ dh_testroot
+# dh_installchangelogs
+ dh_installdocs
+ dh_installexamples
+# dh_install
+# dh_installmenu
+# dh_installdebconf
+# dh_installlogrotate
+# dh_installemacsen
+# dh_installpam
+# dh_installmime
+# dh_python
+# dh_installinit
+# dh_installcron
+# dh_installinfo
+ dh_installman
+ dh_link
+ dh_strip --dbg-package=flashstrobe-dbg
+ dh_compress
+ dh_fixperms
+# dh_perl
+# dh_makeshlibs
+ dh_installdeb
+ dh_shlibdeps
+ dh_gencontrol
+ dh_md5sums
+ dh_builddeb
+
+binary: binary-indep binary-arch
+.PHONY: build clean binary-indep binary-arch binary install configure
--- /dev/null
+QMAKEVERSION = $$[QMAKE_VERSION]
+ISQT4 = $$find(QMAKEVERSION, ^[2-9])
+isEmpty( ISQT4 ) {
+error("Use the qmake include with Qt4.4 or greater, on Debian that is qmake-qt4");
+}
+
+TEMPLATE = subdirs
+SUBDIRS = src
+
--- /dev/null
+/*
+ Copyright (C) 2010 by Juan Carlos Torres <jucato@kdemail.net>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of
+ the License or (at your option) version 3 or any later version
+ accepted by the membership of KDE e.V. (or its successor appro-
+ ved by the membership of KDE e.V.), which shall act as a proxy
+ defined in Section 14 of version 3 of the license.
+
+ 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 General Public License
+ along with this program. If not, see http://www.gnu.org/licenses/.
+*/
+
+
+#include "camera.h"
+
+#include <QDBusConnection>
+#include <QDBusMetaType>
+#include <QDBusInterface>
+#include <QDebug>
+
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <sys/mman.h>
+#include <sys/ioctl.h>
+#include <linux/videodev2.h>
+
+/**
+ * This section sets up the necessary types and methods
+ * to create a D-Bus connection using Qt.
+ */
+
+#define HAL_CAM_SHUTTER_UDI "/org/freedesktop/Hal/devices/platform_cam_shutter"
+#define HAL_CAM_SHUTTER_STATE "button.state.value"
+
+Q_DECLARE_METATYPE(Property)
+Q_DECLARE_METATYPE(QList<Property>)
+
+const QDBusArgument & operator<<(QDBusArgument &arg, const Property &change)
+{
+ arg.beginStructure();
+ arg << change.name << change.added << change.removed;
+ arg.endStructure();
+ return arg;
+}
+const QDBusArgument & operator>>(const QDBusArgument &arg, Property &change)
+{
+ arg.beginStructure();
+ arg >> change.name >> change.added >> change.removed;
+ arg.endStructure();
+ return arg;
+}
+
+
+/**
+ * Camera class definition
+ */
+
+int Camera::m_fd = 0;
+char Camera::m_deviceName[15] = "";
+
+Camera::Camera(QObject* parent) : QObject(parent)
+{
+ m_buffers = NULL;
+ m_numBuffers = 0;
+}
+
+Camera::~Camera()
+{
+ if (m_fd != -1)
+ {
+ close();
+ }
+}
+
+/**
+ * Open and acquire a file descriptor for a file connected to
+ * the character device representing the camera, usually /dev/video0
+ */
+int Camera::open(char* device)
+{
+ struct stat st;
+
+ if (device == NULL)
+ {
+ qDebug() << "Device name not specified";
+ return Camera::GenericError;
+ }
+
+ memcpy(m_deviceName, device, sizeof(m_deviceName));
+
+ if (stat(m_deviceName, &st) == -1)
+ {
+ qDebug() << "Cannot identify device:" << m_deviceName;
+ return Camera::GenericError;
+ }
+
+ if (!S_ISCHR(st.st_mode))
+ {
+ qDebug() << "No such device: " << m_deviceName;
+ return Camera::GenericError;
+ }
+
+ m_fd = ::open(m_deviceName, O_RDWR | O_NONBLOCK, 0);
+
+ if (m_fd == -1)
+ {
+ qDebug() << "Cannot open device: " << m_deviceName;
+ return Camera::GenericError;
+ }
+
+ return m_fd;
+}
+
+int Camera::close()
+{
+ if (m_fd != -1)
+ {
+ if (::close(m_fd) == -1)
+ {
+ qDebug() << "Cannot close device: " << m_deviceName;
+ return Camera::GenericError;
+ }
+ }
+
+ m_fd = -1;
+
+ return Camera::NoError;
+}
+
+/**
+ * Initializes the camera by setting up the
+ * cropping rectangle, data format and memory buffers
+ *
+ * Based on @ref http://v4l2spec.bytesex.org/spec/capture-example.html
+ */
+int Camera::init()
+{
+ struct v4l2_cropcap cropcap;
+ struct v4l2_crop crop;
+ struct v4l2_format fmt;
+ struct v4l2_requestbuffers req;
+
+ // Set cropping rectangle
+ cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ if (ioctl(m_fd, VIDIOC_CROPCAP, &cropcap) != -1)
+ {
+ crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ crop.c = cropcap.defrect; // reset to default
+
+ if (ioctl(m_fd, VIDIOC_S_CROP, &crop) == -1)
+ {
+ qDebug() << "Unable to set cropping rectangle";
+ return Camera::GenericError;
+ }
+ }
+ else
+ {
+ qDebug() << "Unable to get crop capabilities";
+ return Camera::GenericError;
+ }
+
+ // Set data format
+ fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ fmt.fmt.pix.width = 640;
+ fmt.fmt.pix.height = 480;
+ fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;
+ fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
+
+ if (ioctl(m_fd, VIDIOC_S_FMT, &fmt) == -1)
+ {
+ qDebug() << "Unable to set data format";
+ return Camera::GenericError;
+ }
+
+ // Set up memory mapped buffers
+ req.count = 4;
+ req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ req.memory = V4L2_MEMORY_MMAP;
+
+ if (ioctl(m_fd, VIDIOC_REQBUFS, &req) == -1)
+ {
+ qDebug() << "No memory mapping support";
+ return Camera::GenericError;
+ }
+
+ if (req.count < 2)
+ {
+ qDebug() << "Insufficient buffer memory on device: " << m_deviceName;
+ return Camera::GenericError;
+ }
+
+ m_buffers = static_cast<buffer*>(calloc(req.count, sizeof(*m_buffers)));
+
+ if (!m_buffers)
+ {
+ qDebug() << "Out of memory";
+ return Camera::GenericError;
+ }
+
+ for (m_numBuffers = 0; m_numBuffers < req.count; ++m_numBuffers)
+ {
+ struct v4l2_buffer buf;
+
+ buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ buf.memory = V4L2_MEMORY_MMAP;
+ buf.index = m_numBuffers;
+
+ if (ioctl(m_fd, VIDIOC_QUERYBUF, &buf) == -1)
+ {
+ qDebug() << "Unable to query the status of buffer number: " << m_numBuffers;
+ return Camera::GenericError;
+ }
+
+ m_buffers[m_numBuffers].length = buf.length;
+ m_buffers[m_numBuffers].start = mmap(NULL, buf.length, PROT_READ | PROT_WRITE,
+ MAP_SHARED, m_fd, buf.m.offset);
+
+ if (m_buffers[m_numBuffers].start == MAP_FAILED)
+ {
+ qDebug() << "Unable to map memmory";
+ return Camera::GenericError;
+ }
+ }
+
+ return Camera::NoError;
+}
+
+int Camera::deinit()
+{
+ quint32 i;
+
+ // Unmap memory mapped buffers
+ if (m_numBuffers > 0)
+ {
+ for (i = 0; i < m_numBuffers; ++i)
+ {
+ if (munmap(m_buffers[i].start, m_buffers[i].length) == -1)
+ {
+ qDebug() << "Unable to unmap memory";
+ return Camera::GenericError;
+ }
+ }
+
+ m_numBuffers = 0;
+ }
+
+ // Free allocated memory
+ if (m_buffers)
+ {
+ free (m_buffers);
+ }
+
+ m_buffers = NULL;
+
+ return Camera::NoError;
+}
+
+int Camera::stream(bool stream)
+{
+ enum v4l2_buf_type type;
+
+ type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+ // Start or stop streaming
+ if (stream)
+ {
+ if (ioctl(m_fd, VIDIOC_STREAMON, &type) == -1)
+ {
+ qDebug() << "Camera::stream: Unable to start streaming";
+ return Camera::GenericError;
+ }
+ }
+ else
+ {
+ if (ioctl(m_fd, VIDIOC_STREAMOFF, &type) == -1)
+ {
+ qDebug() << "Camera::stream: Unable to stop streaming";
+ return Camera::GenericError;
+ }
+ }
+
+ return Camera::NoError;
+}
+
+/**
+ * Strobes the camera flash ONCE only
+ */
+int Camera::strobe()
+{
+ struct v4l2_control ctrl;
+
+ ctrl.id = V4L2_CID_FLASH_STROBE;
+
+ if (ioctl(m_fd, VIDIOC_S_CTRL, &ctrl) == -1)
+ {
+ qDebug() << "Cannot set flash";
+ return Camera::GenericError;
+ }
+
+ return Camera::NoError;
+}
+
+/**
+ * Sets the LED intensity for strobe (flash) mode only.
+ *
+ * Formulas:
+ * code = (intensity - 35)/15
+ * intensity = (code * 15) + 35
+ *
+ * Range: 215mA to 500mA
+ *
+ * @param intensity Intensity in mA
+ */
+int Camera::setFlashIntensity(int intensity)
+{
+ struct v4l2_control ctrl;
+ int intensityCode = (intensity - 35)/15;
+
+ // Set intensity to safe limits
+ if (intensityCode > 31)
+ {
+ intensityCode = 31;
+ }
+ else if (intensityCode < 0)
+ {
+ intensityCode = 0;
+ }
+
+ // Set flash intensity
+ ctrl.id = V4L2_CID_FLASH_INTENSITY;
+ ctrl.value = intensityCode;
+ if (ioctl(m_fd, VIDIOC_S_CTRL, &ctrl) == -1)
+ {
+ qDebug() << "Cannot set intensity";
+ return Camera::GenericError;
+ }
+
+ if (intensity > 0)
+ {
+ stream(true);
+ }
+ else
+ {
+ stream(false);
+ }
+
+ return Camera::NoError;
+}
+
+int Camera::flashIntensity() const
+{
+ struct v4l2_control ctrl;
+
+ ctrl.id = V4L2_CID_FLASH_INTENSITY;
+
+ if (ioctl(m_fd, VIDIOC_G_CTRL, &ctrl) == -1) {
+ qDebug() << "Cannot get intensity";
+ return Camera::GenericError;
+ }
+
+ return 35 + (ctrl.value * 15);
+}
+
+/**
+ * Sets the flash timeout. Works only in strobe (flash) mode.
+ * Formulas:
+ * 1 sec = 1,000 ms = 1,000,000 us (microseconds)
+ *
+ * Range: 54,600us to 820,000us (54.6ms to 820ms)
+ *
+ * @param timeout Timeout in microseconds
+ */
+int Camera::setTimeout(quint32 timeout)
+{
+ struct v4l2_control ctrl;
+
+ // Set timeout to safe limits
+ if (timeout < 54600)
+ {
+ timeout = 54600;
+ }
+ else if (timeout > 820000)
+ {
+ timeout = 820000;
+ }
+
+ // Set flash timeout
+ ctrl.id = V4L2_CID_FLASH_TIMEOUT;
+ ctrl.value = timeout;
+
+ if (ioctl(m_fd, VIDIOC_S_CTRL, &ctrl) == -1)
+ {
+ qDebug() << "Cannot set timeout";
+ return Camera::GenericError;
+ }
+
+ return Camera::NoError;
+}
+
+quint32 Camera::timeout() const
+{
+ struct v4l2_control ctrl;
+
+ ctrl.id = V4L2_CID_FLASH_TIMEOUT;
+
+ if (ioctl(m_fd, VIDIOC_G_CTRL, &ctrl) == -1) {
+ qDebug() << "Cannot get timeout";
+ return Camera::GenericError;
+ }
+
+ return ctrl.value;
+}
+
+/**
+ * Sets up a D-Bus connection to listen for camera shutter
+ * state changes and calls the slot @ref shutterPropertyModified()
+ */
+void Camera::registerDbusWatcher()
+{
+ qDBusRegisterMetaType< Property >();
+ qDBusRegisterMetaType< QList<Property> >();
+
+ QDBusConnection::systemBus().connect(
+ QString(),
+ HAL_CAM_SHUTTER_UDI,
+ "org.freedesktop.Hal.Device",
+ "PropertyModified",
+ this,
+ SLOT(shutterPropertyModified(int, QList<Property>)));
+}
+
+/**
+ * Checks for the status of the camera shutter using D-Bus and HAL
+ */
+bool Camera::isShutterOpen() const
+{
+ QDBusInterface propertyInterface("org.freedesktop.Hal",
+ HAL_CAM_SHUTTER_UDI,
+ "org.freedesktop.Hal.Device",
+ QDBusConnection::systemBus());
+
+ bool isOpen = propertyInterface.call("GetProperty",
+ HAL_CAM_SHUTTER_STATE).arguments().at(0).toBool();
+
+ return !isOpen;
+}
+
+/**
+ * Called when camera shutter state changes. Checks for the
+ * actual state using @ref isShutterOpen() and emits the
+ * @ref shutterStateChanged() signal
+ */
+void Camera::shutterPropertyModified(int /*numUpdates*/, QList< Property > /*updates*/)
+{
+ bool isOpen = isShutterOpen();
+
+ emit shutterStateChanged(isOpen);
+}
--- /dev/null
+/*
+ Copyright (C) 2010 by Juan Carlos Torres <jucato@kdemail.net>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of
+ the License or (at your option) version 3 or any later version
+ accepted by the membership of KDE e.V. (or its successor appro-
+ ved by the membership of KDE e.V.), which shall act as a proxy
+ defined in Section 14 of version 3 of the license.
+
+ 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 General Public License
+ along with this program. If not, see http://www.gnu.org/licenses/.
+*/
+
+
+#ifndef CAMERA_H
+#define CAMERA_H
+
+#include <QtCore/QObject>
+#include <QtCore/QString>
+#include <QtCore/QList>
+#include <QtDBus/QDBusArgument>
+
+struct buffer
+{
+ void* start;
+ size_t length;
+};
+
+struct Property
+{
+ QString name;
+ bool added;
+ bool removed;
+};
+
+const QDBusArgument& operator<<(QDBusArgument& arg, const Property& change);
+const QDBusArgument& operator>>(QDBusArgument& arg, const Property& change);
+
+/**
+ * @brief Qt-based class for accessing the N900 camera and flash LEDs
+ *
+ * This class provides easy access to the N900's camera and flash LED
+ * functionality, specifically initializing the camera and controlling
+ * the LED torch and flash modes. It also reports on the status of
+ * the camera shutter.
+ *
+ */
+// TODO: Implement torch functionality
+class Camera : public QObject
+{
+ Q_OBJECT
+
+ public:
+ /**
+ * Error codes for easier error message handling
+ */
+ enum ErrorCode
+ {
+ NoError = 0, /**< No error */
+ GenericError = -1 /**< Generic Error */
+ };
+
+ Camera(QObject* parent = 0);
+ ~Camera();
+
+ /**
+ * Opens a character device connected to the camera
+ * and gets a file descriptor.
+ *
+ * @param device Device name, normally /dev/video0
+ * @return @c int Identifying the file descriptor
+ * @return @c int -1 Of opening the device was unsuccessful
+ */
+ static int open(char* device);
+
+ /**
+ * Closes the character device connected to the camera.
+ *
+ * @return @c int 0 If closing the device was successful
+ * @return @c int -1 If closing the device was unsuccessful
+ */
+ int close();
+
+ /**
+ * Initializes the camera. This specifically does the following:
+ * @li Get and set the cropping properties
+ * @li Set the camera data format
+ * @li Allocate memory-mapped buffers
+ *
+ * @return @c int 0 If initialization was successful
+ * @return @c int -1 If initialization was unsuccessful
+ */
+ int init();
+
+ /**
+ * Deinitializes the camera, freeing any allocated memory
+ * used during initialization.
+ *
+ * @return @c int 0 If deinitialization was successful
+ * @return @c int -1 If deinitialization was unsuccessful
+ */
+ int deinit();
+
+ /**
+ * Returns the current set flash intensity. This
+ * is different from the torch intensity used in
+ * torch modes.
+ *
+ * @return @c int The current flash intensity
+ */
+ int flashIntensity() const;
+
+ /**
+ * Returns the strobe timeout. Used only in strobe mode.
+ *
+ * @return @c quint32 Current timeout in microseconds
+ */
+ quint32 timeout() const;
+
+ /**
+ * Convenience function to create a D-Bus connection
+ * to listen for changes in the camera shutter status.
+ */
+ void registerDbusWatcher();
+
+ /**
+ * Function to manually query the status of the camera
+ * shutter using D-Bus and HAL.
+ *
+ * @return @c true If the camera shutter is open
+ * @return @c false If the camera shutter is closed
+ */
+ bool isShutterOpen() const;
+
+ public slots:
+
+ /**
+ * Starts or stops camera data streaming. Used to block
+ * and unblock the camera while using the flash.
+ *
+ * @param stream Whether streaming is on (@c true) or off (@c false)
+ *
+ * @return @c int 0 If starting or stopping the stream was successful
+ * @return @c int 1 If starting or stopping the stream was unsuccessful
+ */
+ int stream(bool stream);
+
+ /**
+ * Flash the LED in strobe mode. This will only flash
+ * the LED once. Repetition must be controlled by the
+ * client of this class.
+ *
+ * @return @c int 0 If strobing was successful
+ * @return @c int -1 If strobing was unsuccessful
+ */
+ int strobe();
+
+ /**
+ * Sets the intensity of the LED in flash mode.
+ *
+ * @param intensity intensity in mA. Valid values range
+ * from 215 to 500 only
+ *
+ * @return @c int 0 If setting the flash intensity was successful
+ * @return @c int -1 If setting the flash intensity was unsuccessful
+ */
+ int setFlashIntensity(int intensity);
+
+ /**
+ * Sets the strobe timeout. Used only in strobe mode.
+ *
+ * @param timeout Timeout in microseconds. Valid values range
+ * from 54600 to 820000 only
+ */
+ int setTimeout(quint32 timeout);
+
+ /**
+ * Slot that is called when the camera shutter status
+ * changes, that is, when it is opened or closed. Internally
+ * calls @ref isShutterOpen() to get the current shutter
+ * status and emits the @ref shutterStateChanged() signal.
+ *
+ * @param numUpdates Unused parameter to match the signal signature
+ * @param updates Unused parameter to match the signal signature
+ */
+ void shutterPropertyModified(int numUpdates, QList<Property> updates);
+
+ signals:
+ /**
+ * Signal to notify change in the camera shutter status.
+ * Users of this class should connect to this to monitor
+ * the shutter state.
+ *
+ * @param open Determines whether the shutter is open (@c true)
+ * or closed (@c false).
+ */
+ void shutterStateChanged(bool open);
+
+ private:
+ static char m_deviceName[15];
+ static int m_fd;
+
+ quint32 m_numBuffers;
+ struct buffer* m_buffers;
+
+};
+
+#endif
--- /dev/null
+[Desktop Entry]
+Encoding=UTF-8
+Version=1.0
+Type=Application
+Name=Flash Strobe
+Exec=/usr/bin/flashstrobe
+Icon=flashstrobe
+X-HildonDesk-ShowInToolbar=true
+X-Osso-Type=application/x-executable
--- /dev/null
+/*
+ Copyright (C) 2010 by Juan Carlos Torres <jucato@kdemail.net>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of
+ the License or (at your option) version 3 or any later version
+ accepted by the membership of KDE e.V. (or its successor appro-
+ ved by the membership of KDE e.V.), which shall act as a proxy
+ defined in Section 14 of version 3 of the license.
+
+ 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 General Public License
+ along with this program. If not, see http://www.gnu.org/licenses/.
+*/
+
+/**
+ * Flash Strobe - Strobe light application for the N900
+ *
+ * Use the N900's flash LEDs as a strobe light. The user can set the
+ * frequency of the strobing in beats per minute (bpm). Additionally,
+ * the user can open any audio file to play in the background. The
+ * camera shutters need to be kept open. For best results, close any
+ * program using the camera.
+ *
+ * 18 Do not point the flash at anyone's eyes
+ */
+
+#include "camera.h"
+#include "mainwindow.h"
+
+#include <QApplication>
+#include <QMessageBox>
+
+int main(int argc, char **argv)
+{
+ QApplication app(argc, argv);
+ char device[15] = "/dev/video0";
+
+ // First check if there is even a camera at all. If none is found, notify the user and quit
+ if (Camera::open(device) == -1)
+ {
+ QMessageBox msg;
+ msg.setWindowTitle(QObject::tr("No Camera"));
+ msg.setText(QObject::tr("There was no camera found on this device. The program will now close"));
+ msg.exec();
+
+ return -1;
+ }
+ else
+ {
+ app.setApplicationName("flashstrobe");
+ MainWindow window;
+ window.show();
+
+ return app.exec();
+ }
+}
--- /dev/null
+/*
+ Copyright (C) 2010 by Juan Carlos Torres <jucato@kdemail.net>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of
+ the License or (at your option) version 3 or any later version
+ accepted by the membership of KDE e.V. (or its successor appro-
+ ved by the membership of KDE e.V.), which shall act as a proxy
+ defined in Section 14 of version 3 of the license.
+
+ 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 General Public License
+ along with this program. If not, see http://www.gnu.org/licenses/.
+*/
+
+
+#include "mainwindow.h"
+#include "camera.h"
+#include "musicplayer.h"
+
+#include <QFont>
+#include <QMessageBox>
+#include <QTimer>
+
+MainWindow::MainWindow(QWidget* parent): QWidget(parent)
+{
+ m_camera = new Camera(this);
+ m_timer = new QTimer(this);
+
+ //Setup the UI widgets and layout
+ m_ui = new Ui::MainWindow;
+ m_player = new MusicPlayer(this);
+
+ m_ui->setupUi(this);
+ m_ui->verticalLayout->insertWidget(0, m_player, 0);
+
+ m_ui->frequencyLabel->setFont(QFont("Sans Serif", 48));
+
+#ifdef Q_WS_MAEMO_5
+ setAttribute(Qt::WA_Maemo5PortraitOrientation,true);
+#endif
+
+ frequencyChanged(m_ui->frequencyDial->value());
+ connect(m_ui->frequencyDial, SIGNAL(valueChanged(int)), this, SLOT(frequencyChanged(int)));
+ connect(m_ui->strobeButton, SIGNAL(toggled(bool)), this, SLOT(toggleStrobe(bool)));
+ connect(m_camera, SIGNAL(shutterStateChanged(bool)), this, SLOT(toggleAppState(bool)));
+ connect(m_timer, SIGNAL(timeout()), m_camera, SLOT(strobe()));
+
+ // Start listening for camera shutter state changes
+ m_camera->registerDbusWatcher();
+
+ toggleAppState(m_camera->isShutterOpen());
+}
+
+MainWindow::~MainWindow()
+{
+ m_camera->deinit();
+}
+
+/**
+ * The user has changed the frequency, normally through the QDial.
+ * The flashing interval is computed as hertz (in milliseconds) while
+ * the actual flash LED timeout is computed as half of that (in microseconds).
+ *
+ * @param frequency Frequency in hertz
+ */
+void MainWindow::frequencyChanged(int frequency)
+{
+ m_ui->frequencyLabel->setText(QString("%1 bpm").arg(frequency*60));
+ m_camera->setTimeout((1000000/frequency)/2);
+ m_timer->setInterval(1000/frequency);
+}
+
+void MainWindow::toggleStrobe(bool checked)
+{
+ int timeout = m_ui->frequencyDial->value();
+ if (checked)
+ {
+ if (m_camera->init() == -1)
+ {
+ QMessageBox::information(this, tr("Camera Unavailable"),
+ tr("Please close any application using the camera"));
+ m_ui->strobeButton->setChecked(false);
+ }
+ else
+ {
+ m_camera->setTimeout((1000000/timeout)/2);
+ m_camera->setFlashIntensity(215);
+ m_timer->start(1000/timeout);
+ }
+ }
+ else
+ {
+ m_timer->stop();
+ m_camera->setTimeout(0);
+ m_camera->setFlashIntensity(0);
+ m_camera->deinit();
+ }
+}
+
+void MainWindow::toggleAppState(bool enable)
+{
+ m_ui->strobeButton->setEnabled(enable);
+ m_ui->frequencyDial->setEnabled(enable);
+
+ if (!enable)
+ {
+ QMessageBox::information(this, tr("Shutter Closed"),
+ tr("Please open the camera shutter before using"));
+
+ if (m_ui->strobeButton->isChecked())
+ {
+ m_ui->strobeButton->setChecked(false);
+ }
+ }
+}
--- /dev/null
+/*
+ Copyright (C) 2010 by Juan Carlos Torres <jucato@kdemail.net>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of
+ the License or (at your option) version 3 or any later version
+ accepted by the membership of KDE e.V. (or its successor appro-
+ ved by the membership of KDE e.V.), which shall act as a proxy
+ defined in Section 14 of version 3 of the license.
+
+ 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 General Public License
+ along with this program. If not, see http://www.gnu.org/licenses/.
+*/
+
+
+#ifndef MAINWINDOW_H
+#define MAINWINDOW_H
+
+#include <QWidget>
+
+class Camera;
+class MusicPlayer;
+
+class QTimer;
+
+#include "ui_mainwindow.h"
+
+/**
+ * @brief Flash Strobe main window
+ *
+ * This is the main window for Flash Strobe. This simple
+ * class creates the widgets for controlling the flash
+ * and adds a MusicPlayer widget for playing music.
+ */
+class MainWindow : public QWidget
+{
+ Q_OBJECT
+
+ public:
+ MainWindow(QWidget* parent = 0);
+ ~MainWindow();
+
+ public slots:
+ /**
+ * Slot for changing the strobing frequency. The actual
+ * frequency is computed to and displayed as beats per minute (bpm)
+ *
+ * @param frequency Strobing frequency in hertz. Valid range is
+ * from 2 to 8 Hz (120 to 600 bpm)
+ */
+ void frequencyChanged(int frequency);
+
+ /**
+ * Slot to turn strobing on or off. Strobing frequency is
+ * set by the user. Flash intensity is fixed at 215 mA. The
+ * strobing repetition is controlled by a QTimer.
+ *
+ * @param checked Determines if strobing is on (@c true) or off (@c false)
+ */
+ void toggleStrobe(bool checked);
+
+ /**
+ * Slot to enable or disable the widgets, depending on certain
+ * conditions, such as the camera shutter state. If the shutter
+ * is closed, widgets are disabled. The MusicPlayer widgets are
+ * controlled independently of the overall application state.
+ *
+ * @param enable Specifies if widgets are enabled (@c true) or disabled (@c false)
+ */
+ void toggleAppState(bool enable);
+
+ private:
+ Ui::MainWindow* m_ui;
+
+ int m_timeout;
+
+ Camera* m_camera;
+ MusicPlayer* m_player;
+
+ QTimer* m_timer;
+};
+
+#endif
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>MainWindow</class>
+ <widget class="QWidget" name="MainWindow">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>480</width>
+ <height>800</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Flash Strobe</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout" stretch="0,1,0">
+ <item>
+ <widget class="QLabel" name="frequencyLabel">
+ <property name="font">
+ <font>
+ <pointsize>48</pointsize>
+ </font>
+ </property>
+ <property name="text">
+ <string>Frequency</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QDial" name="frequencyDial">
+ <property name="minimum">
+ <number>2</number>
+ </property>
+ <property name="maximum">
+ <number>10</number>
+ </property>
+ <property name="pageStep">
+ <number>1</number>
+ </property>
+ <property name="value">
+ <number>6</number>
+ </property>
+ <property name="wrapping">
+ <bool>false</bool>
+ </property>
+ <property name="notchesVisible">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="strobeButton">
+ <property name="text">
+ <string>Strobe</string>
+ </property>
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
--- /dev/null
+/*
+ Copyright (C) 2010 by Juan Carlos Torres <jucato@kdemail.net>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of
+ the License or (at your option) version 3 or any later version
+ accepted by the membership of KDE e.V. (or its successor appro-
+ ved by the membership of KDE e.V.), which shall act as a proxy
+ defined in Section 14 of version 3 of the license.
+
+ 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 General Public License
+ along with this program. If not, see http://www.gnu.org/licenses/.
+*/
+
+
+#include "musicplayer.h"
+
+#include <MediaObject>
+#include <MediaSource>
+#include <AudioOutput>
+#include <VolumeSlider>
+
+#include <QPushButton>
+#include <QLineEdit>
+#include <QHBoxLayout>
+#include <QVBoxLayout>
+#include <QStyle>
+#include <QFileDialog>
+#include <QDesktopServices>
+
+MusicPlayer::MusicPlayer(QWidget* parent, Qt::WindowFlags flags): QWidget(parent, flags)
+{
+ // Create the Phonon objects and paths
+ m_player = new Phonon::MediaObject(this);
+ m_audio = new Phonon::AudioOutput(Phonon::MusicCategory, this);
+ Phonon::createPath(m_player, m_audio);
+
+ // Setup the UI widgets and layout
+ QPushButton* openButton = new QPushButton(this);
+ openButton->setIcon(style()->standardIcon(QStyle::SP_DialogOpenButton));
+
+ m_rewindButton = new QPushButton(this);
+ m_rewindButton->setIcon(style()->standardIcon(QStyle::SP_MediaSkipBackward));
+ m_rewindButton->setEnabled(false);
+
+ m_playButton = new QPushButton(this);
+ m_playIcon = style()->standardIcon(QStyle::SP_MediaPlay);
+ m_pauseIcon = style()->standardIcon(QStyle::SP_MediaPause);
+ m_playButton->setIcon(m_playIcon);
+ m_playButton->setCheckable(true);
+ m_playButton->setChecked(false);
+ m_playButton->setEnabled(false);
+
+ m_filenameEdit = new QLineEdit(this);
+ m_filenameEdit->setPlaceholderText(tr("Open audio file"));
+
+ QHBoxLayout* fileLayout = new QHBoxLayout;
+ fileLayout->addWidget(m_filenameEdit, 1);
+ fileLayout->addWidget(openButton, 0);
+
+ QHBoxLayout* buttonsLayout = new QHBoxLayout;
+ buttonsLayout->addWidget(m_rewindButton, 0);
+ buttonsLayout->addWidget(m_playButton, 0);
+
+ QVBoxLayout* mainLayout = new QVBoxLayout(this);
+ mainLayout->addLayout(fileLayout, 0);
+ mainLayout->addLayout(buttonsLayout, 0);
+
+ setLayout(mainLayout);
+
+ // Setup connections
+ connect(openButton, SIGNAL(clicked(bool)), this, SLOT(openFile()));
+ connect(m_filenameEdit, SIGNAL(textChanged(QString)), this, SLOT(enableButtons(QString)));
+ connect(m_playButton, SIGNAL(toggled(bool)), this, SLOT(playOrPause(bool)));
+ connect(m_rewindButton, SIGNAL(clicked(bool)), this, SLOT(rewind()));
+}
+
+MusicPlayer::~MusicPlayer()
+{
+
+}
+
+void MusicPlayer::openFile()
+{
+ QString filename = QFileDialog::getOpenFileName(this, tr("Open a music file"), QDesktopServices::storageLocation(QDesktopServices::MusicLocation));
+
+ if (!filename.isEmpty())
+ {
+ m_filenameEdit->setText(filename);
+ }
+}
+
+void MusicPlayer::playOrPause(bool checked)
+{
+ QString filename = m_filenameEdit->text();
+
+ // Only set the currentSource if the filename is different
+ // to prevent rewinding the file
+ if (filename != m_player->currentSource().fileName())
+ {
+ m_player->setCurrentSource(Phonon::MediaSource(filename));
+ }
+
+ // checked == true, play the file
+ if (checked)
+ {
+ m_playButton->setIcon(m_pauseIcon);
+ m_player->play();
+
+ // If the file cannot be played, do not play ("pause")
+ if (m_player->state() == Phonon::ErrorState)
+ {
+ m_playButton->setChecked(false);
+ }
+ }
+ else
+ {
+ m_playButton->setIcon(m_playIcon);
+ m_player->pause();
+ }
+}
+
+void MusicPlayer::enableButtons(QString filename)
+{
+ if (!filename.isEmpty())
+ {
+ m_rewindButton->setEnabled(true);
+ m_playButton->setEnabled(true);
+ }
+ else
+ {
+ m_rewindButton->setEnabled(false);
+ m_playButton->setEnabled(false);
+ }
+}
+
+void MusicPlayer::rewind()
+{
+ m_player->seek(0);
+}
+
+void MusicPlayer::setVolume(qreal volume)
+{
+ m_audio->setVolume(volume);
+}
+
+qreal MusicPlayer::volume() const
+{
+ return m_audio->volume();
+}
--- /dev/null
+/*
+ Copyright (C) 2010 by Juan Carlos Torres <jucato@kdemail.net>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of
+ the License or (at your option) version 3 or any later version
+ accepted by the membership of KDE e.V. (or its successor appro-
+ ved by the membership of KDE e.V.), which shall act as a proxy
+ defined in Section 14 of version 3 of the license.
+
+ 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 General Public License
+ along with this program. If not, see http://www.gnu.org/licenses/.
+*/
+
+
+#ifndef MUSICPLAYER_H
+#define MUSICPLAYER_H
+
+#include <QWidget>
+#include <QIcon>
+
+class QPushButton;
+class QIcon;
+class QLineEdit;
+
+namespace Phonon
+{
+ class MediaObject;
+ class AudioOutput;
+ class VolumeSlider;
+}
+
+/**
+ * @brief A simple Phonon-based music player widget
+ *
+ * This class implements a very simple widget for playing music
+ * using Phonon. Features include opening a file, playing/pausing,
+ * rewinding, and adjusting the volume.
+ */
+class MusicPlayer : public QWidget
+{
+ Q_OBJECT
+
+ public:
+ MusicPlayer(QWidget* parent = 0, Qt::WindowFlags flags = 0);
+ virtual ~MusicPlayer();
+
+ /**
+ * Returns the current volume level.
+ *
+ * @return @c qreal Volume level, between 0 and 1.0
+ */
+ qreal volume() const;
+
+ public slots:
+ /**
+ * Calls a QFileDialog for opening a file, initially
+ * from the platform's Music directory.
+ */
+ void openFile();
+
+ /**
+ * Plays or pauses the file currently contained in the
+ * selection. Also updates the player buttons to the
+ * appropriate state. For example, the Play button
+ * displays a pause icon if the file is currently playing,
+ * and a play icon if the file is paused.
+ *
+ * @param checked Determines whether to play (@c true) or
+ * pause (@false) the file
+ */
+ void playOrPause(bool checked);
+
+ /**
+ * Rewinds the current audio file to teh beginning.
+ */
+ void rewind();
+
+ /**
+ * Updates the state of the controls in the player depending on
+ * the state of the line edit indicating the audio file to play.
+ * If the line edit is not empty, the controls are enabled. Otherwise
+ * they are disabled.
+ *
+ * @param filename A string containing the contents of the line edit
+ */
+ void enableButtons(QString filename);
+
+ /**
+ * Sets the current volume level.
+ *
+ * @param volume Volume level, between 0 and 1.0
+ */
+ void setVolume(qreal volume);
+
+ private:
+ Phonon::MediaObject* m_player;
+ Phonon::AudioOutput* m_audio;
+
+ QPushButton* m_playButton;
+ QPushButton* m_rewindButton;
+
+ QIcon m_playIcon;
+ QIcon m_pauseIcon;
+
+ QLineEdit* m_filenameEdit;
+};
+
+#endif
--- /dev/null
+######################################################################
+# Automatically generated by qmake (2.01a) Sat Jul 31 16:32:47 2010
+######################################################################
+
+TEMPLATE = app
+TARGET = flashstrobe
+DEPENDPATH += .
+INCLUDEPATH += .
+QT += dbus phonon
+
+# Input
+HEADERS += camera.h mainwindow.h musicplayer.h
+FORMS += mainwindow.ui
+SOURCES += camera.cpp mainwindow.cpp musicplayer.cpp main.cpp
+
+unix {
+ #VARIABLES
+ isEmpty(PREFIX) {
+ PREFIX = /usr/local
+ }
+ BINDIR = $$PREFIX/bin
+ DATADIR =$$PREFIX/share
+
+ DEFINES += DATADIR=\\\"$$DATADIR\\\" PKGDATADIR=\\\"$$PKGDATADIR\\\"
+
+ #MAKE INSTALL
+
+ INSTALLS += target desktop service iconxpm icon26 icon48 icon64
+
+ target.path =$$BINDIR
+
+ desktop.path = $$DATADIR/applications/hildon
+ desktop.files += $${TARGET}.desktop
+
+ service.path = $$DATADIR/dbus-1/services
+ service.files += $${TARGET}.service
+
+ iconxpm.path = $$DATADIR/pixmaps
+ iconxpm.files += ../data/maemo/$${TARGET}.xpm
+
+ icon26.path = $$DATADIR/icons/hicolor/26x26/apps
+ icon26.files += ../data/26x26/$${TARGET}.png
+
+ icon48.path = $$DATADIR/icons/hicolor/48x48/apps
+ icon48.files += ../data/48x48/$${TARGET}.png
+
+ icon64.path = $$DATADIR/icons/hicolor/64x64/apps
+ icon64.files += ../data/64x64/$${TARGET}.png
+}