Some documenting thingies.
[irreco.git] / irreco / trunk / src / core / irreco_cmd_chain.c
blob08c404820184a3b965a5a8e449cc9a0eaf17f38e
1 /*
2 * irreco - Ir Remote Control
3 * Copyright (C) 2007 Arto Karppinen (arto.karppinen@iki.fi)
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 #include "irreco_cmd_chain.h"
21 #include <hildon/hildon-banner.h>
23 /**
24 * @typedef IrrecoCmdChain
26 * IrrecoCmdChain contains a list of IrrecoCmds, which can then all be
27 * executed one after another by calling irreco_cmd_chain_execute().
35 IrrecoCmdChain *irreco_cmd_chain_create()
37 IrrecoCmdChain *irreco_cmd_chain;
38 IRRECO_ENTER
40 irreco_cmd_chain = g_slice_new0(IrrecoCmdChain);
41 irreco_cmd_chain->execution_rate = IRRECO_SECONDS_TO_USEC(0.3);
42 IRRECO_RETURN_PTR(irreco_cmd_chain);
45 void irreco_cmd_chain_remove_all(IrrecoCmdChain * irreco_cmd_chain)
47 IRRECO_ENTER
49 g_assert(irreco_cmd_chain != NULL);
51 while (irreco_cmd_chain->command_list != NULL) {
52 irreco_cmd_destroy(irreco_cmd_chain->command_list->data);
53 irreco_cmd_chain->command_list = g_list_remove(
54 irreco_cmd_chain->command_list,
55 irreco_cmd_chain->command_list->data);
57 IRRECO_RETURN
60 void irreco_cmd_chain_destroy(IrrecoCmdChain * irreco_cmd_chain)
62 IRRECO_ENTER
63 if (irreco_cmd_chain == NULL) IRRECO_RETURN
64 irreco_cmd_chain_remove_all(irreco_cmd_chain);
65 g_slice_free(IrrecoCmdChain, irreco_cmd_chain);
66 IRRECO_RETURN
69 void irreco_cmd_chain_set_execution_rate(IrrecoCmdChain * irreco_cmd_chain,
70 glong execution_rate)
72 IRRECO_ENTER
73 g_assert(irreco_cmd_chain != NULL);
74 IRRECO_PRINTF("Setting execution rate to \"%li\".\n", execution_rate);
75 irreco_cmd_chain->execution_rate = execution_rate;
76 IRRECO_RETURN
79 void irreco_cmd_chain_append(IrrecoCmdChain * irreco_cmd_chain,
80 IrrecoCmd * irreco_cmd)
82 IRRECO_ENTER
84 g_assert(irreco_cmd_chain != NULL);
86 irreco_cmd_chain->command_list = g_list_append(
87 g_list_last(irreco_cmd_chain->command_list), irreco_cmd);
88 IRRECO_RETURN
91 void irreco_cmd_chain_append_copy(IrrecoCmdChain * irreco_cmd_chain,
92 IrrecoCmd * irreco_cmd)
94 IRRECO_ENTER
96 g_assert(irreco_cmd_chain != NULL);
98 irreco_cmd_chain->command_list = g_list_append(
99 g_list_last(irreco_cmd_chain->command_list),
100 irreco_cmd_dublicate(irreco_cmd));
101 IRRECO_RETURN
104 void irreco_cmd_chain_remove(IrrecoCmdChain * irreco_cmd_chain, guint index)
106 IrrecoCmd *irreco_cmd;
107 IRRECO_ENTER
109 g_assert(irreco_cmd_chain != NULL);
111 IRRECO_DEBUG("Removing command from index \"%u\".\n", index);
112 irreco_cmd = (IrrecoCmd *) g_list_nth_data(g_list_first(
113 irreco_cmd_chain->command_list), index);
114 irreco_cmd_destroy(irreco_cmd);
115 irreco_cmd_chain->command_list = g_list_remove(
116 g_list_first(irreco_cmd_chain->command_list), irreco_cmd);
118 IRRECO_RETURN
121 void irreco_cmd_chain_move(IrrecoCmdChain * irreco_cmd_chain,
122 guint from_index, guint to_index)
124 gpointer data;
125 GList* from_link;
126 gint length;
127 IRRECO_ENTER
129 length = irreco_cmd_chain_length(irreco_cmd_chain);
131 if (from_index < 0) {
132 from_index = 0;
133 } else if (from_index > length) {
134 IRRECO_RETURN
137 if (to_index > length) {
138 to_index = length;
139 } else if (to_index < 0) {
140 IRRECO_RETURN
143 from_link = g_list_nth(g_list_first(
144 irreco_cmd_chain->command_list), from_index);
145 data = from_link->data;
146 irreco_cmd_chain->command_list = g_list_delete_link(
147 irreco_cmd_chain->command_list, from_link);
148 irreco_cmd_chain->command_list = g_list_insert(g_list_first(
149 irreco_cmd_chain->command_list), data, to_index);
151 IRRECO_RETURN
155 * Make a copy of a command chain.
157 * @param from Make a copy of this IrrecoCmdChain, or NULL.
159 void irreco_cmd_chain_copy(IrrecoCmdChain * from,
160 IrrecoCmdChain * to)
162 IRRECO_ENTER
163 irreco_cmd_chain_remove_all(to);
164 to->execution_rate = from->execution_rate;
166 if (from == NULL) IRRECO_RETURN
167 IRRECO_CMD_CHAIN_FOREACH(from, command)
168 irreco_cmd_chain_append_copy(to, command);
169 IRRECO_CMD_CHAIN_FOREACH_END
171 IRRECO_RETURN
174 guint irreco_cmd_chain_length(IrrecoCmdChain * irreco_cmd_chain)
176 IRRECO_ENTER
177 IRRECO_RETURN_UINT(g_list_length(g_list_first(
178 irreco_cmd_chain->command_list)));
181 guint irreco_cmd_chain_lenght(IrrecoCmdChain * irreco_cmd_chain)
183 IRRECO_ENTER
184 if (irreco_cmd_chain->command_list == NULL) IRRECO_RETURN_UINT(0);
185 IRRECO_RETURN_UINT(g_list_length(g_list_first(
186 irreco_cmd_chain->command_list)));
189 IrrecoCmd *irreco_cmd_chain_get(IrrecoCmdChain * irreco_cmd_chain,
190 guint from_index)
192 IRRECO_ENTER
193 if (irreco_cmd_chain->command_list == NULL) IRRECO_RETURN_PTR(NULL);
194 IRRECO_RETURN_PTR(g_list_nth_data(g_list_first(
195 irreco_cmd_chain->command_list),
196 from_index));
199 void irreco_cmd_chain_print(IrrecoCmdChain * irreco_cmd_chain)
201 gint i = 0;
202 guint len;
203 IRRECO_ENTER
205 if (irreco_cmd_chain == NULL) {
206 IRRECO_ERROR("IrrecoCmdChain pointer is NULL.\n");
207 IRRECO_RETURN
210 len = irreco_cmd_chain_lenght(irreco_cmd_chain);
211 IRRECO_PRINTF("Printing command chain. Lenght: %u\n", len);
212 IRRECO_CMD_CHAIN_FOREACH(irreco_cmd_chain, command)
213 IRRECO_PRINTF("Command %i / %u\n", ++i, len);
214 irreco_cmd_print(command);
215 IRRECO_CMD_CHAIN_FOREACH_END
217 IRRECO_RETURN
222 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
223 /* Command chain execution. */
224 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
226 typedef struct _IrrecoCmdChainExecute IrrecoCmdChainExecute;
227 struct _IrrecoCmdChainExecute {
229 IrrecoData *irreco_data;
230 GFunc call_when_done;
231 gpointer user_data;
233 GString *banner_message;
234 GtkWidget *banner;
236 /* Execution time will be timed in relation of time_sync. */
237 GTimeVal time_sync;
238 glong time_pos;
240 IrrecoCmdChain *chain;
241 IrrecoCmd *command;
242 guint pos;
243 guint len;
246 gboolean irreco_cmd_chain_execute_next_1(IrrecoCmdChainExecute *execute);
247 gboolean irreco_cmd_chain_execute_next_2(IrrecoCmdChainExecute *execute);
250 * Start executing the command chain.
252 * If the command chain is longer than one command, then delayed execution is
253 * started. In that case, call_when_done will be called when the command chain
254 * has finished executing.
256 * Data pointer will be the command chain, and user_data what user has given.
258 * @return TRUE if delayed execution started, FALSE otherwise.
260 gboolean irreco_cmd_chain_execute(IrrecoCmdChain * irreco_cmd_chain,
261 IrrecoData *irreco_data,
262 GFunc call_when_done,
263 gpointer user_data)
265 guint len;
266 IRRECO_ENTER
268 /* Empty list. */
269 if (irreco_cmd_chain->command_list == NULL) {
270 IRRECO_RETURN_BOOL(FALSE);
272 /* Only one comamnd. */
273 } else if ((len = irreco_cmd_chain_length(irreco_cmd_chain)) == 1) {
274 irreco_cmd_execute(irreco_cmd_chain_get(irreco_cmd_chain, 0),
275 irreco_data);
276 IRRECO_RETURN_BOOL(FALSE);
278 /* Multiple commands. */
279 } else {
280 IrrecoCmdChainExecute *execute;
282 execute = g_slice_new0(IrrecoCmdChainExecute);
283 execute->banner_message = g_string_new("");
284 execute->irreco_data = irreco_data;
285 execute->chain = irreco_cmd_chain;
286 execute->pos = 0;
287 execute->len = len;
289 execute->call_when_done = call_when_done;
290 execute->user_data = user_data;
292 g_get_current_time(&execute->time_sync);
293 irreco_cmd_chain_execute_next_1(execute);
295 IRRECO_RETURN_BOOL(TRUE);
299 * Command execution phaze one, update banner.
301 gboolean irreco_cmd_chain_execute_next_1(IrrecoCmdChainExecute *execute)
303 gdouble fraction;
304 IRRECO_ENTER
306 IRRECO_PRINTF("Command %i / %u\n", execute->pos + 1, execute->len);
307 execute->command = irreco_cmd_chain_get(execute->chain, execute->pos);
309 g_string_printf(execute->banner_message, "%s%s", _("Executing: "),
310 irreco_cmd_get_long_name(execute->command));
311 IRRECO_PRINTF("%s\n", execute->banner_message->str);
313 if (execute->banner == NULL) {
314 GtkWidget *owner;
315 owner = GTK_WIDGET(irreco_window_manager_get_gtk_window(
316 execute->irreco_data->window_manager));
317 execute->banner = hildon_banner_show_progress(
318 owner, NULL, execute->banner_message->str);
319 } else {
320 hildon_banner_set_text(HILDON_BANNER(execute->banner),
321 execute->banner_message->str);
324 fraction = (float) 1 / (float) execute->len * (float)(execute->pos + 1);
325 IRRECO_DEBUG("Proggressbar fraction %f\n", fraction);
326 hildon_banner_set_fraction(HILDON_BANNER(execute->banner), fraction);
327 g_idle_add(G_SOURCEFUNC(irreco_cmd_chain_execute_next_2), execute);
328 IRRECO_RETURN_BOOL(FALSE);
332 * Command execution phaze two, execute command.
334 gboolean irreco_cmd_chain_execute_next_2(IrrecoCmdChainExecute *execute)
336 gboolean result;
337 IRRECO_ENTER
339 /* Wait command delay is simply added to the time_pos. */
340 if (execute->command->type == IRRECO_COMMAND_WAIT) {
342 /* Wait command overrides the chain specific execution rate.*/
343 execute->time_pos = execute->time_pos
344 + execute->command->wait.delay;
345 execute->pos = execute->pos + 1;
346 result = TRUE;
347 } else {
348 result = irreco_cmd_execute(execute->command,
349 execute->irreco_data);
350 execute->time_pos = execute->time_pos
351 + execute->chain->execution_rate;
352 execute->pos = execute->pos + 1;
355 /* Is something remaining to be executed? */
356 if (result == TRUE && execute->pos < execute->len) {
358 GTimeVal time_current, time_next;
359 glong time_diff;
361 g_get_current_time(&time_current);
362 time_next.tv_sec = execute->time_sync.tv_sec;
363 time_next.tv_usec = execute->time_sync.tv_usec;
364 g_time_val_add(&time_next, execute->time_pos);
366 /* How much time to next execution? */
367 time_diff = irreco_time_diff(&time_current, &time_next);
368 IRRECO_PRINTF("Executing next command after \"%li\" usec.\n",
369 time_diff);
372 glong time = 2147483647;
373 IRRECO_PRINTF("%li\n", time / IRRECO_SECOND_IN_USEC);
376 /* Schedule next call. */
377 if (time_diff > 0) {
378 g_timeout_add(time_diff / 1000,
379 G_SOURCEFUNC(
380 irreco_cmd_chain_execute_next_1),
381 execute);
382 } else {
383 g_idle_add(G_SOURCEFUNC(
384 irreco_cmd_chain_execute_next_1),
385 execute);
388 /* End of chain. */
389 } else {
390 gtk_widget_destroy(execute->banner);
391 g_string_free(execute->banner_message, TRUE);
392 IRRECO_DEBUG("Calling call_when_done()\n");
393 execute->call_when_done(execute->chain, execute->user_data);
394 g_slice_free(IrrecoCmdChainExecute, execute);
397 IRRECO_RETURN_BOOL(FALSE);