2 * irreco - Ir Remote Control
3 * Copyright (C) 2007 Arto Karppinen (arto.karppinen@iki.fi)
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.
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>
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
;
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
)
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
);
60 void irreco_cmd_chain_destroy(IrrecoCmdChain
* irreco_cmd_chain
)
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
);
69 void irreco_cmd_chain_set_execution_rate(IrrecoCmdChain
* irreco_cmd_chain
,
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
;
79 void irreco_cmd_chain_append(IrrecoCmdChain
* irreco_cmd_chain
,
80 IrrecoCmd
* irreco_cmd
)
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
);
91 void irreco_cmd_chain_append_copy(IrrecoCmdChain
* irreco_cmd_chain
,
92 IrrecoCmd
* irreco_cmd
)
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
));
104 void irreco_cmd_chain_remove(IrrecoCmdChain
* irreco_cmd_chain
, guint index
)
106 IrrecoCmd
*irreco_cmd
;
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
);
121 void irreco_cmd_chain_move(IrrecoCmdChain
* irreco_cmd_chain
,
122 guint from_index
, guint to_index
)
129 length
= irreco_cmd_chain_length(irreco_cmd_chain
);
131 if (from_index
< 0) {
133 } else if (from_index
> length
) {
137 if (to_index
> length
) {
139 } else if (to_index
< 0) {
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
);
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
,
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
174 guint
irreco_cmd_chain_length(IrrecoCmdChain
* irreco_cmd_chain
)
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
)
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
,
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
),
199 void irreco_cmd_chain_print(IrrecoCmdChain
* irreco_cmd_chain
)
205 if (irreco_cmd_chain
== NULL
) {
206 IRRECO_ERROR("IrrecoCmdChain pointer is NULL.\n");
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
222 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
223 /* Command chain execution. */
224 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
226 typedef struct _IrrecoCmdChainExecute IrrecoCmdChainExecute
;
227 struct _IrrecoCmdChainExecute
{
229 IrrecoData
*irreco_data
;
230 GFunc call_when_done
;
233 GString
*banner_message
;
236 /* Execution time will be timed in relation of time_sync. */
240 IrrecoCmdChain
*chain
;
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
,
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),
276 IRRECO_RETURN_BOOL(FALSE
);
278 /* Multiple commands. */
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
;
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
)
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
) {
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
);
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
)
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;
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
;
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",
372 glong time
= 2147483647;
373 IRRECO_PRINTF("%li\n", time
/ IRRECO_SECOND_IN_USEC
);
376 /* Schedule next call. */
378 g_timeout_add(time_diff
/ 1000,
380 irreco_cmd_chain_execute_next_1
),
383 g_idle_add(G_SOURCEFUNC(
384 irreco_cmd_chain_execute_next_1
),
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
);