* plugins/debug-manager/disassemble.c,
[anjuta-git-plugin.git] / plugins / debug-manager / queue.c
blob365d848dfb6feb38fee6dea8e60fbc47313f7e13
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 (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;
175 gboolean emit_program_started = FALSE;
177 DEBUG_PRINT("update debugger state new %d old %d", state, self->debugger_state);
179 /* Add missing state if useful */
180 switch (state)
182 case IANJUTA_DEBUGGER_STOPPED:
183 if ((self->debugger_state == IANJUTA_DEBUGGER_PROGRAM_RUNNING) ||
184 (self->debugger_state == IANJUTA_DEBUGGER_PROGRAM_STOPPED))
186 dma_queue_emit_debugger_state (self, IANJUTA_DEBUGGER_PROGRAM_LOADED, NULL);
188 else if (self->debugger_state == IANJUTA_DEBUGGER_PROGRAM_LOADED)
190 dma_queue_emit_debugger_state (self, IANJUTA_DEBUGGER_STARTED, NULL);
192 break;
193 case IANJUTA_DEBUGGER_STARTED:
194 if ((self->debugger_state == IANJUTA_DEBUGGER_PROGRAM_RUNNING) ||
195 (self->debugger_state == IANJUTA_DEBUGGER_PROGRAM_STOPPED))
197 dma_queue_emit_debugger_state (self, IANJUTA_DEBUGGER_PROGRAM_LOADED, NULL);
199 break;
200 case IANJUTA_DEBUGGER_PROGRAM_LOADED:
201 if (self->debugger_state == IANJUTA_DEBUGGER_STOPPED)
203 dma_queue_emit_debugger_state (self, IANJUTA_DEBUGGER_STARTED, NULL);
205 break;
206 case IANJUTA_DEBUGGER_PROGRAM_STOPPED:
207 if (self->debugger_state == IANJUTA_DEBUGGER_STOPPED)
209 dma_queue_emit_debugger_state (self, IANJUTA_DEBUGGER_STARTED, NULL);
211 else if (self->debugger_state == IANJUTA_DEBUGGER_STARTED)
213 dma_queue_emit_debugger_state (self, IANJUTA_DEBUGGER_PROGRAM_LOADED, NULL);
215 break;
216 case IANJUTA_DEBUGGER_PROGRAM_RUNNING:
217 if (self->debugger_state == IANJUTA_DEBUGGER_STOPPED)
219 dma_queue_emit_debugger_state (self, IANJUTA_DEBUGGER_STARTED, NULL);
221 else if (self->debugger_state == IANJUTA_DEBUGGER_STARTED)
223 dma_queue_emit_debugger_state (self, IANJUTA_DEBUGGER_PROGRAM_LOADED, NULL);
225 break;
226 case IANJUTA_DEBUGGER_BUSY:
227 break;
230 if (self->debugger_state != state)
232 switch (state)
234 case IANJUTA_DEBUGGER_BUSY:
235 /* Debugger is busy, nothing to do */
236 return;
237 case IANJUTA_DEBUGGER_STOPPED:
238 self->stop_on_sharedlib = FALSE;
239 signal = DEBUGGER_STOPPED_SIGNAL;
240 self->debugger_state = state;
241 break;
242 case IANJUTA_DEBUGGER_STARTED:
243 self->stop_on_sharedlib = FALSE;
244 signal = self->debugger_state < IANJUTA_DEBUGGER_STARTED ? DEBUGGER_STARTED_SIGNAL : PROGRAM_UNLOADED_SIGNAL;
245 self->debugger_state = state;
246 break;
247 case IANJUTA_DEBUGGER_PROGRAM_LOADED:
248 self->stop_on_sharedlib = FALSE;
249 signal = self->debugger_state < IANJUTA_DEBUGGER_PROGRAM_LOADED ? PROGRAM_LOADED_SIGNAL : PROGRAM_EXITED_SIGNAL;
250 self->debugger_state = state;
251 break;
252 case IANJUTA_DEBUGGER_PROGRAM_STOPPED:
253 if (!self->stop_on_sharedlib)
255 emit_program_started = self->debugger_state < IANJUTA_DEBUGGER_PROGRAM_STOPPED;
256 signal = PROGRAM_STOPPED_SIGNAL;
258 else if (self->debugger_state < IANJUTA_DEBUGGER_PROGRAM_STOPPED)
260 signal = PROGRAM_STARTED_SIGNAL;
262 self->debugger_state = state;
263 break;
264 case IANJUTA_DEBUGGER_PROGRAM_RUNNING:
265 emit_program_started = self->debugger_state < IANJUTA_DEBUGGER_PROGRAM_STOPPED;
266 self->stop_on_sharedlib = FALSE;
267 signal = PROGRAM_RUNNING_SIGNAL;
268 self->debugger_state = state;
269 break;
273 self->prepend_command++;
274 /* Emit signal */
275 switch (signal)
277 case NO_SIGNAL:
278 /* Do nothing */
279 break;
280 case DEBUGGER_STOPPED_SIGNAL:
281 DEBUG_PRINT("** emit debugger-stopped **");
282 g_signal_emit_by_name (self->plugin, "debugger-stopped", err);
283 break;
284 case DEBUGGER_STARTED_SIGNAL:
285 DEBUG_PRINT("** emit debugger-started **");
286 g_signal_emit_by_name (self->plugin, "debugger-started");
287 break;
288 case PROGRAM_LOADED_SIGNAL:
289 DEBUG_PRINT("** emit program-loaded **");
290 g_signal_emit_by_name (self->plugin, "program-loaded");
291 break;
292 case PROGRAM_UNLOADED_SIGNAL:
293 DEBUG_PRINT("** emit program-unloaded **");
294 g_signal_emit_by_name (self->plugin, "program-unloaded");
295 break;
296 case PROGRAM_STARTED_SIGNAL:
297 DEBUG_PRINT("** emit program-started **");
298 g_signal_emit_by_name (self->plugin, "program-started");
299 break;
300 case PROGRAM_EXITED_SIGNAL:
301 DEBUG_PRINT("** emit program-exited **");
302 g_signal_emit_by_name (self->plugin, "program-exited");
303 break;
304 case PROGRAM_STOPPED_SIGNAL:
305 DEBUG_PRINT("** emit program-exited **");
306 if (emit_program_started)
308 DEBUG_PRINT("** emit program-started **");
309 g_signal_emit_by_name (self->plugin, "program-started");
311 DEBUG_PRINT("** emit program-stopped **");
312 g_signal_emit_by_name (self->plugin, "program-stopped");
313 break;
314 case PROGRAM_RUNNING_SIGNAL:
315 if (emit_program_started)
317 DEBUG_PRINT("** emit program-started **");
318 g_signal_emit_by_name (self->plugin, "program-started");
320 DEBUG_PRINT("** emit program-running **");
321 g_signal_emit_by_name (self->plugin, "program-running");
322 break;
324 self->prepend_command--;
327 static void
328 dma_queue_emit_debugger_ready (DmaDebuggerQueue *self)
330 gboolean busy;
332 if (g_queue_is_empty(self->queue) && (self->last == NULL))
334 busy = FALSE;
336 else
338 busy = TRUE;
341 if (busy != self->busy)
343 AnjutaStatus* status;
345 status = anjuta_shell_get_status(ANJUTA_PLUGIN (self->plugin)->shell, NULL);
346 if (busy)
348 anjuta_status_busy_push (status);
349 self->busy = TRUE;
351 else
353 anjuta_status_busy_pop (status);
354 self->busy = FALSE;
359 static void dma_debugger_queue_execute (DmaDebuggerQueue *self);
361 /* Call when debugger has completed the current command */
363 static void
364 dma_debugger_queue_complete (DmaDebuggerQueue *self, IAnjutaDebuggerState state)
366 DEBUG_PRINT("debugger_queue_complete %d", state);
368 if (state != IANJUTA_DEBUGGER_BUSY)
370 if (self->last != NULL)
372 if (dma_command_is_going_to_state (self->last) != state)
374 /* Command end in an unexpected state,
375 * Remove invalid following command */
376 dma_queue_cancel_unexpected (self, state);
379 /* Remove current command */
380 DEBUG_PRINT("end command %x", dma_command_get_type (self->last));
381 dma_command_free (self->last);
382 self->last = NULL;
386 /* Emit new state if necessary */
387 dma_queue_emit_debugger_state (self, state, NULL);
389 /* Send next command */
390 dma_debugger_queue_execute (self);
394 /* Call to send next command */
396 static void
397 dma_debugger_queue_execute (DmaDebuggerQueue *self)
399 DEBUG_PRINT("debugger_queue_execute");
401 /* Check if debugger is connected to a debugger backend */
402 g_return_if_fail (self->debugger != NULL);
404 /* Check if there debugger is busy */
405 if (self->last != NULL)
407 IAnjutaDebuggerState state;
408 /* Recheck state in case of desynchronization */
409 state = ianjuta_debugger_get_state (self->debugger, NULL);
410 dma_debugger_queue_complete (self, state);
413 /* Check if there is something to execute */
414 while (!g_queue_is_empty(self->queue) && (self->last == NULL))
416 DmaQueueCommand *cmd;
417 GError *err = NULL;
418 gboolean ok;
420 cmd = (DmaQueueCommand *)g_queue_pop_head(self->queue);
422 /* Start command */
423 self->last = cmd;
424 DEBUG_PRINT("run command %x", dma_command_get_type (cmd));
425 ok = dma_command_run (cmd, self->debugger, self, &err);
427 if (!ok || (err != NULL))
429 /* Something fail */
430 if (dma_command_is_going_to_state (self->last) != IANJUTA_DEBUGGER_BUSY)
432 /* Command has been canceled in an unexpected state,
433 * Remove invalid following command */
434 dma_queue_cancel_unexpected (self, self->debugger_state);
437 /* Remove current command */
438 DEBUG_PRINT("cancel command %x", dma_command_get_type (self->last));
439 dma_command_free (self->last);
440 self->last = NULL;
442 /* Display error message to user */
443 if (err != NULL)
445 if (err->message != NULL)
447 anjuta_util_dialog_error (GTK_WINDOW (ANJUTA_PLUGIN (self->plugin)->shell), err->message);
450 g_error_free (err);
455 dma_queue_emit_debugger_ready (self);
458 static gboolean
459 dma_queue_check_state (DmaDebuggerQueue *self, DmaQueueCommand* cmd)
461 gboolean recheck;
463 for (recheck = FALSE; recheck != TRUE; recheck = TRUE)
465 IAnjutaDebuggerState state;
467 if (self->prepend_command)
469 /* Prepend command use debugger state or current command state */
470 if (self->last != NULL)
472 state = dma_command_is_going_to_state (self->last);
473 if (state == IANJUTA_DEBUGGER_BUSY)
475 state = self->debugger_state;
478 else
480 state = self->debugger_state;
483 else
485 /* Append command use queue state */
486 state = self->queue_state;
489 /* Only the debugger can be busy */
490 g_return_val_if_fail (state != IANJUTA_DEBUGGER_BUSY, FALSE);
492 if (dma_command_is_valid_in_state (cmd, state))
494 /* State is right */
495 return TRUE;
498 g_warning ("Cancel command %x, debugger in state %d", dma_command_get_type (cmd), state);
500 /* Check if synchronization is still ok */
501 state = ianjuta_debugger_get_state (self->debugger, NULL);
502 dma_debugger_queue_complete (self, state);
504 /* Check again */
507 return FALSE;
510 static gboolean
511 dma_debugger_activate_plugin (DmaDebuggerQueue* self, const gchar *mime_type)
513 AnjutaPluginManager *plugin_manager;
514 AnjutaPluginDescription *plugin;
515 GList *descs = NULL;
516 gchar *value;
518 /* Get list of debugger plugins */
519 plugin_manager = anjuta_shell_get_plugin_manager (ANJUTA_PLUGIN(self->plugin)->shell, NULL);
520 if (mime_type == NULL)
522 /* User has to select the right debugger */
523 descs = anjuta_plugin_manager_query (plugin_manager,
524 "Anjuta Plugin","Interfaces", "IAnjutaDebugger", NULL);
526 else
528 /* Propose only debugger supporting correct mime type */
529 descs = anjuta_plugin_manager_query (plugin_manager,
530 "Anjuta Plugin","Interfaces", "IAnjutaDebugger",
531 "File Loader", "SupportedMimeTypes", mime_type,
532 NULL);
535 if (descs == NULL)
537 /* No plugin found */
538 anjuta_util_dialog_error (GTK_WINDOW (ANJUTA_PLUGIN (self->plugin)->shell),
539 _("Unable to find one debugger plugin acception %s mime type"), mime_type);
541 return FALSE;
543 else if (g_list_length (descs) == 1)
545 /* Only one plugin found, use it */
546 plugin = (AnjutaPluginDescription *)descs->data;
548 else
550 /* Ask the user to select one plugin */
551 plugin = anjuta_plugin_manager_select (plugin_manager,
552 _("Select a plugin"),
553 _("Please select a plugin to activate"),
554 descs);
557 if (plugin != NULL)
559 /* Get debugger location */
560 value = NULL;
561 anjuta_plugin_description_get_string (plugin, "Anjuta Plugin", "Location", &value);
562 g_return_val_if_fail (value != NULL, FALSE);
564 /* Get debugger interface */
565 self->debugger = (IAnjutaDebugger *)anjuta_plugin_manager_get_plugin_by_id (plugin_manager, value);
567 self->support = 0;
568 /* Check if register interface is available */
569 self->support |= IANJUTA_IS_DEBUGGER_REGISTER(self->debugger) ? HAS_REGISTER : 0;
570 /* Check if memory interface is available */
571 self->support |= IANJUTA_IS_DEBUGGER_MEMORY(self->debugger) ? HAS_MEMORY : 0;
572 /* Check if instruction interface is available */
573 self->support |= IANJUTA_IS_DEBUGGER_INSTRUCTION(self->debugger) ? HAS_INSTRUCTION : 0;
574 /* Check if breakpoint interface is available */
575 self->support |= IANJUTA_IS_DEBUGGER_BREAKPOINT(self->debugger) ? HAS_BREAKPOINT : 0;
576 if (IANJUTA_IS_DEBUGGER_BREAKPOINT (self->debugger))
578 self->support |= ianjuta_debugger_breakpoint_implement (IANJUTA_DEBUGGER_BREAKPOINT (self->debugger), NULL) * HAS_BREAKPOINT * 2;
580 /* Check if variable interface is available */
581 self->support |= IANJUTA_IS_DEBUGGER_VARIABLE(self->debugger) ? HAS_VARIABLE : 0;
583 g_free (value);
585 return TRUE;
587 else
589 /* No plugin selected */
591 return FALSE;
595 /* IAnjutaDebugger callback
596 *---------------------------------------------------------------------------*/
598 static void
599 on_dma_debugger_ready (DmaDebuggerQueue *self, IAnjutaDebuggerState state)
601 DEBUG_PRINT ("From debugger: receive debugger ready %d", state);
603 dma_debugger_queue_complete (self, state);
606 static void
607 on_dma_debugger_started (DmaDebuggerQueue *self)
609 DEBUG_PRINT ("From debugger: receive debugger started");
610 dma_queue_emit_debugger_state (self, IANJUTA_DEBUGGER_STARTED, NULL);
613 static void
614 on_dma_debugger_stopped (DmaDebuggerQueue *self, GError *err)
616 IAnjutaDebuggerState state;
618 DEBUG_PRINT ("From debugger: receive debugger stopped with error %p", err);
619 dma_queue_emit_debugger_state (self, IANJUTA_DEBUGGER_STOPPED, err);
621 /* Reread debugger state, could have changed while emitting signal */
622 state = ianjuta_debugger_get_state (self->debugger, NULL);
623 dma_debugger_queue_complete (self, state);
626 static void
627 on_dma_program_loaded (DmaDebuggerQueue *self)
629 DEBUG_PRINT ("From debugger: receive program loaded");
630 dma_queue_emit_debugger_state (self, IANJUTA_DEBUGGER_PROGRAM_LOADED, NULL);
633 static void
634 on_dma_program_running (DmaDebuggerQueue *self)
636 DEBUG_PRINT ("From debugger: debugger_program_running");
637 dma_queue_emit_debugger_state (self, IANJUTA_DEBUGGER_PROGRAM_RUNNING, NULL);
640 static void
641 on_dma_program_stopped (DmaDebuggerQueue *self)
643 DEBUG_PRINT ("From debugger: receive program stopped");
644 dma_queue_emit_debugger_state (self, IANJUTA_DEBUGGER_PROGRAM_STOPPED, NULL);
647 static void
648 on_dma_program_exited (DmaDebuggerQueue *self)
650 DEBUG_PRINT ("From debugger: receive program exited");
651 dma_queue_emit_debugger_state (self, IANJUTA_DEBUGGER_PROGRAM_LOADED, NULL);
654 static void
655 on_dma_program_moved (DmaDebuggerQueue *self, guint pid, gint tid, gulong address, const gchar* src_path, guint line)
657 DEBUG_PRINT ("From debugger: program moved");
658 self->prepend_command++;
659 g_signal_emit_by_name (self->plugin, "program-moved", pid, tid, address, src_path, line);
660 self->prepend_command--;
663 static void
664 on_dma_frame_changed (DmaDebuggerQueue *self, guint frame, gint thread)
666 DEBUG_PRINT ("From debugger: frame changed");
667 self->prepend_command++;
668 g_signal_emit_by_name (self->plugin, "frame-changed", frame, thread);
669 self->prepend_command--;
672 static void
673 on_dma_signal_received (DmaDebuggerQueue *self, const gchar* name, const gchar* description)
675 DEBUG_PRINT ("From debugger: signal received");
676 self->prepend_command++;
677 g_signal_emit_by_name (self->plugin, "signal-received", name, description);
678 self->prepend_command--;
681 static void
682 on_dma_sharedlib_event (DmaDebuggerQueue *self)
684 DEBUG_PRINT ("From debugger: shared lib event");
685 self->stop_on_sharedlib = TRUE;
686 dma_debugger_queue_complete (self, IANJUTA_DEBUGGER_PROGRAM_STOPPED);
687 self->prepend_command++;
688 g_signal_emit_by_name (self->plugin, "sharedlib-event");
689 self->prepend_command--;
690 dma_queue_run (self);
693 /* Public function
694 *---------------------------------------------------------------------------*/
696 /* Command callback will add their commands at the beginning of the queue */
697 void
698 dma_debugger_queue_command_callback (const gpointer data, gpointer user_data, GError* err)
700 DmaDebuggerQueue *self = (DmaDebuggerQueue *)user_data;
702 g_return_if_fail (self->last != NULL);
704 self->prepend_command++;
705 dma_command_callback (self->last, data, err);
706 self->prepend_command--;
709 gboolean
710 dma_debugger_queue_append (DmaDebuggerQueue *self, DmaQueueCommand *cmd)
712 DEBUG_PRINT("append cmd %x prepend %d", dma_command_get_type (cmd), self->prepend_command);
713 DEBUG_PRINT("current %x", self->last == NULL ? 0 : dma_command_get_type (self->last));
714 DEBUG_PRINT("queue %x", self->queue->head == NULL ? 0 : dma_command_get_type (self->queue->head->data));
716 if ((self->debugger != NULL) && dma_queue_check_state(self, cmd))
718 /* If command is asynchronous stop current command */
719 if (dma_command_has_flag (cmd, ASYNCHRONOUS))
721 IAnjutaDebuggerState state;
723 state = dma_command_is_going_to_state (cmd);
724 if (state != IANJUTA_DEBUGGER_BUSY)
726 /* Command is changing debugger state */
727 dma_queue_cancel_unexpected (self, state);
730 /* Append command at the beginning */
731 g_queue_push_head (self->queue, cmd);
733 dma_debugger_queue_complete (self, self->debugger_state);
735 else if (self->prepend_command == 0)
737 /* Append command at the end (in the queue) */
738 IAnjutaDebuggerState state;
740 g_queue_push_tail (self->queue, cmd);
742 state = dma_command_is_going_to_state (cmd);
743 if (state != IANJUTA_DEBUGGER_BUSY)
745 self->queue_state = state;
748 else
750 /* Prepend command at the beginning */
751 g_queue_push_head (self->queue, cmd);
754 dma_debugger_queue_execute(self);
756 return TRUE;
758 else
760 dma_command_free (cmd);
762 return FALSE;
766 void
767 dma_debugger_queue_stop (DmaDebuggerQueue *self)
769 /* Disconnect signal */
770 if (self->debugger)
772 g_signal_handlers_disconnect_by_func (self->debugger, G_CALLBACK (on_dma_debugger_ready), self);
773 g_signal_handlers_disconnect_by_func (self->debugger, G_CALLBACK (on_dma_debugger_started), self);
774 g_signal_handlers_disconnect_by_func (self->debugger, G_CALLBACK (on_dma_debugger_stopped), self);
775 g_signal_handlers_disconnect_by_func (self->debugger, G_CALLBACK (on_dma_program_loaded), self);
776 g_signal_handlers_disconnect_by_func (self->debugger, G_CALLBACK (on_dma_program_running), self);
777 g_signal_handlers_disconnect_by_func (self->debugger, G_CALLBACK (on_dma_program_stopped), self);
778 g_signal_handlers_disconnect_by_func (self->debugger, G_CALLBACK (on_dma_program_exited), self);
779 g_signal_handlers_disconnect_by_func (self->debugger, G_CALLBACK (on_dma_program_moved), self);
780 g_signal_handlers_disconnect_by_func (self->debugger, G_CALLBACK (on_dma_signal_received), self);
781 g_signal_handlers_disconnect_by_func (self->debugger, G_CALLBACK (on_dma_frame_changed), self);
782 g_signal_handlers_disconnect_by_func (self->debugger, G_CALLBACK (on_dma_sharedlib_event), self);
783 self->debugger = NULL;
784 self->support = 0;
788 gboolean
789 dma_debugger_queue_start (DmaDebuggerQueue *self, const gchar *mime_type)
791 dma_debugger_queue_stop (self);
793 /* Look for a debugger supporting mime_type */
794 if (!dma_debugger_activate_plugin (self, mime_type))
796 return FALSE;
799 if (self->debugger)
801 /* Connect signal */
802 g_signal_connect_swapped (self->debugger, "debugger-ready", G_CALLBACK (on_dma_debugger_ready), self);
803 g_signal_connect_swapped (self->debugger, "debugger-started", G_CALLBACK (on_dma_debugger_started), self);
804 g_signal_connect_swapped (self->debugger, "debugger-stopped", G_CALLBACK (on_dma_debugger_stopped), self);
805 g_signal_connect_swapped (self->debugger, "program-loaded", G_CALLBACK (on_dma_program_loaded), self);
806 g_signal_connect_swapped (self->debugger, "program-running", G_CALLBACK (on_dma_program_running), self);
807 g_signal_connect_swapped (self->debugger, "program-stopped", G_CALLBACK (on_dma_program_stopped), self);
808 g_signal_connect_swapped (self->debugger, "program-exited", G_CALLBACK (on_dma_program_exited), self);
809 g_signal_connect_swapped (self->debugger, "program-moved", G_CALLBACK (on_dma_program_moved), self);
810 g_signal_connect_swapped (self->debugger, "signal-received", G_CALLBACK (on_dma_signal_received), self);
811 g_signal_connect_swapped (self->debugger, "frame-changed", G_CALLBACK (on_dma_frame_changed), self);
812 g_signal_connect_swapped (self->debugger, "sharedlib-event", G_CALLBACK (on_dma_sharedlib_event), self);
814 if (self->log == NULL)
816 dma_queue_disable_log (self);
818 else
820 dma_queue_enable_log (self, self->log);
824 return self->debugger != NULL;
827 void
828 dma_queue_enable_log (DmaDebuggerQueue *self, IAnjutaMessageView *log)
830 self->log = log;
831 if (self->debugger != NULL)
833 ianjuta_debugger_enable_log (self->debugger, self->log, NULL);
837 void
838 dma_queue_disable_log (DmaDebuggerQueue *self)
840 self->log = NULL;
841 if (self->debugger != NULL)
843 ianjuta_debugger_disable_log (self->debugger, NULL);
847 IAnjutaDebuggerState
848 dma_debugger_queue_get_state (DmaDebuggerQueue *self)
850 return self->queue_state;
853 gboolean
854 dma_debugger_queue_is_supported (DmaDebuggerQueue *self, DmaDebuggerCapability capability)
856 return self->support & capability ? TRUE : FALSE;
859 /* GObject functions
860 *---------------------------------------------------------------------------*/
862 /* Used in dispose and finalize */
863 static gpointer parent_class;
865 /* dispose is the first destruction step. It is used to unref object created
866 * with instance_init in order to break reference counting cycles. This
867 * function could be called several times. All function should still work
868 * after this call. It has to called its parents.*/
870 static void
871 dma_debugger_queue_dispose (GObject *obj)
873 DmaDebuggerQueue *self = DMA_DEBUGGER_QUEUE (obj);
875 dma_debugger_queue_clear (self);
877 GNOME_CALL_PARENT (G_OBJECT_CLASS, dispose, (obj));
880 /* finalize is the last destruction step. It must free all memory allocated
881 * with instance_init. It is called only one time just before releasing all
882 * memory */
884 static void
885 dma_debugger_queue_finalize (GObject *obj)
887 /*DmaDebuggerQueue *self = DMA_DEBUGGER_QUEUE (obj);*/
889 GNOME_CALL_PARENT (G_OBJECT_CLASS, finalize, (obj));
892 /* instance_init is the constructor. All functions should work after this
893 * call. */
895 static void
896 dma_debugger_queue_instance_init (DmaDebuggerQueue *self)
898 self->plugin = NULL;
899 self->debugger = NULL;
900 self->support = 0;
901 self->queue = g_queue_new ();
902 self->last = NULL;
903 self->busy = FALSE;
904 self->prepend_command = 0;
905 self->debugger_state = IANJUTA_DEBUGGER_STOPPED;
906 self->queue_state = IANJUTA_DEBUGGER_STOPPED;
907 self->log = NULL;
910 /* class_init intialize the class itself not the instance */
912 static void
913 dma_debugger_queue_class_init (DmaDebuggerQueueClass * klass)
915 GObjectClass *object_class;
917 g_return_if_fail (klass != NULL);
918 object_class = G_OBJECT_CLASS (klass);
920 parent_class = g_type_class_peek_parent (klass);
922 object_class->dispose = dma_debugger_queue_dispose;
923 object_class->finalize = dma_debugger_queue_finalize;
926 GType
927 dma_debugger_queue_get_type (void)
929 static GType type = 0;
931 if (!type)
933 static const GTypeInfo type_info =
935 sizeof (DmaDebuggerQueueClass),
936 (GBaseInitFunc) NULL,
937 (GBaseFinalizeFunc) NULL,
938 (GClassInitFunc) dma_debugger_queue_class_init,
939 (GClassFinalizeFunc) NULL,
940 NULL, /* class_data */
941 sizeof (DmaDebuggerQueue),
942 0, /* n_preallocs */
943 (GInstanceInitFunc) dma_debugger_queue_instance_init,
944 NULL /* value_table */
947 type = g_type_register_static (G_TYPE_OBJECT,
948 "DmaDebuggerQueue", &type_info, 0);
951 return type;
954 /* Creation and Destruction
955 *---------------------------------------------------------------------------*/
957 DmaDebuggerQueue*
958 dma_debugger_queue_new (AnjutaPlugin *plugin)
960 DmaDebuggerQueue *self;
962 self = g_object_new (DMA_DEBUGGER_QUEUE_TYPE, NULL);
963 self->plugin = plugin;
965 return self;
968 void
969 dma_debugger_queue_free (DmaDebuggerQueue *self)
971 dma_debugger_queue_stop (self);
972 g_object_unref (self);