Update media-service-upnp to version 0.3.0 ( ca17a69 )
[profile/ivi/media-service-upnp.git] / src / chain-task.c
1 /*
2  * media-service-upnp
3  *
4  * Copyright (C) 2012 Intel Corporation. All rights reserved.
5  *
6  * This program is free software; you can redistribute it and/or modify it
7  * under the terms and conditions of the GNU Lesser General Public License,
8  * version 2.1, as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope it will be useful, but WITHOUT
11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
13  * for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public License
16  * along with this program; if not, write to the Free Software Foundation, Inc.,
17  * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  * Ludovic Ferrandis <ludovic.ferrandis@intel.com>
20  *
21  */
22
23 #include <glib.h>
24
25 #include "chain-task.h"
26 #include "device.h"
27 #include "log.h"
28
29 typedef struct msu_chain_task_atom_t_ msu_chain_task_atom_t;
30 struct msu_chain_task_atom_t_ {
31         GUPnPServiceProxyActionCallback callback;
32         GUPnPServiceProxyAction *p_action;
33         GDestroyNotify free_func;
34         gpointer user_data;
35         msu_chain_task_action t_action;
36         msu_device_t *device;
37 };
38
39 struct msu_chain_task_t_ {
40         msu_chain_task_end end_func;
41         gpointer end_data;
42         GList *task_list;
43         msu_chain_task_atom_t *current;
44         gboolean canceled;
45         guint idle_id;
46 };
47
48 static void prv_free_atom(msu_chain_task_atom_t *atom)
49 {
50         if (atom->free_func != NULL)
51                 atom->free_func(atom->user_data);
52
53         g_free(atom);
54 }
55
56 static gboolean prv_idle_end_func(gpointer user_data)
57 {
58         msu_chain_task_t *chain = (msu_chain_task_t *)user_data;
59
60         chain->end_func(chain, chain->end_data);
61         return FALSE;
62 }
63
64 static gboolean prv_idle_next_task(gpointer user_data)
65 {
66         msu_chain_task_t *chain = (msu_chain_task_t *) user_data;
67         GList *head = chain->task_list;
68
69         chain->task_list = g_list_remove_link(chain->task_list, head);
70         g_list_free_1(head);
71
72         chain->idle_id = 0;
73         msu_chain_task_start(chain);
74
75         return FALSE;
76 }
77
78 static void prv_next_task(msu_chain_task_t *chain)
79 {
80         chain->idle_id = g_idle_add(prv_idle_next_task, chain);
81 }
82
83 gboolean msu_chain_task_is_canceled(msu_chain_task_t *chain)
84 {
85         return chain->canceled;
86 }
87
88 msu_device_t *msu_chain_task_get_device(msu_chain_task_t *chain)
89 {
90         if ((chain != NULL) && (chain->current != NULL))
91                 return chain->current->device;
92
93         return NULL;
94 }
95
96 gpointer *msu_chain_task_get_user_data(msu_chain_task_t *chain)
97 {
98         if ((chain != NULL) && (chain->current != NULL))
99                 return chain->current->user_data;
100
101         return NULL;
102 }
103
104 void msu_chain_task_cancel(msu_chain_task_t *chain)
105 {
106         msu_device_t *device;
107         msu_device_context_t *context;
108
109         if (chain->idle_id) {
110                 g_source_remove(chain->idle_id);
111                 chain->idle_id = 0;
112         }
113
114         device = msu_chain_task_get_device(chain);
115         context = msu_device_get_context(device, NULL);
116
117         if (chain->current->p_action) {
118                 gupnp_service_proxy_cancel_action(context->service_proxy,
119                                                   chain->current->p_action);
120                 chain->current->p_action = 0;
121         }
122
123         chain->canceled = TRUE;
124 }
125
126 void msu_chain_task_begin_action_cb(GUPnPServiceProxy *proxy,
127                                     GUPnPServiceProxyAction *action,
128                                     gpointer user_data)
129 {
130         msu_chain_task_t *chain = (msu_chain_task_t *) user_data;
131         msu_chain_task_atom_t *current;
132
133         if (chain != NULL) {
134                 current = chain->current;
135
136                 if (chain->current != NULL) {
137                         current->callback(proxy, action, current->user_data);
138                         chain->current->p_action = NULL;
139                 }
140
141                 prv_next_task(chain);
142         }
143 }
144
145 void msu_chain_task_start(msu_chain_task_t *chain)
146 {
147         gboolean failed;
148
149         if ((chain->task_list != NULL) && (!chain->canceled)) {
150                 chain->current = chain->task_list->data;
151                 chain->current->p_action = chain->current->t_action(chain,
152                                                                     &failed);
153
154                 if (failed)
155                         chain->canceled = TRUE;
156
157                 if (chain->current->p_action == NULL &&
158                     chain->current->callback == NULL)
159                         prv_next_task(chain);
160
161         } else {
162                 if (chain->end_func)
163                         chain->idle_id = g_idle_add(prv_idle_end_func, chain);
164         }
165 }
166
167 void msu_chain_task_add(msu_chain_task_t *chain,
168                         msu_chain_task_action action,
169                         msu_device_t *device,
170                         GUPnPServiceProxyActionCallback action_cb,
171                         GDestroyNotify free_func,
172                         gpointer cb_user_data)
173 {
174         msu_chain_task_atom_t *atom;
175
176         atom = g_new0(msu_chain_task_atom_t, 1);
177
178         atom->t_action = action;
179         atom->callback = action_cb;
180         atom->free_func = free_func;
181         atom->user_data = cb_user_data;
182         atom->device = device;
183
184         chain->task_list = g_list_append(chain->task_list, atom);
185 }
186
187 void msu_chain_task_delete(msu_chain_task_t *chain)
188 {
189         g_list_free_full(chain->task_list, (GDestroyNotify)prv_free_atom);
190         chain->task_list = NULL;
191         g_free(chain);
192 }
193
194 msu_chain_task_t *msu_chain_task_new(msu_chain_task_end end_func,
195                                      gpointer end_data)
196 {
197         msu_chain_task_t *chain;
198
199         chain = g_new0(msu_chain_task_t, 1);
200         chain->end_func = end_func;
201         chain->end_data = end_data;
202
203         return chain;
204 }