--- /dev/null
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
--- /dev/null
+VERSION = 0.2.5
+TARGET = dialer
+CONFIG += link_pkgconfig network opengl debug
+
+# DEFINES += WANT_DEBUG
+
+# Build configuration
+
+!win32-msvc*:QMAKE_CXXFLAGS += -g
+
+# Features
+DEFINES += DBUS_SERVICE_PATH=\\\"/com/tizen/${QMAKE_TARGET}\\\"
+DEFINES += DBUS_SERVICE=\\\"com.tizen.${QMAKE_TARGET}\\\"
+
+# Sound theme base dir
+DEFINES += SOUNDS_DIR=\\\"\"$$M_INSTALL_DATA/sounds\"\\\"
+
+M_DBUS_SERVICES_DIR = $$M_INSTALL_DATA/dbus-1/services
+
+# Defines for directories, for use in source code.
+# They work cross-platform like this.
+{
+ # APPLET_LIBS determines the location where all applet binaries are
+ DEFINES += APPLET_LIBS=\\\"\"$$M_APPLET_DIR\"\\\"
+
+ # APPLET_DATA determines where the .desktop files are located
+ DEFINES += APPLET_DATA=\\\"\"$$M_APPLET_DATA_DIR\"\\\"
+
+ # APPLET_SETTINGS_DIR determines where the applet global and instance settings files are located
+ DEFINES += APPLET_SETTINGS_DIR=\\\"\"$$M_APPLET_SETTINGS_DIR\"\\\"
+
+ # TRANSLATION_DIR determines the default translation path
+ DEFINES += TRANSLATION_DIR=\\\"\"$$M_TRANSLATION_DIR\"\\\"
+
+ # M_THEME_PRELOAD_DIR and M_THEME_POST_PRELOAD_DIR defines from where
+ # to get lists of images to be preloaded
+ DEFINES += M_THEME_PRELOAD_DIR=\\\"\"$$M_THEME_PRELOAD_DIR\"\\\"
+ DEFINES += M_THEME_POST_PRELOAD_DIR=\\\"\"$$M_THEME_POST_PRELOAD_DIR\"\\\"
+ DEFINES += M_DBUS_SERVICES_DIR=\\\"\"$$M_DBUS_SERVICES_DIR\"\\\"
+ DEFINES += M_XDG_DIR=\\\"\"$$M_XDG_DIR\"\\\"
+}
+
+# defines for dependencies
+!win32:!macx{
+ DEFINES += HAVE_CONTEXTSUBSCRIBER
+ DEFINES += HAVE_ICU
+ DEFINES += HAVE_GCONF
+ DEFINES += HAVE_GSTREAMER
+}
--- /dev/null
+#!/bin/bash
+
+# Until we have working systemd and are integrated with it
+# we are defering to crude hackery like this instead of relying
+# on applifed, which is rumored to be going the way of the dodo.
+
+# Call this script with any parameters supported by dialer (or
+# any Qt std args), for example:
+#
+# dialer-keepalive.sh -prestart -output-level debug
+
+while true
+do
+ /usr/bin/dialer "$@"
+done
--- /dev/null
+[Desktop Entry]
+Type=Application
+Name=Dialer
+Icon=icons-Applications-dialer
+Exec=dialer
+Comment=Tizen voice call application
+X-Desktop-File-Install-Version=0.16
--- /dev/null
+[D-BUS Service]
+Name=com.tizen.hfdialer
+Exec=/usr/bin/dialer -prestart
--- /dev/null
+TEMPLATE = subdirs
+CONFIG += ordered
+
+assets.files += *.png *.jpg
+assets.path += $${installPrefix}/usr/share/hfdialer/images
+
+INSTALLS += assets
--- /dev/null
+#!/bin/bash
+
+# Determine project name based on current directory
+#PROJECT=$(basename $PWD)
+PROJECT="tizen-handset-dialer"
+
+# NOTE: Don't like this? Then uncomment one of the following as appropriate
+#
+# Just set it explictly to whatever you like:
+# PROJECT=libseaside
+#
+# Parse it from any Qt *.pro or *.pri files in CWD:
+# PROJECT=$(grep -E "TARGET ?= ?" *.pr[io]|cut -d' ' -f3)
+
+# Grab most recent tag from git
+TAG=$(git describe --tags --abbrev=0)
+
+# If arg1 is provided, use it as commit/tag/tree-ish id to start
+# the archive creation from...
+[ "${1}z" != "z" ] && {
+ TAG=${1}
+ echo "Creating release starting from: ${TAG}"
+}
+
+VERSION=$(git describe --tags ${1})
+VERSION=${VERSION//version-/}
+VERSION=${VERSION//-g/+}
+VERSION=${VERSION//-/+git}
+
+# Set name of toplevel directory for the archive
+BASE_PREFIX="${PROJECT}-${VERSION}/"
+BRANDING_PREFIX="${PROJECT}-branding-tizen-${VERSION}/"
+
+# Set name of resulting release archive file
+BASE_ARCHIVE=${PROJECT}-${VERSION}.tar.bz2
+BRANDING_ARCHIVE=${PROJECT}-branding-tizen-${VERSION}.tar.bz2
+
+# Clean up any existing base package for this version
+[ -e ${BASE_ARCHIVE} ] && rm -rf ${BASE_ARCHIVE} &&
+ echo "Removed: ${BASE_ARCHIVE}"
+
+# Generate the base package release tar ball
+# NOTE: Becuase I used a git attribute that ignores the tizen theme dir
+# this archive will not include it... that's intentional!
+git archive --prefix=${BASE_PREFIX} ${TAG} | bzip2 -c -- > ${BASE_ARCHIVE} && {
+ echo "Created: ${BASE_ARCHIVE}"
+} || {
+ echo "Creation of release archive ${BASE_ARCHIVE} failed. Reason unknown."
+}
+
+# Clean up any existing branding package for this version
+[ -e ${BRANDING_ARCHIVE} ] && rm -rf ${BRANDING_ARCHIVE} &&
+ echo "Removed: ${BRANDING_ARCHIVE}"
+# Generate the branding package release tar ball
+pushd themes > /dev/null
+git archive --prefix=${BRANDING_PREFIX} ${TAG} tizen/ themes.pro | bzip2 -c -- > ../${BRANDING_ARCHIVE} && {
+ echo "Created: ${BRANDING_ARCHIVE}"
+} || {
+ echo "Creation of release archive ${BRANDING_ARCHIVE} failed. Reason unknown."
+}
+popd > /dev/null
--- /dev/null
+include (common.pri)
+TEMPLATE = subdirs
+CONFIG += ordered debug
+SUBDIRS = src qml dialerassets sounds
+
+#OTHER_FILES += dialer.service
+OTHER_FILES += *.service *.desktop *.sh
+M_INSTALL_BIN = /usr/bin
+M_INSATLL_DATA = /usr/share
+# Keepalive script
+keepalive_script.files = dialer-keepalive.sh
+keepalive_script.path += $$INSTALL_ROOT/usr/bin
+keepalive_script.CONFIG += no_check_exist
+
+# XDG Autostart
+#autostart_entry.files = dialer.desktop
+autostart_entry.files = dialer-prestart.desktop
+autostart_entry.path += /etc/xdg/autostart
+autostart_entry.CONFIG += no_check_exist
+
+# Desktop
+desktop_entry.files = dialer.desktop
+desktop_entry.path += $$INSTALL_ROOT/usr/share/applications
+desktop_entry.CONFIG += no_check_exist
+
+# DBus service
+dbus_service.files = dialer.service
+dbus_service.path += $$INSTALL_ROOT/usr/share$$M_DBUS_SERVICES_DIR
+
+# Documentation
+documentation.files = AUTHORS ChangeLog LICENSE README TODO
+documentation.path = $$INSTALL_ROOT/usr/share/hfdialer/
+
+INSTALLS += \
+ keepalive_script \
+ autostart_entry \
+ desktop_entry \
+ dbus_service \
+ documentation \
+
--- /dev/null
+/*
+ * dialer - QML User Interface Component
+ *
+ * Copyright (c) 2011, Tom Swindell.
+ *
+ * This program is licensed under the terms and conditions of the
+ * Apache License, version 2.0. The full text of the Apache License is at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ */
+
+import Qt 4.7
+
+Item {
+ id: root
+
+ anchors.fill: parent
+
+ states: [
+ State {
+ name: 'shown'
+ PropertyChanges {target: root; opacity: 1.0}
+ },
+ State {
+ name: 'hidden'
+ PropertyChanges {target: root; opacity: 0.0}
+ }
+ ]
+
+ Behavior on opacity {PropertyAnimation {duration: 250}}
+
+ Rectangle {
+ id: blind
+ anchors.fill: parent
+ color: 'black'
+ opacity: 0.7
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ onPressed: {
+ root.state = 'hidden'
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright 2012 Intel Corporation.
+ *
+ * This program is licensed under the terms and conditions of the
+ * Apache License, version 2.0. The full text of the Apache License is at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ */
+
+import Qt 4.7
+
+Item
+{
+ id: root
+ anchors.fill: parent
+ property variant call: null
+
+ state: 'disconnected'
+ onStateChanged: {
+ console.log("*** STATE IS now >> " + root.state);
+ }
+
+ onCallChanged: {
+ if(call) {
+ largeView.call = call;
+ console.log("*** QML *** :: CALL ITEM CHANGED, STATE: " + call.state);
+ root.state = call.state;
+
+ if (call.stateChanged)
+ {
+ call.stateChanged.connect(function(state) {
+ console.log("*** QML *** :: CALL ITEM STATE CHANGED: " + state);
+ console.log("");
+
+ root.state = state;
+ });
+ }
+ else
+ {
+ console.log("*** call.stateChanged doesn't exist.. setting state to disconnect");
+ // root.state = 'disconnected';
+ }
+ }
+ else
+ console.log("*** call doesn't exist.. setting to disconnect");
+ //root.state = 'disconnected';
+ }
+
+ states {
+ State {
+ name: 'active'
+ PropertyChanges {target: root; visible: true}
+ }
+
+ State {
+ name: 'held'
+ PropertyChanges {target: root; visible: true}
+ }
+
+ State {
+ name: 'dialing'
+ PropertyChanges {target: root; visible: true}
+ }
+
+ State {
+ name: 'alerting'
+ PropertyChanges {target: root; visible: true}
+ }
+
+ State {
+ name: 'incoming'
+ PropertyChanges {target: root; visible: true}
+ }
+
+ State {
+ name: 'waiting'
+ PropertyChanges {target: root; visible: true}
+ }
+
+ State {
+ name: 'disconnected'
+ PropertyChanges {target: root; visible: false}
+ }
+ }
+
+ Rectangle
+ {
+ id: background
+ anchors {top: parent.top; left: parent.left; right: parent.right; bottom: parent.bottom; topMargin: parent.height / 4; bottomMargin: parent.height / 5}
+
+ gradient: Gradient {
+ GradientStop {position: 0.0; color: '#4f4f4f'}
+ GradientStop {position: 1.0; color: '#000000'}
+ }
+
+ CallItemViewLarge
+ {
+ id: largeView
+ call: root.call //parent.call
+ state: root.state //parent.state
+ }
+}
+}
+
--- /dev/null
+/*
+ * Copyright 2012 Intel Corporation.
+ *
+ * This program is licensed under the terms and conditions of the
+ * Apache License, version 2.0. The full text of the Apache License is at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ */
+
+import Qt 4.7
+
+import 'javascripts/framework.js' as Support
+
+Item
+{
+ id: root
+
+ anchors.fill: parent
+
+ property variant call
+ property string callDuration: "00:00:00"
+ property string callerLabelText: "Unknown Caller"
+ state : 'disconnected'
+
+ onCallChanged: {
+ console.log("*** call changed in large, before if")
+ if(call && call.msisdn) {
+ console.log("*** in calllarge if >> " + call.state );
+
+ root.state = call.state
+
+ if (call.name) {
+ root.callerLabelText = call.name;
+
+ } else {
+
+ if (call.numberLen <= 10)
+ {
+ root.callerLabelText = call.msisdn[0] + call.msisdn[1] + call.msisdn[2] + '-' +
+ call.msisdn[3] + call.msisdn[4] + call.msisdn[5] + '-' +
+ call.msisdn[6] + call.msisdn[7] + call.msisdn[8] + call.msisdn[9];
+ }
+ else
+ root.callerLabelText = call.msisdn;
+ }
+ }
+ }
+
+ Timer {
+ interval: 1000; repeat: true; running: true;
+
+ onTriggered: {
+ if(call) {
+ if(call.duration && call.duration > 0)
+ {
+ callDuration = Support.friendlyInterval(call.duration);
+ }
+ }
+ }
+ }
+
+ states {
+ State {
+ name: 'active'
+ PropertyChanges {target: answerButton; visible: false}
+ PropertyChanges {target: hangupButton; visible: true; width: parent.width}
+ PropertyChanges {target: stateInd; text: qsTr("Active")}
+ }
+
+ State {
+ name: 'held'
+ PropertyChanges {target: answerButton; visible: false}
+ PropertyChanges {target: hangupButton; visible: true; width: parent.width}
+ PropertyChanges {target: stateInd; text: qsTr("Held")}
+ }
+
+ State {
+ name: 'dialing'
+ PropertyChanges {target: answerButton; visible: false}
+ PropertyChanges {target: hangupButton; visible: true; width: parent.width}
+ PropertyChanges {target: stateInd; text: qsTr("Dialing...")}
+ }
+
+ State {
+ name: 'alerting'
+ PropertyChanges {target: answerButton; visible: false}
+ PropertyChanges {target: hangupButton; visible: true; width: parent.width}
+ PropertyChanges {target: stateInd; text: qsTr("Alerting...")}
+ }
+
+ State {
+ name: 'incoming'
+ PropertyChanges {target: answerButton; visible: true}
+ PropertyChanges {target: hangupButton; visible: true; width: parent.width * 0.45}
+ PropertyChanges {target: stateInd; text: qsTr("Incoming...")}
+ }
+
+ State {
+ name: 'waiting'
+ PropertyChanges {target: answerButton; visible: false}
+ PropertyChanges {target: hangupButton; visible: true; width: parent.width}
+ PropertyChanges {target: stateInd; text: qsTr("Waiting...")}
+ }
+
+ State {
+ name: 'disconnected'
+ PropertyChanges {target: answerButton; visible: false}
+ PropertyChanges {target: hangupButton; visible: false}
+ PropertyChanges {target: stateInd; text: qsTr("Disconnected")}
+ }
+ }
+
+ Text
+ {
+ id: stateInd
+ anchors {top: parent.top; topMargin: 20; horizontalCenter: parent.horizontalCenter}
+ color: '#ffffff'
+ font {pixelSize: 38}
+ text: qsTr("Disconnected")
+ }
+
+ Text
+ {
+ id: callerInd
+ anchors {top: stateInd.bottom; topMargin: 20; horizontalCenter: parent.horizontalCenter}
+ color: '#ffffff'
+ font {pixelSize: 75}
+ text: callerLabelText
+ }
+
+ Image
+ {
+ id: clock
+ source: "/usr/share/hfdialer/images/ivi_icon-time.png"
+ anchors { right: callDurationInd.left; rightMargin: 2; bottom: callerInd.top}
+ width: 25
+ height: 25
+ smooth: true
+ }
+
+ Text
+ {
+ id: callDurationInd
+ anchors {bottom: callerInd.top; right: parent.right; topMargin: 10; rightMargin: parent.width * 0.2}
+ font {pixelSize: 22}
+ color: '#dfdfdf'
+ text: callDuration
+ }
+
+ Item
+ {
+ id: buttons
+ anchors {top: callerInd.bottom; topMargin: 15; left: parent.left; leftMargin: parent.width * 0.2; right: parent.right; rightMargin: parent.width * 0.2}
+
+ width: parent.width * 0.75
+ height: 72
+
+ Image
+ {
+ id: answerButton
+ height: 72
+ width: parent.width *0.45
+ anchors {left: parent.left;}
+ source: "/usr/share/hfdialer/images/ivi_btn-incomingcall-accept.png"
+
+ Image
+ {
+ width: 40; height: width
+ anchors.centerIn: parent
+ smooth: true
+ source: "/usr/share/hfdialer/images/ivi_icon-call.png"
+ }
+
+ MouseArea
+ {
+ anchors.fill: parent
+
+ onPressed: {
+ answerButton.source = "/usr/share/hfdialer/images/ivi_btn-incomingcall-accept-active.png"
+ }
+
+ onReleased: {
+ answerButton.source = "/usr/share/hfdialer/images/ivi_btn-incomingcall-accept.png"
+ }
+
+ onClicked: {
+ console.log("*** QML *** :: Answering call");
+ adapter.currentCall.answer();
+ }
+ }
+ }
+
+ Image
+ {
+ id: hangupButton
+ height: 72
+ width: parent.width * 0.45
+ anchors {right: parent.right;}
+ source: "/usr/share/hfdialer/images/ivi_btn-incomingcall-decline.png"
+
+ Image
+ {
+ width: 40; height: width
+ anchors.centerIn: parent
+ smooth: true
+ source: "/usr/share/hfdialer/images/ivi_icon-endcall.png"
+ }
+
+ MouseArea
+ {
+ anchors.fill: parent
+
+ onPressed: {
+ hangupButton.source = "/usr/share/hfdialer/images/ivi_btn-incomingcall-decline-active.png"
+ }
+
+ onReleased: {
+ hangupButton.source = "/usr/share/hfdialer/images/ivi_btn-incomingcall-decline.png"
+ }
+
+ onClicked: {
+ console.log("*** QML *** :: Hanging up call");
+ root.parent.state = 'disconnected'
+ adapter.hangupAll();
+ root.state = 'disconnected'
+ root.parent.parent.state = 'disconnected'
+ if (root.parent.parent.call)
+ root.parent.parent.call = null
+ if (root.call)
+ root.call = null
+ }
+ }
+ }
+ }
+}
+
--- /dev/null
+/*
+ * Copyright 2012 Intel Corporation.
+ *
+ * This program is licensed under the terms and conditions of the
+ * Apache License, version 2.0. The full text of the Apache License is at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ */
+
+import Qt 4.7
+Item {
+ id: root
+ property string deviceName
+ property string address
+ property string icon: ""
+ property string alias: ""
+ property string dbuspath: ""
+ property variant uuids: []
+
+ property int containerHeight: 80
+ height: containerHeight
+ width: parent.width
+ signal clicked()
+ signal close()
+ Image {
+ id: availableBluetoothItem
+ source: "/usr/share/hfdialer/images/ivi_btn-list-inactive.png"
+ anchors {fill: parent; leftMargin: 8; rightMargin: 8; topMargin: 8}
+
+ Text {
+ id: mainText
+
+ anchors {fill: parent; leftMargin: 15}
+ verticalAlignment: Text.AlignVCenter
+ height: availableBluetoothItem.containerHeight
+ font.pixelSize: parent.height / 2
+ style: Text.Outline
+ styleColor: "#3B3A39"
+ color: "white"
+ text: root.deviceName
+ elide: Text.ElideRight
+ }
+
+ }
+
+ MouseArea {
+ id: mArea
+ anchors.fill: parent
+
+ onPressed: {
+ availableBluetoothItem.source = "/usr/share/hfdialer/images/ivi_btn-list.png"
+ }
+ onReleased: {
+ availableBluetoothItem.source = "/usr/share/hfdialer/images/ivi_btn-list-inactive.png"
+ root.clicked()
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright 2012 Intel Corporation.
+ *
+ * This program is licensed under the terms and conditions of the
+ * Apache License, version 2.0. The full text of the Apache License is at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ */
+
+import Qt 4.7
+Item {
+ id: root
+ property string deviceName
+ property string address
+ property string icon: ""
+ property string alias: ""
+ property string dbuspath: ""
+ property variant uuids: []
+
+ property int containerHeight: 80
+ height: containerHeight
+ width: parent.width
+ signal clicked()
+ signal close()
+ Image {
+ id: availableBluetoothItem
+
+ source: "/usr/share/hfdialer/images/ivi_btn-list-inactive.png"
+
+ anchors {fill: parent; leftMargin: 8; rightMargin: 8; topMargin: 8}
+
+ Text {
+ id: mainText
+
+ anchors {left: parent.left; top: parent.top; bottom: parent.bottom; leftMargin: 15}
+ width: parent.width * 0.75
+
+ verticalAlignment: Text.AlignVCenter
+ height: availableBluetoothItem.containerHeight
+ font.pixelSize: parent.height / 2
+ style: Text.Outline
+ styleColor: "#3B3A39"
+ color: "white"
+ text: root.deviceName
+ elide: Text.ElideRight
+ }
+
+ Image {
+ id: closeButton
+ source: "/usr/share/hfdialer/images/ivi_icon-list-delete.png"
+ anchors { left: mainText.right; right: parent.right; top: parent.top; bottom: parent.bottom}
+
+ MouseArea {
+ id: closeArea
+ anchors.fill: parent
+
+ onPressed: {
+ closeButton.source = "/usr/share/hfdialer/images/ivi_icon-list-delete-active.png"
+ }
+
+ onReleased: {
+ closeButton.source = "/usr/share/hfdialer/images/ivi_icon-list-delete.png"
+ }
+
+ onClicked: {
+ console.log("CLOSE BUTTON CLICKED")
+ root.close()
+ }
+ }
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright 2012 Intel Corporation.
+ *
+ * This program is licensed under the terms and conditions of the
+ * Apache License, version 2.0. The full text of the Apache License is at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ */
+
+import Qt 4.7
+
+Item
+{
+ id: root
+
+ property bool numPadShown: true
+ property DialNumberEntry entry
+
+ height: parent.height
+ property real buttonHeight: (parent.height / 5) - 41;
+
+ function insertText(text)
+ {
+ entry.appendChar(text)
+ }
+
+ function show()
+ {
+ height = 72 * 5 + 4;
+ numPadShown = true;
+ }
+
+ function hide()
+ {
+ height = 72;
+ numPadShown = false;
+ }
+
+ function toggle()
+ {
+ if(numPadShown == true) {hide()} else {show()}
+ }
+
+ Behavior on height {PropertyAnimation {duration: 500; easing.type: Easing.OutBounce}}
+
+ Image
+ {
+ id: numpad
+ width: parent.width; height: childrenRect.height + 21;
+ source: "/usr/share/hfdialer/images/ivi_buttonarea.png"
+ Behavior on opacity {PropertyAnimation {duration: 500}}
+
+ Column
+ {
+ id: columnBox
+ anchors {top: parent.top; right: parent.right; left: parent.left; margins: 11}
+ spacing: 5
+
+ Row
+ {
+ width: parent.width
+ anchors {bottomMargin: 5}
+ spacing: 5
+
+ DialNumPadButton {
+ id: dial1
+ text: qsTr("1");
+ height: buttonHeight;
+ onClicked: root.insertText(text);
+ onPressAndHold: main.dialMailbox();
+ }
+ DialNumPadButton {
+ text: qsTr("2");
+ height: buttonHeight;
+ detail: qsTr("abc");
+ onClicked: root.insertText(text);
+ onPressAndHold: main.dialSpeedDial(1);
+ }
+ DialNumPadButton {
+ text: qsTr("3");
+ height: buttonHeight;
+ detail: qsTr("def");
+ onClicked: root.insertText(text);
+ onPressAndHold: main.dialSpeedDial(2);
+ }
+ }
+ Row
+ {
+ width: parent.width
+ anchors.horizontalCenter: parent.horizontalCenter
+ spacing: 5
+ DialNumPadButton {
+ text: qsTr("4");
+ height: buttonHeight;
+ detail: qsTr("ghi");
+ onClicked: root.insertText(text);
+ onPressAndHold: main.dialSpeedDial(3);
+ }
+ DialNumPadButton {
+ text: qsTr("5");
+ height: buttonHeight;
+ detail: qsTr("jkl");
+ onClicked: root.insertText(text);
+ onPressAndHold: main.dialSpeedDial(4);
+ }
+ DialNumPadButton {
+ text: qsTr("6");
+ height: buttonHeight;
+ detail: qsTr("mno");
+ onClicked: root.insertText(text);
+ onPressAndHold: main.dialSpeedDial(5);
+ }
+ }
+ Row
+ {
+ width: parent.width
+ anchors.horizontalCenter: parent.horizontalCenter
+ spacing: 5
+ DialNumPadButton {
+ text: qsTr("7");
+ height: buttonHeight;
+ detail: qsTr("pqrs");
+ onClicked: root.insertText(text);
+ onPressAndHold: main.dialSpeedDial(6);
+ }
+ DialNumPadButton {
+ text: qsTr("8");
+ height: buttonHeight;
+ detail: qsTr("tuv");
+ onClicked: root.insertText(text);
+ onPressAndHold: main.dialSpeedDial(7);
+ }
+ DialNumPadButton {
+ text: qsTr("9");
+ height: buttonHeight;
+ detail: qsTr("wxyz");
+ onClicked: root.insertText(text);
+ onPressAndHold: main.dialSpeedDial(8);
+ }
+ }
+ Row
+ {
+ width: parent.width
+ anchors.horizontalCenter: parent.horizontalCenter
+ spacing: 5
+ DialNumPadButton {
+ text: qsTr("*");
+ height: buttonHeight;
+ onClicked: root.insertText(text);
+ onPressAndHold: root.insertText("p");
+ }
+ DialNumPadButton {
+ text: qsTr("0");
+ height: buttonHeight;
+ detail: qsTr("+");
+ onClicked: root.insertText(text);
+ onPressAndHold: root.insertText("+");
+ }
+ DialNumPadButton {
+ text: qsTr("#");
+ height: buttonHeight;
+ onClicked: root.insertText(text);
+ onPressAndHold: root.insertText("w");
+ }
+ }
+
+
+
+ Row
+ {
+ id: actions
+ width: parent.width; height: dial1.height
+
+ spacing: 5
+ Image {
+ id: bDelete;
+ width: parent.width / 4; height: parent.height
+ source: "/usr/share/hfdialer/images/ivi_btn-delete.png"
+ Image {
+ anchors{ left: bDelete.left}
+ height: parent.height
+ width: parent.width
+ source: "/usr/share/hfdialer/images/ivi_icon-delete.png"
+ fillMode: Image.PreserveAspectFit
+ }
+ MouseArea
+ {
+ anchors.fill: parent
+ onClicked:
+ {
+ if(entry.textInput.text == entry.placeHolderText)
+ return;
+
+ entry.textInput.text = entry.textInput.text.substring(0, entry.textInput.text.length -1);
+ }
+
+ onPressAndHold: entry.clear();
+
+ }
+ }
+
+ Image {
+ id: bCall;
+
+ height: parent.height
+ width: parent.width - bDelete.width - 5
+ source: "/usr/share/hfdialer/images/ivi_btn-call.png"
+
+ Image {
+ anchors { centerIn: parent}
+ height: parent.height
+ width: parent.width
+ source: "/usr/share/hfdialer/images/ivi_icon-call.png"
+ fillMode: Image.PreserveAspectFit
+ }
+
+ MouseArea{
+ anchors.fill: parent
+ onClicked: {
+ if(entry.isBlank())
+ {
+ console.log("*** QML *** :: You can not dial without a number!");
+ main.showErrorMessage(qsTr("You can't dial without a number!"));
+ return;
+ }
+
+ if(main.dial(entry.textInput.text))
+ {
+ entry.clear();
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright 2012 Intel Corporation.
+ *
+ * This program is licensed under the terms and conditions of the
+ * Apache License, version 2.0. The full text of the Apache License is at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ */
+
+import Qt 4.7
+
+Item
+{
+ id: root
+
+ property Item numpad
+
+ property string text: ''
+ property string detail: ''
+
+ property int marginSize: 10
+
+ signal clicked
+ signal pressAndHold
+
+ width: (parent.width - marginSize) / 3; height: 72
+
+ SystemPalette {id: palette; colorGroup: SystemPalette.Active}
+
+ Image
+ {
+ id: buttonImg
+ anchors {fill: parent;}
+ source: "/usr/share/hfdialer/images/ivi_btn-numbers.png"
+
+ }
+
+ Text
+ {
+ width: parent.width
+ height: parent.height * 0.6
+ anchors {centerIn: parent}
+ text: parent.text
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+ font {pixelSize: parent.height / 2}
+ color: "white"
+ style: Text.Outline;
+ styleColor: "#3B3A39"
+ }
+
+ Text
+ {
+ anchors {top: parent.top; right: parent.right; topMargin: 21; rightMargin: 17}
+ text: parent.detail
+ font {pixelSize: 15}
+ color: "#D8D8D8"
+ }
+
+ MouseArea
+ {
+ anchors.fill: parent
+
+ onPressed: {
+ buttonImg.source = "/usr/share/hfdialer/images/ivi_btn-numbers-active.png"
+ }
+
+ onReleased: {
+ buttonImg.source = "/usr/share/hfdialer/images/ivi_btn-numbers.png"
+ }
+
+ onClicked: {
+ root.clicked();
+ }
+ onPressAndHold: root.pressAndHold();
+ }
+}
--- /dev/null
+/*
+ * dialer - QML User Interface Component
+ *
+ * Copyright (c) 2011, Tom Swindell.
+ *
+ * This program is licensed under the terms and conditions of the
+ * Apache License, version 2.0. The full text of the Apache License is at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ */
+
+import Qt 4.7
+
+Image
+{
+ property string placeHolderText: qsTr("Enter Number")
+ property TextInput textInput: input
+
+ id: root
+ source: "/usr/share/hfdialer/images/ivi_textarea.png"
+ function clear()
+ {
+ input.color = "#3B3A39";
+ input.text = placeHolderText;
+ }
+
+ function isBlank()
+ {
+ return (input.text == placeHolderText);
+ }
+
+ function appendChar(character)
+ {
+ if(input.text == placeHolderText) {input.text = character} else {input.text += character};
+ }
+
+ TextInput
+ {
+ id: input
+ anchors.centerIn: parent
+ color: "#3B3A39"
+ cursorVisible: false
+ activeFocusOnPress: false
+ inputMethodHints: Qt.ImhDialableCharactersOnly
+ font {pixelSize: 42}
+ text: placeHolderText
+
+ Component.onCompleted: forceActiveFocus();
+
+ onTextChanged: {
+ if(text.length == 0) root.clear();
+
+ if(text.length > placeHolderText.length && text.substr(0, placeHolderText.length) == placeHolderText)
+ {
+ text = text.substr(placeHolderText.length);
+ }
+
+ if(text.length < placeHolderText.length && placeHolderText.substr(0, text.length) == text)
+ {
+ text = placeHolderText;
+ }
+
+ if(text == placeHolderText)
+ {
+ color = "#3B3A39";
+ }
+ else
+ {
+ color = "#3B3A39";
+ }
+ }
+
+ onAccepted: {
+ main.dial(text)
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright 2012 Intel Corporation.
+ *
+ * This program is licensed under the terms and conditions of the
+ * Apache License, version 2.0. The full text of the Apache License is at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ */
+
+import Qt 4.7
+
+import Tizen.Bluetooth 0.0
+
+Item
+{
+ id: root
+ width: parent.width; height: parent.height
+
+ property alias activeCall: activeCallView.call
+ property alias callState: activeCallView.state
+
+ Keys.onEscapePressed: {
+ console.log("Escape Pressed");
+ Qt.quit()
+ }
+
+ onCallStateChanged: {
+ if (activeCallView.state != 'disconnected')
+ dialPage.state = 'activeCall'
+ else
+ dialPage.state = 'noCall'
+ }
+
+ Image
+ {
+ id: dialPage
+ anchors.fill: parent
+ source: "/usr/share/hfdialer/images/ivi-v1_ivi-background.jpg"
+ state: 'noCall'
+
+ DialNumberEntry
+ {
+ id: numberEntry
+ anchors {
+ top: parent.top; //bottom: numPad.top
+ left: parent.left; margins: 15 //right: parent.right
+ //margins: 10
+ }
+ width: parent.width * 0.60
+ height: parent.height / 4.5
+ }
+
+ DialNumPad
+ {
+ id: numPad
+ width: numberEntry.width
+ anchors {top: numberEntry.bottom; left: parent.left; bottom: parent.bottom; margins: 15}
+ entry: numberEntry
+ }
+ states{
+ State {
+ name: 'activeCall'
+ PropertyChanges {target: numPad; visible: false}
+ PropertyChanges {target: numberEntry; visible: false}
+ PropertyChanges {target: modemList; visible: false}
+ PropertyChanges {target: vertDivider; visible: false}
+ }
+ State {
+ name: 'noCall'
+ PropertyChanges {target: numPad; visible: true}
+ PropertyChanges {target: numberEntry; visible: true}
+ PropertyChanges {target: modemList; visible: true}
+ PropertyChanges {target: vertDivider; visible: true}
+ }
+
+
+ }
+
+ CallItemView
+ {
+ id: activeCallView
+ }
+
+ Rectangle {
+
+ id: vertDivider
+ anchors {left: numberEntry.right; margins: 8}
+ width: 4
+ height: parent.height
+ color: "#262626"
+
+ }
+
+ Rectangle {
+ id: modemList
+ anchors {left: vertDivider.right; right: parent.right; top: parent.top; bottom: parent.bottom}
+ color: "#51504F"
+
+ Text {
+ id: yourDevicesTxt
+ text: "Your Devices"
+ font.pixelSize: 42
+ color: "white"
+ anchors {top: parent.top; right: parent.right; left: parent.left; bottom: horizDivider1.top; leftMargin: 15}
+
+ }
+
+ Rectangle {
+ id: horizDivider1
+ anchors {left: parent.left; right: parent.right; topMargin: 8; bottomMargin: 8;}
+ y: 62
+ height: 3
+ color: "#B3BF3C"
+ }
+
+ Text {
+ id: moreDevicesTxt
+ text: "More Devices"
+ font.pixelSize: 42
+ color: "white"
+ anchors {right: parent.right; left: parent.left; bottom: horizDivider2.top; leftMargin: 15}
+ height: yourDevicesTxt.height
+ }
+
+ Rectangle {
+ id: horizDivider2
+ anchors {left: parent.left; right: parent.right; topMargin: 8; bottomMargin: 8;}
+ y: parent.height / 2
+ height: 3
+ color: "#B3BF3C"
+ }
+
+ Component.onCompleted: {
+ nearbyDevicesModel.discover(true);
+ console.log("Devices qml has been created, checking for BT: " + btDevicesModel.adapterPresent)
+
+ }
+
+ Component.onDestruction: {
+ nearbyDevicesModel.discover(false);
+ }
+
+ BluetoothDevicesModel {
+ id: btDevicesModel
+ property bool successFullPair: false
+ onDevicePaired: {
+
+ }
+ }
+
+ NearbyDevicesModel {
+ id: nearbyDevicesModel
+
+ property bool discovering: false
+
+ Component.onCompleted: {
+
+ }
+
+ onRequestConfirmation: {
+ console.log("onRequestConfirm called")
+ }
+
+ onRequestPasskey: {
+ console.log("onRequestPasskey called")
+
+ }
+
+ onRequestPidCode: {
+ console.log("onRequestPidCode called")
+ }
+
+ onAdapterPropertiesChanged: {
+
+ if(name == "Discovering") {
+ discovering = value;
+ }
+
+ }
+
+ onNearbyDeviceFound: {
+ //console.log("new device: " + nearbyDevicesModel.alias(index))
+ }
+
+ }
+
+ Flickable{
+ id: activeFlickable
+
+ anchors {top: horizDivider1.bottom; bottom: moreDevicesTxt.top; left: parent.left; right: parent.right}
+ clip: true
+ contentWidth: parent.width
+ contentHeight: parent.height
+ flickableDirection: Flickable.VerticalFlick
+
+ Column {
+ id: deviceList
+ width: parent.width
+ spacing: 2
+ Repeater {
+ model: btDevicesModel
+ delegate: DeviceDelegateActive {
+
+ deviceName: model.name
+ address: model.address
+ dbuspath: model.path
+ uuids: model.profiles
+ property BluetoothDevice device: btDevicesModel.device(dbuspath)
+
+ Connections {
+ target: btDevicesModel
+ onDevicePaired: {
+ console.log("new paired device address:" + device.address + "==" + model.address)
+ if(device.address == model.address){
+ device.trusted = true
+ }
+ }
+
+ onConnectedChanged: {
+ console.log("device CONNECTED, attempting to hook up audio")
+ // device.connectAudio()
+ // device.connectAudioSrc()
+ // device.connectInput()
+ }
+ }
+
+ onClose: {
+ console.log("unparing ...");
+ device.unpair();
+ }
+ }
+ }
+ }
+ }
+
+ Flickable{
+ id: modelFlickable
+ anchors {top: horizDivider2.bottom; bottom: parent.bottom; left: parent.left; right: parent.right}
+ clip: true
+ contentWidth: parent.width
+ contentHeight: parent.height
+ flickableDirection: Flickable.VerticalFlick
+
+ Column {
+ id: nearbyDevicesList
+ width: parent.width
+ height: parent.height / 2
+
+ Repeater {
+ id: modelRepeater
+ model: nearbyDevicesModel
+
+ onCountChanged: {
+ modelFlickable.contentHeight = (count * 80)
+ }
+
+ delegate: DeviceDelegate {
+ id: availableBluetoothItem
+ width: nearbyDevicesList.width
+ deviceName: name
+ icon: model.icon
+ alias: model.alias
+ anchors {margins: 8}
+
+ onClicked: {
+ console.log("BUTTON CLICKED bubbled up")
+ nearbyDevicesModel.discover(false)
+ nearbyDevicesModel.pair(model.address)
+ }
+
+
+ Connections {
+ target: nearbyDevicesModel
+ onRequestConfirmation: {
+ console.log("spawning request confirm dialog, device = " + device + " deviceName = " + deviceName)
+ if(device != deviceName) return;
+
+ dialogLoader.type = "confirmation"
+ dialogLoader.device = device
+ dialogLoader.code = code
+ dialogLoader.sourceComponent = requestConfirmDialogComponent
+
+ }
+
+ onRequestPasskey: {
+ console.log("spawning requestPasskeyDialog")
+ if(device != deviceName) return;
+
+ dialogLoader.type = "passkey"
+ dialogLoader.device = device
+ dialogLoader.sourceComponent = requestPasskeyDialogComponent
+
+ }
+
+ onRequestPidCode: {
+ console.log("spawning requestPidCodeDialog")
+ if(device != deviceName) return;
+
+
+ dialogLoader.type = "pidcode"
+ dialogLoader.device = device
+ dialogLoader.legacyPairing = model.legacyPairing
+ dialogLoader.sourceComponent = requestPidCodeDialogComponent
+
+ console.log(device + " model legacyPairing: " + model.legacyPairing)
+ }
+ }
+ }
+ }
+ }
+ }
+
+
+ Loader {
+ id: dialogLoader
+ anchors.fill: parent
+ property string type: "NULL"
+ property string device: ""
+ property string code: ""
+ property bool legacyPairing: false
+
+ onLoaded: {
+ console.log("LOADER LOADED! type = " + type)
+ if (type === "confirmation" )
+ {
+ item.deviceName = device
+ item.key = code
+ }
+ else if (type === "passkey" )
+ {
+ item.deviceName = device
+ }
+ else if (type === "pidcode" )
+ {
+ item.deviceName = device
+ item.legacyPairing = legacyPairing
+ }
+ }
+ }
+
+ Component {
+ id: requestPasskeyDialogComponent
+ RequestpasskeyDialog {
+ id: requestPasskeyDialog
+
+ onReplyRequestPasskey: {
+ dialogLoader.sourceComponent = undefined
+ nearbyDevicesModel.replyPasskey(reply)
+ }
+ }
+ }
+
+ Component {
+ id: requestPidCodeDialogComponent
+ RequestPidCodeDialog {
+ id: requestPidCodeDialog
+ onReplyRequestPidCode: {
+ dialogLoader.sourceComponent = undefined
+ nearbyDevicesModel.replyRequestPidCode(reply)
+ }
+ onCancelRequest: {
+ dialogLoader.sourceComponent = undefined
+ }
+ }
+ }
+
+ Component {
+ id: requestConfirmDialogComponent
+ RequestConfirmDialog {
+ id: requestConfirmDialog
+ onReplyRequestConfirmation: {
+ dialogLoader.sourceComponent = undefined
+ nearbyDevicesModel.replyRequestConfirmation(reply)
+ }
+ }
+ }
+ }
+ }
+}
+
--- /dev/null
+/*
+ * dialer - QML User Interface Component
+ *
+ * Copyright (c) 2011, Tom Swindell.
+ *
+ * This program is licensed under the terms and conditions of the
+ * Apache License, version 2.0. The full text of the Apache License is at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ */
+
+import Qt 4.7
+
+AbstractDialog {
+ id: root
+
+ property string mesg: ''
+
+ Rectangle {
+ id: dialog
+ width: parent.width * 0.8; height: 300;
+ anchors.centerIn: parent
+ color: "white"
+ radius: 15
+ smooth: true
+
+ Text {
+ id: mesgText
+ width: parent.width * 0.9
+ anchors.centerIn: parent
+ wrapMode: Text.WordWrap
+ color: "black"
+ font.pixelSize: 32
+ text: "<center>" + root.mesg + "</center>"
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright 2012 Intel Corporation.
+ *
+ * This program is licensed under the terms and conditions of the
+ * Apache License, version 2.0. The full text of the Apache License is at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ */
+
+import Qt 4.7
+
+Rectangle {
+ id: root
+ anchors.fill: parent
+ color: "#51504F"
+
+ property string deviceName: ""
+ property string key: ""
+ signal replyRequestConfirmation(bool reply)
+
+Column {
+ id: container
+ width: parent.width - 15
+ anchors {centerIn: parent}
+ spacing: 10
+ Component.onCompleted: {
+ console.log("request confirm dialog height: " + container.height + " width = " + container.width + " name = " + root.deviceName + " code = " + root.key)
+ }
+
+ Text {
+ id: textlabel
+ width: parent.width
+ height: paintedHeight
+ horizontalAlignment: Text.AlignHCenter
+ text: qsTr("Pair with %1 with key %2?").arg(root.deviceName).arg(root.key)
+ wrapMode: Text.WordWrap
+ font.pixelSize: 24
+ color: "White"
+ }
+
+ Row {
+ id: buttonGroup
+ anchors.horizontalCenter: parent.horizontalCenter
+ spacing: 10
+ height: 50
+
+ Image {
+ id: acceptButton
+ source: "/usr/share/hfdialer/images/ivi_btn-incomingcall-accept.png"
+ height: parent.height
+ width: root.width / 2 - 20
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: {
+ replyRequestConfirmation(true);
+ }
+ }
+ Text {
+ text: qsTr("Accept")
+ anchors.centerIn:parent
+ font.pointSize: 14
+ color: "white"
+ }
+ }
+
+ Image {
+ id: rejectButton
+ source: "/usr/share/hfdialer/images/ivi_btn-incomingcall-decline.png"
+
+ height: parent.height
+ width: root.width / 2 - 20
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: {
+ replyRequestConfirmation(false);
+ }
+ }
+
+ Text {
+ text: qsTr("Reject")
+ anchors.centerIn:parent
+ font.pointSize: 14
+ color: "white"
+ }
+ }
+ }
+
+}
+}
--- /dev/null
+/*
+ * Copyright 2012 Intel Corporation.
+ *
+ * This program is licensed under the terms and conditions of the
+ * Apache License, version 2.0. The full text of the Apache License is at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ */
+
+import Qt 4.7
+
+Rectangle {
+ id: root
+ anchors.fill: parent
+ color: "#51504F"
+
+ signal replyRequestPidCode(string reply)
+ signal cancelRequest()
+ property string deviceName
+ property string replyValue: legacyPairing ? "0000" : Math.floor(Math.random()*999999)
+ property bool legacyPairing: false
+
+Column {
+ width: parent.width - 15
+ anchors {centerIn: parent}
+ spacing: 10
+
+ Text {
+ id: textlabel
+ text: qsTr("Enter the following code on %1").arg(deviceName)
+ width: parent.width
+ wrapMode: Text.WordWrap
+ horizontalAlignment: Text.AlignHCenter
+ font.pixelSize: 24
+ color: "white"
+ }
+
+
+
+ Rectangle {
+ id: textInput
+ anchors.horizontalCenter: parent.horizontalCenter
+ height: 40
+ width: parent.width
+ color: "white"
+ radius: 5
+
+ TextEdit {
+ id: textInputField
+ anchors.centerIn: parent
+ width: parent.width
+ height: parent.height * 0.75
+ font.pixelSize: 24
+ color: "black"
+ text: replyValue
+ horizontalAlignment: Text.AlignHCenter
+ }
+ }
+
+ Row {
+ id: buttonGroup
+ anchors.horizontalCenter: parent.horizontalCenter
+ spacing: 10
+ width: parent.width
+ height: 50
+
+ Image {
+ id: acceptButton
+ source: "/usr/share/hfdialer/images/ivi_btn-incomingcall-accept.png"
+ width: buttonGroup.width / 2 - 5
+ height: parent.height
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: {
+ console.log(deviceName + " replying with key: " + textInputField.text)
+ replyRequestPidCode(textInputField.text);
+ }
+ }
+
+ Text {
+ id: acceptButtonText
+ text: qsTr("Accept")
+ anchors.centerIn:parent
+ horizontalAlignment: Text.AlignHCenter
+ font.pixelSize: 20
+ color: "white"
+ }
+ }
+
+ Image {
+ id: rejectButton
+ source: "/usr/share/hfdialer/images/ivi_btn-incomingcall-decline.png"
+ width: buttonGroup.width / 2 - 5
+ height: parent.height
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: {
+ console.log(deviceName + " replying with key: " + textInputField.text)
+ cancelRequest()
+ }
+ }
+
+ Text {
+ id: cancelButtonText
+ text: qsTr("Cancel")
+ anchors.centerIn:parent
+ horizontalAlignment: Text.AlignHCenter
+ font.pixelSize: 20
+ color: "white"
+ }
+ }
+
+
+ }
+
+}
+ ///we do this because this property is actually set post onCompleted:
+ onLegacyPairingChanged: {
+ console.log("legacy pair? " + legacyPairing)
+ if(!legacyPairing) {
+ replyRequestPidCode(textInputField.text);
+ console.log(deviceName + " replying with key: " + replyValue)
+ }
+ }
+
+}
--- /dev/null
+/*
+ * Copyright 2012 Intel Corporation.
+ *
+ * This program is licensed under the terms and conditions of the
+ * Apache License, version 2.0. The full text of the Apache License is at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ */
+
+import Qt 4.7
+
+Rectangle {
+ id: root
+ anchors.fill: parent
+ color: "#51504F"
+
+
+ signal replyRequestPasskey(int reply)
+ property string deviceName
+
+
+Column {
+ width: parent.width - 15
+ spacing: 10
+
+ Text {
+ id: textlabel
+ anchors.horizontalCenter: parent.horizontalCenter
+ text: qsTr("Enter passcode to use:")
+ wrapMode: Text.WordWrap
+ horizontalAlignment: Text.AlignHCenter
+ width: parent.width
+ font.pixelSize: 24
+ color: "white"
+ }
+
+ Rectangle {
+ id: textInput
+ anchors.horizontalCenter: parent.horizontalCenter
+ height: 40
+ width: parent.width
+ color: "white"
+ radius: 5
+
+ TextEdit {
+ id: textInputField
+ anchors.centerIn: parent
+ width: parent.width
+ height: parent.height * 0.75
+ font.pixelSize: 24
+ color: "black"
+ text: replyValue
+ horizontalAlignment: Text.AlignHCenter
+ }
+ }
+
+ Image {
+ id: acceptButton
+ source: "/usr/share/hfdialer/images/ivi_btn-incomingcall-accept.png"
+ anchors.horizontalCenter: parent.horizontalCenter
+ width: textInput.width
+ height: 50
+
+ MouseArea {
+ id: mouseArea
+ anchors.fill: parent
+
+ onClicked: {
+ nearbyDevicesModel.replyRequestPasskey(textInputField.text);
+ }
+ }
+ }
+
+ Text {
+ id: text
+ text: qsTr("Accept")
+ anchors.centerIn:parent
+ horizontalAlignment: Text.AlignHCenter
+ font.pixelSize: 20
+ color: "white"
+ }
+}
+}
--- /dev/null
+/*
+ * Generic Javascript Utility Functions
+ *
+ * Copyright (c) 2011, Tom Swindell.
+ *
+ * This program is licensed under the terms and conditions of the
+ * Apache License, version 2.0. The full text of the Apache License is at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ */
+
+Date.prototype.getFormat = function()
+{
+ return (this.getDate() < 10 ? '0' : '') + this.getDate() + '/' +
+ (this.getMonth() < 10 ? '0' : '') + this.getMonth() + '/' +
+ this.getFullYear() +
+ ' | ' +
+ (this.getHours() < 10 ? '0' : '') + this.getHours() + ':' +
+ (this.getMinutes() < 10 ? '0' : '') + this.getMinutes() + ':' +
+ (this.getSeconds() < 10 ? '0' : '') + this.getSeconds();
+}
+
+function friendlyInterval(duration)
+{
+ duration = Number(duration);
+ if(isNaN(duration)) duration = 0;
+
+ var hours = Math.floor(duration / 3600);
+ var minutes = Math.floor((duration % 3600) / 60);
+ var seconds = duration % 60;
+
+ return (hours < 10 ? '0' : '') + hours + ':' + (minutes < 10 ? '0' : '') + minutes + ':' + (seconds < 10 ? '0' : '') + seconds;
+}
+
+function friendlyDuration(start, end)
+{
+ var duration = Math.floor(((new Date(end)) - (new Date(start))) / 1000);
+ return friendlyInterval(duration);
+}
+
--- /dev/null
+/*
+ * Copyright 2012 Intel Corporation.
+ *
+ * This program is licensed under the terms and conditions of the
+ * Apache License, version 2.0. The full text of the Apache License is at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ */
+
+import Qt 4.7
+import com.tizen.hfdialer 1.0
+
+import 'javascripts/framework.js' as Support
+
+Item
+{
+ id: main
+
+ width: 1024; height: 600
+
+ Dialer { id: adapter }
+
+ Component.onCompleted: {
+ console.log("######## Completed loading component, initializing...");
+
+ adapter.incomingCall.connect(function()
+ {
+ var call = adapter.currentCall;
+
+ console.log("*** QML *** :: INCOMING CALL:" + call);
+ console.log("*** QML *** :: MSISDN: " + call.msisdn);
+ console.log("*** QML *** :: START: " + call.startedAt);
+ console.log("");
+
+ dialpage.activeCall = call
+
+ });
+
+ if(adapter.currentCall)
+ {
+ dialpage.activeCall = call
+ }
+
+ }
+
+ function showErrorMessage(mesg) {
+ mesgDialog.mesg = mesg;
+ mesgDialog.state = 'shown';
+ }
+
+ function dial(msisdn) {
+ if(msisdn.trim().length == 0)
+ {
+ console.log("*** QML *** :: You can't dial without a number!");
+ showErrorMessage(qsTr("No number specified!"));
+ return false;
+ }
+
+ if (!adapter.modemOnline)
+ {
+ console.log("*** QML *** :: modem is not available or powered down");
+ showErrorMessage(qsTr("modem is not available or powered down!"));
+ return false;
+ }
+
+ console.log("*** QML *** :: Attempting to dial MSISDN: " + msisdn);
+
+ dialpage.activeCall = {
+ state: 'dialing',
+ msisdn: msisdn
+ };
+
+ adapter.dial(msisdn);
+
+ return true;
+ }
+
+ function dialMailbox() {
+ if(adapter.mailbox) {
+ console.log("*** QML *** :: Attempting to call mailbox number: " + adapter.mailbox);
+ main.dial(adapter.mailbox);
+ } else {
+ console.log("*** QML *** :: No mailbox number defined!");
+ showErrorMessage(qsTr("No mailbox number defined."));
+ }
+ }
+
+ function dialSpeedDial(index) {
+ if(adapter.speedDial(index))
+ {
+ console.log("*** QML *** :: Calling speed dial " + index + ": " + adapter.speedDial(index));
+ main.dial(adapter.speedDial(index));
+ } else {
+ console.log("*** QML *** :: No speed dial number defined for: " + index);
+ showErrorMessage(qsTr("No speed dial for " + (index + 1)));
+ }
+ }
+
+ DialPage
+ {
+ id: dialpage
+ anchors.fill: parent
+ }
+
+ MessageDialog {
+ id: mesgDialog
+ state: 'hidden'
+ }
+}
+
--- /dev/null
+TEMPLATE = subdirs
+CONFIG += ordered
+
+qml.files = *.qml javascripts
+qml.path = $${installPrefix}/usr/share/hfdialer/qml
+
+INSTALLS += qml
--- /dev/null
+TEMPLATE = subdirs
+CONFIG += ordered
+
+sounds.files += *.wav
+sounds.path += $${installPrefix}/usr/share/hfdialer/sounds
+
+INSTALLS += sounds
--- /dev/null
+/*
+ * hfdialer - Hands Free Voice Call Manager
+ * Copyright (c) 2012, Intel Corporation.
+ *
+ * This program is licensed under the terms and conditions of the
+ * Apache License, version 2.0. The full text of the Apache License is at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ */
+
+#include "common.h"
+#include "callitem.h"
+#include "dialerapplication.h"
+#include "pacontrol.h"
+#include <QGraphicsItem>
+#include <QGraphicsWidget>
+#include <QDebug>
+
+#define DEFAULT_RINGTONE "ring-1.wav"
+
+CallItem::CallItem(const QString path, QObject *parent)
+ : QObject(parent),
+ m_path(path),
+ m_rtKey(new MGConfItem("/apps/dialer/defaultRingtone")),
+ m_isconnected(FALSE)//,
+ //m_ringtonefile("")
+{
+ TRACE
+
+ /* QString l_ringtoneFile = QString("%1/%2/stereo/%3")
+ .arg(SOUNDS_DIR)
+ .arg("tizen")
+ .arg(DEFAULT_RINGTONE);
+ */
+
+ QString l_ringtoneFile = QString("/usr/share/hfdialer/sounds/%1").arg(DEFAULT_RINGTONE);
+ QString l_rtKeyValue = m_rtKey->value(QVariant(l_ringtoneFile)).toString();
+
+ if (QFileInfo(l_rtKeyValue).exists()) {
+ /*
+ m_ringtonefile = l_ringtoneFile;
+ qDebug() << QString("CallItem: %1 using ringtone: %2")
+ .arg(m_path)
+ .arg(m_ringtonefile);
+ */
+ } else {
+ qWarning() << QString("CallItem: %1 ringtone not found: %2")
+ .arg(m_path)
+ .arg(l_rtKeyValue);
+ }
+
+ //m_ringtone->setMedia(QMediaContent(QUrl::fromLocalFile(m_ringtonefile)));
+ //m_ringtone->setVolume(100);
+
+ if (isValid())
+ init();
+}
+
+CallItem::~CallItem()
+{
+ TRACE
+/*
+ if (m_ringtone) {
+ disconnect(m_ringtone, SIGNAL(positionChanged(qint64)));
+ m_ringtone->stop();
+ delete m_ringtone;
+ m_ringtone = 0;
+ }
+*/
+ PAControl::instance()->unrouteAudio();
+
+ if (m_rtKey)
+ delete m_rtKey;
+ m_rtKey = 0;
+/*
+ if (m_peopleItem)
+ delete m_peopleItem;
+ m_peopleItem = 0;
+*/
+ // delete the callproxy object
+ if (callProxy())
+ delete callProxy();
+}
+
+void CallItem::init()
+{
+ TRACE
+ if (!m_path.isEmpty()) {
+ m_call = new CallProxy(m_path);
+ if (m_call->isValid()) {
+ // dynamic_cast<CallItemModel*>(model())->setCall(call);
+ connect(m_call,SIGNAL(stateChanged()),this,SLOT(callStateChanged()));
+ connect(m_call,SIGNAL(dataChanged()),this,SLOT(callDataChanged()));
+ connect(m_call,SIGNAL(multipartyChanged()),this,SLOT(callMultipartyChanged()));
+ } else
+ qCritical("Invalid CallProxy instance!");
+ } else
+ qCritical("Empty call path. Can not create CallProxy!");
+
+ //populatePeopleItem();
+
+ if (state() == STATE_INCOMING ||
+ state() == STATE_WAITING)
+ {
+
+ /*
+ // Start ringing
+ if (!m_isconnected && m_ringtone) {
+ connect(m_ringtone, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)),
+ SLOT(ringtoneStatusChanged(QMediaPlayer::MediaStatus)));
+ m_isconnected = TRUE;
+ m_ringtone->play();
+ }
+*/
+ }
+}
+
+bool CallItem::isValid()
+{
+ TRACE
+ return (!path().isEmpty());
+}
+
+bool CallItem::isValid() const
+{
+ TRACE
+ return (!path().isEmpty());
+}
+
+QString CallItem::path() const
+{
+ TRACE
+ return m_path;
+}
+
+bool CallItem::setPath(QString path)
+{
+ TRACE
+ if (!m_path.isEmpty()) {
+ qCritical("Path already set and can not be changed once it is set");
+ return false;
+ } else if (path.isEmpty()) {
+ qCritical("It makes no sense to set Path to an empty string!?!?");
+ return false;
+ }
+
+ m_path = path;
+
+ init();
+
+ return true;
+}
+
+void CallItem::setDirection(CallDirection direction)
+{
+ TRACE
+ // dynamic_cast<CallItemModel*>(model())->setDirection(direction);
+}
+
+QString CallItem::lineID() const
+{
+ TRACE
+ return m_call->lineID();
+}
+
+QString CallItem::name() const
+{
+ TRACE
+ return m_call->name();
+}
+
+CallState CallItem::state() const
+{
+ TRACE
+ CallState cs = STATE_NONE;
+ QString state = m_call->state();
+
+ if (state == "active")
+ cs = STATE_ACTIVE;
+
+ else if (state == "held")
+ cs = STATE_HELD;
+ else if (state == "dialing")
+ cs = STATE_DIALING;
+ else if (state == "alerting")
+ cs = STATE_ALERTING;
+ else if (state == "incoming")
+ cs = STATE_INCOMING;
+ else if (state == "waiting")
+ cs = STATE_WAITING;
+ else if (state == "disconnected")
+ cs = STATE_DISCONNECTED;
+
+ return cs;
+}
+
+CallDirection CallItem::direction() const
+{
+ TRACE
+ return DIRECTION_NONE;
+ //return dynamic_cast<const CallItemModel*>(model())->direction();
+}
+
+CallDisconnectReason CallItem::reason() const
+{
+ TRACE
+ return DISCONNECT_NONE;
+ //return dynamic_cast<const CallItemModel*>(model())->reasonType();
+}
+
+int CallItem::duration() const
+{
+ TRACE
+ return m_call->duration();
+}
+
+QDateTime CallItem::startTime() const
+{
+ TRACE
+ return m_call->startTime();
+}
+/*
+PeopleItem * CallItem::peopleItem() const
+{
+ TRACE
+ return m_peopleItem;
+}
+*/
+CallProxy* CallItem::callProxy() const
+{
+ TRACE
+ /*
+ if (model())
+ return dynamic_cast<const CallItemModel*>(model())->call();
+ else
+ return NULL;
+*/
+return m_call;
+}
+/*
+void CallItem::setPeopleItem(PeopleItem *person)
+{
+ TRACE
+ if (m_peopleItem)
+ delete m_peopleItem;
+ m_peopleItem = person;
+}
+*/
+void CallItem::click()
+{
+ TRACE
+
+ emit clicked();
+}
+
+void CallItem::silenceRingtone()
+{
+ TRACE
+/*
+ if(m_ringtone)
+ {
+ m_ringtone->stop();
+ }
+*/
+}
+
+void CallItem::callStateChanged()
+{
+ TRACE
+ /*
+ if (state() == STATE_INCOMING ||
+ state() == STATE_WAITING)
+ {
+ // Start ringing
+ if (!m_isconnected && m_ringtone) {
+ connect(m_ringtone, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)),
+ SLOT(ringtoneStatusChanged(QMediaPlayer::MediaStatus)));
+ m_isconnected = TRUE;
+ m_ringtone->play();
+ }
+ } else {
+ // Stop ringing
+ if (m_ringtone) {
+ disconnect(m_ringtone, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)));
+ m_isconnected = FALSE;
+ m_ringtone->stop();
+ }
+ }*/
+ emit stateChanged();
+}
+
+void CallItem::callDataChanged()
+{
+ TRACE
+ // populatePeopleItem();
+}
+
+void CallItem::callDisconnected(const QString &reason)
+{
+ TRACE
+ Q_UNUSED(reason);
+}
+
+/*
+QVariant CallItem::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &val)
+{
+ TRACE
+ if (change == QGraphicsItem::ItemSelectedHasChanged)
+ dynamic_cast<const CallItemModel*>(model())->setSelected(val.toBool());
+ return QGraphicsItem::itemChange(change, val);
+}
+*/
+/*
+void CallItem::populatePeopleItem()
+{
+ TRACE
+
+ QModelIndexList matches;
+ matches.clear();
+ int role = Seaside::SearchRole;
+ int hits = -1;
+
+ //% "Unknown Caller"
+ QString pi_name = qtTrId("xx_unknown_caller");
+ QString pi_photo = "icon-m-content-avatar-placeholder";
+ //% "Private"
+ QString pi_lineid = qtTrId("xx_private");
+
+ if (!lineID().isEmpty()) {
+ pi_lineid = stripLineID(lineID());
+ SeasideSyncModel *contacts = DA_SEASIDEMODEL;
+ QModelIndex first = contacts->index(0,Seaside::ColumnPhoneNumbers);
+ matches = contacts->match(first, role, QVariant(pi_lineid), hits);
+
+ QString firstName = QString();
+ QString lastName = QString();
+
+ if (!matches.isEmpty()) {
+ QModelIndex person = matches.at(0); //First match is all we look at
+ SEASIDE_SHORTCUTS
+ SEASIDE_SET_MODEL_AND_ROW(person.model(), person.row());
+
+ firstName = SEASIDE_FIELD(FirstName, String);
+ lastName = SEASIDE_FIELD(LastName, String);
+ pi_photo = SEASIDE_FIELD(Avatar, String);
+ } else if (!name().isEmpty()) {
+ // We don't have a contact, but we have a callerid name, let's use it
+ firstName = name();
+ }
+
+ if (lastName.isEmpty() && !firstName.isEmpty())
+ // Contacts first (common) name
+ //% "%1"
+ pi_name = qtTrId("xx_first_name").arg(firstName);
+ else if (firstName.isEmpty() && !lastName.isEmpty())
+ // BMC# 8079 - NW
+ // Contacts last (sur) name
+ //% "%1"
+ pi_name = qtTrId("xx_last_name").arg(lastName);
+ else if (!firstName.isEmpty() && !lastName.isEmpty())
+ // Contacts full, sortable name, is "Firstname Lastname"
+ //% "%1 %2"
+ pi_name = qtTrId("xx_first_last_name").arg(firstName)
+ .arg(lastName);
+
+ } else {
+ //% "Unavailable"
+ pi_lineid = qtTrId("xx_unavailable");
+ }
+
+ if (m_peopleItem != NULL)
+ delete m_peopleItem;
+ m_peopleItem = new PeopleItem();
+
+ m_peopleItem->setName(pi_name);
+ m_peopleItem->setPhoto(pi_photo);
+ m_peopleItem->setPhone(pi_lineid);
+}
+*/
+/*
+void CallItem::ringtoneStatusChanged(QMediaPlayer::MediaStatus status)
+{
+ TRACE
+ if (status == QMediaPlayer::EndOfMedia)
+ {
+ m_ringtone->setMedia(QMediaContent(QUrl::fromLocalFile(m_ringtonefile)));
+ m_ringtone->play();
+ }
+}
+*/
+bool CallItem::multiparty()
+{
+ TRACE
+ return false;
+ // return (isValid())?dynamic_cast<const CallItemModel*>(model())->multiparty():false;
+}
+
+void CallItem::callMultipartyChanged()
+{
+ TRACE
+ emit multipartyChanged();
+}
--- /dev/null
+/*
+ * hfdialer - Hands Free Voice Call Manager
+ * Copyright (c) 2012, Intel Corporation.
+ *
+ * This program is licensed under the terms and conditions of the
+ * Apache License, version 2.0. The full text of the Apache License is at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ */
+
+#ifndef CALLITEM_H
+#define CALLITEM_H
+
+#include <QString>
+#include <QDateTime>
+#include <QtDBus>
+//#include <QMediaPlayer>
+#include <MGConfItem>
+#include "callproxy.h"
+
+ enum CallState {
+ STATE_NONE = 0,
+ STATE_ACTIVE,
+ STATE_HELD,
+ STATE_DIALING,
+ STATE_ALERTING,
+ STATE_INCOMING,
+ STATE_WAITING,
+ STATE_DISCONNECTED,
+ STATE_LAST,
+ };
+
+ enum CallDirection {
+ DIRECTION_NONE = 0,
+ DIRECTION_IN,
+ DIRECTION_OUT,
+ DIRECTION_MISSED,
+ DIRECTION_LAST,
+ };
+
+ enum CallDisconnectReason {
+ DISCONNECT_NONE = 0,
+ DISCONNECT_LOCAL,
+ DISCONNECT_REMOTE,
+ DISCONNECT_NETWORK,
+ DISCONNECT_LAST,
+ };
+
+class CallItem: public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QString path READ path WRITE setPath)
+ Q_PROPERTY(QString lineID READ lineID)
+ Q_PROPERTY(QString name READ name)
+ Q_PROPERTY(CallState state READ state)
+ Q_PROPERTY(CallDirection direction READ direction WRITE setDirection)
+ Q_PROPERTY(CallDisconnectReason reason READ reason)
+ Q_PROPERTY(int duration READ duration)
+ Q_PROPERTY(QDateTime startTime READ startTime)
+ Q_PROPERTY(bool multiparty READ multiparty)
+
+ //Q_PROPERTY(PeopleItem* peopleItem READ peopleItem WRITE setPeopleItem)
+ Q_PROPERTY(CallProxy* callProxy READ callProxy)
+
+public:
+ CallItem(const QString path = QString(), QObject *parent = 0);
+ virtual ~CallItem();
+
+ QString path() const;
+ QString lineID() const;
+ QString name() const;
+ CallState state() const;
+ CallDirection direction() const;
+ CallDisconnectReason reason() const;
+ int duration() const;
+ QDateTime startTime() const;
+ //PeopleItem *peopleItem() const;
+ CallProxy *callProxy() const;
+ bool isValid();
+ bool isValid() const;
+ bool multiparty();
+
+public Q_SLOTS:
+ void init();
+ //void setPeopleItem(PeopleItem *person);
+ bool setPath(QString path); // Setting this will create the CallProxy
+ void setDirection(CallDirection direction);
+ void click();
+
+ void silenceRingtone();
+
+Q_SIGNALS:
+ // TODO: handle tap-and-hold
+ void clicked();
+ void stateChanged();
+ void dataChanged();
+ void multipartyChanged();
+
+private Q_SLOTS:
+ void callStateChanged();
+ void callDataChanged();
+ void callDisconnected(const QString &reason);
+// void ringtoneStatusChanged(QMediaPlayer::MediaStatus status);
+ void callMultipartyChanged();
+
+private:
+ //QVariant itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &val);
+ // void populatePeopleItem();
+
+ QString m_path;
+ //PeopleItem *m_peopleItem;
+ //QMediaPlayer *m_ringtone;
+ MGConfItem *m_rtKey;
+ bool m_isconnected;
+ QString m_ringtonefile;
+ CallProxy *m_call;
+
+ Q_DISABLE_COPY(CallItem)
+};
+
+#endif // CALLITEM_H
--- /dev/null
+/*
+ * hfdialer - Hands Free Voice Call Manager
+ * Copyright (c) 2012, Intel Corporation.
+ *
+ * This program is licensed under the terms and conditions of the
+ * Apache License, version 2.0. The full text of the Apache License is at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ */
+
+#include "common.h"
+#include "callmanager.h"
+//#include "resourceproxy.h"
+
+class CallManagerPrivate
+{
+public:
+ //ResourceProxy *resource;
+ QHash<QString, CallItem *> callItems;
+};
+
+CallManager::CallManager(const QString &modemPath, QObject *parent)
+ : OfonoVoiceCallManager(OfonoModem::AutomaticSelect, modemPath, parent),
+ d(new CallManagerPrivate)
+{
+ TRACE
+
+// d->resource = ResourceProxy::instance();
+
+ // Resource proxy binding
+// if (d->resource) {
+// connect(d->resource, SIGNAL(incomingResourceAcquired(CallItem *)),
+// SLOT(proceedIncomingCall(CallItem *)));
+// connect(d->resource, SIGNAL(incomingResourceDenied(CallItem *)),
+// SLOT(deniedIncomingCall(CallItem *)));
+// connect(d->resource, SIGNAL(incomingResourceLost(CallItem *)),
+// SLOT(lostIncomingCall(CallItem *)));
+
+// connect(d->resource, SIGNAL(dialResourceAcquired(const QString)),
+// SLOT(proceedCallDial(const QString)));
+// connect(d->resource, SIGNAL(dialResourceDenied()),
+// SLOT(deniedCallDial()));
+// connect(d->resource, SIGNAL(callResourceLost()),
+// SLOT(lostCallDial()));
+ // }
+
+ // Transform existing calls list, into list of CallItems
+ updateCallItems();
+
+ // Begin tracking calls
+ connect(this, SIGNAL(callAdded(const QString)),
+ this, SLOT(addCall(const QString)));
+ connect(this, SIGNAL(callRemoved(const QString)),
+ this, SLOT(removeCall(const QString)));
+
+ // Hook into parent class signals
+ connect(this, SIGNAL(dialComplete(const bool)),
+ this, SLOT(dialFinished(const bool)));
+ connect(this, SIGNAL(swapCallsComplete(const bool)),
+ this, SLOT(swapFinished(const bool)));
+ connect(this, SIGNAL(hangupAllComplete(const bool)),
+ this, SLOT(hangupAllFinished(const bool)));
+ connect(this, SIGNAL(sendTonesComplete(const bool)),
+ this, SLOT(sendTonesFinished(const bool)));
+ connect(this, SIGNAL(holdAndAnswerComplete(const bool)),
+ this, SLOT(holdAndAnswerFinished(const bool)));
+ connect(this, SIGNAL(transferComplete(const bool)),
+ this, SLOT(transferFinished(const bool)));
+ connect(this, SIGNAL(releaseAndAnswerComplete(const bool)),
+ this, SLOT(releaseAndAnswerFinished(const bool)));
+ connect(this, SIGNAL(privateChatComplete(const bool)),
+ this, SLOT(privateChatFinished(const bool)));
+ connect(this, SIGNAL(createMultipartyComplete(const bool)),
+ this, SLOT(createMultipartyFinished(const bool)));
+ connect(this, SIGNAL(hangupMultipartyComplete(const bool)),
+ this, SLOT(hangupMultipartyFinished(const bool)));
+
+ if (isValid())
+ emit connected();
+}
+
+CallManager::~CallManager()
+{
+ TRACE
+ // FIXME: Do something here!!!
+ qDebug() << QString("Destroying VoiceCallManager");
+ qDebug() << QString("Purging all CallItems");
+ foreach (CallItem *item, d->callItems) {
+ disconnect(item, SIGNAL(stateChanged()));
+ disconnect(item, SIGNAL(dataChanged()));
+ delete item;
+ }
+ if (d->callItems.size() > 0)
+ emit callsChanged();
+ d->callItems.clear();
+}
+
+QList<CallItem *> CallManager::getCallItems() const
+{
+ TRACE
+ return d->callItems.values();
+}
+
+int CallManager::callCount() const
+{
+ TRACE
+ qDebug()<<"call count is currently = "<<d->callItems.size();
+ return d->callItems.size();
+}
+
+int CallManager::multipartyCallCount() const
+{
+ TRACE
+ int call_count = 0;
+ foreach (CallItem *c, d->callItems) {
+ if(c->multiparty()) {
+ call_count++;
+ }
+ }
+ return call_count;
+}
+
+CallItem *CallManager::activeCall() const
+{
+ TRACE
+ if (d->callItems.size())
+ foreach (CallItem *c, d->callItems)
+ if (c->state() == STATE_ACTIVE)
+ return c;
+ return NULL;
+}
+
+CallItem *CallManager::heldCall() const
+{
+ TRACE
+ if (d->callItems.size())
+ foreach (CallItem *c, d->callItems)
+ if (c->state() == STATE_HELD)
+ return c;
+ return NULL;
+}
+
+CallItem *CallManager::dialingCall() const
+{
+ TRACE
+ if (d->callItems.size())
+ foreach (CallItem *c, d->callItems)
+ if (c->state() == STATE_DIALING)
+ return c;
+ return NULL;
+}
+
+CallItem *CallManager::incomingCall() const
+{
+ TRACE
+ if (d->callItems.size())
+ foreach (CallItem *c, d->callItems)
+ if (c->state() == STATE_INCOMING)
+ return c;
+ return NULL;
+}
+
+CallItem *CallManager::waitingCall() const
+{
+ TRACE
+ if (d->callItems.size())
+ foreach (CallItem *c, d->callItems)
+ if (c->state() == STATE_WAITING)
+ return c;
+ return NULL;
+}
+
+CallItem *CallManager::alertingCall() const
+{
+ TRACE
+ if (d->callItems.size())
+ foreach (CallItem *c, d->callItems)
+ if (c->state() == STATE_ALERTING)
+ return c;
+ return NULL;
+}
+
+void CallManager::setActiveCall(const CallItem &call)
+{
+ TRACE
+ //if (!call.isActive())
+ swapCalls();
+}
+/*
+void CallManager::dial(const PeopleItem *person)
+{
+ TRACE
+ dial(person->phone());
+}
+*/
+void CallManager::dial(const QString &number)
+{
+ TRACE
+ // Nothing to do if the modem is not powered up
+
+ if(!modem()->powered()) {
+ emit callsChanged();
+ return;
+ }
+
+ // If not online (flight mode?), check if the requested number is
+ // one of the allowed EmergencyNumbers, in which case, continue.
+ // Otherwise, notify that only Emergency calls are permitted.
+ if(!modem()->online()) {
+ if(modem()->powered() && !emergencyNumbers().contains(number)) {
+ emit callsChanged();
+ emit onlyEmergencyCalls();
+ return;
+ }
+ }
+
+// if (d->resource)
+// d->resource->acquireDialResource(number);
+ proceedCallDial(number);
+}
+
+void CallManager::privateChat(const CallItem &call)
+{
+ //TRACE
+ //OfonoVoiceCallManager::privateChat(call.path());
+}
+
+/*
+ * Resource Policy Manager Handler slots
+ */
+void CallManager::deniedCallDial()
+{
+ TRACE
+ qCritical() << QString("Denied: Dial resource");
+}
+
+void CallManager::lostCallDial()
+{
+ TRACE
+ qCritical() << QString("Lost: Dial resource");
+ hangupAll();
+}
+
+void CallManager::proceedCallDial(const QString number)
+{
+ TRACE
+ OfonoVoiceCallManager::dial(stripLineID(number), QString());
+}
+
+void CallManager::deniedCallAnswer()
+{
+ TRACE
+ qCritical() << QString("Denied: Call resource");
+ hangupAll();
+}
+
+void CallManager::deniedIncomingCall(CallItem *call)
+{
+ TRACE
+
+ qCritical() << QString("Denied: Incoming Call resource");
+ qDebug() << QString("Insert new CallItem %1").arg(call->path());
+ emit callsChanged();
+ emit incomingCall(call);
+}
+
+void CallManager::lostIncomingCall(CallItem *call)
+{
+ TRACE
+ Q_UNUSED(call)
+ qCritical() << QString("Lost: Incoming Call resource");
+}
+
+void CallManager::proceedIncomingCall(CallItem *call)
+{
+ TRACE
+ qDebug() << QString("Acquired: Incoming Call resource");
+ qDebug() << QString("Insert new CallItem %1").arg(call->path());
+ emit callsChanged();
+ emit incomingCall(call);
+}
+
+/*
+ * Private slots for async replies
+ */
+
+void CallManager::updateCallItems()
+{
+ TRACE
+ bool changed = false;
+
+ // If ofono call list is empty (no calls), empty our CallItem list too.
+ if (getCalls().isEmpty() && !d->callItems.isEmpty()) {
+ qDebug() << QString("Purging all CallItems");
+ foreach (CallItem *item, d->callItems)
+ delete item;
+ d->callItems.clear();
+ emit callsChanged();
+
+// if (d->resource)
+// d->resource->releaseResources();
+
+ return;
+ }
+
+ // Remove CallItems that are not in the ofono "calls" list
+ QMutableHashIterator<QString, CallItem*> iter(d->callItems);
+ while (iter.hasNext()) {
+ CallItem *item = iter.next().value();
+ // This item is not in the ofono list, remove it
+ if (!getCalls().contains(item->path())) {
+ qDebug() << QString("Removing old CallItem %1").arg(item->path());
+ delete item;
+ iter.remove();
+ changed = true;
+ }
+ }
+
+ // Insert new CallItems for paths in the ofono "calls" list we are missing
+ foreach (QString path, getCalls()) {
+ // Insert a new CallItem
+ if (!d->callItems.contains(path)) {
+ qDebug() << QString("Inserting new CallItem %1").arg(path);
+ CallItem *call = new CallItem(path);
+ connect (call, SIGNAL(stateChanged()),
+ this, SLOT(callStateChanged()));
+ connect (call, SIGNAL(multipartyChanged()),
+ this, SLOT(callMultipartyChanged()));
+ d->callItems.insert(path, call);
+
+ // NOTE: Must explicity bubble this up since incoming and waiting
+ // calls do not "changeState" unless they are handled or
+ // timeout
+ if ((call->state() == STATE_INCOMING) ||
+ (call->state() == STATE_WAITING)) {
+// if (d->resource)
+// d->resource->acquireIncomingResource(call);
+ proceedIncomingCall(call);
+ } else {
+ changed = true;
+ }
+ }
+ }
+
+ if (changed)
+ emit callsChanged();
+}
+
+void CallManager::addCall(const QString &path)
+{
+ TRACE
+ qDebug() << QString("CallAdded: \"%1\"").arg(path);
+ qDebug() <<"Call number is now "<< callCount();
+ updateCallItems();
+ emit callCountChanged(callCount());
+}
+
+void CallManager::removeCall(const QString &path)
+{
+ TRACE
+ qDebug() << QString("CallRemoved: \"%1\"").arg(path);
+ qDebug() <<"Call number is now "<< callCount();
+ updateCallItems();
+ emit callCountChanged(callCount());
+}
+
+void CallManager::dialFinished(const bool status)
+{
+ TRACE
+ qDebug() <<"Call number is now "<< callCount();
+
+ if (!status) {
+ qCritical() << QString("dial() Failed: %1 - %2")
+ .arg(errorName())
+ .arg(errorMessage());
+ // Fix BMC#10848:
+ // Notify that state of the call has changed when the dialing fails
+ emit callsChanged();
+ }
+}
+
+void CallManager::hangupAllFinished(const bool status)
+{
+ TRACE
+ if (!status)
+ qCritical() << QString("hangupAll() Failed: %1 - %2")
+ .arg(errorName())
+ .arg(errorMessage());
+
+ //If there are still calls for some reason, delete them.
+ if (callCount() > 0)
+ {
+ foreach (CallItem *item, d->callItems) {
+ disconnect(item, SIGNAL(stateChanged()));
+ disconnect(item, SIGNAL(dataChanged()));
+ delete item;
+ }
+
+ d->callItems.clear();
+ callCount();
+ emit callsChanged();
+ }
+callCount();
+}
+
+void CallManager::swapFinished(const bool status)
+{
+ TRACE
+ if (!status)
+ qCritical() << QString("swapCalls() Failed: %1 - %2")
+ .arg(errorName())
+ .arg(errorMessage());
+}
+
+void CallManager::holdAndAnswerFinished(const bool status)
+{
+ TRACE
+ if (!status)
+ qCritical() << QString("HoldAndAnswer() Failed: %1 - %2")
+ .arg(errorName())
+ .arg(errorMessage());
+}
+
+void CallManager::transferFinished(const bool status)
+{
+ TRACE
+ if (!status)
+ qCritical() << QString("Transfer() Failed: %1 - %2")
+ .arg(errorName())
+ .arg(errorMessage());
+}
+
+void CallManager::releaseAndAnswerFinished(const bool status)
+{
+ TRACE
+ if (!status)
+ qCritical() << QString("ReleaseAndAnswer() Failed: %1 - %2")
+ .arg(errorName())
+ .arg(errorMessage());
+}
+
+void CallManager::privateChatFinished(const bool status)
+{
+ TRACE
+ if (!status)
+ qCritical() << QString("PrivateChat() Failed: %1 - %2")
+ .arg(errorName())
+ .arg(errorMessage());
+}
+
+void CallManager::createMultipartyFinished(const bool status)
+{
+ TRACE
+ if (!status)
+ qCritical() << QString("CreateMultiparty() Failed: %1 - %2")
+ .arg(errorName())
+ .arg(errorMessage());
+}
+
+void CallManager::hangupMultipartyFinished(const bool status)
+{
+ TRACE
+ if (!status)
+ qCritical() << QString("HangupMultiparty() Failed: %1 - %2")
+ .arg(errorName())
+ .arg(errorMessage());
+}
+
+void CallManager::sendTonesFinished(const bool status)
+{
+ TRACE
+ if (!status)
+ qCritical() << QString("SendTones() Failed: %1 - %2")
+ .arg(errorName())
+ .arg(errorMessage());
+}
+
+void CallManager::callStateChanged()
+{
+ CallItem *call = dynamic_cast<CallItem *>(sender());
+ qDebug() << QString("%1 (%2) state has changed to %3")
+ .arg(call->path())
+ .arg(call->lineID())
+ .arg(call->state());
+ qDebug() << "number of calls "<< callCount();
+ emit callsChanged();
+}
+
+void CallManager::callMultipartyChanged()
+{
+ TRACE
+ emit callsChanged();
+ emit multipartyCallCountChanged(multipartyCallCount());
+}
--- /dev/null
+/*
+ * hfdialer - Hands Free Voice Call Manager
+ * Copyright (c) 2012, Intel Corporation.
+ *
+ * This program is licensed under the terms and conditions of the
+ * Apache License, version 2.0. The full text of the Apache License is at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ */
+
+#ifndef CALLMANAGER_H
+#define CALLMANAGER_H
+
+#include <ofonovoicecallmanager.h>
+
+#include "callitem.h"
+#include <QtDBus>
+
+class CallManager: public OfonoVoiceCallManager
+{
+ Q_OBJECT
+
+ Q_PROPERTY(int multipartyCallCount READ multipartyCallCount NOTIFY multipartyCallCountChanged)
+ Q_PROPERTY(int callCount READ callCount NOTIFY callCountChanged)
+
+public:
+ explicit CallManager(const QString &modemPath="", QObject *parent=0);
+ virtual ~CallManager();
+
+ /* Properties */
+ int multipartyCallCount() const;
+ int callCount() const;
+
+ // Extended version of OfonoVoiceCallManager::getCalls() that
+ // returns QList of CallItems rather than strings
+ Q_INVOKABLE QList<CallItem *> getCallItems() const;
+
+ Q_INVOKABLE CallItem *activeCall() const;
+ Q_INVOKABLE CallItem *heldCall() const;
+ Q_INVOKABLE CallItem *dialingCall() const;
+ Q_INVOKABLE CallItem *incomingCall() const;
+ Q_INVOKABLE CallItem *waitingCall() const;
+ Q_INVOKABLE CallItem *alertingCall() const;
+
+public Q_SLOTS:
+ void setActiveCall(const CallItem &call);
+
+ // Overloaded version of OfonoVoiceCallManager::dial() that
+ // takes a PeopleItem rather than number string and uses default
+ // as CLIR value
+ // void dial(const PeopleItem *person);
+
+ // Overloaded version of OfonoVoiceCallManager::dial() that
+ // assumes CLIR == default
+ void dial(const QString &number);
+
+ // Overloaded version of OfonoVoiceCallManager::privateChat() that
+ // takes a CallItem rather than path string
+ void privateChat(const CallItem &call);
+
+ // Push denied answer signal to upper layers from call proxy
+ void deniedCallAnswer();
+
+Q_SIGNALS:
+ // Abstracts both callAdded() and callRemoved() into a single event
+ void callsChanged();
+
+ void incomingCall(CallItem *call);
+ void incomingCall(QString path);
+ void callDisconnected(const CallItem &call);
+ void onlyEmergencyCalls();
+ void connected();
+ void multipartyCallCountChanged(const int &count);
+ void callCountChanged(const int &count);
+
+private Q_SLOTS:
+ void updateCallItems();
+ void addCall(const QString &path);
+ void removeCall(const QString &path);
+ void dialFinished(const bool status);
+ void hangupAllFinished(const bool status);
+ void swapFinished(const bool status);
+ void holdAndAnswerFinished(const bool status);
+ void transferFinished(const bool status);
+ void releaseAndAnswerFinished(const bool status);
+ void privateChatFinished(const bool status);
+ void createMultipartyFinished(const bool status);
+ void hangupMultipartyFinished(const bool status);
+ void sendTonesFinished(const bool status);
+ void callStateChanged();
+ void callMultipartyChanged();
+
+ // Handlers for Resource Policy Manager states and conditions
+ void proceedCallDial(const QString number);
+ void deniedCallDial();
+ void lostCallDial();
+ void proceedIncomingCall(CallItem *call);
+ void deniedIncomingCall(CallItem *call);
+ void lostIncomingCall(CallItem *call);
+
+private:
+ class CallManagerPrivate *d;
+
+ Q_DISABLE_COPY(CallManager)
+};
+
+#endif // CALLMANAGER_H
--- /dev/null
+/*
+ * hfdialer - Hands Free Voice Call Manager
+ * Copyright (c) 2012, Intel Corporation.
+ *
+ * This program is licensed under the terms and conditions of the
+ * Apache License, version 2.0. The full text of the Apache License is at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ */
+
+#include "common.h"
+#include "callproxy.h"
+#include "managerproxy.h"
+//#include "resourceproxy.h"
+
+CallProxy::CallProxy(const QString &callPath)
+ : org::ofono::VoiceCall(OFONO_SERVICE,
+ callPath,
+ QDBusConnection::systemBus()),
+ m_lineid(QString()),
+ m_state(QString()),
+ m_startTime(QDateTime()),
+ m_reason(QString()),
+ m_connected(false),
+ m_multiparty(false)
+{
+ TRACE
+
+ if (!org::ofono::VoiceCall::isValid())
+ {
+ qCritical() << QString("Failed to connect to %1 for call %2:\n\t%3")
+ .arg(staticInterfaceName())
+ .arg(callPath)
+ .arg(lastError().message());
+ }
+ else {
+ QDBusPendingReply<QVariantMap> reply;
+ QDBusPendingCallWatcher *watcher;
+
+ reply = GetProperties();
+ watcher = new QDBusPendingCallWatcher(reply);
+
+/*
+ connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)),
+ SLOT(getPropertiesFinished(QDBusPendingCallWatcher*)));
+*/
+
+ // Force this to be sync to ensure we have initial properties
+ watcher->waitForFinished();
+ getPropertiesFinished(watcher);
+
+ if (isValid()) {
+ connect(this,
+ SIGNAL(PropertyChanged(const QString&,const QDBusVariant&)),
+ SLOT(propertyChanged(const QString&,const QDBusVariant&)));
+ connect(this, SIGNAL(DisconnectReason(const QString&)),
+ SLOT(disconnectReason(const QString&)));
+ } else
+ qCritical() << QString("Invalid CallProxy instance: state == %1")
+ .arg(m_state);
+ }
+}
+
+CallProxy::~CallProxy()
+{
+ TRACE
+ // FIXME: Do something here!!!
+}
+
+bool CallProxy::isValid()
+{
+ TRACE
+ return (org::ofono::VoiceCall::isValid() &&
+ m_connected &&
+ (m_state != "disconnected"));
+}
+
+QString CallProxy::lineID() const
+{
+ TRACE
+ return m_lineid;
+}
+
+QString CallProxy::name() const
+{
+ TRACE
+ return m_name;
+}
+
+QString CallProxy::state() const
+{
+ TRACE
+ return m_state;
+}
+
+QDateTime CallProxy::startTime() const
+{
+ TRACE
+ return m_startTime;
+}
+
+int CallProxy::duration() const
+{
+ TRACE
+ if (m_startTime.isValid())
+ return m_startTime.secsTo(QDateTime::currentDateTime());
+ else
+ return 0;
+}
+
+QString CallProxy::reason() const
+{
+ TRACE
+ return m_reason;
+}
+
+bool CallProxy::multiparty() const
+{
+ TRACE
+ return m_multiparty;
+}
+
+void CallProxy::answer()
+{
+ TRACE
+
+// ResourceProxy *resource = ResourceProxy::instance();
+
+// connect(resource, SIGNAL(answerResourceAcquired()), SLOT(proceedCallAnswer()));
+// connect(resource, SIGNAL(answerResourceDenied()), SLOT(deniedCallAnswer()));
+
+// resource->acquireAnswerResource();
+
+proceedCallAnswer();
+}
+
+void CallProxy::proceedCallAnswer()
+{
+ TRACE
+
+// ResourceProxy *resource = ResourceProxy::instance();
+ QDBusPendingReply<QDBusObjectPath> reply;
+ QDBusPendingCallWatcher *watcher;
+
+ // disconnect(resource, SIGNAL(answerResourceAcquired()));
+ // disconnect(resource, SIGNAL(answerResourceDenied()));
+
+ reply = Answer();
+ watcher = new QDBusPendingCallWatcher(reply);
+
+ connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)),
+ SLOT(answerFinished(QDBusPendingCallWatcher*)));
+}
+
+void CallProxy::deniedCallAnswer()
+{
+ TRACE
+
+// ResourceProxy *resource = ResourceProxy::instance();
+
+// disconnect(resource, SIGNAL(answerResourceAcquired()));
+// disconnect(resource, SIGNAL(answerResourceDenied()));
+
+ // Hang up the incoming call, if resources to accept it are inavailabe
+ hangup();
+
+ emit ManagerProxy::instance()->callManager()->deniedCallAnswer();
+}
+
+void CallProxy::deflect(const QString toNumber)
+{
+ TRACE
+
+ QDBusPendingReply<QDBusObjectPath> reply;
+ QDBusPendingCallWatcher *watcher;
+
+ reply = Deflect(toNumber);
+ watcher = new QDBusPendingCallWatcher(reply);
+
+ connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)),
+ SLOT(deflectFinished(QDBusPendingCallWatcher*)));
+}
+
+void CallProxy::hangup()
+{
+ TRACE
+
+ QDBusPendingReply<> reply;
+ QDBusPendingCallWatcher *watcher;
+
+ reply = Hangup();
+ watcher = new QDBusPendingCallWatcher(reply);
+
+ connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)),
+ SLOT(hangupFinished(QDBusPendingCallWatcher*)));
+}
+
+void CallProxy::getPropertiesFinished(QDBusPendingCallWatcher *watcher)
+{
+ TRACE
+
+ QDBusPendingReply<QVariantMap> reply = *watcher;
+
+ if (reply.isError()) {
+ qCritical() << QString("Failed to connect to %1 for call %2:\n\t%3")
+ .arg(staticInterfaceName())
+ .arg(path())
+ .arg(lastError().message());
+ return;
+ }
+
+ QVariantMap props = reply.value();
+
+ QString l_start;
+
+ m_lineid = qdbus_cast<QString>(props["LineIdentification"]);
+ m_name = qdbus_cast<QString>(props["Name"]);
+ m_state = qdbus_cast<QString>(props["State"]);
+ l_start = qdbus_cast<QString>(props["StartTime"]);
+ m_multiparty = qdbus_cast<bool>(props["Multiparty"]);
+
+ setStartTimeFromString(l_start);
+
+ // Indicate for this instance, that we've actually performed at least
+ // one round trip call to this VoiceCall and we are in sync with it
+ m_connected = true;
+}
+
+void CallProxy::answerFinished(QDBusPendingCallWatcher *watcher)
+{
+ TRACE
+ QDBusPendingReply<QDBusObjectPath> reply = *watcher;
+ if (reply.isError())
+ qCritical() << QString("Answer() Failed: %1 - %2")
+ .arg(reply.error().name())
+ .arg(reply.error().message());
+}
+
+void CallProxy::deflectFinished(QDBusPendingCallWatcher *watcher)
+{
+ TRACE
+ QDBusPendingReply<QDBusObjectPath> reply = *watcher;
+ if (reply.isError())
+ qCritical() << QString("Deflect() Failed: %1 - %2")
+ .arg(reply.error().name())
+ .arg(reply.error().message());
+}
+
+void CallProxy::hangupFinished(QDBusPendingCallWatcher *watcher)
+{
+ TRACE
+ QDBusPendingReply<> reply = *watcher;
+ if (reply.isError())
+ qCritical() << QString("Hangup() Failed: %1 - %2")
+ .arg(reply.error().name())
+ .arg(reply.error().message());
+}
+
+void CallProxy::propertyChanged(const QString &in0, const QDBusVariant &in1)
+{
+ TRACE
+
+ if (in0 == "LineIdentification") {
+ m_lineid = qdbus_cast<QString>(in1.variant());
+ emit dataChanged();
+ } else if (in0 == "State") {
+ m_state = qdbus_cast<QString>(in1.variant());
+ emit stateChanged();
+ } else if (in0 == "StartTime") {
+ setStartTimeFromString(qdbus_cast<QString>(in1.variant()));
+ } else if (in0 == "Multiparty") {
+ m_multiparty = qdbus_cast<bool>(in1.variant());
+ emit multipartyChanged();
+ } else {
+ qDebug() << QString("Unexpected property \"%1\" changed...").arg(in0);
+ }
+}
+
+void CallProxy::disconnectReason(const QString &in0)
+{
+ TRACE
+ m_reason = in0;
+ emit callDisconnected(in0);
+}
+
+void CallProxy::setStartTimeFromString(const QString &val)
+{
+ TRACE
+ if (val.isEmpty())
+ return;
+
+ m_startTime = qDateTimeFromOfono(val);
+
+ if (!m_startTime.isValid())
+ m_startTime = QDateTime::QDateTime::currentDateTime();
+}
+
--- /dev/null
+/*
+ * hfdialer - Hands Free Voice Call Manager
+ * Copyright (c) 2012, Intel Corporation.
+ *
+ * This program is licensed under the terms and conditions of the
+ * Apache License, version 2.0. The full text of the Apache License is at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ */
+
+#ifndef CALLPROXY_H
+#define CALLPROXY_H
+
+#include "voicecall_interface.h"
+#include <QtDBus>
+#include <QDebug>
+
+#define OFONO_SERVICE "org.ofono"
+#define OFONO_MANAGER_PATH "/"
+
+#define DEFAULT_CLIR "default"
+
+class CallProxy: public org::ofono::VoiceCall
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QString lineID READ lineID)
+ Q_PROPERTY(QString name READ name)
+ Q_PROPERTY(QString state READ state)
+ Q_PROPERTY(QDateTime startTime READ startTime)
+ Q_PROPERTY(int duration READ duration)
+ Q_PROPERTY(QString reason READ reason)
+ Q_PROPERTY(bool multiparty READ multiparty)
+
+public:
+ CallProxy(const QString &callPath);
+ virtual ~CallProxy();
+ bool isValid();
+
+ QString lineID() const;
+ QString name() const;
+ QString state() const;
+ QDateTime startTime() const;
+ int duration() const;
+ QString reason() const;
+ bool multiparty() const;
+
+public Q_SLOTS:
+ // Answers the incoming call
+ // NOTE: only valid if state is incoming
+ void answer();
+
+ // Deflects the incoming or waiting call to number provided.
+ // NOTE: only valid if state is incoming or waiting
+ void deflect(const QString toNumber);
+
+ // Hangs up the voice call
+ void hangup();
+
+Q_SIGNALS:
+ void callDisconnected(const QString &reason);
+ void stateChanged();
+ void dataChanged();
+ void multipartyChanged();
+
+private Q_SLOTS:
+ // Slots to handle asyncronous DBus replies
+ void getPropertiesFinished(QDBusPendingCallWatcher *watcher);
+ void answerFinished(QDBusPendingCallWatcher *watcher);
+ void deflectFinished(QDBusPendingCallWatcher *watcher);
+ void hangupFinished(QDBusPendingCallWatcher *watcher);
+
+ // Slots to handle DBus signals from ofono
+ void propertyChanged(const QString &in0, const QDBusVariant &in1);
+ void disconnectReason(const QString &in0);
+
+ void proceedCallAnswer();
+ void deniedCallAnswer();
+
+private:
+ void setStartTimeFromString(const QString &val);
+
+private:
+ QStringList m_properties;
+ QString m_lineid;
+ QString m_name;
+ QString m_state;
+ QDateTime m_startTime;
+ QString m_reason;
+ bool m_connected;
+ bool m_multiparty;
+
+ Q_DISABLE_COPY(CallProxy)
+};
+
+#endif // CALLPROXY_H
--- /dev/null
+/*
+ * hfdialer - Hands Free Voice Call Manager
+ * Copyright (c) 2012, Intel Corporation.
+ *
+ * This program is licensed under the terms and conditions of the
+ * Apache License, version 2.0. The full text of the Apache License is at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ */
+
+#ifndef COMMON_H
+#define COMMON_H
+
+#ifndef WANT_DEBUG
+#define TRACE
+#else
+#include <QDebug>
+#define TRACE qDebug()<<QString("[%1] %2(): %3").arg(__FILE__).arg(__func__).arg(__LINE__);
+#endif
+
+/*
+ * Commonly used QRegExp expressions
+ */
+#include <QRegExp>
+#define MATCH_ANY(p) QRegExp(p,Qt::CaseInsensitive,QRegExp::FixedString)
+#define MATCH_ALL QRegExp()
+
+/*
+ * Commonly used values for MNotifications
+ */
+#define DEFAULT_AVATAR_ICON "icon-m-content-avatar-placeholder"
+#define NOTIFICATION_CALL_EVENT "x-nokia.call"
+
+/*
+ * Convienence macro for showing TBD message
+ */
+#define SHOW_TBD \
+ MainWindow *w = dynamic_cast<MainWindow *>(DialerApplication::instance()->activeApplicationWindow()); \
+ if (w) \
+ w->showTBD();
+
+/*
+ * Convience macro for checking available dialer modes
+ */
+#define CONFIG_KEY_TARGET_MODE "/apps/dialer/mode"
+#define MODE_HFP_STR "hfp"
+#define MODE_HANDSET_STR "handset"
+#define MODE_HFP_ENABLED DC->modes().contains(MODE_HFP_STR)
+#define MODE_HANDSET_ENABLED DC->modes().contains(MODE_HANDSET_STR)
+QString stripLineID(QString lineid);
+
+bool currentPageIs(int pagenum);
+
+#include <QDateTime>
+QDateTime qDateTimeFromOfono(const QString &val);
+
+#endif // COMMON_H
--- /dev/null
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
+<node>
+ <interface name="com.tizen.hfdialer" >
+ <method name="call" >
+ <arg direction="in" type="s" name="" />
+ </method>
+ <method name="accept"/>
+ </interface>
+</node>
--- /dev/null
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
+"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
+<node name="">
+ <interface name="org.ofono.CallHistory">
+ <method name="GetVoiceHistory">
+ <arg type="a(usqii)" direction="out"/>
+ <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="QArrayOfHistoryEvent"/>
+ </method>
+ <method name="SetVoiceHistoryRead"/>
+ <signal name="VoiceHistoryChanged">
+ <arg type="u"/>
+ </signal>
+ </interface>
+</node>
--- /dev/null
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
+"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
+<node name="">
+ <interface name="org.ofono.Manager">
+ <method name="GetModems">
+ <arg type="a(oa{sv})" direction="out"/>
+ <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="QArrayOfPathProperties"/>
+ </method>
+ <signal name="ModemAdded">
+ <arg type="o"/>
+ <arg type="a{sv}"/>
+ <annotation name="com.trolltech.QtDBus.QtTypeName.In1" value="QVariantMap"/>
+ </signal>
+ <signal name="ModemRemoved">
+ <arg type="o"/>
+ </signal>
+ </interface>
+</node>
--- /dev/null
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
+"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
+<node name="">
+ <interface name="org.ofono.Modem">
+ <method name="GetProperties">
+ <arg type="a{sv}" direction="out"/>
+ <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="QVariantMap"/>
+ </method>
+ <method name="SetProperty">
+ <arg type="s" direction="in"/>
+ <arg type="v" direction="in"/>
+ </method>
+ <signal name="PropertyChanged">
+ <arg type="s"/>
+ <arg type="v"/>
+ </signal>
+ </interface>
+ <interface name="org.ofono.MessageWaiting">
+ <method name="GetProperties">
+ <arg type="a{sv}" direction="out"/>
+ <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="QVariantMap"/>
+ </method>
+ <method name="SetProperty">
+ <arg type="s" direction="in"/>
+ <arg type="v" direction="in"/>
+ </method>
+ <signal name="PropertyChanged">
+ <arg type="s"/>
+ <arg type="v"/>
+ </signal>
+ </interface>
+ <interface name="org.ofono.CallVolume">
+ <method name="GetProperties">
+ <arg type="a{sv}" direction="out"/>
+ <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="QVariantMap"/>
+ </method>
+ <method name="SetProperty">
+ <arg type="s" direction="in"/>
+ <arg type="v" direction="in"/>
+ </method>
+ <signal name="PropertyChanged">
+ <arg type="s"/>
+ <arg type="v"/>
+ </signal>
+ </interface>
+ <interface name="org.ofono.NetworkRegistration">
+ <method name="GetProperties">
+ <arg type="a{sv}" direction="out"/>
+ <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="QVariantMap"/>
+ </method>
+ <method name="Register"/>
+ <method name="Deregister"/>
+ <method name="GetOperators">
+ <arg type="a(oa{sv})" direction="out"/>
+ <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="QArrayOfPathProperties"/>
+ </method>
+ <method name="Scan">
+ <arg type="a(oa{sv})" direction="out"/>
+ <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="QArrayOfPathProperties"/>
+ </method>
+ <signal name="PropertyChanged">
+ <arg type="s"/>
+ <arg type="v"/>
+ </signal>
+ </interface>
+</node>
--- /dev/null
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
+"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
+<node name="">
+ <interface name="org.ofono.NetworkOperator">
+ <method name="GetProperties">
+ <arg type="a{sv}" direction="out"/>
+ <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="QVariantMap"/>
+
+ </method>
+ <method name="Register"/>
+ <signal name="PropertyChanged">
+ <arg type="s"/>
+ <arg type="v"/>
+ </signal>
+ </interface>
+</node>
--- /dev/null
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
+"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
+<node name="">
+ <interface name="org.ofono.VoiceCall">
+ <method name="GetProperties">
+ <arg type="a{sv}" direction="out"/>
+ <annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="QVariantMap"/>
+ </method>
+ <method name="Deflect">
+ <arg type="s" direction="in"/>
+ </method>
+ <method name="Hangup"/>
+ <method name="Answer"/>
+ <signal name="PropertyChanged">
+ <arg type="s"/>
+ <arg type="v"/>
+ </signal>
+ <signal name="DisconnectReason">
+ <arg type="s"/>
+ </signal>
+ </interface>
+</node>
--- /dev/null
+/*
+ * Copyright (c) 2011, Tom Swindell.
+ *
+ * This program is licensed under the terms and conditions of the
+ * Apache License, version 2.0. The full text of the Apache License is at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ */
+
+#include "common.h"
+#include "dbusdialeradapter.h"
+#include "managerproxy.h"
+
+DBusDialerAdapter::DBusDialerAdapter(DialerApplication *application)
+ : QDBusAbstractAdaptor(application)
+{
+ TRACE
+}
+
+DBusDialerAdapter::~DBusDialerAdapter()
+{
+ TRACE
+}
+
+void DBusDialerAdapter::call(const QString &msisdn)
+{
+ TRACE
+
+ if(!ManagerProxy::instance()->callManager()) return;
+ ManagerProxy::instance()->callManager()->dial(msisdn);
+}
--- /dev/null
+/*
+ * Copyright (c) 2011, Tom Swindell.
+ *
+ * This program is licensed under the terms and conditions of the
+ * Apache License, version 2.0. The full text of the Apache License is at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ */
+#ifndef DBUSDIALERADAPTER_H
+#define DBUSDIALERADAPTER_H
+
+#include "dialerapplication.h"
+#include <QDBusAbstractAdaptor>
+
+class DBusDialerAdapter : public QDBusAbstractAdaptor
+{
+ Q_OBJECT
+ Q_CLASSINFO("D-Bus Interface", "com.tizen.hfdialer")
+
+public:
+ explicit DBusDialerAdapter(DialerApplication *application);
+ ~DBusDialerAdapter();
+
+Q_SIGNALS:
+
+public Q_SLOTS:
+ void call(const QString &msisdn);
+};
+
+#endif // DBUSDIALERADAPTER_H
--- /dev/null
+/*
+ * hfdialer - Hands Free Voice Call Manager
+ * Copyright (c) 2012, Intel Corporation.
+ *
+ * This program is licensed under the terms and conditions of the
+ * Apache License, version 2.0. The full text of the Apache License is at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ */
+
+#include "dbustypes.h"
+
+// Marshall the CallHistoryEvent data into a D-BUS argument
+QDBusArgument & operator << (QDBusArgument &argument,
+ const CallHistoryEvent &d)
+{
+ argument.beginStructure();
+ argument << d.id << d.lineid << d.type << d.start << d.end;
+ argument.endStructure();
+ return argument;
+}
+
+// Retrieve the CallHistoryEvent data from the D-BUS argument
+const QDBusArgument & operator >> (const QDBusArgument &argument,
+ CallHistoryEvent &d)
+{
+ argument.beginStructure();
+ argument >> d.id >> d.lineid >> d.type >> d.start >> d.end;
+ argument.endStructure();
+ return argument;
+}
+
+// Marshall the OfonoPathProperties data into a D-BUS argument
+QDBusArgument & operator << (QDBusArgument &argument,
+ const OfonoPathProperties &d)
+{
+ argument.beginStructure();
+ argument << d.path << d.properties;
+ argument.endStructure();
+ return argument;
+}
+
+// Retrieve the OfonoPathProperties data from the D-BUS argument
+const QDBusArgument & operator >> (const QDBusArgument &argument,
+ OfonoPathProperties &d)
+{
+ argument.beginStructure();
+ argument >> d.path >> d.properties;
+ argument.endStructure();
+ return argument;
+}
--- /dev/null
+/*
+ * hfdialer - Hands Free Voice Call Manager
+ * Copyright (c) 2012, Intel Corporation.
+ *
+ * This program is licensed under the terms and conditions of the
+ * Apache License, version 2.0. The full text of the Apache License is at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ */
+
+#ifndef DIALERDBUSTYPES_H
+#define DIALERDBUSTYPES_H
+
+#include <QtCore/QList>
+#include <QtCore/QMetaType>
+#include <QtDBus/QtDBus>
+
+struct CallHistoryEvent
+{
+ uint id;
+ QString lineid;
+ ushort type;
+ int start;
+ int end;
+};
+
+Q_DECLARE_METATYPE ( CallHistoryEvent )
+
+// Marshall the CallHistoryEvent data into a D-BUS argument
+QDBusArgument &operator<<(QDBusArgument &argument,
+ const CallHistoryEvent &mystruct);
+
+// Retrieve the CallHistoryEvent data from the D-BUS argument
+const QDBusArgument &operator>>(const QDBusArgument &argument,
+ CallHistoryEvent &mystruct);
+
+typedef QList< CallHistoryEvent > QArrayOfHistoryEvent;
+
+Q_DECLARE_METATYPE ( QArrayOfHistoryEvent )
+
+/*
+ * New DBus type needed for Ofono calls that expect an array of
+ * Object paths and that objects properties: "a(oa{sv})"
+ *
+ * Used in:
+ * org.ofono.VoiceCallManager.GetCalls()
+ * org.ofono.NetworkRegistraion.GetOperators()
+ * org.ofono.NetworkRegistration.Scan()
+ * org.ofono.ConnectionManager.GetContexts()
+ * org.ofono.MessageManager.GetMessages()
+ */
+struct OfonoPathProperties
+{
+ QDBusObjectPath path;
+ QVariantMap properties;
+};
+
+Q_DECLARE_METATYPE ( OfonoPathProperties )
+
+// Marshall the OfonoPathProperties data into a D-BUS argument
+QDBusArgument &operator<<(QDBusArgument &argument,
+ const OfonoPathProperties &mystruct);
+
+// Retrieve the CallHistoryEvent data from the D-BUS argument
+const QDBusArgument &operator>>(const QDBusArgument &argument,
+ OfonoPathProperties &mystruct);
+
+typedef QList< OfonoPathProperties > QArrayOfPathProperties;
+
+Q_DECLARE_METATYPE ( QArrayOfPathProperties )
+
+inline void registerMyDataTypes() {
+ qDBusRegisterMetaType< OfonoPathProperties >();
+ qDBusRegisterMetaType< QArrayOfPathProperties >();
+ qDBusRegisterMetaType< CallHistoryEvent >();
+ qDBusRegisterMetaType< QArrayOfHistoryEvent >();
+}
+
+#endif //DIALERDBUSTYPES_H
--- /dev/null
+/*
+ * hfdialer - Hands Free Voice Call Manager
+ * Copyright (c) 2012, Intel Corporation.
+ *
+ * This program is licensed under the terms and conditions of the
+ * Apache License, version 2.0. The full text of the Apache License is at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ */
+
+#include "common.h"
+#include "dbustypes.h"
+#include "dialerapplication.h"
+#include "dialercontext.h"
+#include "dbusdialeradapter.h"
+#include "pacontrol.h"
+#include "qmlmainwindow.h"
+#include <QtGui>
+#include <QDebug>
+#include <QApplication>
+
+#define OFONO_VOICECALLMANAGER_INTERFACE "org.ofono.VoiceCallManager"
+
+DialerApplication::DialerApplication(int &argc, char **argv)
+ : QApplication(argc, argv)
+{
+ TRACE
+ init();
+}
+
+void DialerApplication::releasePrestart()
+{
+ TRACE
+ // Now is the time for set up and display of information
+ // that needs to be done to allow the dialeror other
+ // pages to display correctly when opened. GenericPage has a
+ // activateWidgets() method for common setup and
+ // each Page type (dialer, people, favorites, etc) can also
+ // implement the method for Page specific setup and signal
+ // and slot connections
+
+
+}
+
+void DialerApplication::restorePrestart()
+{
+ TRACE
+ // Now is the time for clean up and resetting an information
+ // that needs to be done to allow the dialer pages to display
+ // correctly when reopened. GenericPage has a
+ // deactivateAndResetWidgets() method for common setup and
+ // each Page type (dialer, people, favorites, etc) can also
+ // implement the method for Page specific clean up
+
+ // Call the default implementation to hide the window.
+}
+
+void DialerApplication::connectAll()
+{
+ TRACE
+
+ ManagerProxy *m_manager = ManagerProxy::instance();
+ if (m_manager->modem() &&
+ m_manager->modem()->isValid() &&
+ !m_manager->modem()->path().isEmpty())
+ {
+ qDebug() << QString("Connecting to CallManager....");
+ m_manager->setNetwork(m_manager->modem()->path());
+ m_manager->setCallManager(m_manager->modem()->path());
+ m_manager->setVolumeManager(m_manager->modem()->path());
+ m_manager->setVoicemail(m_manager->modem()->path());
+
+ connect(m_manager->network(), SIGNAL(connected()), this,
+ SLOT(networkConnected()));
+ connect(m_manager->network(), SIGNAL(disconnected()), this,
+ SLOT(networkDisconnected()));
+ connect(m_manager->callManager(), SIGNAL(connected()), this,
+ SLOT(callManagerConnected()));
+ connect(m_manager->callManager(), SIGNAL(disconnected()), this,
+ SLOT(callManagerDisconnected()));
+ connect(m_manager->callManager(), SIGNAL(callsChanged()), this,
+ SLOT(onCallsChanged()));
+ connect(m_manager->voicemail(), SIGNAL(messagesWaitingChanged()), this,
+ SLOT(messagesWaitingChanged()));
+ if (!MODE_HANDSET_ENABLED)
+ {
+ PAControl* paControl = PAControl::instance();
+ connect(m_manager->callManager(), SIGNAL(callsChanged()), paControl,
+ SLOT(onCallsChanged()));
+
+ }
+ }
+}
+
+bool DialerApplication::isConnected()
+{
+ TRACE
+ return m_connected;
+}
+
+bool DialerApplication::hasError() const
+{
+ TRACE
+ return !m_lastError.isEmpty();
+}
+
+QString DialerApplication::lastError() const
+{
+ TRACE
+ return m_lastError;
+}
+
+void DialerApplication::setError(const QString msg)
+{
+ TRACE
+ m_lastError.clear();
+ m_lastError = QString(msg);
+}
+
+DialerApplication *DialerApplication::instance()
+{
+ TRACE
+ return qobject_cast<DialerApplication *>(QApplication::instance());
+}
+/*
+SeasideSyncModel *DialerApplication::seasideModel()
+{
+ TRACE
+ return m_seasideModel;
+}
+
+SeasideProxyModel *DialerApplication::seasideProxy()
+{
+ TRACE
+ return m_seasideProxy;
+}
+*/
+/*
+HistoryTableModel *DialerApplication::historyModel()
+{
+ TRACE
+ // return m_historyModel;
+}
+
+QSortFilterProxyModel *DialerApplication::historyProxy()
+{
+ TRACE
+ return m_historyProxy;
+}
+*/
+void DialerApplication::init()
+{
+ TRACE
+ m_connected = false;
+ m_lastError = QString();
+
+ // Notify Qt of our custom DBus MetaTypes
+ registerMyDataTypes();
+
+ m_manager = ManagerProxy::instance();
+ if (!m_manager || !m_manager->isValid())
+ //% "Failed to connect to org.ofono.Manager: is ofonod running?"
+ setError(qtTrId("xx_no_ofono_error"));
+ else
+ m_connected = true;
+
+ DBusDialerAdapter *adapter = new DBusDialerAdapter(this);
+ if(!adapter)
+ {
+ qWarning() << "DBus adapter instantiation failed.";
+ }
+
+ if(!QDBusConnection::sessionBus().registerObject(DBUS_SERVICE_PATH, this))
+ {
+ qCritical() << "Error registering dbus object:" <<
+ QDBusConnection::sessionBus().lastError().message();
+ }
+ /*
+ m_seasideModel = new SeasideSyncModel();
+ m_seasideProxy = new SeasideProxyModel();
+ m_seasideProxy->setSourceModel(m_seasideModel);
+ m_seasideProxy->setDynamicSortFilter(true);
+ m_seasideProxy->setFilterKeyColumn(-1);
+ m_seasideProxy->setFilterRegExp(MATCH_ALL);
+ m_seasideProxy->sort(Seaside::ColumnLastName, Qt::AscendingOrder);
+ */
+ //m_historyModel = new HistoryTableModel();
+ // m_historyProxy = new QSortFilterProxyModel();
+ // m_historyProxy->setSourceModel(m_historyModel);
+ // m_historyProxy->setDynamicSortFilter(true);
+ // m_historyProxy->setFilterKeyColumn(HistoryTableModel::COLUMN_LINEID);
+ // m_historyProxy->sort(HistoryTableModel::COLUMN_CALLSTART,
+ // Qt::DescendingOrder);
+
+ /*
+ connect(m_manager->modem(), SIGNAL(connected()),
+ SLOT(modemConnected()));
+ connect(m_manager->modem(), SIGNAL(disconnected()),
+ SLOT(modemDisconnected()));
+ */
+ connect(m_manager, SIGNAL(modemChanged()),
+ SLOT(modemChanged()));
+
+}
+
+void DialerApplication::modemChanged()
+{
+ TRACE
+ if (m_manager->modem() != NULL)
+ {
+ connect(m_manager->modem(), SIGNAL(connected()),
+ SLOT(modemConnected()));
+ connect(m_manager->modem(), SIGNAL(disconnected()),
+ SLOT(modemDisconnected()));
+ }
+}
+
+void DialerApplication::modemConnected()
+{
+ TRACE
+ //TODO: Handle multiple modems
+ if (m_manager->modem() && m_manager->modem()->isValid())
+ {
+ m_modem = m_manager->modem();
+
+ qDebug() << QString("Modem connected");
+ connect(m_modem, SIGNAL(interfacesChanged(QStringList)), this,
+ SLOT(modemInterfacesChanged(QStringList)));
+ connect(m_modem, SIGNAL(poweredChanged(bool)), this,
+ SLOT(modemPowered(bool)));
+
+ if (m_modem->powered() &&
+ m_modem->interfaces().contains(OFONO_VOICECALLMANAGER_INTERFACE))
+ {
+ /* connect all now, modem is enabled */
+ this->connectAll();
+ }
+ }
+}
+
+void DialerApplication::modemDisconnected()
+{
+ TRACE
+ //TODO: Handle multiple modems
+}
+
+void DialerApplication::modemInterfacesChanged(QStringList interfaces)
+{
+ TRACE
+ qDebug() << QString("Modem Interfaces: ") << interfaces;
+
+ if (interfaces.contains(OFONO_VOICECALLMANAGER_INTERFACE) &&
+ m_manager->modem()->powered())
+ {
+ this->connectAll();
+ }
+}
+
+void DialerApplication::modemPowered(bool isPowered)
+{
+ TRACE
+ qDebug() << QString("Modem Powered: ") << isPowered;
+
+ if (isPowered &&
+ m_manager->modem()->interfaces().contains(OFONO_VOICECALLMANAGER_INTERFACE))
+ {
+ this->connectAll();
+ }
+}
+
+void DialerApplication::networkConnected()
+{
+ TRACE
+ if (m_manager->network() && m_manager->network()->isValid())
+ m_network = m_manager->network();
+}
+
+void DialerApplication::networkDisconnected()
+{
+ TRACE
+}
+
+void DialerApplication::callManagerConnected()
+{
+ TRACE
+ if (m_manager->callManager() && m_manager->callManager()->isValid())
+ m_callManager = m_manager->callManager();
+
+
+ qDebug() << QString("Disconnect calls changed signal");
+ disconnect(m_callManager, SIGNAL(callsChanged()));
+
+ qDebug() << QString("Disconnect incoming signal");
+ disconnect(m_callManager, SIGNAL(incomingCall(CallItem*)));
+
+ qDebug() << QString("Disconnect resource lost");
+ disconnect(m_callManager, SIGNAL(callResourceLost(const QString)));
+}
+
+void DialerApplication::callManagerDisconnected()
+{
+ TRACE
+ qDebug() << QString("CallMgr disconnected");
+}
+
+void DialerApplication::messagesWaitingChanged()
+{
+ TRACE
+/*
+ static MNotification *vmail = NULL;
+
+ if (!m_manager->voicemail() || !m_manager->voicemail()->isValid()) {
+ qDebug() << QString("Voicemail proxy is invalid, ignoring");
+ return;
+ }
+
+
+ if (!vmail) {
+ bool found = false;
+ foreach (MNotification *notice, MNotification::notifications()) {
+ if (notice->eventType() == MNotification::MessageArrivedEvent) {
+ // If we've already found a MessageArrived notification,
+ // we must delete others since we only want one
+ if (found) {
+ qDebug() << QString("Removing duplicate voicemail notice");
+ notice->remove();
+ delete notice;
+ }
+ else {
+ vmail = notice;
+ found = true;
+ }
+ }
+ else {
+ // We're only interested in MessageArrived events, all others
+ // can need to be deleted here since they are copies
+ delete notice;
+ }
+ }
+
+ if (!found) {
+ if (!m_manager->voicemail()->waiting()) {
+ qDebug() << QString("No waiting Voicemail messages");
+ return;
+ }
+ else {
+ // This is the first instance of a MessageArrived event
+ qDebug() << QString("Creating new voicemail notice instance");
+ vmail = new MNotification(MNotification::MessageArrivedEvent);
+ vmail->setCount(0);
+ }
+ }
+ else {
+ if (!m_manager->voicemail()->waiting()) {
+ qDebug() << QString("No waiting Voicemail messages");
+ vmail->remove();
+ return;
+ }
+ }
+ }
+
+ // We've got a valid notification and we have messages waiting...
+ int vCount = m_manager->voicemail()->count();
+ int nCount = vmail->count();
+
+ if (vCount < 0) vCount = 0;
+ if (nCount < 0) nCount = 0;
+
+ qDebug() << QString("Voicemails: %1").arg(QString::number(vCount));
+ qDebug() << QString("Notices: %1").arg(QString::number(nCount));
+
+ // No more Voicemail messages waiting, remove notification
+ if (vCount <= 0) {
+ qDebug() << QString("No Voicemails waiting, removing notification");
+ vmail->remove();
+ return;
+ }
+
+ // The waiting voicemail count has changed, update and [re]publish it
+ //% "You have %1 voice messages"
+ vmail->setSummary(qtTrId("xx_messages_waiting").arg(vCount));
+ vmail->setImage("icon-m-telephony-voicemail");
+ vmail->setCount(vCount);
+ qDebug() << QString("Voicemail count changed, publishing notification");
+ vmail->publish();
+*/
+}
+
+void DialerApplication::onCallsChanged()
+{
+ TRACE
+ QMLMainWindow::instance()->tryToShow();
+}
--- /dev/null
+/*
+ * hfdialer - Hands Free Voice Call Manager
+ * Copyright (c) 2012, Intel Corporation.
+ *
+ * This program is licensed under the terms and conditions of the
+ * Apache License, version 2.0. The full text of the Apache License is at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ */
+
+#ifndef DIALERAPPLICATION_h
+#define DIALERAPPLICATION_h
+
+#include "managerproxy.h"
+#include <QSortFilterProxyModel>
+#include <QApplication>
+
+class DialerApplication: public QApplication
+{
+ Q_OBJECT
+
+ Q_PROPERTY(bool isConnected READ isConnected)
+ Q_PROPERTY(bool hasError READ hasError)
+ Q_PROPERTY(QString lastError READ lastError)
+
+public:
+ DialerApplication(int &argc, char **argv);
+
+ static DialerApplication* instance();
+
+ virtual void releasePrestart();
+ virtual void restorePrestart();
+
+ bool hasError() const;
+ QString lastError() const;
+ void setError(const QString msg);
+
+ bool isConnected();
+
+// SeasideSyncModel *seasideModel();
+// SeasideProxyModel *seasideProxy();
+ // HistoryTableModel *historyModel();
+ // QSortFilterProxyModel *historyProxy();
+
+Q_SIGNALS:
+ void showUi();
+ void hideUi();
+
+private Q_SLOTS:
+ void connectAll();
+ void messagesWaitingChanged();
+
+ void modemChanged();
+ void modemConnected();
+ void modemDisconnected();
+ void modemInterfacesChanged(QStringList interfaces);
+ void modemPowered(bool isPowered);
+ void networkConnected();
+ void networkDisconnected();
+ void callManagerConnected();
+ void callManagerDisconnected();
+
+ void onCallsChanged();
+
+private:
+ void init();
+
+ ManagerProxy *m_manager;
+ ModemProxy *m_modem;
+ NetworkProxy *m_network;
+ CallManager *m_callManager;
+
+ bool m_connected;
+ QString m_lastError;
+
+ //SeasideSyncModel *m_seasideModel;
+ //SeasideProxyModel *m_seasideProxy;
+
+ //HistoryTableModel *m_historyModel;
+ // QSortFilterProxyModel *m_historyProxy;
+
+ Q_DISABLE_COPY(DialerApplication);
+};
+
+#endif // DIALERAPPLICATION_H
--- /dev/null
+/*
+ * hfdialer - Hands Free Voice Call Manager
+ * Copyright (c) 2012, Intel Corporation.
+ *
+ * This program is licensed under the terms and conditions of the
+ * Apache License, version 2.0. The full text of the Apache License is at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ */
+
+#include "common.h"
+#include "dialercontext.h"
+
+#define AUTOSELECT OfonoModem::AutomaticSelect
+
+#ifndef CONFIG_KEY_TARGET_MODE
+#define CONFIG_KEY_TARGET_MODE "/apps/dialer/mode"
+#endif
+
+#include <QDebug>
+
+DialerContext *DialerContext::gContext = 0;
+
+class DialerContextPrivate
+{
+public:
+ DialerContextPrivate()
+ : modemManager(0),
+ volumeManager(0),
+ voicemailManager(0),
+ callManager(0),
+ modesKey(CONFIG_KEY_TARGET_MODE)
+ { TRACE }
+
+ ~DialerContextPrivate() {
+ delete volumeManager;
+ volumeManager = 0;
+ delete voicemailManager;
+ voicemailManager = 0;
+ delete callManager;
+ callManager = 0;
+ delete modemManager;
+ modemManager = 0;
+ }
+
+ OfonoModemManager *modemManager;
+ OfonoCallVolume *volumeManager;
+ OfonoMessageWaiting *voicemailManager;
+ CallManager *callManager;
+// ResourceProxy *policyManager;
+ QStringList modes;
+ MGConfItem modesKey;
+};
+
+
+DialerContext::DialerContext(QObject *parent)
+ : QObject(parent),
+ d(new DialerContextPrivate)
+{
+ if (gContext)
+ qFatal(__func__, ": There can be only one!");
+
+ // Read and configure default runtime modes
+ setModes(d->modesKey.value().toStringList());
+
+ // Create misc services
+ // TODO: We may not actually need this, since OfonoModem class
+ // allows for "auto selection" and switching of modems
+ d->modemManager = new OfonoModemManager(parent);
+ d->volumeManager = new OfonoCallVolume(AUTOSELECT,"");
+ d->voicemailManager = new OfonoMessageWaiting(AUTOSELECT,"");
+ d->callManager = new CallManager();
+
+ // OfonoModemManager signals to monitor
+ connect(d->modemManager, SIGNAL(modemAdded(const QString&)),
+ SLOT(onModemAdded(const QString&)));
+ connect(d->modemManager, SIGNAL(modemRemoved(const QString&)),
+ SLOT(onModemRemoved(const QString&)));
+
+ // CallManager signals to monitor
+ connect(d->callManager, SIGNAL(validityChanged(bool)),
+ SLOT(onCallManagerValidityChanged(bool)));
+ connect(d->callManager, SIGNAL(callsChanged()), SLOT(onCallsChanged()));
+
+ // OfonoCallVolume signals to monitor
+ connect(d->volumeManager, SIGNAL(validityChanged(bool)),
+ SLOT(onCallVolumeValidityChanged(bool)));
+
+ // OfonoMessageWaiting signals to monitor
+ connect(d->voicemailManager, SIGNAL(validityChanged(bool)),
+ SLOT(onVoicemailValidityChanged(bool)));
+ connect(d->voicemailManager, SIGNAL(voicemailWaitingChanged(bool)),
+ SLOT(onVoicemailWaitingChanged(bool)));
+ connect(d->voicemailManager, SIGNAL(voicemailMessageCountChanged(int)),
+ SLOT(onVoicemailCountChanged(int)));
+
+ // GConf Key change signals to monitor
+ connect(&d->modesKey, SIGNAL(valueChanged()), SLOT(onModesChanged()));
+
+ // ResourceProxy is a singleton, probably don't need to store this...
+ //d->policyManager = ResourceProxy::instance();
+
+ if (d->callManager)
+ qDebug() << __func__ << ": Using modem - "
+ << d->callManager->modem()->path();
+
+ gContext = this;
+}
+
+/*
+ * Public methods
+ */
+DialerContext::~DialerContext()
+{
+ delete d;
+ d = 0;
+ gContext=0;
+}
+
+DialerContext *DialerContext::instance()
+{
+ if (!gContext)
+ gContext = new DialerContext();
+ return gContext;
+}
+
+OfonoModemManager* DialerContext::modemManager() const
+{
+ return d->modemManager;
+}
+
+OfonoCallVolume* DialerContext::volumeManager() const
+{
+ return d->volumeManager;
+}
+
+OfonoMessageWaiting* DialerContext::voicemailManager() const
+{
+ return d->voicemailManager;
+}
+
+CallManager* DialerContext::callManager() const
+{
+ return d->callManager;
+}
+
+/*
+ResourceProxy* DialerContext::policyManager() const
+{
+ return d->policyManager;
+}
+*/
+
+QStringList DialerContext::modes() const
+{
+ return d->modes;
+}
+
+void DialerContext::setModes(const QStringList &modelist)
+{
+ d->modes = modelist;
+ d->modes.removeDuplicates();
+ emit modesChanged();
+}
+
+/*
+OfonoModem* DialerContext::modem() const
+{
+ if (d->callManager)
+ return d->callManager->modem();
+ return NULL;
+}
+*/
+
+/*
+ * Private methods/slots
+ */
+
+void DialerContext::onModemAdded(const QString &path)
+{
+ TRACE
+ // TODO: Handle modem additions, maybe...
+ qWarning() << __func__ << ": Unhandled ModemAdded - " << path;
+}
+
+void DialerContext::onModemRemoved(const QString &path)
+{
+ TRACE
+ // TODO: Handle modem removals, currently active for sure, others, maybe...
+ qWarning() << __func__ << ": Unhandled ModemAdded - " << path;
+}
+
+void DialerContext::onCallVolumeValidityChanged(bool valid)
+{
+ TRACE
+ // TODO: Reset the volumeManager service reference
+ qWarning() << __func__ << ": valid? " << ((valid)?"true":"false");
+}
+
+void DialerContext::onVoicemailValidityChanged(bool valid)
+{
+ TRACE
+ // TODO: Reset the voicemailManager service reference
+ qWarning() << __func__ << ": valid? " << ((valid)?"true":"false");
+}
+
+void DialerContext::onVoicemailWaitingChanged(bool waiting)
+{
+ TRACE
+ // TODO: Send notifications (or bubble this up for UI to handle?)
+ qDebug() << __func__ << ": Messages? " << ((waiting)?"true":"false");
+}
+
+void DialerContext::onVoicemailCountChanged(int count)
+{
+ TRACE
+ // TODO: Send notifications (or bubble this up for UI to handle?)
+ qDebug() << __func__ << ": Message count == " << count;
+}
+
+void DialerContext::onCallManagerValidityChanged(bool valid)
+{
+ TRACE
+ // TODO: Reset the callManager service reference
+ qWarning() << __func__ << ": valid? " << ((valid)?"true":"false");
+}
+
+void DialerContext::onCallsChanged()
+{
+ TRACE
+ // TODO: Send notifications (or bubble this up for UI to handle?)
+ qDebug() << __func__ << ": Calls count == "
+ << d->callManager->getCalls().count();
+}
+
+void DialerContext::onModesChanged()
+{
+ TRACE
+ setModes(d->modesKey.value().toStringList());
+ // Send notification of change
+ emit modesChanged();
+ qDebug() << __func__ << ": New modes == " << d->modes.join(", ");
+}
--- /dev/null
+/*
+ * hfdialer - Hands Free Voice Call Manager
+ * Copyright (c) 2012, Intel Corporation.
+ *
+ * This program is licensed under the terms and conditions of the
+ * Apache License, version 2.0. The full text of the Apache License is at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ */
+
+#ifndef DIALERCONTEXT_H
+#define DIALERCONTEXT_H
+
+// libofono-qt headers
+#include <ofonomodemmanager.h>
+#include <ofonocallvolume.h>
+#include <ofonomessagewaiting.h>
+
+// local headers
+#include "callmanager.h"
+//#include "resourceproxy.h"
+
+// Convienence Macro for access to Class instance
+#define DC DialerContext::instance()
+
+class DialerContext: public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(OfonoModemManager* modemManager READ modemManager)
+ Q_PROPERTY(OfonoCallVolume* volumeManager READ volumeManager)
+ Q_PROPERTY(OfonoMessageWaiting* voicemailManager READ voicemailManager)
+ Q_PROPERTY(CallManager* callManager READ callManager)
+// Q_PROPERTY(ResourceProxy* policyManager READ policyManager)
+ Q_PROPERTY(QStringList modes READ modes WRITE setModes)
+
+public:
+ virtual ~DialerContext();
+
+ static DialerContext *instance();
+
+ OfonoModemManager* modemManager() const;
+ OfonoCallVolume* volumeManager() const;
+ OfonoMessageWaiting* voicemailManager() const;
+ CallManager* callManager() const;
+ //ResourceProxy* policyManager() const;
+ QStringList modes() const;
+
+public slots:
+ // Slot to set current mode at runtime
+ void setModes(const QStringList &modeList);
+
+Q_SIGNALS:
+ void modesChanged();
+
+private Q_SLOTS:
+
+ // Slots to handle signals from Manager oFono service
+ void onModemAdded(const QString &path);
+ void onModemRemoved(const QString &path);
+
+ // Slots to handle signals from CallVolume oFono service
+ void onCallVolumeValidityChanged(bool valid);
+
+ // Slots to handle signals from MessageWaiting oFono service
+ void onVoicemailValidityChanged(bool valid);
+ void onVoicemailWaitingChanged(bool waiting);
+ void onVoicemailCountChanged(int count);
+
+ // Slots to handle signals from CallManager oFono service
+ void onCallManagerValidityChanged(bool valid);
+ void onCallsChanged();
+
+ // Slot to handle runtime mode changes in GConf key
+ void onModesChanged();
+
+protected:
+ DialerContext(QObject *parent = 0);
+
+private:
+ DialerContext(const DialerContext&);
+ DialerContext& operator= (DialerContext&);
+
+ class DialerContextPrivate *d;
+
+ static DialerContext *gContext;
+};
+
+#endif // DIALERCONTEXT_H
--- /dev/null
+/*
+ * hfdialer - Hands Free Voice Call Manager
+ * Copyright (c) 2012, Intel Corporation.
+ *
+ * This program is licensed under the terms and conditions of the
+ * Apache License, version 2.0. The full text of the Apache License is at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ */
+
+#include "dialercontext.h"
+#include "dialerapplication.h"
+#include "qmlmainwindow.h"
+#include "common.h"
+
+#include <QtGui>
+#include <QApplication>
+#include <QDeclarativeView>
+#include <QFile>
+
+#define CONFIG_KEY_TARGET_UX "/apps/dialer/ux"
+
+#if !defined(CONFIG_DEFAULT_TARGET_UX)
+# define CONFIG_DEFAULT_TARGET_UX "tizen-ux-components"
+#endif
+
+ void myMessageOutput(QtMsgType type, const char *msg)
+ {
+ QFile debugFile("/home/tizen/dialerout.txt");
+ debugFile.open(QIODevice::WriteOnly | QIODevice::Append);
+ QTextStream out(&debugFile);
+
+ out << msg << "\n";
+ debugFile.close();
+ }
+
+int main(int argc, char *argv[])
+{
+ TRACE
+ qInstallMsgHandler(myMessageOutput);
+ DialerApplication app(argc, argv);
+
+ QMLMainWindow *qmw = QMLMainWindow::instance();
+ //setResizeMode(QDeclarativeView::SizeRootObjectToView);
+ qmw->tryToShow();
+
+ return app.exec();
+}
+
+QString stripLineID(QString lineid)
+{
+ TRACE
+ static QRegExp rx = QRegExp("([^0-9*#])");
+
+ if (lineid.indexOf('+') == 0) {
+ lineid.replace(rx, "");
+ return lineid.insert(0,"+");
+ }
+ else
+ return lineid.replace(rx, "");
+}
+
+bool currentPageIs(int pagenum)
+{
+ DialerApplication *app = DialerApplication::instance();
+ return true;
+}
+
+// Returns a valid QDateTime if parsable as such, otherwise the result
+// will be !isValid()
+QDateTime qDateTimeFromOfono(const QString &val)
+{
+ TRACE
+ QDateTime result;
+
+ if (val.isEmpty())
+ return result;
+
+ // NOTE: Ofono formats time to string with the following format spec:
+ // %Y-%m-%dT%H:%M:%S%z (for example: "2001-10-19T10:32:30-05:00")
+
+ // Start by trying to parse this as an ISODate "YYYY-MM-DDTHH:MM:SSTZD"
+ result = QDateTime::fromString(val,Qt::ISODate);
+#ifdef WANT_DEBUG
+ qDebug() << QString("Converted %1 with Qt::ISODate: %2")
+ .arg(val)
+ .arg(result.toString());
+#endif
+
+ if (!result.isValid()) {
+ // ISODate conversion has failed, fallback to manual method
+ // NOTE: QDateTime::fromString(val, Qt::ISODate) Fails since the date
+ // format from Ofono is in RFC 822 form, but QDateTime can't parse it
+ struct tm time_tm;
+ QByteArray bytes = val.toAscii();
+ const char *str = bytes.constData();
+ if (strptime(str, "%Y-%m-%dT%H:%M:%S%z", &time_tm) != NULL) {
+ time_t t = mktime(&time_tm);
+ if (t >= (time_t)(0)) {
+ result.setTime_t(t);
+#ifdef WANT_DEBUG
+ qDebug() << QString("Converted %1 with strptime: %2")
+ .arg(val)
+ .arg(result.toString());
+#endif
+ }
+ }
+
+ if (!result.isValid())
+ qCritical() << QString("Format error, unknown date/time: %1")
+ .arg(str);
+ }
+
+ return result;
+}
--- /dev/null
+/*
+ * hfdialer - Hands Free Voice Call Manager
+ * Copyright (c) 2012, Intel Corporation.
+ *
+ * This program is licensed under the terms and conditions of the
+ * Apache License, version 2.0. The full text of the Apache License is at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ */
+
+#include "managerproxy.h"
+#include "manager_interface.h"
+#include "dialerapplication.h"
+#include <QDebug>
+
+ManagerProxy *ManagerProxy::gManager = 0;
+
+ManagerProxy::ManagerProxy(const QString &service,
+ const QString &path,
+ const QDBusConnection &connection,
+ QObject *parent)
+ : org::ofono::Manager(service, path, connection, parent),
+ m_modemPath (""),
+ m_modem(0),
+ m_network(0),
+ m_callManager(0),
+ m_volumeManager(0),
+ m_voicemail(0)
+{
+TRACE
+ if (gManager)
+ qFatal("ManagerProxy: There can be only one!");
+
+ if (!isValid()) {
+ qDebug() << "Failed to connect to Ofono: \n\t" << lastError().message();
+ } else {
+ QDBusPendingReply<QArrayOfPathProperties> reply;
+ QDBusPendingCallWatcher * watcher;
+
+ reply = GetModems();
+ watcher = new QDBusPendingCallWatcher(reply);
+
+ // Force this to be sync to ensure we have initial properties
+ watcher->waitForFinished();
+ managerDBusGetModemsDone(watcher);
+
+ connect(this,
+ SIGNAL(ModemAdded(const QDBusObjectPath&, const QVariantMap&)),
+ SLOT(modemAdded(const QDBusObjectPath&, const QVariantMap&)));
+ connect(this,
+ SIGNAL(ModemRemoved(const QDBusObjectPath&)),
+ SLOT(modemRemoved(const QDBusObjectPath&)));
+ }
+
+ gManager = this;
+}
+
+ManagerProxy::~ManagerProxy()
+{
+ TRACE
+ if (m_volumeManager)
+ delete m_volumeManager;
+ m_volumeManager = 0;
+
+ if (m_voicemail)
+ delete m_voicemail;
+ m_voicemail = 0;
+
+ if (m_callManager)
+ delete m_callManager;
+ m_callManager = 0;
+
+ if (m_network)
+ delete m_network;
+ m_network = 0;
+
+ if (m_modem)
+ delete m_modem;
+ m_modem = 0;
+
+ gManager=0;
+}
+
+void ManagerProxy::managerDBusGetModemsDone(QDBusPendingCallWatcher *call)
+{
+ QDBusPendingReply<QArrayOfPathProperties> reply = *call;
+TRACE
+ if (reply.isError()) {
+ // TODO: Handle this properly, by setting states, or disabling features
+ qWarning() << "org.ofono.Manager.GetModems() failed: " <<
+ reply.error().message();
+ } else {
+ QArrayOfPathProperties modems = reply.value();
+ if (modems.count() >= 1) {
+ // FIXME: Handle multiple modems...
+ foreach (OfonoPathProperties p, modems)
+ {
+ qDebug() << "modem: " << p.path.path();
+ m_modemList << QString(p.path.path());
+ }
+
+ OfonoPathProperties p = modems[0];
+ if (m_modemPath.isNull() || m_modemPath.isEmpty()) {
+ qDebug() << QString("\n======\nUsing modem: \"%1\"\n======").arg(p.path.path());
+ m_modemPath = QString(p.path.path());
+ setModem(m_modemPath);
+ setNetwork(m_modemPath);
+ setCallManager(m_modemPath);
+ setVolumeManager(m_modemPath);
+ setVoicemail(m_modemPath);
+ // TODO: Connect to service proxies as available/needed here
+ }
+ }
+ }
+}
+
+void ManagerProxy::modemAdded(const QDBusObjectPath &in0,const QVariantMap &in1)
+{
+ Q_UNUSED(in1)
+ TRACE
+
+ // TODO: Handle modem additions, maybe...
+ qWarning() << QString("Unhandled ModemAdded event: \"%1\"")
+ .arg(in0.path());
+
+ qDebug() << QString("modem added: %1").arg(in0.path());
+ m_modemList << QString(in0.path());
+ m_modemList.removeDuplicates();
+}
+
+void ManagerProxy::modemRemoved(const QDBusObjectPath &in0)
+{
+ TRACE
+
+ // TODO: Handle modem removals, currently active for sure, others, maybe...
+ qWarning() << QString("Unhandled ModemRemoved event: \"%1\"")
+ .arg(in0.path());
+
+ qDebug() << QString("modem removed: ").arg(in0.path());
+ m_modemList.removeOne(QString(in0.path()));
+}
+
+ManagerProxy *ManagerProxy::instance()
+{
+ if (!gManager)
+ gManager = new ManagerProxy();
+
+ return gManager;
+}
+
+ModemProxy* ManagerProxy::modem() const
+{
+ return m_modem;
+}
+
+NetworkProxy* ManagerProxy::network() const
+{
+ return m_network;
+}
+
+CallManager* ManagerProxy::callManager() const
+{
+ return m_callManager;
+}
+
+VolumeManager* ManagerProxy::volumeManager() const
+{
+ return m_volumeManager;
+}
+
+VoicemailProxy* ManagerProxy::voicemail() const
+{
+ return m_voicemail;
+}
+
+QStringList ManagerProxy::getModemList()
+{
+ return m_modemList;
+}
+
+void ManagerProxy::setModem(QString modemPath)
+{
+ if (m_modem &&
+ m_modem->isValid() &&
+ m_modem->path() == modemPath)
+ return;
+
+ if (m_modem)
+ {
+ delete m_modem;
+ m_modem = NULL;
+ }
+
+ if (m_modemList.contains(modemPath)) {
+ m_modem = new ModemProxy(modemPath);
+ emit modemChanged();
+ }
+}
+
+void ManagerProxy::setNetwork(QString modempath)
+{
+ if (!m_modem || !m_modem->isValid())
+ return;
+
+ if (modempath == m_modem->path()) {
+ if (m_network && m_network->isValid()) {
+ return;
+ }
+ else {
+ delete m_network;
+ m_network = new NetworkProxy(modempath);
+ emit networkChanged();
+ }
+ }
+ else {
+ if(m_network || !m_network->isValid()) {
+ delete m_network;
+ m_network = new NetworkProxy(modempath);
+ emit networkChanged();
+ }
+ }
+}
+
+void ManagerProxy::setCallManager(QString modempath)
+{
+ if (!m_modem || !m_modem->isValid())
+ return;
+
+ if (modempath == m_modem->path()) {
+ if (m_callManager && m_callManager->isValid()) {
+ return;
+ }
+ else {
+ delete m_callManager;
+ m_callManager = new CallManager(modempath);
+ emit callManagerChanged();
+ }
+ }
+ else {
+ if(m_callManager || !m_callManager->isValid()) {
+ delete m_callManager;
+ m_callManager = new CallManager(modempath);
+ emit callManagerChanged();
+ }
+ }
+}
+
+void ManagerProxy::setVolumeManager(QString modempath)
+{
+ if (!m_modem || !m_modem->isValid())
+ return;
+
+ if (modempath == m_modem->path()) {
+ if (m_volumeManager && m_volumeManager->isValid()) {
+ return;
+ }
+ else {
+ delete m_volumeManager;
+ m_volumeManager = new VolumeManager(modempath);
+ emit volumeManagerChanged();
+ }
+ }
+ else {
+ if(m_volumeManager || !m_volumeManager->isValid()) {
+ delete m_volumeManager;
+ m_volumeManager = new VolumeManager(modempath);
+ emit volumeManagerChanged();
+ }
+ }
+}
+
+void ManagerProxy::setVoicemail(QString modempath)
+{
+ if (!m_modem || !m_modem->isValid())
+ return;
+
+ if (modempath == m_modem->path()) {
+ if (m_voicemail && m_voicemail->isValid()) {
+ return;
+ }
+ else {
+ delete m_voicemail;
+ m_voicemail = new VoicemailProxy(modempath);
+ emit voicemailChanged();
+ }
+ }
+ else {
+ if(m_voicemail || !m_voicemail->isValid()) {
+ delete m_voicemail;
+ m_voicemail = new VoicemailProxy(modempath);
+ emit voicemailChanged();
+ }
+ }
+}
--- /dev/null
+/*
+ * hfdialer - Hands Free Voice Call Manager
+ * Copyright (c) 2012, Intel Corporation.
+ *
+ * This program is licensed under the terms and conditions of the
+ * Apache License, version 2.0. The full text of the Apache License is at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ */
+
+#ifndef MANAGERPROXY_H
+#define MANAGERPROXY_H
+
+#include "manager_interface.h"
+#include "modemproxy.h"
+#include "networkproxy.h"
+#include "callmanager.h"
+//#include "resourceproxy.h"
+#include "common.h"
+#include <QtDBus>
+#include <QDebug>
+
+#define OFONO_SERVICE "org.ofono"
+#define OFONO_MANAGER_PATH "/"
+
+class ManagerProxy: public org::ofono::Manager
+{
+ Q_OBJECT
+ Q_PROPERTY(ModemProxy* modem READ modem)
+ Q_PROPERTY(NetworkProxy* network READ network)
+
+public:
+ virtual ~ManagerProxy();
+
+ static ManagerProxy *instance();
+ QStringList getModemList();
+ void setModem(QString modempath);
+ void setNetwork(QString modempath);
+ void setCallManager(QString modempath);
+ void setVolumeManager(QString modempath);
+ void setVoicemail(QString modempath);
+
+ ModemProxy* modem() const;
+ NetworkProxy* network() const;
+ CallManager* callManager() const;
+ VolumeManager* volumeManager() const;
+ VoicemailProxy* voicemail() const;
+
+public slots:
+ void managerDBusGetModemsDone(QDBusPendingCallWatcher *call);
+
+Q_SIGNALS:
+ void modemChanged();
+ void networkChanged();
+ void callManagerChanged();
+ void volumeManagerChanged();
+ void voicemailChanged();
+
+private Q_SLOTS:
+ void modemAdded(const QDBusObjectPath &in0, const QVariantMap &in1);
+ void modemRemoved(const QDBusObjectPath &in0);
+
+protected:
+ ManagerProxy(const QString &service=OFONO_SERVICE,
+ const QString &path=OFONO_MANAGER_PATH,
+ const QDBusConnection &connection=QDBusConnection::systemBus(),
+ QObject *parent = 0);
+
+private:
+ ManagerProxy(const ManagerProxy&);
+ ManagerProxy& operator= (ManagerProxy&);
+
+ QString m_modemPath;
+ ModemProxy *m_modem;
+ NetworkProxy *m_network;
+ CallManager *m_callManager;
+ VolumeManager *m_volumeManager;
+ VoicemailProxy *m_voicemail;
+ QStringList m_modemList;
+
+ static ManagerProxy *gManager;
+};
+
+#endif
--- /dev/null
+/*
+ * hfdialer - Hands Free Voice Call Manager
+ * Copyright (c) 2012, Intel Corporation.
+ *
+ * This program is licensed under the terms and conditions of the
+ * Apache License, version 2.0. The full text of the Apache License is at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ */
+
+#include "modemproxy.h"
+#include <QDebug>
+#include "common.h"
+
+ModemProxy::ModemProxy(const QString &objectPath)
+ : org::ofono::Modem(OFONO_SERVICE,
+ objectPath,
+ QDBusConnection::systemBus()),
+ m_interfaces(0)
+{
+TRACE
+ if (!isValid()) {
+ qDebug() << "Failed to connect to Ofono: \n\t" << lastError().message();
+ } else {
+ m_path = objectPath;
+ QDBusPendingReply<QVariantMap> reply;
+ QDBusPendingCallWatcher * watcher;
+
+ reply = GetProperties();
+ watcher = new QDBusPendingCallWatcher(reply);
+
+ connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)),
+ this, SLOT(modemDBusGetPropDone(QDBusPendingCallWatcher*)));
+
+ connect(this,
+ SIGNAL(PropertyChanged(const QString&,const QDBusVariant&)),
+ SLOT(propertyChanged(const QString&,const QDBusVariant&)));
+ }
+}
+
+ModemProxy::~ModemProxy()
+{
+TRACE
+}
+
+QStringList ModemProxy::interfaces() const { return m_interfaces; }
+QString ModemProxy::path() const { return m_path; }
+QString ModemProxy::manufacturer() const { return m_manufacturer; }
+QString ModemProxy::model() const { return m_model; }
+QString ModemProxy::revision() const { return m_revision; }
+QString ModemProxy::serial() const { return m_serial; }
+bool ModemProxy::powered() const { return m_powered; }
+bool ModemProxy::online() const { return m_online; }
+
+void ModemProxy::setPowered(bool is_powered)
+{
+TRACE
+ if (m_powered == is_powered)
+ return;
+
+ QDBusPendingReply<QVariantMap> reply;
+ reply = SetProperty("Powered", QDBusVariant(is_powered?true:false));
+ if (reply.isError())
+ qCritical() << "SetProperty \"Powered\" failed!";
+}
+
+void ModemProxy::setOnline(bool is_online)
+{
+TRACE
+ if (m_online == is_online)
+ return;
+
+ QDBusPendingReply<QVariantMap> reply;
+ reply = SetProperty("Online", QDBusVariant(m_online?"true":"false"));
+ if (reply.isError())
+ qCritical() << "SetProperty \"Powered\" failed!";
+ else
+ m_online = is_online;
+}
+
+void ModemProxy::modemDBusGetPropDone(QDBusPendingCallWatcher *call)
+{
+TRACE
+ QDBusPendingReply<QVariantMap> reply = *call;
+
+ if (reply.isError()) {
+ // TODO: Handle this properly, by setting states, or disabling features...
+ qDebug() << "org.ofono.ModemProxy.getProperties() failed: " <<
+ reply.error().message();
+ } else {
+ QVariantMap properties = reply.value();
+ m_interfaces = qdbus_cast<QStringList >(properties["Interfaces"]);
+ m_manufacturer = qdbus_cast<QString>(properties["Manufacturer"]);
+ m_model = qdbus_cast<QString>(properties["Model"]);
+ m_powered = qdbus_cast<bool>(properties["Powered"]);
+ m_revision = qdbus_cast<QString>(properties["Revision"]);
+ m_serial = qdbus_cast<QString>(properties["Serial"]);
+ m_online = qdbus_cast<bool>(properties["Online"]);
+
+ // First sucessfull GetProperties == connected
+ if (!m_connected) {
+ m_connected = true;
+ emit connected();
+ }
+ }
+}
+
+void ModemProxy::propertyChanged(const QString &in0, const QDBusVariant &in1)
+{
+TRACE
+ qDebug() << "org.ofono.ModemProxy.propertyChanged()"
+ << in0 << ": " << in1.variant();
+ if (in0 == "Interfaces") {
+ m_interfaces = qdbus_cast<QStringList>(in1.variant());
+ emit interfacesChanged(m_interfaces);
+ }
+ else if (in0 == "Powered") {
+ m_powered = qdbus_cast<bool>(in1.variant());
+ emit poweredChanged(m_powered);
+ } else if (in0 == "Online") {
+ m_online = qdbus_cast<bool>(in1.variant());
+ emit onlineChanged(m_online);
+ } else {
+ qDebug() << QString("Unhandled property \"%1\" changed...").arg(in0);
+ }
+}
+
+/*
+ * VoicemailProxy (aka MessageWaiting) implementation
+ */
+
+VoicemailProxy::VoicemailProxy(const QString &objectPath)
+ : org::ofono::MessageWaiting(OFONO_SERVICE,
+ objectPath,
+ QDBusConnection::systemBus()),
+ m_connected(false)
+{
+TRACE
+ if (!isValid()) {
+ qDebug() << "Failed to connect to Ofono: \n\t" << lastError().message();
+ } else {
+ m_path = objectPath;
+ QDBusPendingReply<QVariantMap> reply;
+ QDBusPendingCallWatcher * watcher;
+
+ reply = GetProperties();
+ watcher = new QDBusPendingCallWatcher(reply);
+
+ connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)),
+ this, SLOT(voicemailDBusGetPropDone(QDBusPendingCallWatcher*)));
+ connect(this, SIGNAL(PropertyChanged(const QString&, const QDBusVariant&)),
+ SLOT(voicemailPropertyChanged(const QString&, const QDBusVariant&)));
+ }
+}
+
+VoicemailProxy::~VoicemailProxy()
+{
+TRACE
+}
+
+bool VoicemailProxy::isConnected() const { return m_connected; }
+QString VoicemailProxy::path() const { return m_path; }
+QString VoicemailProxy::mailbox() const { return m_mailbox; }
+int VoicemailProxy::count() const { return m_count; }
+bool VoicemailProxy::waiting() const { return m_waiting; }
+
+void VoicemailProxy::setMailbox(QString lineid)
+{
+TRACE
+ if (lineid.isEmpty() || (m_mailbox == lineid))
+ return;
+
+ QDBusPendingReply<> reply;
+ reply = SetProperty("VoicemailMailboxNumber", QDBusVariant(lineid));
+ reply.waitForFinished();
+
+ if (reply.isError())
+ qCritical() << "SetProperty \"VoicemailMailboxNumber\" failed: " <<
+ reply.error().message();
+ else
+ m_mailbox = lineid;
+}
+
+void VoicemailProxy::voicemailDBusGetPropDone(QDBusPendingCallWatcher *call)
+{
+TRACE
+ QDBusPendingReply<QVariantMap> reply = *call;
+
+ if (reply.isError()) {
+ // TODO: Handle this properly, by setting states, or disabling features...
+ qDebug() << "org.ofono.MessageWaiting.getProperties() failed: " <<
+ reply.error().message();
+ } else {
+ QVariantMap properties = reply.value();
+ bool waiting = qdbus_cast<bool>(properties["VoicemailWaiting"]);
+ int count = qdbus_cast<int>(properties["VoicemailMessageCount"]);
+ QString mailbox = qdbus_cast<QString>(properties["VoicemailMailboxNumber"]);
+
+ if (count != m_count) {
+ m_count = count;
+ emit messagesWaitingChanged();
+ }
+ if (waiting != m_waiting) {
+ m_waiting = waiting;
+ emit messagesWaitingChanged();
+ }
+ if (!mailbox.isEmpty() && (mailbox != m_mailbox)) {
+ m_mailbox = mailbox;
+ emit mailboxChanged();
+ }
+
+ // First sucessfull GetProperties == connected
+ if (!m_connected) {
+ m_connected = true;
+ emit connected();
+ }
+ }
+}
+
+void VoicemailProxy::voicemailPropertyChanged(const QString &in0, const QDBusVariant &in1)
+{
+TRACE
+ qDebug() << QString("Property \"%1\" changed...").arg(in0);
+ bool waiting;
+ int count;
+ QString mailbox;
+ if (in0 == "VoicemailWaiting") {
+ waiting = qdbus_cast<bool>(in1.variant());
+ } else if (in0 == "VoicemailMessageCount") {
+ count = qdbus_cast<int>(in1.variant());
+ } else if (in0 == "VoicemailMailboxNumber") {
+ mailbox = qdbus_cast<QString>(in1.variant());
+ } else
+ qDebug() << QString("Unexpected property changed...");
+
+ if ((count != m_count) || (waiting != m_waiting)) {
+ m_count = count;
+ m_waiting = waiting;
+ emit messagesWaitingChanged();
+ }
+ if (!mailbox.isEmpty() && (mailbox != m_mailbox)) {
+ m_mailbox = mailbox;
+ emit mailboxChanged();
+ }
+}
+
+/*
+ * CallVolume Manager implementation
+ */
+
+VolumeManager::VolumeManager(const QString &objectPath)
+ : org::ofono::CallVolume(OFONO_SERVICE,
+ objectPath,
+ QDBusConnection::systemBus())
+{
+TRACE
+ if (!isValid()) {
+ qDebug() << "Failed to connect to Ofono: \n\t" << lastError().message();
+ } else {
+ m_path = objectPath;
+ QDBusPendingReply<QVariantMap> reply;
+ QDBusPendingCallWatcher * watcher;
+
+ reply = GetProperties();
+ watcher = new QDBusPendingCallWatcher(reply);
+
+ connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)),
+ this, SLOT(volumeDBusGetPropDone(QDBusPendingCallWatcher*)));
+ }
+}
+
+VolumeManager::~VolumeManager()
+{
+TRACE
+}
+
+QString VolumeManager::path() const { return m_path; }
+int VolumeManager::speakerVolume() const { return m_speakerVolume; }
+int VolumeManager::micVolume() const { return m_micVolume; }
+bool VolumeManager::muted() const { return m_muted; }
+bool VolumeManager::isConnected() const { return m_connected; }
+
+void VolumeManager::setSpeakerVolume(int volume)
+{
+TRACE
+ if (m_speakerVolume == volume)
+ return;
+
+ if ((volume < 0) || (volume > 100)) {
+ qWarning() << "SpeakerVolume value out of range (0<>100)";
+ return;
+ }
+
+ QDBusPendingReply<> reply;
+ reply = SetProperty("SpeakerVolume", QDBusVariant(volume));
+ reply.waitForFinished();
+
+ if (reply.isError())
+ qCritical() << "SetProperty \"SpeakerVolume\" failed: " <<
+ reply.error().message();
+ else
+ m_speakerVolume = volume;
+}
+
+void VolumeManager::setMicVolume(int volume)
+{
+TRACE
+ if (m_micVolume == volume)
+ return;
+
+ if ((volume < 0) || (volume > 100)) {
+ qWarning() << "MicrophoneVolume value out of range (0<>100)";
+ return;
+ }
+
+ QDBusPendingReply<> reply;
+ reply = SetProperty("MicrophoneVolume", QDBusVariant(volume));
+ reply.waitForFinished();
+
+ if (reply.isError())
+ qCritical() << "SetProperty \"MicrophoneVolume\" failed: " <<
+ reply.error().message();
+ else
+ m_micVolume = volume;
+}
+
+void VolumeManager::setMuted(bool is_muted)
+{
+TRACE
+ if (m_muted == is_muted)
+ return;
+
+ QDBusPendingReply<> reply;
+ reply = SetProperty("Muted", QDBusVariant(is_muted));
+ reply.waitForFinished();
+
+ if (reply.isError())
+ qCritical() << "SetProperty \"Muted\" failed: " <<
+ reply.error().message();
+ else
+ m_muted = is_muted;
+}
+
+void VolumeManager::volumeDBusGetPropDone(QDBusPendingCallWatcher *call)
+{
+TRACE
+ QDBusPendingReply<QVariantMap> reply = *call;
+
+ if (reply.isError()) {
+ // TODO: Handle this properly, by setting states, or disabling features...
+ qDebug() << "org.ofono.CallVolume.getProperties() failed: " <<
+ reply.error().message();
+ } else {
+ QVariantMap properties = reply.value();
+ m_speakerVolume = qdbus_cast<int>(properties["SpeakerVolume"]);
+ m_micVolume = qdbus_cast<int>(properties["MicrophoneVolume"]);
+ m_muted = qdbus_cast<bool>(properties["Muted"]);
+
+ // First sucessfull GetProperties == connected
+ if (!m_connected) {
+ m_connected = true;
+ emit connected();
+ }
+ }
+}
--- /dev/null
+/*
+ * hfdialer - Hands Free Voice Call Manager
+ * Copyright (c) 2012, Intel Corporation.
+ *
+ * This program is licensed under the terms and conditions of the
+ * Apache License, version 2.0. The full text of the Apache License is at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ */
+
+#ifndef MODEMPROXY_H
+#define MODEMPROXY_H
+
+#include "modem_interface.h"
+#include <QtDBus>
+#include <QDebug>
+
+#define OFONO_SERVICE "org.ofono"
+#define OFONO_MANAGER_PATH "/"
+
+class ModemProxy: public org::ofono::Modem
+{
+ Q_OBJECT
+ Q_PROPERTY(QStringList interfaces READ interfaces)
+ Q_PROPERTY(QString path READ path)
+ Q_PROPERTY(QString manufacturer READ manufacturer)
+ Q_PROPERTY(QString model READ model)
+ Q_PROPERTY(QString revision READ revision)
+ Q_PROPERTY(QString serial READ serial)
+ Q_PROPERTY(bool powered READ powered WRITE setPowered)
+ Q_PROPERTY(bool online READ online WRITE setOnline)
+
+public:
+ ModemProxy(const QString &objectPath);
+ virtual ~ModemProxy();
+
+ QStringList interfaces() const;
+ QString path() const;
+ QString manufacturer() const;
+ QString model() const;
+ QString revision() const;
+ QString serial() const;
+ bool powered() const;
+ bool online() const;
+
+public slots:
+ void setPowered(bool is_powered);
+ void setOnline(bool is_online);
+
+ void modemDBusGetPropDone(QDBusPendingCallWatcher *call);
+
+Q_SIGNALS:
+ void interfacesChanged(QStringList interfaces);
+ void poweredChanged(bool powered);
+ void onlineChanged(bool powered);
+ void connected();
+ void disconnected();
+
+private Q_SLOTS:
+ // Slots to handle DBus signals from ofono
+ void propertyChanged(const QString &in0, const QDBusVariant &in1);
+
+private:
+ QStringList m_properties; // raw return from GetProperties
+ QStringList m_interfaces;
+ QString m_path;
+ QString m_manufacturer;
+ QString m_model;
+ QString m_revision;
+ QString m_serial;
+ bool m_powered;
+ bool m_online;
+ bool m_connected;
+};
+
+class VoicemailProxy: public org::ofono::MessageWaiting
+{
+ Q_OBJECT
+
+ Q_PROPERTY(bool isConnected READ isConnected NOTIFY connected)
+ Q_PROPERTY(bool waiting READ waiting)
+ Q_PROPERTY(int count READ count)
+ Q_PROPERTY(QString mailbox READ mailbox WRITE setMailbox)
+
+public:
+ VoicemailProxy(const QString &objectPath);
+ virtual ~VoicemailProxy();
+
+ bool isConnected() const;
+
+ QString path() const;
+ bool waiting() const;
+ int count() const;
+ QString mailbox() const;
+
+public slots:
+ void setMailbox(QString lineid);
+
+Q_SIGNALS:
+ void messagesWaitingChanged();
+ void mailboxChanged();
+ void connected();
+ void disconnected();
+
+private slots:
+ void voicemailDBusGetPropDone(QDBusPendingCallWatcher *call);
+ void voicemailPropertyChanged(const QString &in0, const QDBusVariant &in1);
+
+private:
+ QStringList m_properties; // raw return from GetProperties
+ QString m_path;
+ bool m_waiting;
+ int m_count;
+ QString m_mailbox;
+ bool m_connected;
+};
+
+class VolumeManager: public org::ofono::CallVolume
+{
+ Q_OBJECT
+ Q_PROPERTY(int speakerVolume READ speakerVolume WRITE setSpeakerVolume)
+ Q_PROPERTY(int micVolume READ micVolume WRITE setMicVolume)
+ Q_PROPERTY(bool muted READ muted WRITE setMuted)
+ Q_PROPERTY(bool isConnected READ isConnected)
+
+public:
+ VolumeManager(const QString &objectPath);
+ virtual ~VolumeManager();
+
+ QString path() const;
+ int speakerVolume() const;
+ int micVolume() const;
+ bool muted() const;
+ bool isConnected() const;
+
+public slots:
+ void setSpeakerVolume(int volume);
+ void setMicVolume(int volume);
+ void setMuted(bool is_muted);
+ void volumeDBusGetPropDone(QDBusPendingCallWatcher *call);
+
+Q_SIGNALS:
+ void speakerVolumeChanged(int volume);
+ void micVolumeChanged(int volume);
+ void muteChanged(bool muted);
+ void connected();
+ void disconnected();
+
+private:
+ QStringList m_properties; // raw return from GetProperties
+ QString m_path;
+ int m_speakerVolume;
+ int m_micVolume;
+ bool m_muted;
+ bool m_connected;
+};
+
+#endif
--- /dev/null
+/*
+ * hfdialer - Hands Free Voice Call Manager
+ * Copyright (c) 2012, Intel Corporation.
+ *
+ * This program is licensed under the terms and conditions of the
+ * Apache License, version 2.0. The full text of the Apache License is at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ */
+
+#include "networkproxy.h"
+#include <QDebug>
+
+/* **************************************************************
+ * Network Operator Class
+ * **************************************************************/
+/* TODO: make property reference/storage more generic
+
+typedef struct {
+ unsigned int id;
+ const char *name;
+} OperatorProperty;
+
+enum OperatorPropertyID {
+ CountryCode = 0,
+ NetworkCode,
+ Name,
+ Status,
+ Technologies,
+};
+
+static OperatorProperty operatorProperty[] = {
+ { CountryCode, "MobileCountryCode", },
+ { NetworkCode, "MobileNetworkCode", },
+ { Name, "Name", },
+ { Status, "Status", },
+ { Technologies, "Technologies", },
+};
+*/
+
+OperatorProxy::OperatorProxy(const QString &operatorPath)
+ : org::ofono::NetworkOperator(OFONO_SERVICE,
+ operatorPath,
+ QDBusConnection::systemBus()),
+ m_path(operatorPath), m_countryCode(""),
+ m_networkCode(""), m_name(""), m_status(""), m_technologies("")
+{
+ if (!isValid()) {
+ qCritical() << org::ofono::NetworkOperator::staticInterfaceName() <<
+ " connection failed: " << lastError().message();
+ } else {
+ QDBusPendingReply<QVariantMap> reply;
+ QDBusPendingCallWatcher * watcher;
+
+ reply = GetProperties();
+ watcher = new QDBusPendingCallWatcher(reply);
+
+ connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)),
+ this, SLOT(operatorDBusGetPropDone(QDBusPendingCallWatcher*)));
+ }
+}
+
+OperatorProxy::~OperatorProxy()
+{
+}
+
+QString OperatorProxy::path() const { return m_path; }
+QString OperatorProxy::countryCode() const { return m_countryCode; }
+QString OperatorProxy::networkCode() const { return m_networkCode; }
+QString OperatorProxy::name() const { return m_name; }
+QString OperatorProxy::status() const { return m_status; }
+QStringList OperatorProxy::technologies() const { return m_technologies; }
+
+void OperatorProxy::operatorDBusGetPropDone(QDBusPendingCallWatcher *call)
+{
+ QDBusPendingReply<QVariantMap> reply = *call;
+
+ if (reply.isError()) {
+ // TODO: Handle this properly
+ qCritical() << org::ofono::NetworkOperator::staticInterfaceName() <<
+ ".GetProperties() failed: " << reply.error().message();
+ } else {
+ QVariantMap properties = reply.value();
+ m_countryCode = qdbus_cast<QString>(properties["MobileCountryCode"]);
+ m_networkCode = qdbus_cast<QString>(properties["MobileNetworkCode"]);
+ m_name = qdbus_cast<QString>(properties["Name"]);
+ m_status = qdbus_cast<QString>(properties["Status"]);
+ m_technologies = qdbus_cast<QStringList>(properties["Technologies"]);
+ }
+}
+
+/* **************************************************************
+ * Network Registration Class
+ * **************************************************************/
+NetworkProxy::NetworkProxy(const QString &modemPath)
+ : org::ofono::NetworkRegistration(OFONO_SERVICE,
+ modemPath,
+ QDBusConnection::systemBus()),
+ m_mode(""), m_name(""), m_status(""), m_connected(false)
+{
+ if (!isValid()) {
+ qCritical() << org::ofono::NetworkRegistration::staticInterfaceName() <<
+ " connection failed: " << lastError().message();
+ } else {
+ QDBusPendingReply<QVariantMap> reply;
+ QDBusPendingCallWatcher * watcher;
+
+ reply = GetProperties();
+ watcher = new QDBusPendingCallWatcher(reply);
+
+ connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)),
+ this, SLOT(networkDBusGetPropDone(QDBusPendingCallWatcher*)));
+ }
+}
+
+NetworkProxy::~NetworkProxy()
+{
+}
+
+QList<OperatorProxy*> NetworkProxy::operators() const { return m_operators; }
+OperatorProxy* NetworkProxy::currentOperator() const
+{
+ return m_currentOperator;
+}
+QString NetworkProxy::mode() const { return m_mode; }
+QString NetworkProxy::name() const { return m_name; }
+QString NetworkProxy::status() const { return m_status; }
+
+void NetworkProxy::networkDBusGetPropDone(QDBusPendingCallWatcher *call)
+{
+ QDBusPendingReply<QVariantMap> reply = *call;
+
+ if (reply.isError()) {
+ // TODO: Handle this properly
+ qCritical() << org::ofono::NetworkRegistration::staticInterfaceName() <<
+ ".GetProperties() failed: " << reply.error().message();
+ } else {
+ QVariantMap properties = reply.value();
+ QList<QDBusObjectPath> paths =
+ qdbus_cast<QList<QDBusObjectPath> >(properties["AvailableOperators"]);
+
+ foreach (QDBusObjectPath p, paths) {
+ QString path = QString(p.path());
+ OperatorProxy *op = new OperatorProxy(path);
+
+ m_operatorPaths.append(path);
+ m_operators.append(op);
+
+ // GetProperties() has probably not completed yet, so this
+ // test will be unlikely to work.
+ // TODO: connect to the propertyChanged() signal and do this there
+/*
+ if (op->status() == "current") {
+ m_currentOperator = op;
+ qDebug() << "Current network operator is " <<
+ m_currentOperator->name() << " (" <<
+ m_currentOperator->path() << ")";
+ }
+*/
+ }
+ m_mode = qdbus_cast<QString>(properties["Mode"]);
+ m_name = qdbus_cast<QString>(properties["Operator"]);
+ m_status = qdbus_cast<QString>(properties["Status"]);
+
+ // First sucessfull GetProperties == connected
+ if (!m_connected) {
+ m_connected = true;
+ emit connected();
+ }
+ }
+}
+
--- /dev/null
+/*
+ * hfdialer - Hands Free Voice Call Manager
+ * Copyright (c) 2012, Intel Corporation.
+ *
+ * This program is licensed under the terms and conditions of the
+ * Apache License, version 2.0. The full text of the Apache License is at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ */
+
+#ifndef NETWORKPROXY_H
+#define NETWORKPROXY_H
+
+#include "modem_interface.h"
+#include "operator_interface.h"
+#include <QtDBus>
+#include <QDebug>
+
+#define OFONO_SERVICE "org.ofono"
+#define OFONO_MANAGER_PATH "/"
+
+/* **************************************************************
+ * Network Operator Class
+ * **************************************************************/
+class OperatorProxy: public org::ofono::NetworkOperator
+{
+ Q_OBJECT
+ Q_PROPERTY(QString path READ path)
+ Q_PROPERTY(QString countryCode READ countryCode)
+ Q_PROPERTY(QString networkCode READ networkCode)
+ Q_PROPERTY(QString name READ name)
+ Q_PROPERTY(QString status READ status)
+ Q_PROPERTY(QStringList technologies READ technologies)
+
+public:
+ OperatorProxy(const QString &objectPath);
+ virtual ~OperatorProxy();
+
+ QString path() const;
+ QString countryCode() const;
+ QString networkCode() const;
+ QString name() const;
+ QString status() const;
+ QStringList technologies() const;
+
+public slots:
+ void operatorDBusGetPropDone(QDBusPendingCallWatcher *call);
+
+Q_SIGNALS:
+ void propertyChanged();
+
+private:
+ QStringList m_properties; // raw return from GetProperties
+ QString m_path;
+ QString m_countryCode;
+ QString m_networkCode;
+ QString m_name;
+ QString m_status;
+ QStringList m_technologies;
+};
+
+/* **************************************************************
+ * Network Registration Class
+ * **************************************************************/
+class NetworkProxy: public org::ofono::NetworkRegistration
+{
+ Q_OBJECT
+ Q_PROPERTY(QList<OperatorProxy*> operators READ operators)
+ Q_PROPERTY(OperatorProxy currentOperator READ currentOperator)
+ Q_PROPERTY(QString mode READ mode)
+ Q_PROPERTY(QString name READ name)
+ Q_PROPERTY(QString status READ status)
+
+public:
+ NetworkProxy(const QString &objectPath);
+ virtual ~NetworkProxy();
+
+ QList<OperatorProxy*> operators() const;
+ OperatorProxy* currentOperator() const;
+ QString mode() const;
+ QString name() const;
+ QString status() const;
+
+public slots:
+ void networkDBusGetPropDone(QDBusPendingCallWatcher *call);
+
+Q_SIGNALS:
+ void propertyChanged();
+ void connected();
+ void disconnected();
+
+private:
+ OperatorProxy *m_currentOperator;
+
+ QStringList m_properties; // raw return from GetProperties
+ QStringList m_operatorPaths;
+ QList<OperatorProxy*> m_operators;
+ QString m_mode;
+ QString m_name;
+ QString m_status;
+ bool m_connected;
+};
+
+#endif
--- /dev/null
+/*
+ * hfdialer - Hands Free Voice Call Manager
+ * Copyright (c) 2012, Intel Corporation.
+ *
+ * This program is licensed under the terms and conditions of the
+ * Apache License, version 2.0. The full text of the Apache License is at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ */
+
+#include "pacontrol.h"
+#include "managerproxy.h"
+#include "callmanager.h"
+#include <string.h>
+#include <QStringBuilder>
+#include <QList>
+#include <QDebug>
+
+// Define our pulse audio loop and connection variables
+static PAControl* paControl = new PAControl;
+// Create a mainloop API and connection to the default server
+static pa_glib_mainloop *pa_ml = NULL;
+
+static void pa_subscribed_events_cb(pa_context *c, enum pa_subscription_event_type t, uint32_t , void *);
+
+static void operation_callback(pa_context *c, int success, void *userdata) {
+ Q_UNUSED(c);
+ Q_UNUSED(userdata);
+ if (!success) {
+ qDebug() << QString("Operation Failed");
+ paControl->setErrorMsg(QString("Operation Failed"));
+ }
+}
+
+static void module_callback(pa_context *c, uint32_t index, void *userdata) {
+ Q_UNUSED(c);
+ Q_UNUSED(userdata);
+ if (index == PA_INVALID_INDEX) {
+ qDebug() << QString("Load module failed");
+ paControl->setErrorMsg(QString("Load module failed"));
+ }
+}
+
+static void pa_sourcelist_cb(pa_context *c, const pa_source_info *l, int is_last, void *userdata) {
+ Q_UNUSED(c);
+ Q_UNUSED(userdata);
+ PADevice *source;
+
+ if (is_last > 0) {
+ //end of the list
+ paControl->release();
+ return;
+ }
+
+ //qDebug() << "pa_sourcelist_cb() Source added: " << l->name;
+ source = new PADevice();
+ source->index = l->index;
+ if(l->name != NULL)
+ source->name = l->name;
+ if(l->description != NULL)
+ source->description = l->description;
+ paControl->addSource(source);
+}
+
+static void pa_sinklist_cb(pa_context *c, const pa_sink_info *l, int is_last, void *userdata) {
+ Q_UNUSED(c);
+ Q_UNUSED(userdata);
+ PADevice *sink;
+
+ if (is_last > 0) {
+ //end of the list
+ paControl->release();
+ return;
+ }
+
+ //qDebug() << "pa_sinklist_cb() Sink added: " << l->name;
+ sink = new PADevice();
+ sink->index = l->index;
+ if(l->name != NULL)
+ sink->name = l->name;
+ if(l->description != NULL)
+ sink->description = l->description;
+ paControl->addSink(sink);
+}
+
+static void pa_modulelist_cb(pa_context *c, const pa_module_info *i, int is_last, void *userdata) {
+ Q_UNUSED(c);
+ Q_UNUSED(userdata);
+ PAModule *module;
+
+ if (is_last > 0) {
+ //end of the list
+ paControl->release();
+ return;
+ }
+
+ //qDebug() << "pa_modulelist_cb() Module added: " << i->name;
+ module = new PAModule();
+ module->index = i->index;
+ if(i->name != NULL)
+ module->name = i->name;
+ if(i->argument != NULL)
+ module->argument = i->argument;
+ paControl->addModule(module);
+}
+
+static void pa_state_cb(pa_context *c, void *) {
+
+ pa_context_state_t state = pa_context_get_state(c);
+ if(state == PA_CONTEXT_READY)
+ {
+ paControl->setState(true);
+ pa_context_set_subscribe_callback(c, pa_subscribed_events_cb, NULL);
+ pa_operation *o;
+ if (!(o = pa_context_subscribe(c, (pa_subscription_mask_t)
+ (PA_SUBSCRIPTION_MASK_MODULE|
+ PA_SUBSCRIPTION_MASK_SINK|
+ PA_SUBSCRIPTION_MASK_SOURCE|
+ PA_SUBSCRIPTION_MASK_SINK_INPUT|
+ PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT), NULL, NULL))) {
+ qWarning("pa_context_subscribe() failed");
+ }
+ if(o) pa_operation_unref(o);
+ ///Get an initial list of sinks, sources and modules.
+ paControl->addRef();
+ pa_context_get_sink_info_list(c, pa_sinklist_cb, NULL);
+ paControl->addRef();
+ pa_context_get_source_info_list(c, pa_sourcelist_cb, NULL);
+ paControl->addRef();
+ pa_context_get_module_info_list(c, pa_modulelist_cb, NULL);
+ }
+ else if(state == PA_CONTEXT_FAILED)
+ {
+ ///Pulseaudio crashed?
+ paControl->setState(false);
+ }
+ else
+ {
+ qDebug()<<"PA state: "<<(int) state;
+ }
+}
+
+static void pa_subscribed_events_cb(pa_context *c, enum pa_subscription_event_type t, uint32_t , void *)
+{
+ switch (t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK)
+ {
+ case PA_SUBSCRIPTION_EVENT_SINK:
+ qDebug("PA_SUBSCRIPTION_EVENT_SINK event triggered");
+ foreach(PADevice* dev, paControl->sinkList)
+ {
+ delete dev;
+ }
+ paControl->sinkList.clear();
+ paControl->addRef();
+ pa_context_get_sink_info_list(c, pa_sinklist_cb, NULL);
+ break;
+ case PA_SUBSCRIPTION_EVENT_SOURCE:
+ qDebug("PA_SUBSCRIPTION_EVENT_SOURCE event triggered");
+ foreach(PADevice* dev, paControl->sourceList)
+ {
+ delete dev;
+ }
+ paControl->sourceList.clear();
+ paControl->addRef();
+ pa_context_get_source_info_list(c, pa_sourcelist_cb, NULL);
+ break;
+ case PA_SUBSCRIPTION_EVENT_MODULE:
+ qDebug("PA_SUBSCRIPTION_EVENT_MODULE event triggered");
+ foreach(PAModule* dev, paControl->moduleList)
+ {
+ delete dev;
+ }
+ paControl->moduleList.clear();
+ paControl->addRef();
+ pa_context_get_module_info_list(c, pa_modulelist_cb, NULL);
+ break;
+ }
+}
+
+PAControl::PAControl(QObject *parent)
+ :QObject(parent) {
+ paControl = this;
+ status = SUCCESS;
+ m_paState=false;
+
+ paInit();
+}
+
+PAControl::~PAControl()
+{
+ paCleanup();
+
+ foreach (PADevice *source, sourceList) {
+ qDebug() << QString("delete source");
+ delete source;
+ }
+ foreach (PADevice *sink, sinkList) {
+ qDebug() << QString("delete sink");
+ delete sink;
+ }
+ foreach (PAModule *module, moduleList) {
+ qDebug() << QString("delete module");
+ delete module;
+ }
+
+ qDebug() << QString("~PAControl()");
+ paControl = NULL;
+}
+
+PAControl* PAControl::instance()
+{
+ return paControl;
+}
+
+void PAControl::paInit() {
+ qDebug() << "paInit()";
+
+ // Create a mainloop API and connection to the default server
+ if(!pa_ml)
+ pa_ml = pa_glib_mainloop_new(NULL);
+ pa_ctx = pa_context_new(
+ pa_glib_mainloop_get_api(pa_ml),
+ "com.tizen.hfp");
+
+ // This function connects to the pulse server
+ if (pa_context_connect(pa_ctx,
+ NULL,
+ PA_CONTEXT_NOFAIL, NULL) < 0)
+ {
+ qCritical("PulseAudioService: pa_context_connect() failed");
+ paCleanup();
+ return;
+ }
+
+ m_refCounter = 0;
+ m_connected = false;
+ m_audioRouted = false;
+ m_btSourceReady =false;
+ m_btSinkReady = false;
+
+ pa_context_set_state_callback(pa_ctx, pa_state_cb, NULL);
+}
+
+void PAControl::paCleanup() {
+ qDebug() << "paCleanup()";
+ if(pa_ctx)
+ pa_context_disconnect(pa_ctx);
+ if(pa_ctx)
+ pa_context_unref(pa_ctx);
+}
+
+void PAControl::setState(bool state)
+{
+ m_paState = state;
+ if(state == false)
+ {
+ emit paFailed();
+ }
+}
+
+void PAControl::addRef()
+{
+ m_refCounter++;
+}
+
+void PAControl::release()
+{
+ m_refCounter--;
+ Q_ASSERT(m_refCounter >= 0);
+}
+
+void PAControl::reconnect() {
+ qDebug() << "Pulseaudio: reconnect()";
+ if(paControl)
+ delete paControl;
+ paControl = new PAControl();
+}
+
+
+
+PADevice* PAControl::findBluezSource() {
+
+ if (sourceList.size() == 0)
+ {
+ addRef();
+ pa_op = pa_context_get_source_info_list(pa_ctx, pa_sourcelist_cb, NULL);
+ if(pa_op) pa_operation_unref(pa_op);
+
+ return NULL;
+ }
+
+ foreach (PADevice *source, sourceList) {
+ QString name = source->name;
+
+ if (name.startsWith(QString("bluez_source."), Qt::CaseSensitive)) {
+ qDebug() << QString(" Matched Bluez source: ") << name;
+ return source;
+ }
+ }
+
+ qDebug() << QString("Bluez source: none found");
+ return NULL;
+}
+
+PADevice* PAControl::findBluezSink() {
+
+ if (sinkList.size() == 0)
+ {
+ addRef();
+ pa_op = pa_context_get_sink_info_list(pa_ctx, pa_sinklist_cb, NULL);
+ if(pa_op) pa_operation_unref(pa_op);
+
+ return NULL;
+ }
+
+ foreach (PADevice *sink, sinkList) {
+ QString name = sink->name;
+
+ if (name.startsWith(QString("bluez_sink."), Qt::CaseSensitive)) {
+ qDebug() << QString(" Matched Bluez sink: ") << name;
+ return sink;
+ }
+ }
+
+ qDebug() << QString("Bluez sink: none found");
+ return NULL;
+}
+
+PADevice* PAControl::findAlsaSource(QString alsasource) {
+
+ if (sourceList.size() == 0)
+ {
+ addRef();
+ pa_op = pa_context_get_source_info_list(pa_ctx, pa_sourcelist_cb, NULL);
+ if(pa_op) pa_operation_unref(pa_op);
+
+ return NULL;
+ }
+
+ foreach (PADevice *source, sourceList) {
+ qDebug() << QString("Alsa source: ") << source->name;
+ QString name = source->name;
+
+ if (!alsasource.isNull() && !alsasource.isEmpty())
+ {
+ // if alsa source name is provided
+ if (alsasource == name)
+ {
+ qDebug() << QString(" Matched Alsa source: ") << name;
+ return source;
+ }
+ } else if (name.startsWith(QString("alsa_input."), Qt::CaseSensitive) &&
+ name.endsWith(QString("analog-stereo"), Qt::CaseSensitive) &&
+ !name.contains(QString("timb"))) {
+ // this is default behavior, it will try to look up one
+ qDebug() << QString(" Matched Alsa source: ") << name;
+ return source;
+ }
+ }
+
+ qDebug() << QString("Alsa source: none found");
+ return NULL;
+}
+
+PADevice* PAControl::findAlsaSink(QString alsasink) {
+
+ if (sinkList.size() == 0)
+ {
+ addRef();
+ pa_op = pa_context_get_sink_info_list(pa_ctx, pa_sinklist_cb, NULL);
+ if(pa_op) pa_operation_unref(pa_op);
+
+ return NULL;
+ }
+
+ foreach (PADevice *sink, sinkList) {
+ qDebug() << QString("Alsa sink: ") << sink->name;
+ QString name = sink->name;
+
+ if (!alsasink.isNull() && !alsasink.isEmpty())
+ {
+ // if alsa sink name is provided
+ if (alsasink == name)
+ {
+ qDebug() << QString(" Matched Alsa sink: ") << name;
+ return sink;
+ }
+ } else if (name.startsWith(QString("alsa_output."), Qt::CaseSensitive) &&
+ name.endsWith(QString("analog-stereo"), Qt::CaseSensitive) &&
+ !name.contains(QString("timb"))) {
+ // this is default behavior, it will try to look up one
+ qDebug() << QString(" Matched Alsa sink: ") << name;
+ return sink;
+ }
+ }
+
+ qDebug() << QString("Alsa sink: none found");
+ return NULL;
+}
+
+PAModule* PAControl::findModule(QString name, QString pattern) {
+
+ if (moduleList.size() == 0)
+ {
+ addRef();
+ pa_op = pa_context_get_module_info_list(pa_ctx, pa_modulelist_cb, NULL);
+ if(pa_op) pa_operation_unref(pa_op);
+
+ return NULL;
+ }
+
+ foreach (PAModule *module, moduleList) {
+ if (module->name.contains(name) && module->argument.contains(pattern)) {
+ qDebug() << QString(" Matched module: ") << module->name;
+ qDebug() << QString(" argument: ") << module->argument;
+ return module;
+ }
+ }
+
+ qDebug() << QString("Module: none found");
+ return NULL;
+}
+
+QList<PAModule*> PAControl::getAllModules()
+{
+ if (moduleList.size() == 0)
+ {
+ addRef();
+ pa_op = pa_context_get_module_info_list(pa_ctx, pa_modulelist_cb, NULL);
+ if(pa_op) pa_operation_unref(pa_op);
+ }
+
+ return moduleList;
+}
+
+void PAControl::addSource(PADevice* device)
+{
+ foreach(PADevice* dev, sourceList)
+ {
+ if(dev->name == device->name)
+ {
+ delete device;
+ return; /// already exists
+ }
+ }
+
+ sourceList.append(device);
+ emit sourceAppeared(device);
+}
+
+void PAControl::addSink(PADevice* device)
+{
+ foreach(PADevice* dev, sinkList)
+ {
+ if(dev->name == device->name)
+ {
+ delete device;
+ return; /// already exists
+ }
+ }
+
+ sinkList.append(device);
+ emit sinkAppeared(device);
+}
+
+void PAControl::addModule(PAModule *module)
+{
+ foreach(PAModule* dev, moduleList)
+ {
+ if(dev->name == module->name && dev->index == module->index)
+ {
+ delete module;
+ return; /// already exists
+ }
+ }
+
+ moduleList.append(module);
+ emit moduleAppeared(module);
+}
+
+void PAControl::routeSourceWithSink(PADevice *source, PADevice *sink) {
+ qDebug() << "Routing from " << source->name << " to " << sink->name;
+
+ if (source != NULL && sink != NULL) {
+ QString arg = "source=\"" % source->name % "\" sink=\"" % sink->name % "\"";
+
+ pa_op = pa_context_load_module(pa_ctx, "module-loopback", arg.toAscii().data(), module_callback, NULL);
+ if(pa_op) pa_operation_unref(pa_op);
+
+ qDebug() << QString("load-module module-loopback ") << arg;
+ }
+}
+
+void PAControl::toggleMuteSource(PADevice *source, bool isMute) {
+
+ if (source != NULL) {
+ pa_op =pa_context_set_source_mute_by_name(pa_ctx, source->name.toAscii().data(), isMute, operation_callback, NULL);
+ if(pa_op) pa_operation_unref(pa_op);
+
+ qDebug() << QString("set source mute ") << source->name << QString(" to ") << isMute;
+ }
+}
+
+void PAControl::unloadModule(PAModule* module) {
+
+ if (module != NULL && module->index >= 0) {
+ pa_op = pa_context_unload_module(pa_ctx, module->index, operation_callback, NULL);
+ if(pa_op) pa_operation_unref(pa_op);
+ qDebug() << QString("unload-module module-loopback ") << QString(module->name) << QString(" at index ") << module->index;
+ }
+}
+
+PAStatus PAControl::getStatus() {
+ return this->status;
+}
+
+void PAControl::setErrorMsg(QString msg) {
+ if (msg != NULL)
+ {
+ this->status = ERROR;
+ this->errorMsg = msg;
+ }
+}
+
+QString PAControl::getErrorMsg() {
+ return this->errorMsg;
+}
+
+void PAControl::onSourceAppeared(PADevice* device) {
+
+ CallManager *cm = ManagerProxy::instance()->callManager();
+ if (!cm || !cm->isValid())
+ return;
+
+ if(cm->callCount() == 0)
+ {
+ qDebug() << "no calls active, ignore";
+ return;
+ }
+
+ if(device->name.contains("bluez_source"))
+ {
+ m_btSourceReady = true;
+ }
+
+ if(!m_audioRouted && m_btSourceReady && m_btSinkReady)
+ {
+ qDebug() << QString("Route microphone and speakers");
+ routeAudio();
+ }
+}
+
+void PAControl::onSinkAppeared(PADevice* device) {
+ CallManager *cm = ManagerProxy::instance()->callManager();
+ if (!cm || !cm->isValid())
+ return;
+
+ if(cm->callCount() == 0)
+ {
+ qDebug() << "no calls active, ignore";
+ return;
+ }
+
+ if((device)->name.contains("bluez_sink"))
+ {
+ m_btSinkReady = true;
+ }
+
+ if(!m_audioRouted && m_btSourceReady && m_btSinkReady)
+ {
+ qDebug() << QString("Route microphone and speakers");
+ routeAudio();
+ }
+}
+
+void PAControl::routeAudio()
+{
+ PADevice* source;
+ PADevice* sink;
+ PADevice* mic;
+ PADevice* speaker;
+
+ if (m_audioRouted)
+ {
+ qDebug() << QString("Audio already routed");
+ return;
+ }
+
+ if (m_refCounter > 0)
+ {
+ qDebug() << "PA callback not finished, retry";
+ QTimer::singleShot(1000, this, SLOT(routeAudio()));
+ return;
+ }
+
+ qDebug() << QString("Route audio");
+ source = paControl->findBluezSource();
+ sink = paControl->findBluezSink();
+
+ if(source == NULL || sink == NULL) {
+ qDebug() << QString("Bluez source or speaker not found");
+ return;
+ }
+
+ QString alsaSourceName = MGConfItem(QString("/apps/dialer/alsasource")).value().toString();
+ QString alsaSinkName = MGConfItem(QString("/apps/dialer/alsasink")).value().toString();
+
+ mic = paControl->findAlsaSource(alsaSourceName);
+ speaker = paControl->findAlsaSink(alsaSinkName);
+
+ if (mic != NULL and speaker != NULL)
+ {
+ paControl->routeSourceWithSink(source, speaker);
+ paControl->routeSourceWithSink(mic, sink);
+ qDebug() << QString("Create loopback modules successful");
+ }
+ else {
+ qDebug() << QString("Alsa source and speaker not found");
+ }
+
+ m_audioRouted = true;
+ disconnect(this, SIGNAL(sourceAppeared(PADevice*)));
+ disconnect(this, SIGNAL(sinkAppeared(PADevice*)));
+}
+
+void PAControl::unrouteAudio()
+{
+ qDebug() << QString("Unroute audio");
+ PAControl* paControl = PAControl::instance();
+
+ QList<PAModule*> mlist = paControl->getAllModules();
+ foreach(PAModule *module, mlist)
+ {
+ if (module->name.contains("module-loopback") &&
+ module->argument.contains("bluez") &&
+ module->argument.contains("alsa")) {
+ qDebug() << QString("Found loopback module, index: ") << module->index;
+ paControl->unloadModule(module);
+ qDebug() << QString("Remove loopback module successful");
+ }
+ }
+
+ m_audioRouted = false;
+ m_btSourceReady = false;
+ m_btSinkReady = false;
+}
+
+void PAControl::onCallsChanged()
+{
+ CallManager *cm = ManagerProxy::instance()->callManager();
+ if (!cm || !cm->isValid())
+ {
+ return;
+ }
+
+ if (cm->dialingCall() || cm->activeCall() || cm->callCount() > 1)
+ {
+ // new call is dialing or phone is picked up
+ qDebug() << "PAControl: new call in progress";
+
+ if(m_audioRouted)
+ {
+ qDebug() << QString("Audio already routed");
+ return;
+ }
+
+ if(m_btSourceReady && m_btSinkReady)
+ {
+ qDebug() << QString("Route microphone and speakers");
+ routeAudio();
+ }
+ else
+ {
+ if(this->findBluezSource() != NULL && this->findBluezSink() != NULL)
+ {
+ // bt source and sink exists
+ m_btSourceReady = true;
+ m_btSinkReady = true;
+ qDebug() << QString("Route microphone and speakers");
+ routeAudio();
+ }
+ else
+ {
+ //no bt source or sink yet, let's wait until source and sink appears
+ m_btSourceReady = false;
+ m_btSinkReady = false;
+ connect(this, SIGNAL(sourceAppeared(PADevice*)), this, SLOT(onSourceAppeared(PADevice*)));
+ connect(this, SIGNAL(sinkAppeared(PADevice*)), this, SLOT(onSinkAppeared(PADevice*)));
+ qDebug() << QString("Audio not routed yet, wait for bt source and sinks");
+ }
+ }
+ }
+ else if (cm->callCount() <= 0)
+ {
+ qDebug() << QString("no more ofono calls");
+ if(m_audioRouted)
+ {
+ qDebug() << QString("Unroute microphone and speakers");
+ unrouteAudio();
+ }
+ }
+}
+
--- /dev/null
+/*
+ * hfdialer - Hands Free Voice Call Manager
+ * Copyright (c) 2012, Intel Corporation.
+ *
+ * This program is licensed under the terms and conditions of the
+ * Apache License, version 2.0. The full text of the Apache License is at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ */
+
+#ifndef PACONTROL_H
+#define PACONTROL_H
+#include <pulse/context.h>
+#include <pulse/pulseaudio.h>
+#include <pulse/glib-mainloop.h>
+#include <QObject>
+
+class PADevice {
+public:
+ QString name;
+ int index;
+ QString description;
+};
+
+class PAModule {
+public:
+ QString name;
+ int index;
+ QString argument;
+};
+
+enum PAStatus {
+ SUCCESS = 0,
+ ERROR = 1,
+};
+
+class PAControl : public QObject
+{
+ Q_OBJECT
+public:
+ PAControl(QObject *parent = 0);
+ ~PAControl();
+
+ static PAControl* instance();
+
+ void reconnect();
+ PADevice* findBluezSource();
+ PADevice* findBluezSink();
+ PADevice* findAlsaSource(QString alsasource);
+ PADevice* findAlsaSink(QString alsasink);
+ PAModule* findModule(QString name, QString pattern);
+ QList<PAModule*> getAllModules();
+ void routeSourceWithSink(PADevice *source, PADevice *sink);
+
+ void unloadModule(PAModule* module);
+ void toggleMuteSource(PADevice *source, bool isMute);
+
+ PAStatus getStatus();
+ void setErrorMsg(QString msg);
+ QString getErrorMsg();
+
+ void setState(bool state);
+ void addRef();
+ void release();
+
+ void addSource(PADevice* device);
+ void addSink(PADevice* device);
+ void addModule(PAModule* module);
+
+ QList<PADevice*> sourceList;
+ QList<PADevice*> sinkList;
+ QList<PAModule*> moduleList;
+
+public Q_SLOTS:
+ void routeAudio();
+ void unrouteAudio();
+
+Q_SIGNALS:
+ void sourceAppeared(PADevice* device);
+ void sinkAppeared(PADevice* device);
+ void moduleAppeared(PAModule* device);
+ void paFailed();
+
+private Q_SLOTS:
+ void onSourceAppeared(PADevice* device);
+ void onSinkAppeared(PADevice* device);
+ void onCallsChanged();
+
+private:
+ pa_operation *pa_op;
+ pa_context *pa_ctx;
+ PAStatus status;
+ QString errorMsg;
+
+ void paInit();
+ void paCleanup();
+
+
+ bool m_paState;
+ int m_refCounter;
+ bool m_connected;
+ bool m_audioRouted;
+ bool m_btSourceReady;
+ bool m_btSinkReady;
+};
+
+#endif // PACONTROL_H
--- /dev/null
+/*************************************************************************
+This file is part of libresourceqt
+
+Copyright (C) 2010 Nokia Corporation.
+
+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
+version 2.1 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, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
+USA.
+*************************************************************************/
+/**
+ * @file audio-resource.h
+ * @brief Declaration of ResourcePolicy::AudioResource resource class.
+ *
+ * @copyright Copyright (C) 2010 Nokia Corporation.
+ * @author Wolf Bergenheim
+ * \par License
+ * @license LGPL
+ * This file is part of libresourceqt
+ * \par
+ * Copyright (C) 2010 Nokia Corporation.
+ * \par
+ * 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
+ * version 2.1 of the License.
+ * \par
+ * 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.
+ * \par
+ * 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 AUDIO_RESOURCE_H
+#define AUDIO_RESOURCE_H
+
+#include <QObject>
+#include <QString>
+#include <policy/resource.h>
+
+namespace ResourcePolicy
+{
+
+/**
+ * The AudioResource class represents the audio device. It is a bit
+ * different from other resource types in that in takes more parameters to
+ * allow the programmer to classify the audio stream used by the application.
+ */
+class AudioResource: public QObject, public Resource
+{
+ Q_OBJECT
+public:
+ /**
+ * The constructor.
+ * \param audioGroup The audio group which this application belongs to.
+ * This is an optional parameter.
+ */
+ AudioResource(const QString &audioGroup = QString());
+ AudioResource(const AudioResource &other);
+ virtual ~AudioResource();
+
+ //! Accessor for the audioGroup.
+ QString audioGroup() const;
+ //! A test to check whether the audio group is set or not.
+ bool audioGroupIsSet() const;
+ /**
+ * Set the audio group (classification)
+ * \param newGroup The new audio group to set.
+ */
+ void setAudioGroup(const QString & newGroup);
+
+ //! \return The PID of the process which is responsible for rendering the audio stream.
+ quint32 processID() const;
+ /**
+ * Use this to indicate to the Resource Manager the PID of the audio
+ * stream renderer.
+ * \param newPID Set this to the PID of the process which will render the audio.
+ */
+ void setProcessID(quint32 newPID);
+
+ //! \return the name of the stream tag.
+ QString streamTagName() const;
+ //! \return the value of the stream tag.
+ QString streamTagValue() const;
+ //! A test to check whether the stream tag has been set or not.
+ bool streamTagIsSet() const;
+ /**
+ * Set the tream tag to help policy to correctly identify the audio stream
+ * beloning to you.
+ * \param name The name of the tag. For example "media.name"
+ * \param value The value of the stream tag.
+ */
+ void setStreamTag(const QString &name, const QString &value);
+
+ virtual ResourceType type() const;
+private:
+ QString group;
+ quint32 pid;
+ QString streamName;
+ QString streamValue;
+signals:
+ /**
+ * This signal is emitted when any of the properties of the AudioResource
+ * are changed. This signal is connected to in the ResourceSet to
+ * track the changes to the AudioResource object.
+ * \param group The new audio group
+ * \param pid The new PID of the audio renderer
+ * \param name The new Stream tag name
+ * \param value the new stream tag value
+ */
+ void audioPropertiesChanged(const QString &group, quint32 pid,
+ const QString &name, const QString &value);
+};
+}
+
+#endif
--- /dev/null
+/*************************************************************************
+This file is part of libresourceqt
+
+Copyright (C) 2010 Nokia Corporation.
+
+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
+version 2.1 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, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
+USA.
+*************************************************************************/
+/**
+ * @file resource-set.h
+ * @brief Declaration of ResourcePolicy::ResourceSet
+ *
+ * @copyright Copyright (C) 2010 Nokia Corporation.
+ * @author Wolf Bergenheim
+ * \par License
+ * @license LGPL
+ * This file is part of libresourceqt
+ * \par
+ * Copyright (C) 2010 Nokia Corporation.
+ * \par
+ * 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
+ * version 2.1 of the License.
+ * \par
+ * 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.
+ * \par
+ * 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 RESOURCE_SET_H
+#define RESOURCE_SET_H
+
+#include <QString>
+#include <QObject>
+#include <QVector>
+#include <QList>
+#include <policy/resources.h>
+#include <policy/audio-resource.h>
+
+/**
+ * \mainpage Resource Policy Library
+ *
+ * \section intro_section Introduction
+ *
+ * This library is used to request resources from the Policy Resource Manager.
+ * To use this library two classes are provided: \ref ResourcePolicy::Resource and
+ * \ref ResourcePolicy::ResourceSet.
+ *
+ * \section library_use_section Library Usage
+ *
+ * To use the Resource Policy Library, you first need to create the
+ * \ref ResourcePolicy::ResourceSet like this:
+ * \code
+ * ResourcePolicy::ResourceSet *resources = new ResourcePolicy::ResourceSet("player");
+ * \endcode
+ * Then to add resources to the set use the ResourceSet::addResource() method to add
+ * resources to the ResourcePolicy::ResourceSet. Like this:
+ * \code
+ * resources->addResource(AudioPlaybackType);
+ * resources->addResource(VideoPlaybackType);
+ * \endcode
+ * If you want to pre-populate the AudioResource with the audio group (it is a good idea)
+ * and other audio parameters you can create an audio object yourself and then
+ * give that to the ResourcePolicy::ResourceSet. Note that you should NOT free this object.
+ * The ResourcePolicy::ResourceSet takes ownership of this pointer.
+ * \code
+ * ResourcePolicy::AudioResource *audioResource = new ResourcePolicy::AudioResource("player");
+ * resources->addResourceObject(audioResource);
+ * \endcode
+ * Calling the ResourcePolicy::ResourceSet::deleteResource() method will remove
+ * and delete the object. Then when you want to acquire the ResourcePolicy::ResourceSet
+ * you simply use the ResourcePolicy::ResourceSet::acquire() method, like this:
+ * \code
+ * QObject::connect(resources, SIGNAL(resourcesAcquired()),
+ * this, SLOT(acquireOkHandler(QList<ResourcePolicy::Resource>)));
+ * QObject::connect(resources, SIGNAL(resourcesDenied()), this, SLOT(acquireDeniedHandler()));
+ * resources->acquire();
+ * \endcode
+ * You should also connect to the ResourcePolicy::ResourceSet::lostResources() signal like this:
+ * \code
+ * QObject::connect(resources, SIGNAL(lostResources()),
+ * this, SLOT(lostResources()));
+ * \endcode
+ * This signal tells you when you should stop using the resources you have asked for.
+ * So it is important that you connect to it.
+ *
+ * To modify the properties of the resources you can use the ResourcePolicy::ResourceSet::resource() method.
+ *
+ * \section see_devel_doc See Also
+ * For a more detailed guide see the
+ * <a href="https://projects.maemo.org/mediawiki/index.php/Maemo_Developer_Guide/Developing_Harmattan_applications/Application_policy_guidelines">Application policy guidelines</a>.
+ */
+
+/**
+ * \brief The Namespace for Resource Policy.
+ * All Resource Policy Qt APIs reside under the ResourcePolicy namespace.
+ */
+namespace ResourcePolicy
+{
+class ResourceEngine;
+/**
+ * The resourceSet repesents a set of attributes. Each set can only contain
+ * a single Resource of a given type. That is one AudioPlaybackResource, etc.
+ *
+ * Internally the set is stored as a QVector of \ref Resource objects.
+ */
+class ResourceSet: public QObject
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(ResourceSet)
+public:
+ /**
+ * Alternative constructor with additional parameters for setting
+ * alwaysReply and autoRelease.
+ * \param applicationClass This parameter defines the application class.
+ * The application class is used to determine the priority order of the
+ * application.
+ * \param parent The parent of this class.
+ * \param alwaysReply see setAlwaysReply()
+ * \param autoRelease see setAutoRelease()
+ */
+ ResourceSet(const QString &applicationClass, QObject *parent,
+ bool alwaysReply, bool autoRelease);
+ /**
+ * Alternative backwards-compatible constructor.
+ * \param applicationClass This parameter defines the application class.
+ * The application class is used to determine the priority order of the
+ * application.
+ * \param parent The optional parent of of this class.
+ */
+ ResourceSet(const QString &applicationClass, QObject *parent = NULL);
+ /**
+ * The destructor
+ */
+ ~ResourceSet();
+
+ /**
+ * This method adds a resource to the set. A set contains only a single
+ * instance of a given resource. If the ResourceSet already contains a
+ * resource of the given type it will be overridden.
+ * \param resourceType The resource to add to the set. A copy of this object
+ * is stored in the Set.
+ */
+ bool addResource(ResourceType resourceType);
+
+ /**
+ * This method adds a resource to the set. A set contains only a single
+ * instance of a given resource. If the ResourceSet already contains a
+ * resource of the given type it will be overridden.
+ * \param resource The resource to add to the set.
+ * The ResourcePolicy::ResourseSet takes ownership of the pointer. Do NOT free!
+ */
+ void addResourceObject(Resource *resource);
+
+ /**
+ * This method removes the resource of the given type
+ * \param type The type of the resource to remove from the set.
+ */
+ void deleteResource(ResourceType type);
+
+ /**
+ * This method returns a list of all resource in the set.
+ * \return a QList of all resources in the set.
+ */ QList<Resource *> resources() const;
+ /**
+ * This method returns a const pointer to a resource of a specific type.
+ * \param type The type of resource we are interested in.
+ * \return a pointer to the Resource if it is defined NULL otherwise.
+ */
+ Resource * resource(ResourceType type) const;
+ /**
+ * Checks if the \ref ResourceSet contains the given \ref Resource
+ * \param type The Resource to look for
+ * \return true if the \ref Resource is defined in this \ref ResourceSet
+ */
+ bool contains(ResourceType type) const;
+
+ /**
+ * Checks if the \ref ResourceSet contains all given resources.
+ * \param types A list of resources to check for
+ * \return true if \b all given resources are defined in the ResourceSet.
+ */
+ bool contains(const QList<ResourceType> &types) const;
+
+ /**
+ * Returns the unique identifier for this ResourceSet.
+ * @return the unique identifier for this ResourceSet.
+ */
+ quint32 id() const;
+
+ /**
+ * Returns the registered application class (given in the constructor).
+ */
+ QString applicationClass();
+
+ /**
+ * Initialize and connect the ResourceEngine of this ResourceSet.
+ * Use this method after adding resources to the ResourceSet initially.
+ * \return true if the method succeeds without encountering errors.
+ */
+ bool initAndConnect();
+
+ /**
+ * Try to acquire the \ref ResourceSet. The resourcesGranted() or
+ * resourcesDenied() signal will be emited depending on whether the
+ * requested resources could be acquired or not.
+ */
+ bool acquire();
+ /**
+ * Release the acquired resources.
+ */
+ bool release();
+ /**
+ * Commit changes to the \ref ResourcePolicy::ResourceSet. Remember to call update()
+ * after adding and/or removing resources.
+ */
+ bool update();
+
+ /**
+ * Sets the auto-release. When loosing the resources due to another
+ * application with a higher priority the default is that we automatically
+ * re-gain our resources without having to re-request them. However if
+ * the AutoRelease is set we release the resources and need to re-acquire
+ * them, when the pre-emting application releases its resources.
+ *
+ * This feature is by default disabled.
+ *
+ * This flag should be set once only before calling anything else
+ * (excluding setAlwaysReply()), and cannot be unset.
+ */
+ bool setAutoRelease();
+ /**
+ * Check whether we have setAutoRelease().
+ * \return true if auto-release is ennabled.
+ */
+ bool willAutoRelease();
+ /**
+ * Sets that the resourcesGranted() signal is emited even if we already
+ * have the requested resources granted. By default this feature is off.
+ *
+ * This flag should be set once only before calling anything else
+ * (excluding setAutoRelease()), and cannot be unset.
+ */
+ bool setAlwaysReply();
+ /**
+ * Check whether the always-get-reply flag has been set.
+ * \return true if we will always get a reply (even if there is no change).
+ */
+ bool alwaysGetReply();
+
+signals:
+ /**
+ * This signal is emited when the Resource Policy Manager notifies that
+ * the given resources have become available.
+ * \param availableResources A list of available resources. The list of
+ * available resources contains only available resource which we have in the set.
+ */
+ void resourcesBecameAvailable(const QList<ResourcePolicy::ResourceType> &availableResources);
+ /**
+ * This signal is emitted as a response to the acquire() request.
+ * \param grantedOptionalResources The list of granted optional resources.
+ * All the mandatory resources have also been acquired.
+ */
+ void resourcesGranted(const QList<ResourcePolicy::ResourceType> &grantedOptionalResources);
+ /**
+ * This signal is emitted as a response to the acquire() request, in the
+ * case where one or more of the mandatory resources were not available.
+ */
+ void resourcesDenied();
+ /**
+ * This signal is emitted as a response to the release() request.
+ */
+ void resourcesReleased();
+ /**
+ * This signal is emited when the manager releases our acquired resources,
+ * so that we have to acquire them again when the user wishes to interact
+ * with us.
+ */
+ void resourcesReleasedByManager();
+ /**
+ * This signal is emitted when some other program with a higher priority
+ * supersedes us, and as a result we loose (some of) our resources.
+ * It is very important to connect to this signal as it is signaling when
+ * the acquired resources shouldn't be used anymore.
+ */
+ void lostResources();
+
+ /**
+ * Subscribe to this signal to receive error notifications,
+ * particularly security errors.
+ */
+ void errorCallback(quint32, const char*);
+
+ /**
+ * This signals that we have connected to the Resource Manager.
+ */
+ void connectedToManager();
+
+private:
+
+ bool initialize();
+
+ quint32 identifier;
+ const QString resourceClass;
+ Resource* resourceSet[NumberOfTypes];
+ ResourceEngine *resourceEngine;
+ AudioResource *audioResource;
+ bool autoRelease;
+ bool alwaysReply;
+ bool initialized;
+ bool pendingAcquire;
+ bool pendingUpdate;
+ bool pendingAudioProperties;
+ bool haveAudioProperties;
+
+ void registerAudioProperties();
+
+private slots:
+ void connectedHandler();
+ void handleGranted(quint32);
+ void handleDeny();
+ void handleReleased();
+ void handleResourcesLost(quint32);
+ void handleResourcesBecameAvailable(quint32);
+
+ void handleAudioPropertiesChanged(const QString &group, quint32 pid,
+ const QString &name, const QString &value);
+
+};
+}
+
+#endif
+
--- /dev/null
+/*************************************************************************
+This file is part of libresourceqt
+
+Copyright (C) 2010 Nokia Corporation.
+
+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
+version 2.1 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, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
+USA.
+*************************************************************************/
+/**
+ * @file resource.h
+ * @brief Declaration of ResourcePolicy::Resource and
+ * ResourcePolicy::ResourceType
+ *
+ * @copyright Copyright (C) 2010 Nokia Corporation.
+ * @author Wolf Bergenheim
+ * \par License
+ * @license LGPL
+ * This file is part of libresourceqt
+ * \par
+ * Copyright (C) 2010 Nokia Corporation.
+ * \par
+ * 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
+ * version 2.1 of the License.
+ * \par
+ * 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.
+ * \par
+ * 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 RESOURCE_H
+#define RESOURCE_H
+
+#include <QtCore>
+
+namespace ResourcePolicy
+{
+/**
+ * This enumeration represents the resources which can be reserved.
+ * \see ResourcePolicy::ResourceSet for info on how to reserve resources.
+ */
+enum ResourceType {
+ AudioPlaybackType = 0, ///< For audio playback
+ VideoPlaybackType, ///< For video playback
+ AudioRecorderType, ///< For audio recording (using of the microphone)
+ VideoRecorderType, ///< For video recording (using the camera)
+ VibraType, ///< For Vibra
+ LedsType, ///< For LEDs
+ BacklightType, ///< For the backlight (of the display)
+ SystemButtonType, ///< For the system (power) button
+ LockButtonType, ///< For the lock button
+ ScaleButtonType, ///< The scale (zoom) button
+ SnapButtonType, ///< Use this if you are a camera application
+ LensCoverType,
+ HeadsetButtonsType, ///< Use this to reserve the headset buttons
+ NumberOfTypes
+};
+
+class ResourceSet;
+
+/**
+ * This class is the super class for all resources. It represents a generic
+ * \ref Resource. The type specific resource classes should be used.
+ */
+class Resource
+{
+ friend class ResourceSet;
+public:
+ /**
+ * Whether or not this resource is optional, in that it doesn't need to
+ * be available for the set to be acquired.
+ * \return true when this resource is optional.
+ */
+ bool isOptional() const;
+ /**
+ * Set the resource to be optional or mandatory.
+ * \param resourceIsOptional This optional parameter defaults to true.
+ * The default, true, results in the resource becoming optional. When it
+ * is set to false the resource becomes mandatory.
+ */
+ void setOptional(bool resourceIsOptional = true);
+ /**
+ * Whether or not the resource to be shared. If it is shared then other
+ * programs are allowed to share this resource.
+ * \return true when this resource is shared.
+ */
+ bool isGranted() const;
+
+ /**
+ * Use this method to check for the type of Resource
+ * \return The ResourceType associated to this resource
+ */
+ virtual ResourceType type() const = 0;
+ virtual ~Resource();
+protected:
+ Resource();
+ Resource(const Resource &other);
+
+ /**
+ * \internal
+ * This holds the type of the resource.
+ */
+ ResourceType resourceType;
+ /**
+ * \internal
+ * This is true when this resource is optional.
+ * \sa isOptional
+ * \sa setOptional
+ */
+ bool optional;
+ /**
+ * \internal
+ * This is just a unique identifier for the resource.
+ */
+ quint32 identifier;
+private:
+ void setGranted();
+ void unsetGranted();
+ bool granted;
+
+};
+}
+
+#endif
+
--- /dev/null
+/*************************************************************************
+This file is part of libresourceqt
+
+Copyright (C) 2010 Nokia Corporation.
+
+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
+version 2.1 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, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
+USA.
+*************************************************************************/
+/**
+ * @file resources.h
+ * @brief Declaration of The different resource classes:
+ * ResourcePolicy::AudioRecorderResource
+ * ResourcePolicy::BacklightResource
+ * ResourcePolicy::LedsResource
+ * ResourcePolicy::VibraResource
+ * ResourcePolicy::VideoRecorderResource
+ * ResourcePolicy::VideoResource
+ * ResourcePolicy::LockButtonResource
+ * ResourcePolicy::ScaleButtonResource
+ * ResourcePolicy::SystemButtonResource
+ * ResourcePolicy::LensCoverResource
+ * ResourcePolicy::HeadsetButtonsResource
+ *
+ * @copyright Copyright (C) 2010 Nokia Corporation.
+ * @author Wolf Bergenheim
+ * \par License
+ * @license LGPL
+ * This file is part of libresourceqt
+ * \par
+ * Copyright (C) 2010 Nokia Corporation.
+ * \par
+ * 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
+ * version 2.1 of the License.
+ * \par
+ * 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.
+ * \par
+ * 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 RESOURCES_H
+#define RESOURCES_H
+
+#include <policy/resource.h>
+#include <QString>
+
+namespace ResourcePolicy
+{
+
+/**
+ * The AudioRecorderResource class represents the audio recorder device.
+ */
+class AudioRecorderResource: public Resource
+{
+public:
+ /**
+ * The constructor.
+ */
+ AudioRecorderResource();
+ /**
+ * The copy constructor.
+ * \param other The resource to copy from
+ */
+ AudioRecorderResource(const AudioRecorderResource &other);
+ /**
+ * The destructor.
+ */
+ virtual ~AudioRecorderResource();
+
+ /**
+ * \return the resource type
+ */
+ virtual ResourceType type() const;
+};
+
+/**
+ * The BacklightResource is used by applications wanting to control the
+ * backlight
+ */
+class BacklightResource: public Resource
+{
+public:
+ /**
+ * The constructor.
+ */
+ BacklightResource();
+ /**
+ * The copy constructor.
+ * \param other The resource to copy from
+ */
+ BacklightResource(const BacklightResource &other);
+ /**
+ * The destructor.
+ */
+ virtual ~BacklightResource();
+
+ /**
+ * \return the resource type
+ */
+ virtual ResourceType type() const;
+};
+
+/**
+ * Resource to be used when the application wants to fiddle with the leds.
+ */
+class LedsResource: public Resource
+{
+public:
+ /**
+ * The constructor.
+ */
+ LedsResource();
+ /**
+ * The copy constructor.
+ * \param other The resource to copy from
+ */
+ LedsResource(const LedsResource &other);
+ /**
+ * The destructor.
+ */
+ virtual ~LedsResource();
+
+ /**
+ * \return the resource type
+ */
+ virtual ResourceType type() const;
+};
+
+/**
+ * Resource to be used when the application wants to use the vibra.
+ */
+class VibraResource: public Resource
+{
+public:
+ /**
+ * The constructor.
+ */
+ VibraResource();
+ /**
+ * The copy constructor.
+ * \param other The resource to copy from
+ */
+ VibraResource(const VibraResource &other);
+ /**
+ * The destructor.
+ */
+ virtual ~VibraResource();
+
+ /**
+ * \return the resource type
+ */
+ virtual ResourceType type() const;
+};
+
+/**
+ * Resource to be used when the application wants to record video.
+ */
+class VideoRecorderResource: public Resource
+{
+public:
+ /**
+ * The constructor.
+ */
+ VideoRecorderResource();
+ /**
+ * The copy constructor.
+ * \param other The resource to copy from
+ */
+ VideoRecorderResource(const VideoRecorderResource &other);
+ /**
+ * The destructor.
+ */
+ virtual ~VideoRecorderResource();
+
+ /**
+ * \return the resource type
+ */
+ virtual ResourceType type() const;
+};
+
+/**
+ * Resource to be used when the application wants to render video with the
+ * DSP decoder to render the viewfinder.
+ */
+class VideoResource: public Resource
+{
+public:
+ /**
+ * The constructor.
+ */
+ VideoResource();
+ /**
+ * The copy constructor.
+ * \param other The resource to copy from
+ */
+ VideoResource(const VideoResource &other);
+ /**
+ * The destructor.
+ */
+ virtual ~VideoResource();
+
+ /**
+ * \return the resource type
+ */
+ virtual ResourceType type() const;
+};
+
+/**
+ * Resource to be used when the application wants to control the system button.
+ */
+class SystemButtonResource: public Resource
+{
+public:
+ /**
+ * The constructor.
+ */
+ SystemButtonResource();
+ /**
+ * The copy constructor.
+ * \param other The resource to copy from
+ */
+ SystemButtonResource(const SystemButtonResource &other);
+ /**
+ * The destructor.
+ */
+ virtual ~SystemButtonResource();
+
+ /**
+ * \return the resource type
+ */
+ virtual ResourceType type() const;
+};
+
+/**
+ * Resource to be used when the application wants to control the lock button.
+ */
+class LockButtonResource: public Resource
+{
+public:
+ /**
+ * The constructor.
+ */
+ LockButtonResource();
+ /**
+ * The copy constructor.
+ * \param other The resource to copy from
+ */
+ LockButtonResource(const LockButtonResource &other);
+ /**
+ * The destructor.
+ */
+ virtual ~LockButtonResource();
+
+ /**
+ * \return the resource type
+ */
+ virtual ResourceType type() const;
+};
+
+/**
+ * Resource to be used when the application wants to control
+ * the volume/scale button.
+ */
+class ScaleButtonResource: public Resource
+{
+public:
+ /**
+ * The constructor.
+ */
+ ScaleButtonResource();
+ /**
+ * The copy constructor.
+ * \param other The resource to copy from
+ */
+ ScaleButtonResource(const ScaleButtonResource &other);
+ /**
+ * The destructor.
+ */
+ virtual ~ScaleButtonResource();
+
+ /**
+ * \return the resource type
+ */
+ virtual ResourceType type() const;
+};
+
+/**
+ * Resource to be used when the application wants to take still pictures.
+ */
+class SnapButtonResource: public Resource
+{
+public:
+ /**
+ * The constructor.
+ */
+ SnapButtonResource();
+ /**
+ * The copy constructor.
+ * \param other The resource to copy from
+ */
+ SnapButtonResource(const SnapButtonResource &other);
+ /**
+ * The destructor.
+ */
+ virtual ~SnapButtonResource();
+
+ /**
+ * \return the resource type
+ */
+ virtual ResourceType type() const;
+};
+
+class LensCoverResource: public Resource
+{
+public:
+ /**
+ * The constructor.
+ */
+ LensCoverResource();
+ /**
+ * The copy constructor.
+ * \param other The resource to copy from
+ */
+ LensCoverResource(const LensCoverResource &other);
+ /**
+ * The destructor.
+ */
+ virtual ~LensCoverResource();
+
+ /**
+ * \return the resource type
+ */
+ virtual ResourceType type() const;
+};
+
+/**
+ * Resource to be used when the application wants to control the
+ * headset buttons.
+ */
+class HeadsetButtonsResource: public Resource
+{
+public:
+ /**
+ * The constructor.
+ */
+ HeadsetButtonsResource();
+ /**
+ * The copy constructor.
+ * \param other The resource to copy from
+ */
+ HeadsetButtonsResource(const HeadsetButtonsResource &other);
+ /**
+ * The destructor.
+ */
+ virtual ~HeadsetButtonsResource();
+
+ /**
+ * \return the resource type
+ */
+ virtual ResourceType type() const;
+};
+
+}
+#endif
+
--- /dev/null
+/*
+ * dialer - Declarative Dialer UX Main Window.
+ * Copyright (c) 2011, Tom Swindell.
+ *
+ * This program is licensed under the terms and conditions of the
+ * Apache License, version 2.0. The full text of the Apache License is at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ */
+
+#include "common.h"
+#include "qmlcallitem.h"
+
+class QMLCallItemPrivate
+{
+public:
+ CallItem *proxy;
+};
+
+QMLCallItem::QMLCallItem(CallItem *proxy, QObject *parent)
+ : QObject(parent), d(new QMLCallItemPrivate)
+{
+ TRACE
+ d->proxy = proxy;
+
+ QObject::connect(proxy->callProxy(), SIGNAL(stateChanged()), SLOT(onStateChanged()));
+}
+
+QMLCallItem::~QMLCallItem()
+{
+ TRACE
+ delete this->d;
+}
+
+CallItem* QMLCallItem::proxy() const
+{
+ TRACE
+ return d->proxy;
+}
+
+QString QMLCallItem::msisdn() const
+{
+ TRACE
+ if (d->proxy->callProxy())
+ return d->proxy->callProxy()->lineID();
+ return QString();
+}
+
+int QMLCallItem::numberLen() const
+{
+ TRACE
+ QString number = msisdn();
+ return number.size();
+}
+
+QString QMLCallItem::name() const
+{
+ TRACE
+ if (d->proxy->callProxy())
+ return d->proxy->callProxy()->name();
+ return QString();
+}
+
+QString QMLCallItem::state() const
+{
+ TRACE
+ if (d->proxy->callProxy())
+ return d->proxy->callProxy()->state();
+ return QString();
+}
+
+QString QMLCallItem::reason() const
+{
+ TRACE
+ if (d->proxy->callProxy())
+ return d->proxy->callProxy()->reason();
+ return QString();
+}
+
+QDateTime QMLCallItem::startedAt() const
+{
+ TRACE
+ if (d->proxy->callProxy())
+ return d->proxy->callProxy()->startTime();
+ return QDateTime();
+}
+
+int QMLCallItem::duration() const
+{
+ TRACE
+ return 32;
+
+ if (d->proxy->callProxy())
+ return d->proxy->callProxy()->duration();
+ return 66;
+}
+
+bool QMLCallItem::isMultiparty() const
+{
+ TRACE
+ if (d->proxy->callProxy())
+ return d->proxy->callProxy()->multiparty();
+ return false;
+}
+
+void QMLCallItem::answer()
+{
+ TRACE
+ if (d->proxy->callProxy())
+ d->proxy->callProxy()->answer();
+}
+
+void QMLCallItem::deflect(const QString &msisdn)
+{
+ TRACE
+ if (d->proxy->callProxy())
+ d->proxy->callProxy()->deflect(msisdn);
+}
+
+void QMLCallItem::hangup()
+{
+ TRACE
+ if (d->proxy->callProxy())
+ d->proxy->callProxy()->hangup();
+}
+
+void QMLCallItem::onStateChanged()
+{
+ TRACE
+ emit this->stateChanged(d->proxy->callProxy()->state());
+}
--- /dev/null
+/*
+ * dialer - CallItem Declarative Proxy Implementation.
+ * Copyright (c) 2011, Tom Swindell.
+ *
+ * This program is licensed under the terms and conditions of the
+ * Apache License, version 2.0. The full text of the Apache License is at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ */
+
+#ifndef QMLCALLITEM_H
+#define QMLCALLITEM_H
+
+#include "callitem.h"
+
+#include <QObject>
+#include <QDateTime>
+
+class QMLCallItem : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QString msisdn READ msisdn)
+ Q_PROPERTY(QString name READ name)
+ Q_PROPERTY(QString state READ state NOTIFY stateChanged)
+ Q_PROPERTY(QString reason READ reason)
+ Q_PROPERTY(int numberLen READ numberLen)
+ Q_PROPERTY(QDateTime startedAt READ startedAt)
+ Q_PROPERTY(int duration READ duration)
+
+ Q_PROPERTY(bool isMultiparty READ isMultiparty)
+
+public:
+ explicit QMLCallItem(CallItem *proxy, QObject *parent = 0);
+ ~QMLCallItem();
+
+ QString msisdn () const;
+ int numberLen () const;
+ QString name () const;
+ QString state () const;
+
+ QDateTime startedAt () const;
+ int duration () const;
+
+ QString reason () const;
+ bool isMultiparty () const;
+
+ CallItem* proxy () const;
+
+Q_SIGNALS:
+ void stateChanged (const QString &state);
+
+public Q_SLOTS:
+ void answer ();
+ void deflect (const QString &msisdn);
+ void hangup ();
+
+protected Q_SLOTS:
+ void onStateChanged ();
+
+private:
+ class QMLCallItemPrivate *d;
+
+ Q_DISABLE_COPY(QMLCallItem)
+};
+
+#endif // QMLCALLITEM_H
--- /dev/null
+/*
+ * dialer - Declarative Dialer UX Main Window.
+ * Copyright (c) 2011, Tom Swindell.
+ *
+ * This program is licensed under the terms and conditions of the
+ * Apache License, version 2.0. The full text of the Apache License is at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ */
+
+#include "common.h"
+#include "qmldialer.h"
+#include "dialerapplication.h"
+#include "dialercontext.h"
+#include "callmanager.h"
+#include "managerproxy.h"
+
+#define CONFIG_KEY_VOICEMAIL_NUMBER "/apps/dialer/voicemail/number"
+
+class QMLDialerPrivate
+{
+public:
+ QMLDialerPrivate()
+ : currentCall(NULL)
+ { TRACE }
+
+ QMLCallItem *currentCall;
+};
+
+QMLDialer::QMLDialer(QObject *parent)
+ : QObject(parent), d(new QMLDialerPrivate)
+{
+ TRACE
+ CallManager *cm = ManagerProxy::instance()->callManager();
+
+ this->connectAll();
+ connect(ManagerProxy::instance(), SIGNAL(callManagerChanged()), SLOT(onCallManagerChanged()));
+
+ if(cm && cm->activeCall()) d->currentCall = new QMLCallItem(cm->activeCall(), this);
+}
+
+QMLDialer::~QMLDialer()
+{
+ TRACE
+ delete this->d;
+}
+
+QString QMLDialer::mailbox() const
+{
+ TRACE
+
+ if(ManagerProxy::instance()->voicemail()->isConnected())
+ {
+ return ManagerProxy::instance()->voicemail()->mailbox();
+ }
+
+ // Fall back to GConf voicemail setting.
+ return MGConfItem(CONFIG_KEY_VOICEMAIL_NUMBER).value().toString();
+}
+
+bool QMLDialer::modemOnline()
+{
+ if(ManagerProxy::instance()->modem() &&
+ ManagerProxy::instance()->modem()->isValid())
+ {
+ return ManagerProxy::instance()->modem()->powered();
+ }
+
+ return false;
+}
+
+void QMLDialer::setMailbox(const QString &number)
+{
+ TRACE
+
+ if(ManagerProxy::instance()->voicemail()->isConnected())
+ {
+ ManagerProxy::instance()->voicemail()->setMailbox(number);
+ return;
+ }
+
+ // Fall back to GConf voicemail setting.
+ MGConfItem(CONFIG_KEY_VOICEMAIL_NUMBER).set(number);
+}
+
+void QMLDialer::setModemOnline(bool online)
+{
+ if(ManagerProxy::instance()->modem()->isValid())
+ {
+ ManagerProxy::instance()->modem()->setPowered(online);
+ return;
+ }
+}
+
+QString QMLDialer::speedDial(int index) const
+{
+ TRACE
+ return MGConfItem(QString("/apps/dialer/speeddial/%1").arg(index)).value().toString();
+}
+
+void QMLDialer::setSpeedDial(int index, const QString &number)
+{
+ TRACE
+ MGConfItem(QString("/apps/dialer/speeddial/%1").arg(index)).set(number);
+}
+
+QMLCallItem* QMLDialer::currentCall() const
+{
+ TRACE
+ return d->currentCall;
+}
+
+void QMLDialer::dial(const QString &msisdn)
+{
+ TRACE
+ CallManager *cm = ManagerProxy::instance()->callManager();
+ if (cm && cm->isValid())
+ {
+ cm->dial(msisdn);
+ }
+
+}
+
+void QMLDialer::hangupAll()
+{
+ TRACE
+ CallManager *cm = ManagerProxy::instance()->callManager();
+ if ((cm && cm->isValid()))
+ {
+ cm->hangupAll();
+ }
+}
+
+void QMLDialer::silenceRingtone()
+{
+ if(ManagerProxy::instance()->volumeManager()->isConnected())
+ {
+ qDebug() << "Attempting to mute call with volume manager.";
+ ManagerProxy::instance()->volumeManager()->setMuted(true);
+ }
+ else if(d->currentCall)
+ {
+ qDebug() << "Attempting to mute call with call item signaller.";
+ d->currentCall->proxy()->silenceRingtone();
+ }
+ else
+ {
+ qDebug() << "Couldn't decide how to mute ringtone!";
+ }
+}
+
+void QMLDialer::sendTones(const QString &tones)
+{
+ TRACE
+ CallManager *cm = ManagerProxy::instance()->callManager();
+ if (cm && cm->isValid())
+ cm->sendTones(tones);
+}
+
+void QMLDialer::transfer()
+{
+ TRACE
+ CallManager *cm = ManagerProxy::instance()->callManager();
+ if (cm && cm->isValid())
+ cm->transfer();
+}
+
+void QMLDialer::swapCalls()
+{
+ TRACE
+ CallManager *cm = ManagerProxy::instance()->callManager();
+ if (cm && cm->isValid())
+ cm->swapCalls();
+}
+
+void QMLDialer::releaseAndAnswer()
+{
+ TRACE
+ CallManager *cm = ManagerProxy::instance()->callManager();
+ if (cm && cm->isValid())
+ cm->releaseAndAnswer();
+}
+
+void QMLDialer::holdAndAnswer()
+{
+ TRACE
+ CallManager *cm = ManagerProxy::instance()->callManager();
+ if (cm && cm->isValid())
+ cm->holdAndAnswer();
+}
+
+void QMLDialer::createMultiparty()
+{
+ /* TRACE
+ CallManager *cm = ManagerProxy::instance()->callManager();
+ if (cm && cm->isValid())
+ cm->createMultiparty();
+*/
+}
+
+void QMLDialer::hangupMultiparty()
+{
+/*
+ TRACE
+ CallManager *cm = ManagerProxy::instance()->callManager();
+ if (cm && cm->isValid())
+ cm->hangupMultiparty();
+*/
+}
+
+void QMLDialer::privateChat(const QMLCallItem &call)
+{
+ TRACE
+ CallManager *cm = ManagerProxy::instance()->callManager();
+ if (cm && cm->isValid())
+ cm->privateChat(*call.proxy());
+}
+
+void QMLDialer::onCallsChanged()
+{
+ TRACE
+ CallManager *cm = ManagerProxy::instance()->callManager();
+
+ if(cm->activeCall())
+ {
+ this->onIncomingCall(cm->activeCall());
+ }
+ else
+ {
+ delete d->currentCall;
+ d->currentCall = NULL;
+ }
+}
+
+void QMLDialer::onIncomingCall(CallItem *callitem)
+{
+ TRACE
+
+ d->currentCall = new QMLCallItem(callitem, this);
+ emit this->incomingCall();
+}
+
+void QMLDialer::connectAll()
+{
+ TRACE
+ CallManager *cm = ManagerProxy::instance()->callManager();
+
+ if (cm && cm->isValid())
+ {
+ disconnect(cm, SIGNAL(callsChanged()));
+ disconnect(cm, SIGNAL(incomingCall(CallItem*)));
+ connect(cm, SIGNAL(callsChanged()), this, SLOT(onCallsChanged()));
+ connect(cm, SIGNAL(incomingCall(CallItem*)), SLOT(onIncomingCall(CallItem*)));
+ qDebug() << QString("CallMgr is connected");
+ }
+ else if (cm)
+ {
+ disconnect(cm, SIGNAL(connected()));
+ connect(cm, SIGNAL(connected()), this, SLOT(connectAll()));
+ qDebug() << QString("CallMgr is not yet valid");
+ }
+}
+
+void QMLDialer::onCallManagerChanged()
+{
+ TRACE
+
+ CallManager *cm = ManagerProxy::instance()->callManager();
+ this->connectAll();
+ if(cm && cm->activeCall()) d->currentCall = new QMLCallItem(cm->activeCall(), this);
+}
--- /dev/null
+/*
+ * dialer - Declarative Dialer Adapter.
+ * Copyright (c) 2011, Tom Swindell.
+ *
+ * This program is licensed under the terms and conditions of the
+ * Apache License, version 2.0. The full text of the Apache License is at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ */
+
+#ifndef QMLDIALER_H
+#define QMLDIALER_H
+
+#include <QObject>
+
+#include "qmlcallitem.h"
+
+class QMLDialer : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QString mailbox READ mailbox WRITE setMailbox)
+ Q_PROPERTY(QMLCallItem* currentCall READ currentCall)
+ Q_PROPERTY(bool modemOnline READ modemOnline WRITE setModemOnline)
+
+public:
+ explicit QMLDialer(QObject *parent = 0);
+ ~QMLDialer();
+
+ QString mailbox () const;
+ QMLCallItem* currentCall () const;
+ bool modemOnline ();
+
+Q_SIGNALS:
+ void incomingCall();
+ void outgoingCall();
+
+public Q_SLOTS:
+ void setMailbox(const QString &number);
+ void setModemOnline(bool online);
+
+ QString speedDial(int index) const;
+ void setSpeedDial(int index, const QString &number);
+
+ void dial(const QString &msisdn);
+ void hangupAll();
+
+ void silenceRingtone();
+
+ void sendTones(const QString &tones);
+
+ void transfer();
+ void swapCalls();
+ void releaseAndAnswer();
+ void holdAndAnswer();
+
+ void createMultiparty();
+ void hangupMultiparty();
+ void privateChat(const QMLCallItem &callitem);
+
+protected Q_SLOTS:
+ void connectAll();
+
+ void onCallsChanged();
+ void onIncomingCall(CallItem *callitem);
+
+ void onCallManagerChanged();
+
+private:
+ class QMLDialerPrivate *d;
+};
+
+#endif // QMLDIALER_H
--- /dev/null
+/*
+ * dialer - Declarative Dialer UX Main Window.
+ * Copyright (c) 2011, Tom Swindell.
+ *
+ * This program is licensed under the terms and conditions of the
+ * Apache License, version 2.0. The full text of the Apache License is at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ */
+
+#include "common.h"
+#include "dialerapplication.h"
+
+#include "qmlcallitem.h"
+#include "qmldialer.h"
+
+#include "qmlmainwindow.h"
+
+#include <QtDeclarative>
+
+#define CONFIG_KEY_QML_LOAD_URL "/apps/dialer/qml/url"
+
+#define DEFAULT_QML_LOAD_URL "file:///usr/share/hfdialer/qml/main.qml"
+
+class QMLMainWindowPrivate
+{
+public:
+ QMLMainWindowPrivate()
+ : adapter(NULL),
+ engine(NULL),
+ component(NULL),
+ item(NULL)
+ { TRACE }
+
+ QMLDialer *adapter;
+ QDeclarativeEngine *engine;
+ QDeclarativeView *qdv;
+
+ QDeclarativeComponent *component;
+ QDeclarativeItem *item;
+};
+
+static void registerDataTypes()
+{
+ TRACE
+ qmlRegisterType<QMLDialer>("com.tizen.hfdialer", 1, 0, "Dialer");
+
+ qmlRegisterUncreatableType<QMLCallItem>("com.tizen.hfdialer", 1, 0, "CallItem", "");
+}
+
+QMLMainWindow::QMLMainWindow(QWidget *parent)
+ : QDeclarativeView(parent),
+ d(new QMLMainWindowPrivate)
+{
+ TRACE
+ DialerApplication *da = DialerApplication::instance();
+ CallManager *cm = ManagerProxy::instance()->callManager();
+
+ setResizeMode(QDeclarativeView::SizeRootObjectToView);
+
+ this->setWindowTitle(qtTrId("xx_window"));
+
+ this->setupUi();
+
+ da->setActiveWindow(this);
+
+ connect(this->engine(), SIGNAL(quit()), this, SLOT(close()));
+}
+
+QMLMainWindow::~QMLMainWindow()
+{
+ TRACE
+ delete this->d;
+}
+
+QMLMainWindow* QMLMainWindow::instance()
+{
+ TRACE
+ static QMLMainWindow *_instance = NULL;
+
+ if(_instance == NULL)
+ {
+ registerDataTypes();
+ _instance = new QMLMainWindow;
+ }
+
+ return _instance;
+}
+
+
+QMLMainWindow* QMLMainWindow::instanceP(QWidget* parent)
+{
+ TRACE
+ static QMLMainWindow *_instance = NULL;
+
+ if(_instance == NULL)
+ {
+ registerDataTypes();
+ _instance = new QMLMainWindow(parent);
+ }
+
+ return _instance;
+}
+
+void QMLMainWindow::setupUi()
+{
+ TRACE
+ MGConfItem qmlUrl(CONFIG_KEY_QML_LOAD_URL);
+
+ d->engine = new QDeclarativeEngine(this);
+
+ d->engine->addImportPath("/usr/share/hfdialer/qml/base");
+
+ d->engine->rootContext()->setContextProperty("controller", this); //TODO: Remove
+ // d->engine->rootContext()->setContextProperty("History", DialerApplication::instance()->historyProxy());
+ this->setSource(QUrl::fromLocalFile("/usr/share/hfdialer/qml/main.qml"));
+ //this->setResizeMode(QDeclarativeView::SizeRootObjectToView);
+ //this->setSize(this->geometry);
+ d->component = new QDeclarativeComponent(d->engine, this);
+ d->component->loadUrl(qmlUrl.value(DEFAULT_QML_LOAD_URL).toString());
+
+ if(d->component->isError())
+ {
+ qCritical() << "Failed to load QML Component:" << d->component->errorString();
+ return;
+ }
+
+ d->item = qobject_cast<QDeclarativeItem*>(d->component->create());
+ if(!d->item)
+ {
+ qCritical() << "Failed to create item from component!";
+ return;
+ }
+}
+
+void QMLMainWindow::tryToShow()
+{
+ TRACE
+
+ if (d->component->isReady())
+ {
+ DialerApplication *da = DialerApplication::instance();
+ da->setActiveWindow(this);
+ da->activeWindow()->show();
+ da->activeWindow()->activateWindow();
+ da->activeWindow()->raise();
+ this->show();
+ }
+
+}
+void QMLMainWindow::hide()
+{
+ TRACE
+ QGraphicsView::hide();
+}
+
+void QMLMainWindow::closeEvent(QCloseEvent *event)
+{
+ TRACE
+/* if(this->closeOnLazyShutdown())
+ {
+ this->setCloseOnLazyShutdown(false);
+ }
+*/
+ event->accept();
+
+}
+
+void QMLMainWindow::onGeometryChanged()
+{
+ TRACE
+ // d->item->setSize(d->widget->size());
+}
+
+void QMLMainWindow::setAdapter(QMLDialer *adapter)
+{
+ TRACE
+ d->adapter = adapter;
+}
--- /dev/null
+/*
+ * dialer - Declarative Dialer UX Main Window.
+ * Copyright (c) 2011, Tom Swindell.
+ *
+ * This program is licensed under the terms and conditions of the
+ * Apache License, version 2.0. The full text of the Apache License is at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ */
+
+#ifndef QMLMAINWINDOW_H
+#define QMLMAINWINDOW_H
+
+#include <QDeclarativeView>
+#include <QDeclarativeComponent>
+#include "qmldialer.h"
+#include "callitem.h"
+
+class QMLMainWindowPrivate;
+
+class QMLMainWindow : public QDeclarativeView
+{
+ Q_OBJECT
+
+public:
+ static QMLMainWindow* instance();
+ static QMLMainWindow* instanceP(QWidget* parent);
+ ~QMLMainWindow();
+
+public Q_SLOTS:
+ void hide();
+ void tryToShow();
+
+ void setAdapter(QMLDialer *adapter); //TODO: Refactor out
+
+protected Q_SLOTS:
+ void setupUi();
+
+ void onGeometryChanged();
+
+protected:
+ virtual void closeEvent(QCloseEvent *event);
+
+private:
+ explicit QMLMainWindow(QWidget *parent = 0);
+ QMLMainWindowPrivate *d;
+ QDeclarativeView qv;
+ Q_DISABLE_COPY(QMLMainWindow)
+};
+
+#endif // QMLMAINWINDOW_H
--- /dev/null
+include (../common.pri)
+TEMPLATE = app
+QT += dbus declarative
+CONFIG += qdbus mobility qt-mobility link_pkgconfig network debug
+PKGCONFIG += libpulse-mainloop-glib
+MOBILITY += contacts multimedia
+MOC_DIR = .moc
+OBJECTS_DIR = .obj
+MGEN_OUTDIR = .gen
+
+if (wayland) {
+ PKGCONFIG += mlite-wayland ofono-qt-wayland
+} else {
+ PKGCONFIG += mlite-xlib ofono-qt-xlib
+}
+
+DEFINES += CONFIG_DEFAULT_TARGET_UX=\\\"tizen-ux-components\\\"
+
+target.path += $$INSTALL_ROOT/usr/bin
+
+SOURCES += main.cpp \
+ dialercontext.cpp \
+ dialerapplication.cpp \
+ managerproxy.cpp \
+ modemproxy.cpp \
+ networkproxy.cpp \
+ callitem.cpp \
+ callproxy.cpp \
+ callmanager.cpp \
+ dbustypes.cpp \
+ pacontrol.cpp \
+ qmlmainwindow.cpp \
+ qmldialer.cpp \
+ qmlcallitem.cpp \
+ dbusdialeradapter.cpp
+
+HEADERS += \
+ common.h \
+ dialercontext.h \
+ dialerapplication.h \
+ managerproxy.h \
+ modemproxy.h \
+ networkproxy.h \
+ callitem.h \
+ callproxy.h \
+ callmanager.h \
+ dbustypes.h \
+ pacontrol.h \
+ $$MODEL_HEADERS \
+ $$STYLE_HEADERS \
+ $$DBUS_INTERFACE_HEADERS \
+ $$DBUS_ADAPTOR_HEADERS \
+ qmlmainwindow.h \
+ qmldialer.h \
+ qmlcallitem.h \
+ dbusdialeradapter.h
+
+DBUS_ADAPTORS += dbus/com.tizen.hfdialer.xml
+
+DBUS_INTERFACES += \
+ dbus/org.ofono.voicecall.xml \
+ dbus/org.ofono.manager.xml \
+ dbus/org.ofono.modem.xml \
+ dbus/org.ofono.operator.xml \
+
+ system(qdbusxml2cpp -a dialer_adaptor.h: dbus/com.tizen.hfdialer.xml)
+ system(qdbusxml2cpp -i dbustypes.h -p manager_interface.h: dbus/org.ofono.manager.xml)
+ system(qdbusxml2cpp -i dbustypes.h -p modem_interface.h: dbus/org.ofono.modem.xml)
+
+MAKE_CLEAN += $$OBJECTS_DIR/*.o
+MAKE_DISTCLEAN += \
+ $$MOC_DIR/* $$MOC_DIR \
+ $$OBJECTS_DIR/* $$OBJECTS_DIR \
+ $$MGEN_OUTDIR/* $$MGEN_OUTDIR \
+
+# Install
+INSTALLS += target