--- /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
+[Desktop Entry]
+Type=Application
+Name=Handsfree Dialer
+Icon=hfdialer
+Exec=dialer
+Comment=Handsfree Dialer Application
+X-Desktop-File-Install-Version=0.16
--- /dev/null
+[D-BUS Service]
+Name=com.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
+<!DOCTYPE busconfig PUBLIC
+ "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+<busconfig>
+ <policy context="default">
+ <allow own="com.hfdialer" />
+ <allow send_destination="com.hfdialer" />
+ <allow send_interface="com.hfdialer" />
+ </policy>
+</busconfig>
--- /dev/null
+%define buildwayland 1
+%if %{buildwayland}
+%define backend wayland
+%else
+%define backend xlib
+%endif
+
+Name: hfdialer-%{backend}
+Summary: QML based Voice Call Application
+Version: 0.3.2
+Release: 11.1
+Group: System/GUI/Other
+License: Apache License, Version 2.0
+URL: http://www.tizen.org
+Source0: hfdialer-%{version}.tar.bz2
+Requires: ofono
+Requires: pulseaudio
+Requires: bluetooth-qt-%{backend}
+BuildRequires: pkgconfig(QtCore-%{backend})
+BuildRequires: pkgconfig(QtOpenGL-%{backend})
+BuildRequires: pkgconfig(QtDeclarative-%{backend})
+BuildRequires: pkgconfig(libpulse)
+BuildRequires: pkgconfig(libpulse-mainloop-glib)
+BuildRequires: pkgconfig(ofono-qt-%{backend})
+BuildRequires: pkgconfig(mlite-%{backend})
+BuildRequires: desktop-file-utils
+
+%description
+QML based Dialer Application
+
+
+%prep
+%setup -q -n hfdialer-%{version}
+
+%build
+unset LD_AS_NEEDED
+
+%qmake CONFIG+=%{backend}
+
+make %{?jobs:-j%jobs}
+
+%install
+rm -rf %{buildroot}
+
+%qmake_install
+
+desktop-file-install --delete-original \
+ --dir %{buildroot}%{_datadir}/applications \
+ %{buildroot}%{_datadir}/applications/*.desktop
+
+
+%files
+%defattr(-,root,root,-)
+/etc/dbus-1/system.d/hfdialer.conf
+%{_bindir}/dialer
+%{_datadir}/dbus-1/services/dialer.service
+%{_datadir}/applications/dialer.desktop
+%{_datadir}/hfdialer
+%{_datadir}/hfdialer/qml
+%{_datadir}/hfdialer/LICENSE
+
--- /dev/null
+VERSION = 0.3.2
+CONFIG += link_pkgconfig network opengl
+
+TEMPLATE = subdirs
+CONFIG += ordered
+SUBDIRS = src qml dialerassets sounds
+
+OTHER_FILES += *.service *.desktop *.sh
+
+# 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/dbus-1/services
+
+dbus_conf.files = hfdialer.conf
+dbus_conf.path += $$INSTALL_ROOT/etc/dbus-1/system.d
+
+# Documentation
+documentation.files = AUTHORS ChangeLog LICENSE README TODO
+documentation.path = $$INSTALL_ROOT/usr/share/hfdialer/
+
+INSTALLS += \
+ desktop_entry \
+ dbus_service \
+ dbus_conf \
+ documentation \
+
+PROJECT_NAME = hfdialer
+
+dist.commands += rm -fR $${PROJECT_NAME}-$${VERSION} &&
+dist.commands += git clone . $${PROJECT_NAME}-$${VERSION} &&
+dist.commands += rm -fR $${PROJECT_NAME}-$${VERSION}/.git &&
+dist.commands += tar jcpvf $${PROJECT_NAME}-$${VERSION}.tar.bz2 $${PROJECT_NAME}-$${VERSION}
+QMAKE_EXTRA_TARGETS += dist
--- /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);
+ }
+ Connections {
+ target: adapter
+ onCallCountChanged: {
+ if (callCount <= 0)
+ root.state = 'disconnected'
+ }
+ }
+ 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;
+ });
+ }
+ }
+ }
+
+ 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: root; callDuration: "00:00:00"}
+ 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: root; callDuration: "00:00:00"}
+ 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: root; callDuration: "00:00:00"}
+ 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: callDurationInd; text: "00:00:00"}
+ 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}
+
+ Image {
+ id: iconImg
+ source: icon == "phone" ? "/usr/share/hfdialer/images/bluetooth-smartphone.png" :
+ "/usr/share/hfdialer/images/computer.png"
+ height: availableBluetoothItem.containerHeight * 0.75
+ width: height
+ anchors {left: parent.left; verticalCenter: parent.verticalCenter; leftMargin: icon == "phone"? 10 : 10;}
+ }
+
+ Text {
+ id: mainText
+
+ anchors {left: iconImg.right; right: parent.right; top: parent.top; bottom: parent.bottom; rightMargin: 10; leftMargin: icon == "phone"? 18 : 18;}
+ 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()
+
+ Connections {
+ target: adapter
+ onModemOnlineChanged: {
+
+ //If the modem gets powered down for any reason, attempt to power it again to maintain connection
+ if (!adapter.modemOnline)
+ {
+ mainText.color = "grey"
+ availableBluetoothItem.source = "/usr/share/hfdialer/images/ivi_btn-list-inactive.png"
+ }
+ else
+ {
+ mainText.color = "white"
+ availableBluetoothItem.source = "/usr/share/hfdialer/images/ivi_btn-list.png"
+ }
+ }
+ }
+
+ Image {
+ id: availableBluetoothItem
+
+ source: !adapter.modemOnline? "/usr/share/hfdialer/images/ivi_btn-list-inactive.png" : availableBluetoothItem.source = "/usr/share/hfdialer/images/ivi_btn-list.png"
+ anchors {fill: parent; leftMargin: 8; rightMargin: 8; topMargin: 8}
+
+ MouseArea {
+ id: clickArea
+ 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"
+ }
+
+ onClicked: {
+ adapter.modemOnline = true
+ }
+ }
+
+ 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: !adapter.modemOnline? "grey" : "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
+ property TextInput pidEdit
+ property bool pidRequest: false
+
+ height: parent.height
+ property real buttonHeight: (parent.height / 5) - 41;
+
+ function insertText(text)
+ {
+ if (!pidRequest)
+ entry.appendChar(text)
+ else if (text != "*" && text != "#")
+ {
+ pidEdit.text += text
+ }
+ }
+
+ 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 (!pidRequest){
+
+ if(entry.textInput.text == entry.placeHolderText)
+ return;
+
+ entry.textInput.text = entry.textInput.text.substring(0, entry.textInput.text.length -1);
+ }
+ else
+ pidEdit.text = pidEdit.text.substring(0, pidEdit.text.length -1);
+ }
+
+ onPressAndHold:
+ {
+ if (!pidRequest)
+ entry.clear();
+ else
+ pidEdit.text = "";
+ }
+ }
+ }
+
+ Image {
+ id: bCall;
+
+ height: parent.height
+ width: parent.width - bDelete.width - closeButton.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 (!pidRequest)
+ {
+ 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();
+ }
+ }
+ }
+ }
+ }
+
+ Image
+ {
+ id: closeButton
+ source: "/usr/share/hfdialer/images/ivi_btn-close.png"
+ height: parent.height
+ width: (parent.width / 7) - 5
+
+ MouseArea {
+ id: closeArea
+ anchors.fill: parent
+
+ onClicked: {
+ console.log("CLOSE BUTTON CLICKED")
+
+ Qt.quit()
+ }
+ }
+ }
+ }
+ }
+ }
+}
--- /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'
+ }
+
+ Timer {
+ id: reconnectTimer
+ interval: 3000
+ repeat: false
+ running: false
+
+ onTriggered:
+ {
+ adapter.modemOnline = true
+ }
+ }
+
+ Connections {
+ target: adapter
+ onModemOnlineChanged: {
+
+ //If the modem gets powered down for any reason, attempt to power it again to maintain connection
+ if (!adapter.modemOnline)
+ {
+ reconnectTimer.running = true;
+ }
+ }
+ }
+
+ 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
+
+ Component.onCompleted: {
+
+ //Once model is completed, check if the modem is powered. If not, power it
+ if (!adapter.modemOnline)
+ {
+ adapter.modemOnline = true
+ }
+ }
+
+ delegate: DeviceDelegateActive {
+ id: deligateItem
+ 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: {
+ }
+ }
+
+ onClose: {
+ console.log("unparing ...");
+ device.unpair();
+ btDevicesModel.deviceRemoved(device.path);
+ }
+ }
+ }
+ }
+ }
+
+ 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
+
+ Component.onCompleted: {
+ numPad.pidRequest = true
+ numPad.pidEdit = textInputField
+ }
+
+ 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
+
+ TextInput {
+ id: textInputField
+ anchors.centerIn: parent
+ width: parent.width
+ height: parent.height * 0.75
+ font.pixelSize: 24
+ color: "black"
+ text: replyValue
+ horizontalAlignment: Text.AlignHCenter
+ activeFocusOnPress: false
+ }
+ }
+
+ 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)
+ numPad.pidRequest = false
+ 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)
+ numPad.pidRequest = false
+ 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
+
+ Component.onCompleted: {
+ numPad.pidRequest = true
+ numPad.pidEdit = textInputField
+ }
+
+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
+
+ TextInput {
+ id: textInputField
+ anchors.centerIn: parent
+ width: parent.width
+ height: parent.height * 0.75
+ font.pixelSize: 24
+ color: "black"
+ text: replyValue
+ horizontalAlignment: Text.AlignHCenter
+ activeFocusOnPress: false
+ }
+ }
+
+ 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: {
+ numPad.pidRequest = false
+ 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.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
+
+OTHER_FILES += *.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)
+{
+ TRACE;
+ 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()) {
+ qWarning() << QString("CallItem: %1 ringtone not found: %2")
+ .arg(m_path)
+ .arg(l_rtKeyValue);
+ }
+
+ if (isValid()) {
+ init();
+ }
+}
+
+CallItem::~CallItem()
+{
+ TRACE;
+ PAControl::instance()->unrouteAudio();
+
+ if (m_rtKey) {
+ delete m_rtKey;
+ }
+ m_rtKey = 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!");
+ }
+}
+
+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;
+}
+
+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;
+}
+
+CallDisconnectReason CallItem::reason() const
+{
+ TRACE;
+ return DISCONNECT_NONE;
+}
+
+int CallItem::duration() const
+{
+ TRACE;
+ return m_call->duration();
+}
+
+QDateTime CallItem::startTime() const
+{
+ TRACE;
+ return m_call->startTime();
+}
+
+CallProxy* CallItem::callProxy() const
+{
+ TRACE;
+ return m_call;
+}
+
+void CallItem::click()
+{
+ TRACE;
+
+ emit clicked();
+}
+
+void CallItem::silenceRingtone()
+{
+ TRACE;
+}
+
+void CallItem::callStateChanged()
+{
+ TRACE;
+ emit stateChanged();
+}
+
+void CallItem::callDataChanged()
+{
+ TRACE;
+}
+
+void CallItem::callDisconnected(const QString &reason)
+{
+ TRACE;
+ Q_UNUSED(reason);
+}
+
+
+bool CallItem::multiparty()
+{
+ TRACE;
+ return false;
+}
+
+void CallItem::callMultipartyChanged()
+{
+ TRACE;
+ emit multipartyChanged();
+}
+
+/* Local Variables: */
+/* mode:c++ */
+/* c-basic-offset:4 */
+/* indent-tabs-mode: nil */
+/* End: */
--- /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 <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(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;
+ CallProxy *callProxy() const;
+ bool isValid();
+ bool isValid() const;
+ bool multiparty();
+
+public Q_SLOTS:
+ void init();
+ 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 callMultipartyChanged();
+
+private:
+ QString m_path;
+ MGConfItem *m_rtKey;
+ bool m_isconnected;
+ QString m_ringtonefile;
+ CallProxy *m_call;
+
+ Q_DISABLE_COPY(CallItem)
+};
+
+#endif // CALLITEM_H
+
+/* Local Variables: */
+/* mode:c++ */
+/* c-basic-offset:4 */
+/* indent-tabs-mode: nil */
+/* End: */
--- /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"
+
+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;
+
+ // 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)));
+
+ connect(this,SIGNAL(callsChanged()),this,SLOT(callChangedSlot()));
+
+ connect(this, SIGNAL(validityChanged(bool)), this, SLOT(modemValidityChanged(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();
+}
+
+void CallManager::modemValidityChanged(bool valid)
+{
+ TRACE;
+ if (valid)
+ emit connected();
+}
+
+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;
+ swapCalls();
+}
+
+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;
+ }
+ }
+
+ proceedCallDial(number);
+}
+
+void CallManager::privateChat(const CallItem &call)
+{
+ TRACE;
+}
+
+/*
+ * 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();
+ 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)) {
+ 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());
+}
+
+void CallManager::callChangedSlot()
+{
+ TRACE
+ qDebug()<<"callChanged called!";
+}
+
+/* Local Variables: */
+/* mode:c++ */
+/* c-basic-offset:4 */
+/* indent-tabs-mode: nil */
+/* End: */
--- /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
+ // 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 callChangedSlot();
+ 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();
+ void modemValidityChanged(bool valid);
+
+ // 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
+
+/* Local Variables: */
+/* mode:c++ */
+/* c-basic-offset:4 */
+/* indent-tabs-mode: nil */
+/* End: */
--- /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 <QDateTime>
+#include "common.h"
+#include "callproxy.h"
+#include "managerproxy.h"
+
+// Returns a valid QDateTime if parsable as such, otherwise the result
+// will be !isValid()
+static 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 VERBOSE
+ 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 VERBOSE
+ 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;
+}
+
+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);
+
+ // 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;
+ proceedCallAnswer();
+}
+
+void CallProxy::proceedCallAnswer()
+{
+ TRACE;
+
+ QDBusPendingReply<QDBusObjectPath> reply;
+ QDBusPendingCallWatcher *watcher;
+
+ reply = Answer();
+ watcher = new QDBusPendingCallWatcher(reply);
+
+ connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)),
+ SLOT(answerFinished(QDBusPendingCallWatcher*)));
+}
+
+void CallProxy::deniedCallAnswer()
+{
+ TRACE;
+
+ // 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();
+}
+
+/* Local Variables: */
+/* mode:c++ */
+/* c-basic-offset:4 */
+/* indent-tabs-mode: nil */
+/* End: */
--- /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
+
+/* Local Variables: */
+/* mode:c++ */
+/* c-basic-offset:4 */
+/* indent-tabs-mode: nil */
+/* End: */
--- /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
+
+class QString;
+
+#ifdef VERBOSE
+#include <QDebug>
+#define TRACE qDebug() << "[" << __FILE__ << "]" << __func__ << "():" << __LINE__;
+#else
+#define TRACE
+#endif
+
+QString stripLineID(QString lineid);
+
+#endif // COMMON_H
+
+/* Local Variables: */
+/* mode:c++ */
+/* c-basic-offset:4 */
+/* indent-tabs-mode: nil */
+/* End: */
--- /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.hfdialer" >
+ <method name="call" >
+ <arg direction="in" type="s" name="" />
+ </method>
+ <method name="accept"/>
+ <method name="raise"/>
+ </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);
+}
+
+/* Local Variables: */
+/* mode:c++ */
+/* c-basic-offset:4 */
+/* indent-tabs-mode: nil */
+/* End: */
--- /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.hfdialer");
+
+public:
+ explicit DBusDialerAdapter(DialerApplication *application);
+ ~DBusDialerAdapter();
+
+Q_SIGNALS:
+
+public Q_SLOTS:
+ void call(const QString &msisdn);
+};
+
+#endif // DBUSDIALERADAPTER_H
+
+/* Local Variables: */
+/* mode:c++ */
+/* c-basic-offset:4 */
+/* indent-tabs-mode: nil */
+/* End: */
--- /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;
+}
+
+/* Local Variables: */
+/* mode:c++ */
+/* c-basic-offset:4 */
+/* indent-tabs-mode: nil */
+/* End: */
--- /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
+
+/* Local Variables: */
+/* mode:c++ */
+/* c-basic-offset:4 */
+/* indent-tabs-mode: nil */
+/* End: */
--- /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 "hfdialer_adaptor.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()));
+ PAControl* paControl = PAControl::instance();
+ qDebug()<<"UBER DEBUG!!! I can has connect with paControl onCallsChanged";
+ 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());
+}
+
+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;
+
+ HfdialerAdaptor *adapter = new HfdialerAdaptor(this);
+ if(!adapter)
+ {
+ qWarning() << "DBus adapter instantiation failed.";
+ }
+
+ if(!QDBusConnection::systemBus().registerService("com.hfdialer"))
+ {
+ qCritical() << "Error registering on zee bus: " <<
+ QDBusConnection::systemBus().lastError().message();
+ }
+
+ if(!QDBusConnection::systemBus().registerObject(DBUS_SERVICE_PATH, this))
+ {
+ qCritical() << "Error registering dbus object:" <<
+ QDBusConnection::systemBus().lastError().message();
+ }
+ connect(m_manager, SIGNAL(modemChanged()),
+ SLOT(modemChanged()));
+
+ this->connectAll();
+
+ m_mainWindow = QMLMainWindow::instance();
+ connect(m_mainWindow, SIGNAL(closeWindow()),this, SLOT(closeWindow()));
+}
+
+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()));
+ }
+ else
+ {
+ qDebug()<<"modem is null";
+ }
+}
+
+void DialerApplication::modemConnected()
+{
+ TRACE;
+ //TODO: Handle multiple modems
+ if (m_manager->modem() && m_manager->modem()->isValid())
+ {
+ m_modem = m_manager->modem();
+
+ m_modem->setPowered(true);
+
+ 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;
+}
+
+void DialerApplication::onCallsChanged()
+{
+ TRACE;
+ QMLMainWindow::instance()->tryToShow();
+}
+
+void DialerApplication::raise()
+{
+ TRACE;
+ QMLMainWindow::instance()->tryToShow();
+}
+
+void DialerApplication::closeWindow()
+{
+ TRACE;
+ m_mainWindow->hide();
+}
+
+/* Local Variables: */
+/* mode:c++ */
+/* c-basic-offset:4 */
+/* indent-tabs-mode: nil */
+/* End: */
--- /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 "qmlmainwindow.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();
+
+Q_SIGNALS:
+ void showUi();
+ void hideUi();
+public Q_SLOTS:
+ void closeWindow();
+ void raise();
+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;
+ QMLMainWindow *m_mainWindow;
+ QDBusConnection *m_bus;
+ Q_DISABLE_COPY(DialerApplication);
+};
+
+#endif // DIALERAPPLICATION_H
+
+/* Local Variables: */
+/* mode:c++ */
+/* c-basic-offset:4 */
+/* indent-tabs-mode: nil */
+/* End: */
--- /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;
+ 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()));
+
+ 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;
+}
+
+QStringList DialerContext::modes() const
+{
+ return d->modes;
+}
+
+void DialerContext::setModes(const QStringList &modelist)
+{
+ d->modes = modelist;
+ d->modes.removeDuplicates();
+ emit modesChanged();
+}
+
+/*
+ * 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(", ");
+}
+
+/* Local Variables: */
+/* mode:c++ */
+/* c-basic-offset:4 */
+/* indent-tabs-mode: nil */
+/* End: */
--- /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"
+
+// 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(QStringList modes READ modes WRITE setModes);
+
+public:
+ virtual ~DialerContext();
+
+ static DialerContext *instance();
+
+ OfonoModemManager* modemManager() const;
+ OfonoCallVolume* volumeManager() const;
+ OfonoMessageWaiting* voicemailManager() const;
+ CallManager* callManager() 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
+
+/* Local Variables: */
+/* mode:c++ */
+/* c-basic-offset:4 */
+/* indent-tabs-mode: nil */
+/* End: */
--- /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>
+
+int main(int argc, char *argv[])
+{
+ TRACE;
+ QDBusConnection bus = QDBusConnection::systemBus();
+ QStringList serviceNames = bus.interface()->registeredServiceNames();
+
+ if (serviceNames.contains("com.hfdialer"))
+ {
+ QDBusMessage message = QDBusMessage::createMethodCall("com.hfdialer","/com/dialer","com.hfdialer", "raise");
+ bus.call(message,QDBus::NoBlock);
+
+ return 0;
+ }
+
+ DialerApplication app(argc, argv);
+
+ QMLMainWindow *qmw = QMLMainWindow::instance();
+
+ QString argString(argv[1]);
+
+ if (argString != "noshow")
+ 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, "");
+ }
+}
+
+/* Local Variables: */
+/* mode:c++ */
+/* c-basic-offset:4 */
+/* indent-tabs-mode: nil */
+/* End: */
--- /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;
+
+ if (m_modem && m_modem->isValid() && !m_modem->powered())
+ m_modem->setPowered(true);
+}
+
+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();
+
+ setModem(in0.path());
+ setCallManager(m_modemPath);
+}
+
+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)
+ {
+ //If we have a modem, it's valid, but not powered, power it up.
+ if (!m_modem->powered())
+ m_modem->setPowered(true);
+
+ return;
+ }
+
+ if (m_modem)
+ {
+ if (m_modemList.contains(m_modem->path()))
+ {
+ m_modemList.removeAll(m_modem->path());
+ }
+ 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)
+{
+ TRACE
+ 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)
+ delete m_callManager;
+
+ m_callManager = new CallManager(modempath);
+ connect(m_callManager, SIGNAL(connected()), this, SIGNAL(callManagerChanged()));
+ 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();
+ }
+ }
+}
+
+/* Local Variables: */
+/* mode:c++ */
+/* c-basic-offset:4 */
+/* indent-tabs-mode: nil */
+/* End: */
--- /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 "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
+
+/* Local Variables: */
+/* mode:c++ */
+/* c-basic-offset:4 */
+/* indent-tabs-mode: nil */
+/* End: */
--- /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;
+
+ QVariant powered(is_powered);
+
+ QDBusPendingReply<QVariantMap> reply;
+ reply = SetProperty("Powered", QDBusVariant(powered));
+
+ 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();
+ }
+ }
+}
+
+/* Local Variables: */
+/* mode:c++ */
+/* c-basic-offset:4 */
+/* indent-tabs-mode: nil */
+/* End: */
--- /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
+
+/* Local Variables: */
+/* mode:c++ */
+/* c-basic-offset:4 */
+/* indent-tabs-mode: nil */
+/* End: */
--- /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
+ * **************************************************************/
+
+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);
+
+ }
+ 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();
+ }
+ }
+}
+
+/* Local Variables: */
+/* mode:c++ */
+/* c-basic-offset:4 */
+/* indent-tabs-mode: nil */
+/* End: */
--- /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
+
+/* Local Variables: */
+/* mode:c++ */
+/* c-basic-offset:4 */
+/* indent-tabs-mode: nil */
+/* End: */
--- /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;
+ }
+
+ 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;
+ }
+
+ 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()
+{
+ TRACE;
+
+ CallManager *cm = ManagerProxy::instance()->callManager();
+ if (!cm || !cm->isValid())
+ {
+ qDebug("no call manager. Aborting");
+ 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();
+ }
+ }
+}
+
+/* Local Variables: */
+/* mode:c++ */
+/* c-basic-offset:4 */
+/* indent-tabs-mode: nil */
+/* End: */
+
--- /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
+
+/* Local Variables: */
+/* mode:c++ */
+/* c-basic-offset:4 */
+/* indent-tabs-mode: nil */
+/* End: */
--- /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;
+
+ if (d->proxy)
+ {
+ if (d->proxy->callProxy())
+ return d->proxy->callProxy()->duration();
+ }
+ return 0;
+}
+
+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());
+}
+
+/* Local Variables: */
+/* mode:c++ */
+/* c-basic-offset:4 */
+/* indent-tabs-mode: nil */
+/* End: */
--- /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
+
+/* Local Variables: */
+/* mode:c++ */
+/* c-basic-offset:4 */
+/* indent-tabs-mode: nil */
+/* End: */
--- /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()));
+ connect(cm, SIGNAL(callCountChanged()), SIGNAL(callCountChanged(cm->callCount())));
+
+ 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() && ManagerProxy::instance()->modem())
+ {
+ 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;
+}
+
+int QMLDialer::callCount()
+{
+ TRACE;
+ CallManager *cm = ManagerProxy::instance()->callManager();
+ return cm->callCount();
+}
+
+
+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()
+{
+}
+
+void QMLDialer::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;
+ emit callCountChanged(cm->callCount());
+ }
+
+}
+
+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 (ManagerProxy::instance()->modem() && ManagerProxy::instance()->modem()->isValid())
+ {
+ connect(ManagerProxy::instance()->modem(), SIGNAL(poweredChanged(bool)), this, SIGNAL(modemOnlineChanged(bool)));
+ }
+
+ 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);
+}
+
+/* Local Variables: */
+/* mode:c++ */
+/* c-basic-offset:4 */
+/* indent-tabs-mode: nil */
+/* End: */
--- /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 NOTIFY modemOnlineChanged);
+ Q_PROPERTY(int callCount READ callCount NOTIFY callCountChanged);
+
+public:
+ explicit QMLDialer(QObject *parent = 0);
+ ~QMLDialer();
+
+ QString mailbox () const;
+ QMLCallItem* currentCall () const;
+ bool modemOnline ();
+ int callCount ();
+
+Q_SIGNALS:
+ void incomingCall();
+ void outgoingCall();
+ void callCountChanged(int callCount);
+ void modemOnlineChanged(bool powered);
+
+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
+
+/* Local Variables: */
+/* mode:c++ */
+/* c-basic-offset:4 */
+/* indent-tabs-mode: nil */
+/* End: */
--- /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.hfdialer", 1, 0, "Dialer");
+
+ qmlRegisterUncreatableType<QMLCallItem>("com.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();
+
+ connect(this->engine(), SIGNAL(quit()), this, SLOT(closeEvent()));
+}
+
+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->rootContext()->setContextProperty("controller", this); //TODO: Remove
+ this->setSource(QUrl::fromLocalFile("/usr/share/hfdialer/qml/main.qml"));
+ 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();
+ this->show();
+ }
+
+}
+void QMLMainWindow::closeEvent()
+{
+ TRACE;
+ emit closeWindow();
+}
+
+void QMLMainWindow::onGeometryChanged()
+{
+ TRACE;
+}
+
+void QMLMainWindow::setAdapter(QMLDialer *adapter)
+{
+ TRACE;
+ d->adapter = adapter;
+}
+
+/* Local Variables: */
+/* mode:c++ */
+/* c-basic-offset:4 */
+/* indent-tabs-mode: nil */
+/* End: */
--- /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();
+
+Q_SIGNALS:
+ void closeWindow();
+
+public Q_SLOTS:
+ void tryToShow();
+ void closeEvent();
+ void setAdapter(QMLDialer *adapter); //TODO: Refactor out
+
+protected Q_SLOTS:
+ void setupUi();
+
+ void onGeometryChanged();
+
+private:
+ explicit QMLMainWindow(QWidget *parent = 0);
+ QMLMainWindowPrivate *d;
+ QDeclarativeView qv;
+ Q_DISABLE_COPY(QMLMainWindow)
+};
+
+#endif // QMLMAINWINDOW_H
+
+/* Local Variables: */
+/* mode:c++ */
+/* c-basic-offset:4 */
+/* indent-tabs-mode: nil */
+/* End: */
--- /dev/null
+TARGET = dialer
+TEMPLATE = app
+QT += dbus declarative
+CONFIG += qdbus mobility qt-mobility link_pkgconfig network
+PKGCONFIG += libpulse-mainloop-glib
+MOBILITY += contacts multimedia
+MOC_DIR = .moc
+OBJECTS_DIR = .obj
+MGEN_OUTDIR = .gen
+
+DEFINES += DBUS_SERVICE_PATH=\\\"/com/${QMAKE_TARGET}\\\"
+DEFINES += DBUS_SERVICE=\\\"com.${QMAKE_TARGET}\\\"
+
+verbose {
+ DEFINES += VERBOSE
+}
+
+wayland {
+ PKGCONFIG += mlite-wayland ofono-qt-wayland
+}
+xlib{
+ PKGCONFIG += mlite-xlib ofono-qt-xlib
+}
+!xlib:!wayland{
+ PKGCONFIG += mlite ofono-qt
+}
+
+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 \
+ voicecall_interface.cpp \
+ operator_interface.cpp \
+ hfdialer_adaptor.cpp \
+ manager_interface.cpp \
+ modem_interface.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 \
+ voicecall_interface.h \
+ operator_interface.h \
+ hfdialer_adaptor.h \
+ manager_interface.h \
+ modem_interface.h \
+ qmlmainwindow.h \
+ qmldialer.h \
+ qmlcallitem.h \
+ dbusdialeradapter.h
+
+
+
+system(qdbusxml2cpp -p voicecall_interface dbus/org.ofono.voicecall.xml)
+system(qdbusxml2cpp -p operator_interface dbus/org.ofono.operator.xml)
+system(qdbusxml2cpp -a hfdialer_adaptor dbus/com.hfdialer.xml)
+system(qdbusxml2cpp -i dbustypes.h -p manager_interface dbus/org.ofono.manager.xml)
+system(qdbusxml2cpp -i dbustypes.h -p modem_interface 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