+ klass = gst_element_factory_get_metadata(gst_element_get_factory(elem), GST_ELEMENT_METADATA_KLASS);
+ mime = gst_structure_get_name(gst_caps_get_structure(caps, 0));
+ caps_str = gst_caps_to_string(caps);
+
+ LOGW("unknown type of caps : %s from %s",
+ caps_str, GST_ELEMENT_NAME(elem));
+
+ MMPLAYER_FREEIF(caps_str);
+
+ /* There is no available codec. */
+ __mmplayer_check_not_supported_codec(player, klass, mime);
+}
+
+static gboolean
+__mmplayer_gst_decode_autoplug_continue(GstElement *bin, GstPad *pad,
+ GstCaps *caps, gpointer data)
+{
+ mmplayer_t *player = (mmplayer_t *)data;
+ const char *mime = NULL;
+ gboolean ret = TRUE;
+
+ MMPLAYER_LOG_GST_CAPS_TYPE(caps);
+ mime = gst_structure_get_name(gst_caps_get_structure(caps, 0));
+
+ if (g_str_has_prefix(mime, "audio")) {
+ GstStructure *caps_structure = NULL;
+ gint samplerate = 0;
+ gint channels = 0;
+ gchar *caps_str = NULL;
+
+ caps_structure = gst_caps_get_structure(caps, 0);
+ gst_structure_get_int(caps_structure, "rate", &samplerate);
+ gst_structure_get_int(caps_structure, "channels", &channels);
+
+ if ((channels > 0 && samplerate == 0)) {
+ LOGD("exclude audio...");
+ ret = FALSE;
+ }
+
+ caps_str = gst_caps_to_string(caps);
+ /* set it directly because not sent by TAG */
+ if (g_strrstr(caps_str, "mobile-xmf"))
+ mm_player_set_attribute((MMHandleType)player, NULL,
+ "content_audio_codec", "mobile-xmf", strlen("mobile-xmf"), NULL);
+
+ MMPLAYER_FREEIF(caps_str);
+ } else if (g_str_has_prefix(mime, "video") && player->videodec_linked) {
+ LOGD("already video linked");
+ ret = FALSE;
+ } else {
+ LOGD("found new stream");
+ }
+
+ return ret;
+}
+
+static gboolean
+__mmplayer_is_audio_offload_device_type(mmplayer_t *player)
+{
+ gboolean ret = FALSE;
+ GDBusConnection *conn = NULL;
+ GError *err = NULL;
+ GVariant *result = NULL;
+ const gchar *dbus_device_type = NULL;
+ const gchar *dbus_ret = NULL;
+ gint idx = 0;
+
+ conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
+ if (!conn || err) {
+ LOGE("failed g_bus_get_sync() (%s)", (err ? err->message : "null"));
+ g_error_free(err);
+ goto DONE;
+ }
+
+ result = g_dbus_connection_call_sync(conn,
+ "org.pulseaudio.Server",
+ "/org/pulseaudio/StreamManager",
+ "org.pulseaudio.StreamManager",
+ "GetCurrentMediaRoutingPath",
+ g_variant_new("(s)", "out"),
+ G_VARIANT_TYPE("(ss)"),
+ G_DBUS_CALL_FLAGS_NONE,
+ 2000,
+ NULL,
+ &err);
+ if (!result || err) {
+ LOGE("failed g_dbus_connection_call_sync() (%s)", (err ? err->message : "null"));
+ g_error_free(err);
+ goto DONE;
+ }
+
+ /* device type is listed in stream-map.json at mmfw-sysconf */
+ g_variant_get(result, "(&s&s)", &dbus_device_type, &dbus_ret);
+
+ LOGI("g_dbus_connection_call_sync() success (%s, %s)", dbus_device_type, dbus_ret);
+ if (strncmp("STREAM_MANAGER_RETURN_OK", dbus_ret, strlen(dbus_ret)))
+ goto DONE;
+
+ /* the device type is listed in ini file among audio-jack, bt-a2dp, usb-audio, builtin-speaker */
+ for (idx = 0; player->ini.audio_offload_device_type[idx][0] != '\0'; idx++) {
+ if (strstr(dbus_device_type, player->ini.audio_offload_device_type[idx])) {
+ LOGD("audio offload is supportable");
+ ret = TRUE;
+ goto DONE;
+ }
+ }
+
+ LOGD("audio offload is not supportable");
+
+DONE:
+ g_variant_unref(result);
+ if (conn)
+ g_object_unref(conn);
+
+ return ret;
+}
+
+static void __mmplayer_rebuild_audio_pipeline(mmplayer_t *player)
+{
+ mmplayer_state_e current_state = MM_PLAYER_STATE_NONE;
+ gint64 position = 0;
+
+ MMPLAYER_RETURN_IF_FAIL(player && player->attrs &&
+ player->pipeline && player->pipeline->mainbin);
+
+ MMPLAYER_CMD_LOCK(player);
+ current_state = MMPLAYER_CURRENT_STATE(player);
+
+ if (!gst_element_query_position(player->pipeline->mainbin[MMPLAYER_M_PIPE].gst, GST_FORMAT_TIME, &position))
+ LOGW("getting current position failed in paused");
+
+ _mmplayer_unrealize((MMHandleType)player);
+ _mmplayer_realize((MMHandleType)player);
+
+ _mmplayer_set_position((MMHandleType)player, position);
+
+ /* async not to be blocked in streaming case */
+ mm_player_set_attribute((MMHandleType)player, NULL, "profile_prepare_async", TRUE, NULL);
+
+ _mmplayer_pause((MMHandleType)player);
+
+ if (current_state == MM_PLAYER_STATE_PLAYING)
+ _mmplayer_start((MMHandleType)player);
+ MMPLAYER_CMD_UNLOCK(player);
+
+ LOGD("rebuilding audio pipeline is completed.");
+}
+
+void __mmplayer_audio_device_connected_cb(MMSoundDevice_t device_h, bool is_connected, void *user_data)
+{
+ mmplayer_t *player = (mmplayer_t *)user_data;
+ mm_sound_device_type_e dev_type = MM_SOUND_DEVICE_TYPE_BUILTIN_SPEAKER;
+ gboolean is_supportable = FALSE;
+
+ if (mm_sound_get_device_type(device_h, &dev_type) != MM_ERROR_NONE)
+ LOGW("failed to get device type");
+ else
+ LOGD("dev type (%d), connected (%d)", dev_type, is_connected);
+
+ if ((dev_type != MM_SOUND_DEVICE_TYPE_BLUETOOTH_A2DP) &&
+ (dev_type != MM_SOUND_DEVICE_TYPE_AUDIOJACK) &&
+ (dev_type != MM_SOUND_DEVICE_TYPE_USB_AUDIO)) {
+ LOGD("ignore this dev connected info");
+ return;
+ }
+
+ is_supportable = __mmplayer_is_audio_offload_device_type(player);
+ if (player->build_audio_offload == is_supportable) {
+ LOGD("keep current pipeline without re-building");
+ return;
+ }
+
+ /* rebuild pipeline */
+ LOGD("re-build pipeline - offload: %d", is_supportable);
+ player->build_audio_offload = FALSE;
+ __mmplayer_rebuild_audio_pipeline(player);
+
+ return;
+}
+
+static gboolean
+__mmplayer_add_audio_device_connected_cb(mmplayer_t *player)
+{
+ unsigned int id = 0;
+
+ if (player->audio_device_cb_id != 0) {
+ LOGW("audio device connected cb was already added (%u)", player->audio_device_cb_id);
+ return TRUE;
+ }
+
+ if (mm_sound_add_device_connected_callback(MM_SOUND_DEVICE_IO_DIRECTION_OUT_FLAG,
+ __mmplayer_audio_device_connected_cb, player, &id) == MM_ERROR_NONE) {
+ LOGD("added device connected cb (%u)", id);
+ player->audio_device_cb_id = id;
+ } else {
+ LOGW("failed to add device connected cb");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+int _mmplayer_audio_offload_is_activated(MMHandleType hplayer, bool *activated)
+{
+ mmplayer_t *player = (mmplayer_t *)hplayer;
+
+ MMPLAYER_FENTER();
+ MMPLAYER_RETURN_VAL_IF_FAIL(player, MM_ERROR_PLAYER_NOT_INITIALIZED);
+ MMPLAYER_RETURN_VAL_IF_FAIL(activated, MM_ERROR_INVALID_ARGUMENT);
+
+ *activated = player->build_audio_offload;
+
+ LOGD("offload activated : %d", (int)*activated);
+
+ MMPLAYER_FLEAVE();
+ return MM_ERROR_NONE;
+}