![]() |
Home · All Namespaces · All Classes |
00001 /**************************************************************************** 00002 ** 00003 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). 00004 ** All rights reserved. 00005 ** Contact: Nokia Corporation (directui@nokia.com) 00006 ** 00007 ** This file is part of systemui. 00008 ** 00009 ** If you have questions regarding the use of this file, please contact 00010 ** Nokia at directui@nokia.com. 00011 ** 00012 ** This library is free software; you can redistribute it and/or 00013 ** modify it under the terms of the GNU Lesser General Public 00014 ** License version 2.1 as published by the Free Software Foundation 00015 ** and appearing in the file LICENSE.LGPL included in the packaging 00016 ** of this file. 00017 ** 00018 ****************************************************************************/ 00019 #include "volumebarlogic.h" 00020 00021 #include <stdlib.h> 00022 #include <string.h> 00023 00024 #include <QTimer> 00025 #include <QVariant> 00026 #include <QString> 00027 #include <QDebug> 00028 00029 #define DBUS_ERR_CHECK(err) \ 00030 if (dbus_error_is_set (&err)) \ 00031 { \ 00032 qWarning() << err.message; \ 00033 dbus_error_free (&err); \ 00034 } 00035 00036 #define DEFAULT_ADDRESS "unix:path=/var/run/pulse/dbus-socket" 00037 00038 #define VOLUME_SV "com.Nokia.MainVolume1" 00039 #define VOLUME_PATH "/com/meego/mainvolume1" 00040 #define VOLUME_IF "com.Nokia.MainVolume1" 00041 00042 VolumeBarLogic::VolumeBarLogic () : 00043 QObject (), 00044 dbus_conn (NULL), 00045 currentvolume (0), 00046 currentmax (0) 00047 { 00048 openConnection (true); 00049 } 00050 00051 VolumeBarLogic::~VolumeBarLogic () 00052 { 00053 if (dbus_conn) { 00054 dbus_connection_unref (dbus_conn); 00055 dbus_conn = 0; 00056 } 00057 } 00058 00059 void VolumeBarLogic::openConnection (bool init) 00060 { 00061 /* 00062 * Check the connection first, maybe this function 00063 * only called because of lost connection 00064 */ 00065 if ((dbus_conn != NULL) && (dbus_connection_get_is_connected (dbus_conn))) 00066 return; 00067 00068 DBusError dbus_err; 00069 char *pa_bus_address = getenv ("PULSE_DBUS_SERVER"); 00070 00071 if (pa_bus_address == NULL) 00072 pa_bus_address = (char *) DEFAULT_ADDRESS; 00073 00074 dbus_error_init (&dbus_err); 00075 00076 dbus_conn = dbus_connection_open (pa_bus_address, &dbus_err); 00077 00078 DBUS_ERR_CHECK (dbus_err); 00079 00080 if (dbus_conn != NULL) { 00081 dbus_connection_setup_with_g_main (dbus_conn, NULL); 00082 00083 dbus_connection_add_filter ( 00084 dbus_conn, 00085 (DBusHandleMessageFunction) VolumeBarLogic::stepsUpdatedSignal, 00086 (void *) this, NULL); 00087 00088 if (init == true) 00089 initValues (); 00090 } 00091 } 00092 00093 void VolumeBarLogic::initValues () 00094 { 00095 DBusMessage *msg; 00096 DBusMessage *reply; 00097 DBusError error; 00098 00099 dbus_error_init (&error); 00100 00101 msg = dbus_message_new_method_call (VOLUME_SV, 00102 VOLUME_PATH, 00103 "org.freedesktop.DBus.Properties", 00104 "GetAll"); 00105 const char *volume_if = VOLUME_IF; 00106 dbus_message_append_args (msg, 00107 DBUS_TYPE_STRING, &volume_if, 00108 DBUS_TYPE_INVALID); 00109 00110 reply = 00111 dbus_connection_send_with_reply_and_block ( 00112 dbus_conn, msg, -1, &error); 00113 00114 DBUS_ERR_CHECK (error); 00115 00116 dbus_message_unref (msg); 00117 00118 if (reply && (dbus_message_get_type (reply) == 00119 DBUS_MESSAGE_TYPE_METHOD_RETURN)) { 00120 DBusMessageIter iter; 00121 dbus_message_iter_init (reply, &iter); 00122 // Recurse into the array [array of dicts] 00123 while (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_INVALID) { 00124 DBusMessageIter dict_entry; 00125 dbus_message_iter_recurse (&iter, &dict_entry); 00126 00127 // Recurse into the dict [ dict_entry (string, variant(int)) ] 00128 while (dbus_message_iter_get_arg_type (&dict_entry) != DBUS_TYPE_INVALID) { 00129 DBusMessageIter in_dict; 00130 // Recurse into the dict_entry [ string, variant(int) ] 00131 dbus_message_iter_recurse (&dict_entry, &in_dict); 00132 { 00133 char *prop_name = NULL; 00134 // Get the string value, "property name" 00135 dbus_message_iter_get_basic (&in_dict, &prop_name); 00136 00137 dbus_message_iter_next (&in_dict); 00138 00139 DBusMessageIter variant; 00140 // Recurese into the variant [ variant(int) ] 00141 dbus_message_iter_recurse (&in_dict, &variant); 00142 00143 quint32 value; 00144 // Get the variant value which is uint32 00145 dbus_message_iter_get_basic (&variant, &value); 00146 00147 if (prop_name && 00148 strcmp (prop_name, "StepCount") == 0) 00149 currentmax = value; 00150 else if (prop_name && 00151 strcmp (prop_name, "CurrentStep") == 0) 00152 currentvolume = value; 00153 } 00154 00155 dbus_message_iter_next (&dict_entry); 00156 } 00157 dbus_message_iter_next (&iter); 00158 } 00159 } 00160 00161 if (reply) 00162 dbus_message_unref (reply); 00163 00164 addSignalMatch (); 00165 } 00166 00167 void VolumeBarLogic::addSignalMatch () 00168 { 00169 DBusMessage *message = NULL; 00170 char *signal = (char *) "com.Nokia.MainVolume1.StepsUpdated"; 00171 char **emptyarray = { NULL }; 00172 00173 message = dbus_message_new_method_call (NULL, 00174 "/org/pulseaudio/core1", 00175 NULL, 00176 "ListenForSignal"); 00177 00178 if (message != NULL) { 00179 dbus_message_append_args (message, 00180 DBUS_TYPE_STRING, &signal, 00181 DBUS_TYPE_ARRAY, DBUS_TYPE_OBJECT_PATH, &emptyarray, 0, 00182 DBUS_TYPE_INVALID); 00183 00184 dbus_connection_send (dbus_conn, message, NULL); 00185 } else { 00186 qWarning() << "Cannot listen for PulseAudio signals [out of memory]"; 00187 } 00188 00189 if (message) 00190 dbus_message_unref (message); 00191 } 00192 00193 void VolumeBarLogic::stepsUpdatedSignal ( 00194 DBusConnection *conn, DBusMessage *message, VolumeBarLogic *logic) 00195 { 00196 Q_UNUSED (conn); 00197 00198 if (message && dbus_message_has_member (message, "StepsUpdated")) { 00199 DBusError error; 00200 quint32 value = 0; 00201 quint32 maxvalue = 0; 00202 00203 dbus_error_init (&error); 00204 00205 if (dbus_message_get_args (message, &error, 00206 DBUS_TYPE_UINT32, &maxvalue, 00207 DBUS_TYPE_UINT32, &value, 00208 DBUS_TYPE_INVALID)) { 00209 logic->stepsUpdated (value, maxvalue); 00210 } 00211 00212 DBUS_ERR_CHECK (error); 00213 } 00214 } 00215 00216 void VolumeBarLogic::stepsUpdated (quint32 value, quint32 maxvalue) 00217 { 00218 currentvolume = value; 00219 currentmax = maxvalue; 00220 00221 emit volumeChanged (value, maxvalue); 00222 } 00223 00224 void VolumeBarLogic::setVolume (quint32 value) 00225 { 00226 currentvolume = value; 00227 00228 // Check the connection, maybe PulseAudio restarted meanwhile 00229 openConnection (); 00230 00231 // Don't try to set the volume via d-bus when it isn't available 00232 if (dbus_conn == NULL) 00233 return; 00234 00235 DBusMessage *message; 00236 char *volume_if = (char *) VOLUME_IF; 00237 char *method = (char *) "CurrentStep"; 00238 00239 message = dbus_message_new_method_call (VOLUME_SV, 00240 VOLUME_PATH, 00241 "org.freedesktop.DBus.Properties", 00242 "Set"); 00243 00244 if (message && 00245 dbus_message_append_args (message, 00246 DBUS_TYPE_STRING, &volume_if, 00247 DBUS_TYPE_STRING, &method, 00248 DBUS_TYPE_INVALID)) { 00249 DBusMessageIter append; 00250 DBusMessageIter sub; 00251 00252 // Create and append the variant argument ... 00253 dbus_message_iter_init_append (message, &append); 00254 00255 dbus_message_iter_open_container (&append, 00256 DBUS_TYPE_VARIANT, 00257 DBUS_TYPE_UINT32_AS_STRING, 00258 &sub); 00259 // Set the variant argument value: 00260 dbus_message_iter_append_basic (&sub, DBUS_TYPE_UINT32, &value); 00261 // Close the append iterator 00262 dbus_message_iter_close_container (&append, &sub); 00263 00264 // Send/flush the message immediately: 00265 dbus_connection_send (dbus_conn, message, NULL); 00266 } else { 00267 qWarning() << "Cannot set volume! [not enough memory]"; 00268 } 00269 00270 if (message) 00271 dbus_message_unref (message); 00272 } 00273 00274 quint32 VolumeBarLogic::volume () 00275 { 00276 ping (); 00277 00278 return currentvolume; 00279 } 00280 00281 quint32 VolumeBarLogic::maxVolume () 00282 { 00283 ping (); 00284 00285 return currentmax; 00286 } 00287 00288 /* 00289 * This function should be called before we're showing the 00290 * current volume on the screen... 00291 * 00292 * Because sometimes we can lost the connection to PulseAudio, 00293 * and meanwhile PulseAudio volume-values changed, and we 00294 * didn't get any info about those... 00295 */ 00296 void VolumeBarLogic::ping () 00297 { 00298 if ((dbus_conn != NULL) && 00299 (dbus_connection_get_is_connected (dbus_conn))) 00300 return; 00301 00302 /* 00303 * Connection lost, re-query the values 00304 */ 00305 openConnection (true); 00306 00307 stepsUpdated (currentvolume, currentmax); 00308 } 00309
| Copyright © 2010 Nokia Corporation | Generated on Wed Nov 10 16:04:52 2010 Doxygen 1.6.1 |
MeeGo Touch |
