Integrate adding files with the file manager
[anjuta-git-plugin.git] / plugins / debug-manager / queue.c
blob7c13328f8f6109fdf63ce7a35891f4f9cd02ec90
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
2 /*
3 queue.c
4 Copyright (C) 2005 Sébastien Granjoux
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 * Keep all debugger commands in a queue and send them one by one to the
23 * debugger (implementing IAnjutaDebugger).
24 *---------------------------------------------------------------------------*/
26 #include <config.h>
28 #include "queue.h"
30 /*#define DEBUG*/
31 #include <libanjuta/anjuta-debug.h>
32 #include <libanjuta/interfaces/ianjuta-message-manager.h>
33 #include <libanjuta/interfaces/ianjuta-debugger-register.h>
34 #include <libanjuta/interfaces/ianjuta-debugger-memory.h>
35 #include <libanjuta/interfaces/ianjuta-debugger-instruction.h>
36 #include <libanjuta/interfaces/ianjuta-debugger-breakpoint.h>
37 #include <libanjuta/interfaces/ianjuta-debugger-variable.h>
40 #include <stdarg.h>
42 /* Contants defintion
43 *---------------------------------------------------------------------------*/
45 #define ICON_FILE "anjuta-debug-manager.plugin.png"
47 /* Private type
48 *---------------------------------------------------------------------------*/
50 struct _DmaDebuggerQueue {
51 GObject parent;
53 AnjutaPlugin* plugin;
54 IAnjutaDebugger* debugger;
55 guint support;
57 /* Command queue */
58 GQueue *queue;
59 DmaQueueCommand *last;
60 gint prepend_command;
62 IAnjutaDebuggerState debugger_state;
63 IAnjutaDebuggerState queue_state;
64 gboolean stop_on_sharedlib;
66 /* View for debugger messages */
67 IAnjutaMessageView* log;
69 gboolean busy;
72 struct _DmaDebuggerQueueClass {
73 GObjectClass parent;
76 /* Call backs
77 *---------------------------------------------------------------------------*/
79 /* Queue function
80 *---------------------------------------------------------------------------*/
82 static void
83 dma_queue_cancel (DmaDebuggerQueue *self, DmaCommandFlag flag)
85 GList* node = g_queue_peek_head_link(self->queue);
87 /* Cancel all commands in queue with the flag */
88 while (node != NULL)
90 GList* next = g_list_next (node);
91 DmaQueueCommand* cmd = (DmaQueueCommand *)node->data;
93 if (dma_command_has_flag (cmd, flag))
95 dma_command_cancel (cmd);
96 g_queue_delete_link (self->queue, node);
98 node = next;
102 /* Cancel all commands those cannot handle this unexpected state
103 * Return TRUE if the state of the queue need to be changed too
106 static gboolean
107 dma_queue_cancel_unexpected (DmaDebuggerQueue *self, IAnjutaDebuggerState state)
109 GList* node = g_queue_peek_head_link(self->queue);
111 /* IANJUTA_DEBUGGER_BUSY is used as a do nothing marker*/
112 if (state == IANJUTA_DEBUGGER_BUSY) return FALSE;
114 /* Cancel all commands in queue with the flag */
115 while (node != NULL)
117 GList* next = g_list_next (node);
118 DmaQueueCommand* cmd = (DmaQueueCommand *)node->data;
120 if (!dma_command_is_valid_in_state(cmd, state))
122 /* Command is not allowed in this state, cancel it */
123 dma_command_cancel (cmd);
124 g_queue_delete_link (self->queue, node);
126 else if (dma_command_is_going_to_state (cmd) != IANJUTA_DEBUGGER_BUSY)
128 /* A command setting the state is kept,
129 debugger state is known again afterward, queue state is kept too */
131 return FALSE;
133 node = next;
135 /* End in this unexpected state */
136 self->queue_state = state;
138 return TRUE;
141 static void
142 dma_debugger_queue_clear (DmaDebuggerQueue *self)
144 g_queue_foreach (self->queue, (GFunc)dma_command_free, NULL);
145 /* Do not use g_queue_clear yet as it is defined only in GLib 2.14 */
146 while (g_queue_pop_head(self->queue) != NULL);
147 if (self->last != NULL)
149 DEBUG_PRINT("clear command %x", dma_command_get_type (self->last));
150 dma_command_free (self->last);
151 self->last = NULL;
154 /* Queue is empty so has the same state than debugger */
155 self->queue_state = self->debugger_state;
157 self->prepend_command = 0;
160 static void
161 dma_queue_emit_debugger_state_change (DmaDebuggerQueue *self, IAnjutaDebuggerState state, GError* err)
163 enum
165 NO_SIGNAL,
166 DEBUGGER_STOPPED_SIGNAL,
167 DEBUGGER_STARTED_SIGNAL,
168 PROGRAM_LOADED_SIGNAL,
169 PROGRAM_UNLOADED_SIGNAL,
170 PROGRAM_STARTED_SIGNAL,
171 PROGRAM_EXITED_SIGNAL,
172 PROGRAM_RUNNING_SIGNAL,
173 PROGRAM_STOPPED_SIGNAL
174 } signal = NO_SIGNAL;
176 DEBUG_PRINT("change debugger state new %d old %d", state, self->debugger_state);
178 switch (state)
180 case IANJUTA_DEBUGGER_BUSY:
181 /* Debugger is busy, nothing to do */
182 g_return_if_reached();
183 return;
184 case IANJUTA_DEBUGGER_STOPPED:
185 self->stop_on_sharedlib = FALSE;
186 signal = DEBUGGER_STOPPED_SIGNAL;
187 self->debugger_state = state;
188 break;
189 case IANJUTA_DEBUGGER_STARTED:
190 self->stop_on_sharedlib = FALSE;
191 signal = self->debugger_state < IANJUTA_DEBUGGER_STARTED ? DEBUGGER_STARTED_SIGNAL : PROGRAM_UNLOADED_SIGNAL;
192 self->debugger_state = state;
193 break;
194 case IANJUTA_DEBUGGER_PROGRAM_LOADED:
195 self->stop_on_sharedlib = FALSE;
196 signal = self->debugger_state < IANJUTA_DEBUGGER_PROGRAM_LOADED ? PROGRAM_LOADED_SIGNAL : PROGRAM_EXITED_SIGNAL;
197 self->debugger_state = state;
198 break;
199 case IANJUTA_DEBUGGER_PROGRAM_STOPPED:
200 if (self->debugger_state < IANJUTA_DEBUGGER_PROGRAM_STOPPED)
202 signal = PROGRAM_STARTED_SIGNAL;
203 /* Emit a debugger stopped after program started */
204 self->debugger_state = IANJUTA_DEBUGGER_PROGRAM_RUNNING;
205 break;
207 if (!self->stop_on_sharedlib)
209 signal = PROGRAM_STOPPED_SIGNAL;
211 self->debugger_state = state;
212 break;
213 case IANJUTA_DEBUGGER_PROGRAM_RUNNING:
214 self->stop_on_sharedlib = FALSE;
215 if (self->debugger_state < IANJUTA_DEBUGGER_PROGRAM_STOPPED)
217 signal = PROGRAM_STARTED_SIGNAL;
218 /* Emit a debugger stopped after program started */
219 self->debugger_state = IANJUTA_DEBUGGER_PROGRAM_STOPPED;
220 break;
222 signal = PROGRAM_RUNNING_SIGNAL;
223 self->debugger_state = state;
224 break;
227 self->prepend_command++;
228 /* Emit signal */
229 switch (signal)
231 case NO_SIGNAL:
232 /* Do nothing */
233 break;
234 case DEBUGGER_STOPPED_SIGNAL:
235 DEBUG_PRINT("** emit debugger-stopped **");
236 g_signal_emit_by_name (self->plugin, "debugger-stopped", err);
237 break;
238 case DEBUGGER_STARTED_SIGNAL:
239 DEBUG_PRINT("** emit debugger-started **");
240 g_signal_emit_by_name (self->plugin, "debugger-started");
241 break;
242 case PROGRAM_LOADED_SIGNAL:
243 DEBUG_PRINT("** emit program-loaded **");
244 g_signal_emit_by_name (self->plugin, "program-loaded");
245 break;
246 case PROGRAM_UNLOADED_SIGNAL:
247 DEBUG_PRINT("** emit program-unloaded **");
248 g_signal_emit_by_name (self->plugin, "program-unloaded");
249 break;
250 case PROGRAM_STARTED_SIGNAL:
251 DEBUG_PRINT("** emit program-started **");
252 g_signal_emit_by_name (self->plugin, "program-started");
253 break;
254 case PROGRAM_EXITED_SIGNAL:
255 DEBUG_PRINT("** emit program-exited **");
256 g_signal_emit_by_name (self->plugin, "program-exited");
257 break;
258 case PROGRAM_STOPPED_SIGNAL:
259 DEBUG_PRINT("** emit program-stopped **");
260 g_signal_emit_by_name (self->plugin, "program-stopped");
261 break;
262 case PROGRAM_RUNNING_SIGNAL:
263 DEBUG_PRINT("** emit program-running **");
264 g_signal_emit_by_name (self->plugin, "program-running");
265 break;
267 self->prepend_command--;
270 static void
271 dma_queue_emit_debugger_state (DmaDebuggerQueue *self, IAnjutaDebuggerState state, GError* err)
273 DEBUG_PRINT("update debugger state new %d old %d", state, self->debugger_state);
275 /* Add missing states if useful */
276 for(;self->debugger_state != state;)
278 IAnjutaDebuggerState next_state = state;
280 switch (state)
282 case IANJUTA_DEBUGGER_STOPPED:
283 if ((self->debugger_state == IANJUTA_DEBUGGER_PROGRAM_RUNNING) ||
284 (self->debugger_state == IANJUTA_DEBUGGER_PROGRAM_STOPPED))
286 next_state = IANJUTA_DEBUGGER_PROGRAM_LOADED;
288 else if (self->debugger_state == IANJUTA_DEBUGGER_PROGRAM_LOADED)
290 next_state = IANJUTA_DEBUGGER_STARTED;
292 break;
293 case IANJUTA_DEBUGGER_STARTED:
294 if ((self->debugger_state == IANJUTA_DEBUGGER_PROGRAM_RUNNING) ||
295 (self->debugger_state == IANJUTA_DEBUGGER_PROGRAM_STOPPED))
297 next_state = IANJUTA_DEBUGGER_PROGRAM_LOADED;
299 break;
300 case IANJUTA_DEBUGGER_PROGRAM_LOADED:
301 if (self->debugger_state == IANJUTA_DEBUGGER_STOPPED)
303 next_state = IANJUTA_DEBUGGER_STARTED;
305 break;
306 case IANJUTA_DEBUGGER_PROGRAM_STOPPED:
307 if (self->debugger_state == IANJUTA_DEBUGGER_STOPPED)
309 next_state = IANJUTA_DEBUGGER_STARTED;
311 else if (self->debugger_state == IANJUTA_DEBUGGER_STARTED)
313 next_state = IANJUTA_DEBUGGER_PROGRAM_LOADED;
315 break;
316 case IANJUTA_DEBUGGER_PROGRAM_RUNNING:
317 if (self->debugger_state == IANJUTA_DEBUGGER_STOPPED)
319 next_state = IANJUTA_DEBUGGER_STARTED;
321 else if (self->debugger_state == IANJUTA_DEBUGGER_STARTED)
323 next_state = IANJUTA_DEBUGGER_PROGRAM_LOADED;
325 break;
326 case IANJUTA_DEBUGGER_BUSY:
327 return;
329 dma_queue_emit_debugger_state_change (self, next_state, NULL);
333 static void
334 dma_queue_emit_debugger_ready (DmaDebuggerQueue *self)
336 gboolean busy;
338 if (g_queue_is_empty(self->queue) && (self->last == NULL))
340 busy = FALSE;
342 else
344 busy = TRUE;
347 if (busy != self->busy)
349 AnjutaStatus* status;
351 status = anjuta_shell_get_status(ANJUTA_PLUGIN (self->plugin)->shell, NULL);
352 if (busy)
354 anjuta_status_busy_push (status);
355 self->busy = TRUE;
357 else
359 anjuta_status_busy_pop (status);
360 self->busy = FALSE;
365 static void dma_debugger_queue_execute (DmaDebuggerQueue *self);
367 /* Call when debugger has completed the current command */
369 static void
370 dma_debugger_queue_complete (DmaDebuggerQueue *self, IAnjutaDebuggerState state)
372 DEBUG_PRINT("debugger_queue_complete %d", state);
374 if (state != IANJUTA_DEBUGGER_BUSY)
376 if (self->last != NULL)
378 if (dma_command_is_going_to_state (self->last) != state)
380 /* Command end in an unexpected state,
381 * Remove invalid following command */
382 dma_queue_cancel_unexpected (self, state);
385 /* Remove current command */
386 DEBUG_PRINT("end command %x", dma_command_get_type (self->last));
387 dma_command_free (self->last);
388 self->last = NULL;
392 /* Emit new state if necessary */
393 dma_queue_emit_debugger_state (self, state, NULL);
395 /* Send next command */
396 dma_debugger_queue_execute (self);
400 /* Call to send next command */
402 static void
403 dma_debugger_queue_execute (DmaDebuggerQueue *self)
405 DEBUG_PRINT("debugger_queue_execute");
407 /* Check if debugger is connected to a debugger backend */
408 g_return_if_fail (self->debugger != NULL);
410 /* Check if there debugger is busy */
411 if (self->last != NULL)
413 IAnjutaDebuggerState state;
414 /* Recheck state in case of desynchronization */
415 state = ianjuta_debugger_get_state (self->debugger, NULL);
416 dma_debugger_queue_complete (self, state);
419 /* Check if there is something to execute */
420 while (!g_queue_is_empty(self->queue) && (self->last == NULL))
422 DmaQueueCommand *cmd;
423 GError *err = NULL;
424 gboolean ok;
426 cmd = (DmaQueueCommand *)g_queue_pop_head(self->queue);
428 /* Start command */
429 self->last = cmd;
430 DEBUG_PRINT("run command %x", dma_command_get_type (cmd));
431 ok = dma_command_run (cmd, self->debugger, self, &err);
433 if (!ok || (err != NULL))
435 /* Something fail */
436 if (dma_command_is_going_to_state (self->last) != IANJUTA_DEBUGGER_BUSY)
438 /* Command has been canceled in an unexpected state,
439 * Remove invalid following command */
440 dma_queue_cancel_unexpected (self, self->debugger_state);
443 /* Remove current command */
444 DEBUG_PRINT("cancel command %x", dma_command_get_type (self->last));
445 dma_command_free (self->last);
446 self->last = NULL;
448 /* Display error message to user */
449 if (err != NULL)
451 if (err->message != NULL)
453 anjuta_util_dialog_error (GTK_WINDOW (ANJUTA_PLUGIN (self->plugin)->shell), err->message);
456 g_error_free (err);
461 dma_queue_emit_debugger_ready (self);
464 static gboolean
465 dma_queue_check_state (DmaDebuggerQueue *self, DmaQueueCommand* cmd)
467 gboolean recheck;
469 for (recheck = FALSE; recheck != TRUE; recheck = TRUE)
471 IAnjutaDebuggerState state;
473 if (self->prepend_command || dma_command_has_flag (cmd, HIGH_PRIORITY))
475 /* Prepend command and high priority command use debugger state or current command state */
476 if (self->last != NULL)
478 state = dma_command_is_going_to_state (self->last);
479 if (state == IANJUTA_DEBUGGER_BUSY)
481 state = self->debugger_state;
484 else
486 state = self->debugger_state;
489 else
491 /* Append command use queue state */
492 state = self->queue_state;
495 /* Only the debugger can be busy */
496 g_return_val_if_fail (state != IANJUTA_DEBUGGER_BUSY, FALSE);
498 if (dma_command_is_valid_in_state (cmd, state))
500 /* State is right */
501 return TRUE;
504 g_warning ("Cancel command %x, debugger in state %d", dma_command_get_type (cmd), state);
506 /* Check if synchronization is still ok */
507 state = ianjuta_debugger_get_state (self->debugger, NULL);
508 dma_debugger_queue_complete (self, state);
510 /* Check again */
513 return FALSE;
516 static gboolean
517 dma_debugger_activate_plugin (DmaDebuggerQueue* self, const gchar *mime_type)
519 AnjutaPluginManager *plugin_manager;
520 AnjutaPluginDescription *plugin;
521 GList *descs = NULL;
522 gchar *value;
524 /* Get list of debugger plugins */
525 plugin_manager = anjuta_shell_get_plugin_manager (ANJUTA_PLUGIN(self->plugin)->shell, NULL);
526 if (mime_type == NULL)
528 /* User has to select the right debugger */
529 descs = anjuta_plugin_manager_query (plugin_manager,
530 "Anjuta Plugin","Interfaces", "IAnjutaDebugger", NULL);
532 else
534 /* Propose only debugger supporting correct mime type */
535 descs = anjuta_plugin_manager_query (plugin_manager,
536 "Anjuta Plugin","Interfaces", "IAnjutaDebugger",
537 "File Loader", "SupportedMimeTypes", mime_type,
538 NULL);
541 if (descs == NULL)
543 /* No plugin found */
544 anjuta_util_dialog_error (GTK_WINDOW (ANJUTA_PLUGIN (self->plugin)->shell),
545 _("Unable to find one debugger plugin supporting a target with %s mime type"), mime_type);
547 return FALSE;
549 else if (g_list_length (descs) == 1)
551 /* Only one plugin found, use it */
552 plugin = (AnjutaPluginDescription *)descs->data;
554 else
556 /* Ask the user to select one plugin */
557 plugin = anjuta_plugin_manager_select (plugin_manager,
558 _("Select a plugin"),
559 _("Please select a plugin to activate"),
560 descs);
563 if (plugin != NULL)
565 /* Get debugger location */
566 value = NULL;
567 anjuta_plugin_description_get_string (plugin, "Anjuta Plugin", "Location", &value);
568 g_return_val_if_fail (value != NULL, FALSE);
570 /* Get debugger interface */
571 self->debugger = (IAnjutaDebugger *)anjuta_plugin_manager_get_plugin_by_id (plugin_manager, value);
573 self->support = 0;
574 /* Check if register interface is available */
575 self->support |= IANJUTA_IS_DEBUGGER_REGISTER(self->debugger) ? HAS_REGISTER : 0;
576 /* Check if memory interface is available */
577 self->support |= IANJUTA_IS_DEBUGGER_MEMORY(self->debugger) ? HAS_MEMORY : 0;
578 /* Check if instruction interface is available */
579 self->support |= IANJUTA_IS_DEBUGGER_INSTRUCTION(self->debugger) ? HAS_INSTRUCTION : 0;
580 /* Check if breakpoint interface is available */
581 self->support |= IANJUTA_IS_DEBUGGER_BREAKPOINT(self->debugger) ? HAS_BREAKPOINT : 0;
582 if (IANJUTA_IS_DEBUGGER_BREAKPOINT (self->debugger))
584 self->support |= ianjuta_debugger_breakpoint_implement (IANJUTA_DEBUGGER_BREAKPOINT (self->debugger), NULL) * HAS_BREAKPOINT * 2;
586 /* Check if variable interface is available */
587 self->support |= IANJUTA_IS_DEBUGGER_VARIABLE(self->debugger) ? HAS_VARIABLE : 0;
589 g_free (value);
591 return TRUE;
593 else
595 /* No plugin selected */
597 return FALSE;
601 /* IAnjutaDebugger callback
602 *---------------------------------------------------------------------------*/
604 static void
605 on_dma_debugger_ready (DmaDebuggerQueue *self, IAnjutaDebuggerState state)
607 DEBUG_PRINT ("From debugger: receive debugger ready %d", state);
609 dma_debugger_queue_complete (self, state);
612 static void
613 on_dma_debugger_started (DmaDebuggerQueue *self)
615 DEBUG_PRINT ("From debugger: receive debugger started");
616 dma_queue_emit_debugger_state (self, IANJUTA_DEBUGGER_STARTED, NULL);
619 static void
620 on_dma_debugger_stopped (DmaDebuggerQueue *self, GError *err)
622 IAnjutaDebuggerState state;
624 DEBUG_PRINT ("From debugger: receive debugger stopped with error %p", err);
625 dma_queue_emit_debugger_state (self, IANJUTA_DEBUGGER_STOPPED, err);
627 /* Reread debugger state, could have changed while emitting signal */
628 state = ianjuta_debugger_get_state (self->debugger, NULL);
629 dma_debugger_queue_complete (self, state);
632 static void
633 on_dma_program_loaded (DmaDebuggerQueue *self)
635 DEBUG_PRINT ("From debugger: receive program loaded");
636 dma_queue_emit_debugger_state (self, IANJUTA_DEBUGGER_PROGRAM_LOADED, NULL);
639 static void
640 on_dma_program_running (DmaDebuggerQueue *self)
642 DEBUG_PRINT ("From debugger: debugger_program_running");
643 dma_queue_emit_debugger_state (self, IANJUTA_DEBUGGER_PROGRAM_RUNNING, NULL);
646 static void
647 on_dma_program_stopped (DmaDebuggerQueue *self)
649 DEBUG_PRINT ("From debugger: receive program stopped");
650 dma_queue_emit_debugger_state (self, IANJUTA_DEBUGGER_PROGRAM_STOPPED, NULL);
653 static void
654 on_dma_program_exited (DmaDebuggerQueue *self)
656 DEBUG_PRINT ("From debugger: receive program exited");
657 dma_queue_emit_debugger_state (self, IANJUTA_DEBUGGER_PROGRAM_LOADED, NULL);
660 static void
661 on_dma_program_moved (DmaDebuggerQueue *self, guint pid, gint tid, gulong address, const gchar* src_path, guint line)
663 DEBUG_PRINT ("From debugger: program moved");
664 self->prepend_command++;
665 g_signal_emit_by_name (self->plugin, "program-moved", pid, tid, address, src_path, line);
666 self->prepend_command--;
669 static void
670 on_dma_frame_changed (DmaDebuggerQueue *self, guint frame, gint thread)
672 DEBUG_PRINT ("From debugger: frame changed");
673 self->prepend_command++;
674 g_signal_emit_by_name (self->plugin, "frame-changed", frame, thread);
675 self->prepend_command--;
678 static void
679 on_dma_signal_received (DmaDebuggerQueue *self, const gchar* name, const gchar* description)
681 DEBUG_PRINT ("From debugger: signal received");
682 self->prepend_command++;
683 g_signal_emit_by_name (self->plugin, "signal-received", name, description);
684 self->prepend_command--;
687 static void
688 on_dma_sharedlib_event (DmaDebuggerQueue *self)
690 DEBUG_PRINT ("From debugger: shared lib event");
691 self->stop_on_sharedlib = TRUE;
692 dma_debugger_queue_complete (self, IANJUTA_DEBUGGER_PROGRAM_STOPPED);
693 self->prepend_command++;
694 g_signal_emit_by_name (self->plugin, "sharedlib-event");
695 self->prepend_command--;
696 dma_queue_run (self);
699 /* Public function
700 *---------------------------------------------------------------------------*/
702 /* Command callback will add their commands at the beginning of the queue */
703 void
704 dma_debugger_queue_command_callback (const gpointer data, gpointer user_data, GError* err)
706 DmaDebuggerQueue *self = (DmaDebuggerQueue *)user_data;
708 g_return_if_fail (self->last != NULL);
710 self->prepend_command++;
711 if (self->queue_state != IANJUTA_DEBUGGER_STOPPED)
713 dma_command_callback (self->last, data, err);
715 self->prepend_command--;
718 gboolean
719 dma_debugger_queue_append (DmaDebuggerQueue *self, DmaQueueCommand *cmd)
721 DEBUG_PRINT("append cmd %x prepend %d", dma_command_get_type (cmd), self->prepend_command);
722 DEBUG_PRINT("current %x", self->last == NULL ? 0 : dma_command_get_type (self->last));
723 DEBUG_PRINT("queue %x", self->queue->head == NULL ? 0 : dma_command_get_type (self->queue->head->data));
725 if ((self->debugger != NULL) && dma_queue_check_state(self, cmd))
727 /* If command is asynchronous stop current command */
728 if (dma_command_has_flag (cmd, ASYNCHRONOUS))
730 IAnjutaDebuggerState state;
732 state = dma_command_is_going_to_state (cmd);
733 if (state != IANJUTA_DEBUGGER_BUSY)
735 /* Command is changing debugger state */
736 dma_queue_cancel_unexpected (self, state);
739 /* Append command at the beginning */
740 g_queue_push_head (self->queue, cmd);
742 /* We must not interrupt command having callback, as the command
743 * will be removed, the callback when emitted will be redirected to
744 * the handler of the next command */
745 if ((state == IANJUTA_DEBUGGER_STOPPED) || (self->debugger_state == IANJUTA_DEBUGGER_PROGRAM_RUNNING))
747 dma_debugger_queue_complete (self, self->debugger_state);
750 else if ((self->prepend_command > 0) || dma_command_has_flag (cmd, HIGH_PRIORITY))
752 IAnjutaDebuggerState state;
754 state = dma_command_is_going_to_state (cmd);
755 if (state != IANJUTA_DEBUGGER_BUSY)
757 /* Command is changing debugger state */
758 dma_queue_cancel_unexpected (self, state);
761 /* Prepend command at the beginning */
762 g_queue_push_head (self->queue, cmd);
764 else
766 /* Append command at the end (in the queue) */
767 IAnjutaDebuggerState state;
769 g_queue_push_tail (self->queue, cmd);
771 state = dma_command_is_going_to_state (cmd);
772 if (state != IANJUTA_DEBUGGER_BUSY)
774 self->queue_state = state;
778 dma_debugger_queue_execute(self);
780 return TRUE;
782 else
784 dma_command_free (cmd);
786 return FALSE;
790 void
791 dma_debugger_queue_stop (DmaDebuggerQueue *self)
793 /* Disconnect signal */
794 if (self->debugger)
796 g_signal_handlers_disconnect_by_func (self->debugger, G_CALLBACK (on_dma_debugger_ready), self);
797 g_signal_handlers_disconnect_by_func (self->debugger, G_CALLBACK (on_dma_debugger_started), self);
798 g_signal_handlers_disconnect_by_func (self->debugger, G_CALLBACK (on_dma_debugger_stopped), self);
799 g_signal_handlers_disconnect_by_func (self->debugger, G_CALLBACK (on_dma_program_loaded), self);
800 g_signal_handlers_disconnect_by_func (self->debugger, G_CALLBACK (on_dma_program_running), self);
801 g_signal_handlers_disconnect_by_func (self->debugger, G_CALLBACK (on_dma_program_stopped), self);
802 g_signal_handlers_disconnect_by_func (self->debugger, G_CALLBACK (on_dma_program_exited), self);
803 g_signal_handlers_disconnect_by_func (self->debugger, G_CALLBACK (on_dma_program_moved), self);
804 g_signal_handlers_disconnect_by_func (self->debugger, G_CALLBACK (on_dma_signal_received), self);
805 g_signal_handlers_disconnect_by_func (self->debugger, G_CALLBACK (on_dma_frame_changed), self);
806 g_signal_handlers_disconnect_by_func (self->debugger, G_CALLBACK (on_dma_sharedlib_event), self);
807 self->debugger = NULL;
808 self->support = 0;
812 gboolean
813 dma_debugger_queue_start (DmaDebuggerQueue *self, const gchar *mime_type)
815 dma_debugger_queue_stop (self);
817 /* Look for a debugger supporting mime_type */
818 if (!dma_debugger_activate_plugin (self, mime_type))
820 return FALSE;
823 if (self->debugger)
825 /* Connect signal */
826 g_signal_connect_swapped (self->debugger, "debugger-ready", G_CALLBACK (on_dma_debugger_ready), self);
827 g_signal_connect_swapped (self->debugger, "debugger-started", G_CALLBACK (on_dma_debugger_started), self);
828 g_signal_connect_swapped (self->debugger, "debugger-stopped", G_CALLBACK (on_dma_debugger_stopped), self);
829 g_signal_connect_swapped (self->debugger, "program-loaded", G_CALLBACK (on_dma_program_loaded), self);
830 g_signal_connect_swapped (self->debugger, "program-running", G_CALLBACK (on_dma_program_running), self);
831 g_signal_connect_swapped (self->debugger, "program-stopped", G_CALLBACK (on_dma_program_stopped), self);
832 g_signal_connect_swapped (self->debugger, "program-exited", G_CALLBACK (on_dma_program_exited), self);
833 g_signal_connect_swapped (self->debugger, "program-moved", G_CALLBACK (on_dma_program_moved), self);
834 g_signal_connect_swapped (self->debugger, "signal-received", G_CALLBACK (on_dma_signal_received), self);
835 g_signal_connect_swapped (self->debugger, "frame-changed", G_CALLBACK (on_dma_frame_changed), self);
836 g_signal_connect_swapped (self->debugger, "sharedlib-event", G_CALLBACK (on_dma_sharedlib_event), self);
838 if (self->log == NULL)
840 dma_queue_disable_log (self);
842 else
844 dma_queue_enable_log (self, self->log);
848 return self->debugger != NULL;
851 void
852 dma_queue_enable_log (DmaDebuggerQueue *self, IAnjutaMessageView *log)
854 self->log = log;
855 if (self->debugger != NULL)
857 ianjuta_debugger_enable_log (self->debugger, self->log, NULL);
861 void
862 dma_queue_disable_log (DmaDebuggerQueue *self)
864 self->log = NULL;
865 if (self->debugger != NULL)
867 ianjuta_debugger_disable_log (self->debugger, NULL);
871 IAnjutaDebuggerState
872 dma_debugger_queue_get_state (DmaDebuggerQueue *self)
874 return self->queue_state;
877 gboolean
878 dma_debugger_queue_is_supported (DmaDebuggerQueue *self, DmaDebuggerCapability capability)
880 return self->support & capability ? TRUE : FALSE;
883 /* GObject functions
884 *---------------------------------------------------------------------------*/
886 /* Used in dispose and finalize */
887 static gpointer parent_class;
889 /* dispose is the first destruction step. It is used to unref object created
890 * with instance_init in order to break reference counting cycles. This
891 * function could be called several times. All function should still work
892 * after this call. It has to called its parents.*/
894 static void
895 dma_debugger_queue_dispose (GObject *obj)
897 DmaDebuggerQueue *self = DMA_DEBUGGER_QUEUE (obj);
899 dma_debugger_queue_clear (self);
901 G_OBJECT_CLASS (parent_class)->dispose (obj);
904 /* finalize is the last destruction step. It must free all memory allocated
905 * with instance_init. It is called only one time just before releasing all
906 * memory */
908 static void
909 dma_debugger_queue_finalize (GObject *obj)
911 DmaDebuggerQueue *self = DMA_DEBUGGER_QUEUE (obj);
913 g_queue_free (self->queue);
915 G_OBJECT_CLASS (parent_class)->finalize (obj);
918 /* instance_init is the constructor. All functions should work after this
919 * call. */
921 static void
922 dma_debugger_queue_instance_init (DmaDebuggerQueue *self)
924 self->plugin = NULL;
925 self->debugger = NULL;
926 self->support = 0;
927 self->queue = g_queue_new ();
928 self->last = NULL;
929 self->busy = FALSE;
930 self->prepend_command = 0;
931 self->debugger_state = IANJUTA_DEBUGGER_STOPPED;
932 self->queue_state = IANJUTA_DEBUGGER_STOPPED;
933 self->log = NULL;
936 /* class_init intialize the class itself not the instance */
938 static void
939 dma_debugger_queue_class_init (DmaDebuggerQueueClass * klass)
941 GObjectClass *object_class;
943 g_return_if_fail (klass != NULL);
944 object_class = G_OBJECT_CLASS (klass);
946 parent_class = g_type_class_peek_parent (klass);
948 object_class->dispose = dma_debugger_queue_dispose;
949 object_class->finalize = dma_debugger_queue_finalize;
952 GType
953 dma_debugger_queue_get_type (void)
955 static GType type = 0;
957 if (!type)
959 static const GTypeInfo type_info =
961 sizeof (DmaDebuggerQueueClass),
962 (GBaseInitFunc) NULL,
963 (GBaseFinalizeFunc) NULL,
964 (GClassInitFunc) dma_debugger_queue_class_init,
965 (GClassFinalizeFunc) NULL,
966 NULL, /* class_data */
967 sizeof (DmaDebuggerQueue),
968 0, /* n_preallocs */
969 (GInstanceInitFunc) dma_debugger_queue_instance_init,
970 NULL /* value_table */
973 type = g_type_register_static (G_TYPE_OBJECT,
974 "DmaDebuggerQueue", &type_info, 0);
977 return type;
980 /* Creation and Destruction
981 *---------------------------------------------------------------------------*/
983 DmaDebuggerQueue*
984 dma_debugger_queue_new (AnjutaPlugin *plugin)
986 DmaDebuggerQueue *self;
988 self = g_object_new (DMA_DEBUGGER_QUEUE_TYPE, NULL);
989 self->plugin = plugin;
991 return self;
994 void
995 dma_debugger_queue_free (DmaDebuggerQueue *self)
997 dma_debugger_queue_stop (self);
998 g_object_unref (self);