debug-manager: use g_spawn_sync() instead of fork() and waitpid()
[anjuta.git] / plugins / debug-manager / queue.c
blob8097ca4f4464440525269831cc28c289247b7c14
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 /* Contants defintion
41 *---------------------------------------------------------------------------*/
43 #define ICON_FILE "anjuta-debug-manager.plugin.png"
45 /* Private type
46 *---------------------------------------------------------------------------*/
48 struct _DmaDebuggerQueue {
49 GObject parent;
51 AnjutaPlugin* plugin;
52 IAnjutaDebugger* debugger;
53 guint support;
55 /* Command queue */
56 GQueue *queue;
57 DmaQueueCommand *last;
58 GList *insert_command; /* Insert command at the head of the list */
60 IAnjutaDebuggerState debugger_state;
61 IAnjutaDebuggerState queue_state;
62 gboolean stop_on_sharedlib;
64 /* View for debugger messages */
65 IAnjutaMessageView* log;
67 gboolean busy;
70 struct _DmaDebuggerQueueClass {
71 GObjectClass parent;
74 /* Call backs
75 *---------------------------------------------------------------------------*/
77 /* Queue function
78 *---------------------------------------------------------------------------*/
81 /* Cancel all commands those cannot handle this unexpected state
82 * Return TRUE if the state of the queue need to be changed too
85 static gboolean
86 dma_queue_cancel_unexpected (DmaDebuggerQueue *self, IAnjutaDebuggerState state)
88 GList* node = g_queue_peek_head_link(self->queue);
90 /* IANJUTA_DEBUGGER_BUSY is used as a do nothing marker*/
91 if (state == IANJUTA_DEBUGGER_BUSY) return FALSE;
93 /* Cancel all commands in queue with the flag */
94 while (node != NULL)
96 GList* next = g_list_next (node);
97 DmaQueueCommand* cmd = (DmaQueueCommand *)node->data;
99 if (!dma_command_is_valid_in_state(cmd, state))
101 /* Command is not allowed in this state, cancel it */
102 dma_command_cancel (cmd);
103 g_queue_delete_link (self->queue, node);
105 else if (dma_command_is_going_to_state (cmd) != IANJUTA_DEBUGGER_BUSY)
107 /* A command setting the state is kept,
108 debugger state is known again afterward, queue state is kept too */
110 return FALSE;
112 node = next;
114 /* End in this unexpected state */
115 self->queue_state = state;
117 return TRUE;
120 static void
121 dma_debugger_queue_clear (DmaDebuggerQueue *self)
123 g_queue_foreach (self->queue, (GFunc)dma_command_free, NULL);
124 /* Do not use g_queue_clear yet as it is defined only in GLib 2.14 */
125 while (g_queue_pop_head(self->queue) != NULL);
126 if (self->last != NULL)
128 DEBUG_PRINT("clear command %x", dma_command_get_type (self->last));
129 dma_command_free (self->last);
130 self->last = NULL;
133 /* Queue is empty so has the same state than debugger */
134 self->queue_state = self->debugger_state;
136 g_list_free (self->insert_command);
137 self->insert_command = NULL;
140 static void
141 dma_queue_emit_debugger_state_change (DmaDebuggerQueue *self, IAnjutaDebuggerState state, GError* err)
143 enum
145 NO_SIGNAL,
146 DEBUGGER_STOPPED_SIGNAL,
147 DEBUGGER_STARTED_SIGNAL,
148 PROGRAM_LOADED_SIGNAL,
149 PROGRAM_UNLOADED_SIGNAL,
150 PROGRAM_STARTED_SIGNAL,
151 PROGRAM_EXITED_SIGNAL,
152 PROGRAM_RUNNING_SIGNAL,
153 PROGRAM_STOPPED_SIGNAL
154 } signal = NO_SIGNAL;
156 DEBUG_PRINT("change debugger state new %d old %d", state, self->debugger_state);
158 switch (state)
160 case IANJUTA_DEBUGGER_BUSY:
161 /* Debugger is busy, nothing to do */
162 g_return_if_reached();
163 return;
164 case IANJUTA_DEBUGGER_STOPPED:
165 self->stop_on_sharedlib = FALSE;
166 signal = DEBUGGER_STOPPED_SIGNAL;
167 self->debugger_state = state;
168 break;
169 case IANJUTA_DEBUGGER_STARTED:
170 self->stop_on_sharedlib = FALSE;
171 signal = self->debugger_state < IANJUTA_DEBUGGER_STARTED ? DEBUGGER_STARTED_SIGNAL : PROGRAM_UNLOADED_SIGNAL;
172 self->debugger_state = state;
173 break;
174 case IANJUTA_DEBUGGER_PROGRAM_LOADED:
175 self->stop_on_sharedlib = FALSE;
176 signal = self->debugger_state < IANJUTA_DEBUGGER_PROGRAM_LOADED ? PROGRAM_LOADED_SIGNAL : PROGRAM_EXITED_SIGNAL;
177 self->debugger_state = state;
178 break;
179 case IANJUTA_DEBUGGER_PROGRAM_STOPPED:
180 if (self->debugger_state < IANJUTA_DEBUGGER_PROGRAM_STOPPED)
182 signal = PROGRAM_STARTED_SIGNAL;
183 /* Emit a debugger stopped after program started */
184 self->debugger_state = IANJUTA_DEBUGGER_PROGRAM_RUNNING;
185 break;
187 if (!self->stop_on_sharedlib)
189 signal = PROGRAM_STOPPED_SIGNAL;
191 self->debugger_state = state;
192 break;
193 case IANJUTA_DEBUGGER_PROGRAM_RUNNING:
194 self->stop_on_sharedlib = FALSE;
195 if (self->debugger_state < IANJUTA_DEBUGGER_PROGRAM_STOPPED)
197 signal = PROGRAM_STARTED_SIGNAL;
198 /* Emit a debugger stopped after program started */
199 self->debugger_state = IANJUTA_DEBUGGER_PROGRAM_STOPPED;
200 break;
202 signal = PROGRAM_RUNNING_SIGNAL;
203 self->debugger_state = state;
204 break;
207 self->insert_command = g_list_prepend (self->insert_command, g_queue_peek_head_link (self->queue));
208 /* Emit signal */
209 switch (signal)
211 case NO_SIGNAL:
212 /* Do nothing */
213 break;
214 case DEBUGGER_STOPPED_SIGNAL:
215 DEBUG_PRINT("%s", "** emit debugger-stopped **");
216 g_signal_emit_by_name (self->plugin, "debugger-stopped", err);
217 break;
218 case DEBUGGER_STARTED_SIGNAL:
219 DEBUG_PRINT("%s", "** emit debugger-started **");
220 g_signal_emit_by_name (self->plugin, "debugger-started");
221 break;
222 case PROGRAM_LOADED_SIGNAL:
223 DEBUG_PRINT("%s", "** emit program-loaded **");
224 g_signal_emit_by_name (self->plugin, "program-loaded");
225 break;
226 case PROGRAM_UNLOADED_SIGNAL:
227 DEBUG_PRINT("%s", "** emit program-unloaded **");
228 g_signal_emit_by_name (self->plugin, "program-unloaded");
229 break;
230 case PROGRAM_STARTED_SIGNAL:
231 DEBUG_PRINT("%s", "** emit program-started **");
232 g_signal_emit_by_name (self->plugin, "program-started");
233 break;
234 case PROGRAM_EXITED_SIGNAL:
235 DEBUG_PRINT("%s", "** emit program-exited **");
236 g_signal_emit_by_name (self->plugin, "program-exited");
237 break;
238 case PROGRAM_STOPPED_SIGNAL:
239 DEBUG_PRINT("%s", "** emit program-stopped **");
240 g_signal_emit_by_name (self->plugin, "program-stopped");
241 break;
242 case PROGRAM_RUNNING_SIGNAL:
243 DEBUG_PRINT("%s", "** emit program-running **");
244 g_signal_emit_by_name (self->plugin, "program-running");
245 break;
247 self->insert_command = g_list_delete_link (self->insert_command, self->insert_command);
250 static void
251 dma_queue_emit_debugger_state (DmaDebuggerQueue *self, IAnjutaDebuggerState state, GError* err)
253 DEBUG_PRINT("update debugger state new %d old %d", state, self->debugger_state);
255 /* Add missing states if useful */
256 for(;self->debugger_state != state;)
258 IAnjutaDebuggerState next_state = state;
260 switch (state)
262 case IANJUTA_DEBUGGER_STOPPED:
263 if ((self->debugger_state == IANJUTA_DEBUGGER_PROGRAM_RUNNING) ||
264 (self->debugger_state == IANJUTA_DEBUGGER_PROGRAM_STOPPED))
266 next_state = IANJUTA_DEBUGGER_PROGRAM_LOADED;
268 else if (self->debugger_state == IANJUTA_DEBUGGER_PROGRAM_LOADED)
270 next_state = IANJUTA_DEBUGGER_STARTED;
272 break;
273 case IANJUTA_DEBUGGER_STARTED:
274 if ((self->debugger_state == IANJUTA_DEBUGGER_PROGRAM_RUNNING) ||
275 (self->debugger_state == IANJUTA_DEBUGGER_PROGRAM_STOPPED))
277 next_state = IANJUTA_DEBUGGER_PROGRAM_LOADED;
279 break;
280 case IANJUTA_DEBUGGER_PROGRAM_LOADED:
281 if (self->debugger_state == IANJUTA_DEBUGGER_STOPPED)
283 next_state = IANJUTA_DEBUGGER_STARTED;
285 break;
286 case IANJUTA_DEBUGGER_PROGRAM_STOPPED:
287 if (self->debugger_state == IANJUTA_DEBUGGER_STOPPED)
289 next_state = IANJUTA_DEBUGGER_STARTED;
291 else if (self->debugger_state == IANJUTA_DEBUGGER_STARTED)
293 next_state = IANJUTA_DEBUGGER_PROGRAM_LOADED;
295 break;
296 case IANJUTA_DEBUGGER_PROGRAM_RUNNING:
297 if (self->debugger_state == IANJUTA_DEBUGGER_STOPPED)
299 next_state = IANJUTA_DEBUGGER_STARTED;
301 else if (self->debugger_state == IANJUTA_DEBUGGER_STARTED)
303 next_state = IANJUTA_DEBUGGER_PROGRAM_LOADED;
305 break;
306 case IANJUTA_DEBUGGER_BUSY:
307 return;
309 dma_queue_emit_debugger_state_change (self, next_state, NULL);
313 static void
314 dma_queue_emit_debugger_ready (DmaDebuggerQueue *self)
316 gboolean busy;
318 if (g_queue_is_empty(self->queue) && (self->last == NULL))
320 busy = FALSE;
322 else
324 busy = TRUE;
327 if (busy != self->busy)
329 AnjutaStatus* status;
331 status = anjuta_shell_get_status(ANJUTA_PLUGIN (self->plugin)->shell, NULL);
332 self->busy = busy;
336 static void dma_debugger_queue_execute (DmaDebuggerQueue *self);
338 /* Call when debugger has completed the current command */
340 static void
341 dma_debugger_queue_complete (DmaDebuggerQueue *self, IAnjutaDebuggerState state)
343 DEBUG_PRINT("debugger_queue_complete %d", state);
345 if (state != IANJUTA_DEBUGGER_BUSY)
347 if (self->last != NULL)
349 if (dma_command_is_going_to_state (self->last) != state)
351 /* Command end in an unexpected state,
352 * Remove invalid following command */
353 dma_queue_cancel_unexpected (self, state);
356 /* Remove current command */
357 DEBUG_PRINT("end command %x", dma_command_get_type (self->last));
358 dma_command_free (self->last);
359 self->last = NULL;
363 /* Emit new state if necessary */
364 dma_queue_emit_debugger_state (self, state, NULL);
366 /* Send next command */
367 dma_debugger_queue_execute (self);
371 /* Call to send next command */
373 static void
374 dma_debugger_queue_execute (DmaDebuggerQueue *self)
376 DEBUG_PRINT("%s", "debugger_queue_execute");
378 /* Check if debugger is connected to a debugger backend */
379 g_return_if_fail (self->debugger != NULL);
381 /* Check if there debugger is busy */
382 if (self->last != NULL)
384 IAnjutaDebuggerState state;
385 /* Recheck state in case of desynchronization */
386 state = ianjuta_debugger_get_state (self->debugger, NULL);
387 dma_debugger_queue_complete (self, state);
390 /* Check if there is something to execute */
391 while (!g_queue_is_empty(self->queue) && (self->last == NULL))
393 DmaQueueCommand *cmd;
394 GError *err = NULL;
395 gboolean ok;
397 cmd = (DmaQueueCommand *)g_queue_pop_head(self->queue);
399 /* Start command */
400 self->last = cmd;
401 DEBUG_PRINT("run command %x", dma_command_get_type (cmd));
402 ok = dma_command_run (cmd, self->debugger, self, &err);
404 if (!ok || (err != NULL))
406 /* Something fail */
407 if (dma_command_is_going_to_state (self->last) != IANJUTA_DEBUGGER_BUSY)
409 /* Command has been canceled in an unexpected state,
410 * Remove invalid following command */
411 dma_queue_cancel_unexpected (self, self->debugger_state);
414 /* Remove current command */
415 DEBUG_PRINT("cancel command %x", dma_command_get_type (self->last));
416 dma_command_free (self->last);
417 self->last = NULL;
419 /* Display error message to user */
420 if (err != NULL)
422 if (err->message != NULL)
424 anjuta_util_dialog_error (GTK_WINDOW (ANJUTA_PLUGIN (self->plugin)->shell), err->message);
427 g_error_free (err);
432 dma_queue_emit_debugger_ready (self);
435 static gboolean
436 dma_queue_check_state (DmaDebuggerQueue *self, DmaQueueCommand* cmd)
438 gboolean recheck;
440 for (recheck = FALSE; recheck != TRUE; recheck = TRUE)
442 IAnjutaDebuggerState state;
444 if ((self->insert_command != NULL) || dma_command_has_flag (cmd, HIGH_PRIORITY))
446 /* Prepend command and high priority command use debugger state or current command state */
447 if (self->last != NULL)
449 state = dma_command_is_going_to_state (self->last);
450 if (state == IANJUTA_DEBUGGER_BUSY)
452 state = self->debugger_state;
455 else
457 state = self->debugger_state;
460 else
462 /* Append command use queue state */
463 state = self->queue_state;
466 /* Only the debugger can be busy */
467 g_return_val_if_fail (state != IANJUTA_DEBUGGER_BUSY, FALSE);
469 if (dma_command_is_valid_in_state (cmd, state))
471 /* State is right */
472 return TRUE;
475 g_warning ("Cancel command %x, debugger in state %d", dma_command_get_type (cmd), state);
477 /* Check if synchronization is still ok */
478 state = ianjuta_debugger_get_state (self->debugger, NULL);
479 dma_debugger_queue_complete (self, state);
481 /* Check again */
484 return FALSE;
487 static gboolean
488 dma_debugger_activate_plugin (DmaDebuggerQueue* self, const gchar *mime_type)
490 AnjutaPluginManager *plugin_manager;
491 AnjutaPluginDescription *plugin;
492 GList *descs = NULL;
493 gchar *value;
495 /* Get list of debugger plugins */
496 plugin_manager = anjuta_shell_get_plugin_manager (ANJUTA_PLUGIN(self->plugin)->shell, NULL);
497 if (mime_type == NULL)
499 /* User has to select the right debugger */
500 descs = anjuta_plugin_manager_query (plugin_manager,
501 "Anjuta Plugin","Interfaces", "IAnjutaDebugger", NULL);
503 else
505 /* Propose only debugger supporting correct mime type */
506 descs = anjuta_plugin_manager_query (plugin_manager,
507 "Anjuta Plugin","Interfaces", "IAnjutaDebugger",
508 "File Loader", "SupportedMimeTypes", mime_type,
509 NULL);
512 if (descs == NULL)
514 /* No plugin found */
515 anjuta_util_dialog_error (GTK_WINDOW (ANJUTA_PLUGIN (self->plugin)->shell),
516 _("Unable to find a debugger plugin supporting a target with %s MIME type"), mime_type);
518 return FALSE;
520 else if (g_list_length (descs) == 1)
522 /* Only one plugin found, use it */
523 plugin = (AnjutaPluginDescription *)descs->data;
525 else
527 /* Ask the user to select one plugin */
528 plugin = anjuta_plugin_manager_select (plugin_manager,
529 _("Select a plugin"),
530 _("Please select a plugin to activate"),
531 descs);
534 if (plugin != NULL)
536 /* Get debugger location */
537 value = NULL;
538 anjuta_plugin_description_get_string (plugin, "Anjuta Plugin", "Location", &value);
539 g_return_val_if_fail (value != NULL, FALSE);
541 /* Get debugger interface */
542 self->debugger = (IAnjutaDebugger *)anjuta_plugin_manager_get_plugin_by_id (plugin_manager, value);
544 self->support = 0;
545 /* Check if register interface is available */
546 self->support |= IANJUTA_IS_DEBUGGER_REGISTER(self->debugger) ? HAS_REGISTER : 0;
547 /* Check if memory interface is available */
548 self->support |= IANJUTA_IS_DEBUGGER_MEMORY(self->debugger) ? HAS_MEMORY : 0;
549 /* Check if instruction interface is available */
550 self->support |= IANJUTA_IS_DEBUGGER_INSTRUCTION(self->debugger) ? HAS_INSTRUCTION : 0;
551 /* Check if breakpoint interface is available */
552 self->support |= IANJUTA_IS_DEBUGGER_BREAKPOINT(self->debugger) ? HAS_BREAKPOINT : 0;
553 if (IANJUTA_IS_DEBUGGER_BREAKPOINT (self->debugger))
555 self->support |= ianjuta_debugger_breakpoint_implement_breakpoint (IANJUTA_DEBUGGER_BREAKPOINT (self->debugger), NULL) * HAS_BREAKPOINT * 2;
557 /* Check if variable interface is available */
558 self->support |= IANJUTA_IS_DEBUGGER_VARIABLE(self->debugger) ? HAS_VARIABLE : 0;
560 g_free (value);
562 return TRUE;
564 else
566 /* No plugin selected */
568 return FALSE;
572 /* IAnjutaDebugger callback
573 *---------------------------------------------------------------------------*/
575 static void
576 on_dma_debugger_ready (DmaDebuggerQueue *self, IAnjutaDebuggerState state)
578 DEBUG_PRINT ("From debugger: receive debugger ready %d", state);
580 dma_debugger_queue_complete (self, state);
583 static void
584 on_dma_debugger_started (DmaDebuggerQueue *self)
586 DEBUG_PRINT ("%s", "From debugger: receive debugger started");
587 dma_queue_emit_debugger_state (self, IANJUTA_DEBUGGER_STARTED, NULL);
590 static void
591 on_dma_debugger_stopped (DmaDebuggerQueue *self, GError *err)
593 IAnjutaDebuggerState state;
595 DEBUG_PRINT ("From debugger: receive debugger stopped with error %p", err);
596 dma_queue_emit_debugger_state (self, IANJUTA_DEBUGGER_STOPPED, err);
598 /* Reread debugger state, could have changed while emitting signal */
599 state = ianjuta_debugger_get_state (self->debugger, NULL);
600 dma_debugger_queue_complete (self, state);
603 static void
604 on_dma_program_loaded (DmaDebuggerQueue *self)
606 DEBUG_PRINT ("%s", "From debugger: receive program loaded");
607 dma_queue_emit_debugger_state (self, IANJUTA_DEBUGGER_PROGRAM_LOADED, NULL);
610 static void
611 on_dma_program_running (DmaDebuggerQueue *self)
613 DEBUG_PRINT ("%s", "From debugger: debugger_program_running");
614 dma_queue_emit_debugger_state (self, IANJUTA_DEBUGGER_PROGRAM_RUNNING, NULL);
617 static void
618 on_dma_program_stopped (DmaDebuggerQueue *self)
620 DEBUG_PRINT ("%s", "From debugger: receive program stopped");
621 dma_queue_emit_debugger_state (self, IANJUTA_DEBUGGER_PROGRAM_STOPPED, NULL);
624 static void
625 on_dma_program_exited (DmaDebuggerQueue *self)
627 DEBUG_PRINT ("%s", "From debugger: receive program exited");
628 dma_queue_emit_debugger_state (self, IANJUTA_DEBUGGER_PROGRAM_LOADED, NULL);
631 static void
632 on_dma_program_moved (DmaDebuggerQueue *self, guint pid, gint tid, gulong address, const gchar* src_path, guint line)
634 DEBUG_PRINT ("%s", "From debugger: program moved");
635 self->insert_command = g_list_prepend (self->insert_command, g_queue_peek_head_link (self->queue));
636 g_signal_emit_by_name (self->plugin, "program-moved", pid, tid, address, src_path, line);
637 self->insert_command = g_list_delete_link (self->insert_command, self->insert_command);
640 static void
641 on_dma_frame_changed (DmaDebuggerQueue *self, guint frame, gint thread)
643 DEBUG_PRINT ("%s", "From debugger: frame changed");
644 self->insert_command = g_list_prepend (self->insert_command, g_queue_peek_head_link (self->queue));
645 g_signal_emit_by_name (self->plugin, "frame-changed", frame, thread);
646 self->insert_command = g_list_delete_link (self->insert_command, self->insert_command);
649 static void
650 on_dma_signal_received (DmaDebuggerQueue *self, const gchar* name, const gchar* description)
652 DEBUG_PRINT ("%s", "From debugger: signal received");
653 self->insert_command = g_list_prepend (self->insert_command, g_queue_peek_head_link (self->queue));
654 g_signal_emit_by_name (self->plugin, "signal-received", name, description);
655 self->insert_command = g_list_delete_link (self->insert_command, self->insert_command);
658 static void
659 on_dma_sharedlib_event (DmaDebuggerQueue *self)
661 DEBUG_PRINT ("%s", "From debugger: shared lib event");
662 self->stop_on_sharedlib = TRUE;
663 dma_debugger_queue_complete (self, IANJUTA_DEBUGGER_PROGRAM_STOPPED);
664 self->insert_command = g_list_prepend (self->insert_command, g_queue_peek_head_link (self->queue));
665 g_signal_emit_by_name (self->plugin, "sharedlib-event");
666 self->insert_command = g_list_delete_link (self->insert_command, self->insert_command);
667 dma_queue_run (self);
670 /* Public function
671 *---------------------------------------------------------------------------*/
673 /* Command callback will add their commands at the beginning of the queue */
674 void
675 dma_debugger_queue_command_callback (const gpointer data, gpointer user_data, GError* err)
677 DmaDebuggerQueue *self = (DmaDebuggerQueue *)user_data;
679 g_return_if_fail (self->last != NULL);
681 self->insert_command = g_list_prepend (self->insert_command, g_queue_peek_head_link (self->queue));
682 if (self->queue_state != IANJUTA_DEBUGGER_STOPPED)
684 dma_command_callback (self->last, data, err);
686 self->insert_command = g_list_delete_link (self->insert_command, self->insert_command);
689 gboolean
690 dma_debugger_queue_append (DmaDebuggerQueue *self, DmaQueueCommand *cmd)
692 DEBUG_PRINT("append cmd %x prepend %p", dma_command_get_type (cmd), self->insert_command);
693 DEBUG_PRINT("current %x", self->last == NULL ? 0 : dma_command_get_type (self->last));
694 DEBUG_PRINT("queue %x", self->queue->head == NULL ? 0 : dma_command_get_type (self->queue->head->data));
696 if ((self->debugger != NULL) && dma_queue_check_state(self, cmd))
698 /* If command is asynchronous stop current command */
699 if (dma_command_has_flag (cmd, ASYNCHRONOUS))
701 IAnjutaDebuggerState state;
703 state = dma_command_is_going_to_state (cmd);
704 if (state != IANJUTA_DEBUGGER_BUSY)
706 /* Command is changing debugger state */
707 dma_queue_cancel_unexpected (self, state);
710 /* Append command at the beginning */
711 g_queue_push_head (self->queue, cmd);
713 /* We must not interrupt command having callback, as the command
714 * will be removed, the callback when emitted will be redirected to
715 * the handler of the next command */
716 if ((state == IANJUTA_DEBUGGER_STOPPED) || (self->debugger_state == IANJUTA_DEBUGGER_PROGRAM_RUNNING))
718 dma_debugger_queue_complete (self, self->debugger_state);
721 else if (dma_command_has_flag (cmd, HIGH_PRIORITY))
723 IAnjutaDebuggerState state;
725 state = dma_command_is_going_to_state (cmd);
726 if (state != IANJUTA_DEBUGGER_BUSY)
728 /* Command is changing debugger state */
729 dma_queue_cancel_unexpected (self, state);
732 /* Prepend command at the beginning */
733 g_queue_push_head (self->queue, cmd);
735 else if ((self->insert_command != NULL) && (self->insert_command->data != NULL))
737 IAnjutaDebuggerState state;
739 state = dma_command_is_going_to_state (cmd);
740 if (state != IANJUTA_DEBUGGER_BUSY)
742 /* Command is changing debugger state */
743 dma_queue_cancel_unexpected (self, state);
746 /* Insert command in the beginning */
747 g_queue_insert_before (self->queue, (GList *)self->insert_command->data, cmd);
749 else
751 /* Append command at the end (in the queue) */
752 IAnjutaDebuggerState state;
754 g_queue_push_tail (self->queue, cmd);
756 state = dma_command_is_going_to_state (cmd);
757 if (state != IANJUTA_DEBUGGER_BUSY)
759 self->queue_state = state;
763 dma_debugger_queue_execute(self);
765 return TRUE;
767 else
769 dma_command_free (cmd);
771 return FALSE;
775 void
776 dma_debugger_queue_stop (DmaDebuggerQueue *self)
778 /* Disconnect signal */
779 if (self->debugger)
781 g_signal_handlers_disconnect_by_func (self->debugger, G_CALLBACK (on_dma_debugger_ready), self);
782 g_signal_handlers_disconnect_by_func (self->debugger, G_CALLBACK (on_dma_debugger_started), self);
783 g_signal_handlers_disconnect_by_func (self->debugger, G_CALLBACK (on_dma_debugger_stopped), self);
784 g_signal_handlers_disconnect_by_func (self->debugger, G_CALLBACK (on_dma_program_loaded), self);
785 g_signal_handlers_disconnect_by_func (self->debugger, G_CALLBACK (on_dma_program_running), self);
786 g_signal_handlers_disconnect_by_func (self->debugger, G_CALLBACK (on_dma_program_stopped), self);
787 g_signal_handlers_disconnect_by_func (self->debugger, G_CALLBACK (on_dma_program_exited), self);
788 g_signal_handlers_disconnect_by_func (self->debugger, G_CALLBACK (on_dma_program_moved), self);
789 g_signal_handlers_disconnect_by_func (self->debugger, G_CALLBACK (on_dma_signal_received), self);
790 g_signal_handlers_disconnect_by_func (self->debugger, G_CALLBACK (on_dma_frame_changed), self);
791 g_signal_handlers_disconnect_by_func (self->debugger, G_CALLBACK (on_dma_sharedlib_event), self);
792 self->debugger = NULL;
793 self->support = 0;
797 gboolean
798 dma_debugger_queue_start (DmaDebuggerQueue *self, const gchar *mime_type)
800 dma_debugger_queue_stop (self);
802 /* Look for a debugger supporting mime_type */
803 if (!dma_debugger_activate_plugin (self, mime_type))
805 return FALSE;
808 if (self->debugger)
810 /* Connect signal */
811 g_signal_connect_swapped (self->debugger, "debugger-ready", G_CALLBACK (on_dma_debugger_ready), self);
812 g_signal_connect_swapped (self->debugger, "debugger-started", G_CALLBACK (on_dma_debugger_started), self);
813 g_signal_connect_swapped (self->debugger, "debugger-stopped", G_CALLBACK (on_dma_debugger_stopped), self);
814 g_signal_connect_swapped (self->debugger, "program-loaded", G_CALLBACK (on_dma_program_loaded), self);
815 g_signal_connect_swapped (self->debugger, "program-running", G_CALLBACK (on_dma_program_running), self);
816 g_signal_connect_swapped (self->debugger, "program-stopped", G_CALLBACK (on_dma_program_stopped), self);
817 g_signal_connect_swapped (self->debugger, "program-exited", G_CALLBACK (on_dma_program_exited), self);
818 g_signal_connect_swapped (self->debugger, "program-moved", G_CALLBACK (on_dma_program_moved), self);
819 g_signal_connect_swapped (self->debugger, "signal-received", G_CALLBACK (on_dma_signal_received), self);
820 g_signal_connect_swapped (self->debugger, "frame-changed", G_CALLBACK (on_dma_frame_changed), self);
821 g_signal_connect_swapped (self->debugger, "sharedlib-event", G_CALLBACK (on_dma_sharedlib_event), self);
823 if (self->log == NULL)
825 dma_queue_disable_log (self);
827 else
829 dma_queue_enable_log (self, self->log);
833 return self->debugger != NULL;
836 void
837 dma_queue_enable_log (DmaDebuggerQueue *self, IAnjutaMessageView *log)
839 self->log = log;
840 if (self->debugger != NULL)
842 ianjuta_debugger_enable_log (self->debugger, self->log, NULL);
846 void
847 dma_queue_disable_log (DmaDebuggerQueue *self)
849 self->log = NULL;
850 if (self->debugger != NULL)
852 ianjuta_debugger_disable_log (self->debugger, NULL);
856 IAnjutaDebuggerState
857 dma_debugger_queue_get_state (DmaDebuggerQueue *self)
859 return self->queue_state;
862 gboolean
863 dma_debugger_queue_is_supported (DmaDebuggerQueue *self, DmaDebuggerCapability capability)
865 return self->support & capability ? TRUE : FALSE;
868 /* GObject functions
869 *---------------------------------------------------------------------------*/
871 /* Used in dispose and finalize */
872 static gpointer parent_class;
874 /* dispose is the first destruction step. It is used to unref object created
875 * with instance_init in order to break reference counting cycles. This
876 * function could be called several times. All function should still work
877 * after this call. It has to called its parents.*/
879 static void
880 dma_debugger_queue_dispose (GObject *obj)
882 DmaDebuggerQueue *self = DMA_DEBUGGER_QUEUE (obj);
884 dma_debugger_queue_clear (self);
886 G_OBJECT_CLASS (parent_class)->dispose (obj);
889 /* finalize is the last destruction step. It must free all memory allocated
890 * with instance_init. It is called only one time just before releasing all
891 * memory */
893 static void
894 dma_debugger_queue_finalize (GObject *obj)
896 DmaDebuggerQueue *self = DMA_DEBUGGER_QUEUE (obj);
898 g_queue_free (self->queue);
900 G_OBJECT_CLASS (parent_class)->finalize (obj);
903 /* instance_init is the constructor. All functions should work after this
904 * call. */
906 static void
907 dma_debugger_queue_instance_init (DmaDebuggerQueue *self)
909 self->plugin = NULL;
910 self->debugger = NULL;
911 self->support = 0;
912 self->queue = g_queue_new ();
913 self->last = NULL;
914 self->busy = FALSE;
915 self->insert_command = NULL;
916 self->debugger_state = IANJUTA_DEBUGGER_STOPPED;
917 self->queue_state = IANJUTA_DEBUGGER_STOPPED;
918 self->log = NULL;
921 /* class_init intialize the class itself not the instance */
923 static void
924 dma_debugger_queue_class_init (DmaDebuggerQueueClass * klass)
926 GObjectClass *object_class;
928 g_return_if_fail (klass != NULL);
929 object_class = G_OBJECT_CLASS (klass);
931 parent_class = g_type_class_peek_parent (klass);
933 object_class->dispose = dma_debugger_queue_dispose;
934 object_class->finalize = dma_debugger_queue_finalize;
937 GType
938 dma_debugger_queue_get_type (void)
940 static GType type = 0;
942 if (!type)
944 static const GTypeInfo type_info =
946 sizeof (DmaDebuggerQueueClass),
947 (GBaseInitFunc) NULL,
948 (GBaseFinalizeFunc) NULL,
949 (GClassInitFunc) dma_debugger_queue_class_init,
950 (GClassFinalizeFunc) NULL,
951 NULL, /* class_data */
952 sizeof (DmaDebuggerQueue),
953 0, /* n_preallocs */
954 (GInstanceInitFunc) dma_debugger_queue_instance_init,
955 NULL /* value_table */
958 type = g_type_register_static (G_TYPE_OBJECT,
959 "DmaDebuggerQueue", &type_info, 0);
962 return type;
965 /* Creation and Destruction
966 *---------------------------------------------------------------------------*/
968 DmaDebuggerQueue*
969 dma_debugger_queue_new (AnjutaPlugin *plugin)
971 DmaDebuggerQueue *self;
973 self = g_object_new (DMA_DEBUGGER_QUEUE_TYPE, NULL);
974 self->plugin = plugin;
976 return self;
979 void
980 dma_debugger_queue_free (DmaDebuggerQueue *self)
982 dma_debugger_queue_stop (self);
983 g_object_unref (self);