/** * Send the call state and type * * @param method_call A DBusMessage to reply to; * pass NULL to send a signal instead * @param call_state A string representation of an alternate state * to send instead of the real call state * @param call_type A string representation of an alternate type * to send instead of the real call type * @return TRUE on success, FALSE on failure */ static gboolean send_call_state(DBusMessage *const method_call, const gchar *const call_state, const gchar *const call_type) { DBusMessage *msg = NULL; gboolean status = FALSE; const gchar *sstate; const gchar *stype; /* Allow spoofing */ if (call_state != NULL) sstate = call_state; else sstate = call_state_repr(datapipe_get_gint(call_state_pipe)); if (call_type != NULL) stype = call_type; else stype = call_type_repr(datapipe_get_gint(call_type_pipe)); /* If method_call is set, send a reply, * otherwise, send a signal */ if (method_call != NULL) { msg = dbus_new_method_reply(method_call); } else { /* sig_call_state_ind */ msg = dbus_new_signal(MCE_SIGNAL_PATH, MCE_SIGNAL_IF, MCE_CALL_STATE_SIG); } /* Append the call state and call type */ if (dbus_message_append_args(msg, DBUS_TYPE_STRING, &sstate, DBUS_TYPE_STRING, &stype, DBUS_TYPE_INVALID) == FALSE) { mce_log(LL_CRIT, "Failed to append %sarguments to D-Bus message " "for %s.%s", method_call ? "reply " : "", method_call ? MCE_REQUEST_IF : MCE_SIGNAL_IF, method_call ? MCE_CALL_STATE_GET : MCE_CALL_STATE_SIG); dbus_message_unref(msg); goto EXIT; } /* Send the message */ status = dbus_send_message(msg); EXIT: return status; }
/** Handle call_state_pipe notifications * * @param data (not used) */ static void mia_datapipe_call_state_cb(gconstpointer data) { call_state_t prev = call_state; call_state = GPOINTER_TO_INT(data); if( call_state == prev ) goto EXIT; mce_log(LL_DEBUG, "call_state = %s", call_state_repr(call_state)); EXIT: return; }
/** Update oFono voice call object from key string and variant * * @param self oFono voice call object */ static void ofono_vcall_update_1(ofono_vcall_t *self, DBusMessageIter *iter) { const char *key = 0; DBusMessageIter var; if( !mce_dbus_iter_get_string(iter, &key) ) goto EXIT; if( !mce_dbus_iter_get_variant(iter, &var) ) goto EXIT; if( !strcmp(key, "Emergency") ) { bool emergency = false; if( !mce_dbus_iter_get_bool(&var, &emergency) ) goto EXIT; self->type = ofono_calltype_to_mce(emergency); mce_log(LL_DEBUG, "* %s = ofono:%s -> mce:%s", key, emergency ? "true" : "false", call_type_repr(self->type)); } else if( !strcmp(key, "State") ) { const char *str = 0; if( !mce_dbus_iter_get_string(&var, &str) ) goto EXIT; self->state = ofono_callstate_to_mce(str); mce_log(LL_DEBUG, "* %s = ofono:%s -> mce:%s", key,str, call_state_repr(self->state)); } #if 0 else { mce_log(LL_DEBUG, "* %s = %s", key, "..."); } #endif EXIT: return; }
/** Evaluate mce call state * * Emit signals and update data pipes as needed * * @return true if call state / type changed, false otherwise */ static bool call_state_rethink_now(void) { bool changed = false; static ofono_vcall_t previous = { .state = CALL_STATE_INVALID, .type = NORMAL_CALL, }; ofono_vcall_t combined = { .state = CALL_STATE_NONE, .type = NORMAL_CALL, }; /* consider simulated call state */ ofono_vcall_merge_vcall(&combined, &simulated); /* consider ofono modem emergency properties */ if( modems_lut ) g_hash_table_foreach(modems_lut, call_state_merge_modem_cb, &combined); /* consider ofono voice call properties */ if( vcalls_lut ) g_hash_table_foreach(vcalls_lut, call_state_merge_vcall_cb, &combined); /* skip broadcast if no change */ if( !memcmp(&previous, &combined, sizeof combined) ) goto EXIT; changed = true; previous = combined; call_state_t call_state = combined.state; call_type_t call_type = combined.type; const char *state_str = call_state_repr(call_state); const char *type_str = call_type_repr(call_type); mce_log(LL_DEBUG, "call_state=%s, call_type=%s", state_str, type_str); /* If the state changed, signal the new state; * first externally, then internally * * The reason we do it externally first is to * make sure that the camera application doesn't * grab audio, otherwise the ring tone might go missing */ // TODO: is the above legacy statement still valid? send_call_state(NULL, state_str, type_str); execute_datapipe(&call_state_pipe, GINT_TO_POINTER(call_state), USE_INDATA, CACHE_INDATA); execute_datapipe(&call_type_pipe, GINT_TO_POINTER(call_type), USE_INDATA, CACHE_INDATA); EXIT: return changed; }