RDK Documentation (Open Sourced RDK Components)
mediabrowser.c
Go to the documentation of this file.
1 /*
2  * If not stated otherwise in this file or this component's Licenses.txt file the
3  * following copyright and licenses apply:
4  *
5  * Copyright 2021 RDK Management
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19 /**
20  * @file mediabrowser.c
21  * @brief This source file contains functions that will help us to discover mediaservers in network.
22  */
23 #include "mediabrowser_private.h"
24 #include "mediabrowser.h"
25 
26 GList *msList = NULL; // mediaserver list
27 
28 /**
29  * Custom glist search function based on UDN
30  * */
31 static gint
32 g_list_find_udn(mediaServerCfg *gwData, gconstpointer *udn)
33 {
34  int result = -1;
35  if (strcmp_s((gchar *)udn, strlen((gchar *)udn), gwData->udn, &result) == EOK &&
36  !result)
37  {
38  return 0;
39  }
40  return 1;
41 }
42 
43 static gboolean
44 browse_remote_directory(GUPnPServiceInfo *browserService, gchar *root, int startIndex, int maxCount, guint *totalResults, gchar **result)
45 {
46  gchar *browseFlag = BROWSE_MODE_CHILD_NODE;
47  gchar *filter = "*";
48  gchar *sortCriteria = "";
49  GError *error = NULL;
50  guint numberReturned, totalMatches, updateId;
51  gboolean status = TRUE;
52 
53 #ifdef GUPNP_1_2
54  GUPnPServiceProxyAction *action = gupnp_service_proxy_action_new("Browse",
55  "ObjectID", G_TYPE_STRING, root, "BrowseFlag", G_TYPE_STRING, browseFlag,
56  "Filter", G_TYPE_STRING, filter, "StartingIndex", G_TYPE_INT, startIndex,
57  "RequestedCount", G_TYPE_INT, maxCount, "SortCriteria", G_TYPE_STRING, sortCriteria,
58  NULL);
59  gupnp_service_proxy_call_action(browserService, action, NULL, &error);
60  if (error == NULL)
61  {
62  gupnp_service_proxy_action_get_result(action,
63  &error, "Result", G_TYPE_STRING, result,
64  "NumberReturned ", G_TYPE_INT, &numberReturned,
65  "TotalMatches", G_TYPE_INT, &totalMatches,
66  "UpdateID ", G_TYPE_INT, &updateId,
67  NULL);
68  g_clear_pointer(&action, gupnp_service_proxy_action_unref);
69  }
70 #else
71  gupnp_service_proxy_send_action(browserService, "Browse", &error,
72  "ObjectID", G_TYPE_STRING, root, "BrowseFlag", G_TYPE_STRING, browseFlag,
73  "Filter", G_TYPE_STRING, filter, "StartingIndex", G_TYPE_INT, startIndex,
74  "RequestedCount", G_TYPE_INT, maxCount, "SortCriteria", G_TYPE_STRING, sortCriteria,
75  NULL,
76  "Result", G_TYPE_STRING, result,
77  "NumberReturned ", G_TYPE_INT, &numberReturned,
78  "TotalMatches", G_TYPE_INT, &totalMatches,
79  "UpdateID ", G_TYPE_INT, &updateId,
80  NULL);
81 #endif
82  if (NULL != error) // Didn't went well
83  {
84  g_message("[%s] UPNP Browse call failed : %s\n", __FUNCTION__, error->message);
85  g_clear_error(&error);
86  status = FALSE;
87  }
88  return status;
89 }
90 
91 bool browse_remote_dir_with_udn(const char *server_udn, const char *path_id, int start_index,
92  int max_entries, int *totalCount, char **results)
93 {
94  GList *msListItem = NULL;
95  g_mutex_lock(locker);
96  msListItem = g_list_find_custom(msList, server_udn, (GCompareFunc)g_list_find_udn);
97  g_mutex_unlock(locker);
98 
99  if (NULL == msListItem)
100  {
101  g_message("[%s] Failed to identify the device in cache %s ", __FUNCTION__, server_udn);
102  return false;
103  }
104  mediaServerCfg *msConfig = (mediaServerCfg *)msListItem->data;
105 
106  return browse_remote_directory(msConfig->browserService, path_id, start_index, max_entries, totalCount, results);
107 }
108 
109 static void
110 device_proxy_available_mr_cb(GUPnPControlPoint *cp, GUPnPDeviceProxy *dproxy)
111 {
112  g_message("%s] Found a new UPNP media server", __FUNCTION__);
113  if ((NULL == cp) || (NULL == dproxy))
114  {
115  g_message("[%s] Got empty control point or device proxy. Leaving", __FUNCTION__);
116  return;
117  }
118  gchar *data = gupnp_device_info_get_udn(GUPNP_DEVICE_INFO(dproxy));
119  g_message("[%s] Got UDN as %s ", __FUNCTION__, data);
120  GList *msListItem = NULL;
121 
122  g_mutex_lock(locker);
123  msListItem = g_list_find_custom(msList, data, (GCompareFunc)g_list_find_udn);
124  g_mutex_unlock(locker);
125  if (NULL != msListItem)
126  {
127  g_message("[%s] Existing device, ignoring.", __FUNCTION__);
128  return;
129  }
130  mediaServerCfg *mserver = g_new(mediaServerCfg, 1);
131  mserver->friendlyname = NULL;
132  mserver->udn = strdup(data);
133  g_free(data);
134 
135  data = gupnp_device_info_get_friendly_name(GUPNP_DEVICE_INFO(dproxy));
136  g_message("[%s] Got Friendly name as %s ", __FUNCTION__, data);
137  mserver->friendlyname = strdup(data);
138  g_free(data);
139  /*
140  GList *service_list = gupnp_device_info_list_services(GUPNP_DEVICE_INFO(dproxy));
141  int srv_list_size = g_list_length(service_list);
142  g_message("[%s] There are total %d services ", __FUNCTION__, srv_list_size);
143  */
144  mserver->browserService = gupnp_device_info_get_service(GUPNP_DEVICE_INFO(dproxy), XUPNP_SERVICE_CONTENT_DIR);
145 
146  g_mutex_lock(locker);
147  msList = g_list_append(msList, mserver);
148  g_mutex_unlock(locker);
149 }
150 
151 static void
152 device_proxy_unavailable_mr_cb(GUPnPControlPoint *cp, GUPnPDeviceProxy *dproxy)
153 {
154 
155  g_message("Mediaserver disconnected event received.");
156  if ((NULL == cp) || (NULL == dproxy))
157  {
158  g_message("[%s] Got empty control point or device proxy. Leaving", __FUNCTION__);
159  return;
160  }
161  gchar *data = gupnp_device_info_get_udn(GUPNP_DEVICE_INFO(dproxy));
162  g_message("[%s] Got UDN as %s ", __FUNCTION__, data);
163 
164  GList *msListItem = NULL;
165  g_mutex_lock(locker);
166  g_list_find_custom(msList, data, (GCompareFunc)g_list_find_udn);
167 
168  if (NULL != msListItem)
169  {
170 
171  msList = g_list_remove_link(msList, msListItem);
172  g_mutex_unlock(locker);
173  {
174  mediaServerCfg *msItem = msListItem->data;
175  free(msItem->friendlyname);
176  free(msItem->udn);
177  g_clear_object(&(msItem->browserService));
178  g_free(msItem);
179  }
180  g_list_free(msListItem);
181  }
182  else
183  {
184  g_message("[%s] Not found in cache. ", __FUNCTION__);
185  }
186 
187 }
188 /**
189  * This method registered mediaserver control point and notification call backs.
190  * */
191 void registerBrowserConfig(GUPnPContext *context)
192 {
193  g_message("[%s] Registering media renderer device ", __FUNCTION__);
194  cp_media_rndr = gupnp_control_point_new(context, XUPNP_DEVICE_MEDIASERVER_CONTROL_URN);
195  g_signal_connect(cp_media_rndr, "device-proxy-available", G_CALLBACK(device_proxy_available_mr_cb), NULL);
196  g_signal_connect(cp_media_rndr, "device-proxy-unavailable", G_CALLBACK(device_proxy_unavailable_mr_cb), NULL);
197  gssdp_resource_browser_set_active(GSSDP_RESOURCE_BROWSER(cp_media_rndr), TRUE);
198 }
199 /**
200  * Initialises the variables used in mediabrowser
201  * */
203 {
204  locker = g_mutex_new();
205  init_ipc_iface();
206 }
207 /**
208  * De-initialises the variables used in mediabrowser
209  * */
211 {
212  g_mutex_free(locker);
213  close_rpc_iface();
214 }
init_media_browser
void init_media_browser()
Definition: mediabrowser.c:202
close_media_browser
void close_media_browser()
Definition: mediabrowser.c:210
_mediaServerCfg
Definition: mediabrowser_private.h:36
g_list_find_udn
static gint g_list_find_udn(mediaServerCfg *gwData, gconstpointer *udn)
Definition: mediabrowser.c:32
registerBrowserConfig
void registerBrowserConfig(GUPnPContext *context)
Definition: mediabrowser.c:191
TRUE
#define TRUE
Defines for TRUE/FALSE/ENABLE flags.
Definition: wifi_common_hal.h:199