1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
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 *---------------------------------------------------------------------------*/
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>
41 *---------------------------------------------------------------------------*/
43 #define ICON_FILE "anjuta-debug-manager.plugin.png"
46 *---------------------------------------------------------------------------*/
48 struct _DmaDebuggerQueue
{
52 IAnjutaDebugger
* debugger
;
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
;
70 struct _DmaDebuggerQueueClass
{
75 *---------------------------------------------------------------------------*/
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
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 */
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 */
114 /* End in this unexpected state */
115 self
->queue_state
= state
;
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
);
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
;
141 dma_queue_emit_debugger_state_change (DmaDebuggerQueue
*self
, IAnjutaDebuggerState state
, GError
* err
)
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
);
160 case IANJUTA_DEBUGGER_BUSY
:
161 /* Debugger is busy, nothing to do */
162 g_return_if_reached();
164 case IANJUTA_DEBUGGER_STOPPED
:
165 self
->stop_on_sharedlib
= FALSE
;
166 signal
= DEBUGGER_STOPPED_SIGNAL
;
167 self
->debugger_state
= state
;
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
;
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
;
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
;
187 if (!self
->stop_on_sharedlib
)
189 signal
= PROGRAM_STOPPED_SIGNAL
;
191 self
->debugger_state
= state
;
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
;
202 signal
= PROGRAM_RUNNING_SIGNAL
;
203 self
->debugger_state
= state
;
207 self
->insert_command
= g_list_prepend (self
->insert_command
, g_queue_peek_head_link (self
->queue
));
214 case DEBUGGER_STOPPED_SIGNAL
:
215 DEBUG_PRINT("%s", "** emit debugger-stopped **");
216 g_signal_emit_by_name (self
->plugin
, "debugger-stopped", err
);
218 case DEBUGGER_STARTED_SIGNAL
:
219 DEBUG_PRINT("%s", "** emit debugger-started **");
220 g_signal_emit_by_name (self
->plugin
, "debugger-started");
222 case PROGRAM_LOADED_SIGNAL
:
223 DEBUG_PRINT("%s", "** emit program-loaded **");
224 g_signal_emit_by_name (self
->plugin
, "program-loaded");
226 case PROGRAM_UNLOADED_SIGNAL
:
227 DEBUG_PRINT("%s", "** emit program-unloaded **");
228 g_signal_emit_by_name (self
->plugin
, "program-unloaded");
230 case PROGRAM_STARTED_SIGNAL
:
231 DEBUG_PRINT("%s", "** emit program-started **");
232 g_signal_emit_by_name (self
->plugin
, "program-started");
234 case PROGRAM_EXITED_SIGNAL
:
235 DEBUG_PRINT("%s", "** emit program-exited **");
236 g_signal_emit_by_name (self
->plugin
, "program-exited");
238 case PROGRAM_STOPPED_SIGNAL
:
239 DEBUG_PRINT("%s", "** emit program-stopped **");
240 g_signal_emit_by_name (self
->plugin
, "program-stopped");
242 case PROGRAM_RUNNING_SIGNAL
:
243 DEBUG_PRINT("%s", "** emit program-running **");
244 g_signal_emit_by_name (self
->plugin
, "program-running");
247 self
->insert_command
= g_list_delete_link (self
->insert_command
, self
->insert_command
);
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
;
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
;
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
;
280 case IANJUTA_DEBUGGER_PROGRAM_LOADED
:
281 if (self
->debugger_state
== IANJUTA_DEBUGGER_STOPPED
)
283 next_state
= IANJUTA_DEBUGGER_STARTED
;
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
;
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
;
306 case IANJUTA_DEBUGGER_BUSY
:
309 dma_queue_emit_debugger_state_change (self
, next_state
, NULL
);
314 dma_queue_emit_debugger_ready (DmaDebuggerQueue
*self
)
318 if (g_queue_is_empty(self
->queue
) && (self
->last
== NULL
))
327 if (busy
!= self
->busy
)
329 /* FIXME: set AnjutaStatus to busy? */
334 static void dma_debugger_queue_execute (DmaDebuggerQueue
*self
);
336 /* Call when debugger has completed the current command */
339 dma_debugger_queue_complete (DmaDebuggerQueue
*self
, IAnjutaDebuggerState state
)
341 DEBUG_PRINT("debugger_queue_complete %d", state
);
343 if (state
!= IANJUTA_DEBUGGER_BUSY
)
345 if (self
->last
!= NULL
)
347 if (dma_command_is_going_to_state (self
->last
) != state
)
349 /* Command end in an unexpected state,
350 * Remove invalid following command */
351 dma_queue_cancel_unexpected (self
, state
);
354 /* Remove current command */
355 DEBUG_PRINT("end command %x", dma_command_get_type (self
->last
));
356 dma_command_free (self
->last
);
361 /* Emit new state if necessary */
362 dma_queue_emit_debugger_state (self
, state
, NULL
);
364 /* Send next command */
365 dma_debugger_queue_execute (self
);
369 /* Call to send next command */
372 dma_debugger_queue_execute (DmaDebuggerQueue
*self
)
374 DEBUG_PRINT("%s", "debugger_queue_execute");
376 /* Check if debugger is connected to a debugger backend */
377 g_return_if_fail (self
->debugger
!= NULL
);
379 /* Check if there debugger is busy */
380 if (self
->last
!= NULL
)
382 IAnjutaDebuggerState state
;
383 /* Recheck state in case of desynchronization */
384 state
= ianjuta_debugger_get_state (self
->debugger
, NULL
);
385 dma_debugger_queue_complete (self
, state
);
388 /* Check if there is something to execute */
389 while (!g_queue_is_empty(self
->queue
) && (self
->last
== NULL
))
391 DmaQueueCommand
*cmd
;
395 cmd
= (DmaQueueCommand
*)g_queue_pop_head(self
->queue
);
399 DEBUG_PRINT("run command %x", dma_command_get_type (cmd
));
400 ok
= dma_command_run (cmd
, self
->debugger
, self
, &err
);
402 if (!ok
|| (err
!= NULL
))
405 if (dma_command_is_going_to_state (self
->last
) != IANJUTA_DEBUGGER_BUSY
)
407 /* Command has been canceled in an unexpected state,
408 * Remove invalid following command */
409 dma_queue_cancel_unexpected (self
, self
->debugger_state
);
412 /* Remove current command */
413 DEBUG_PRINT("cancel command %x", dma_command_get_type (self
->last
));
414 dma_command_free (self
->last
);
417 /* Display error message to user */
420 if (err
->message
!= NULL
)
422 anjuta_util_dialog_error (GTK_WINDOW (ANJUTA_PLUGIN (self
->plugin
)->shell
), err
->message
);
430 dma_queue_emit_debugger_ready (self
);
434 dma_queue_check_state (DmaDebuggerQueue
*self
, DmaQueueCommand
* cmd
)
438 for (recheck
= FALSE
; recheck
!= TRUE
; recheck
= TRUE
)
440 IAnjutaDebuggerState state
;
442 if ((self
->insert_command
!= NULL
) || dma_command_has_flag (cmd
, HIGH_PRIORITY
))
444 /* Prepend command and high priority command use debugger state or current command state */
445 if (self
->last
!= NULL
)
447 state
= dma_command_is_going_to_state (self
->last
);
448 if (state
== IANJUTA_DEBUGGER_BUSY
)
450 state
= self
->debugger_state
;
455 state
= self
->debugger_state
;
460 /* Append command use queue state */
461 state
= self
->queue_state
;
464 /* Only the debugger can be busy */
465 g_return_val_if_fail (state
!= IANJUTA_DEBUGGER_BUSY
, FALSE
);
467 if (dma_command_is_valid_in_state (cmd
, state
))
473 g_warning ("Cancel command %x, debugger in state %d", dma_command_get_type (cmd
), state
);
475 /* Check if synchronization is still ok */
476 state
= ianjuta_debugger_get_state (self
->debugger
, NULL
);
477 dma_debugger_queue_complete (self
, state
);
486 dma_debugger_activate_plugin (DmaDebuggerQueue
* self
, const gchar
*mime_type
)
488 AnjutaPluginManager
*plugin_manager
;
489 AnjutaPluginHandle
*plugin
;
490 GList
*plugins
= NULL
;
493 /* Get list of debugger plugins */
494 plugin_manager
= anjuta_shell_get_plugin_manager (ANJUTA_PLUGIN(self
->plugin
)->shell
, NULL
);
495 if (mime_type
== NULL
)
497 /* User has to select the right debugger */
498 plugins
= anjuta_plugin_manager_query (plugin_manager
,
499 "Anjuta Plugin","Interfaces", "IAnjutaDebugger", NULL
);
503 /* Propose only debugger supporting correct mime type */
504 plugins
= anjuta_plugin_manager_query (plugin_manager
,
505 "Anjuta Plugin","Interfaces", "IAnjutaDebugger",
506 "File Loader", "SupportedMimeTypes", mime_type
,
512 /* No plugin found */
513 anjuta_util_dialog_error (GTK_WINDOW (ANJUTA_PLUGIN (self
->plugin
)->shell
),
514 _("Unable to find a debugger plugin supporting a target with %s MIME type"), mime_type
);
518 else if (g_list_length (plugins
) == 1)
520 /* Only one plugin found, use it */
521 plugin
= (AnjutaPluginHandle
*)plugins
->data
;
525 /* Ask the user to select one plugin */
526 plugin
= anjuta_plugin_manager_select (plugin_manager
,
527 _("Select a plugin"),
528 _("Please select a plugin to activate"),
534 /* Get debugger interface */
535 self
->debugger
= (IAnjutaDebugger
*)anjuta_plugin_manager_get_plugin_by_handle (plugin_manager
, plugin
);
538 /* Check if register interface is available */
539 self
->support
|= IANJUTA_IS_DEBUGGER_REGISTER(self
->debugger
) ? HAS_REGISTER
: 0;
540 /* Check if memory interface is available */
541 self
->support
|= IANJUTA_IS_DEBUGGER_MEMORY(self
->debugger
) ? HAS_MEMORY
: 0;
542 /* Check if instruction interface is available */
543 self
->support
|= IANJUTA_IS_DEBUGGER_INSTRUCTION(self
->debugger
) ? HAS_INSTRUCTION
: 0;
544 /* Check if breakpoint interface is available */
545 self
->support
|= IANJUTA_IS_DEBUGGER_BREAKPOINT(self
->debugger
) ? HAS_BREAKPOINT
: 0;
546 if (IANJUTA_IS_DEBUGGER_BREAKPOINT (self
->debugger
))
548 self
->support
|= ianjuta_debugger_breakpoint_implement_breakpoint (IANJUTA_DEBUGGER_BREAKPOINT (self
->debugger
), NULL
) * HAS_BREAKPOINT
* 2;
550 /* Check if variable interface is available */
551 self
->support
|= IANJUTA_IS_DEBUGGER_VARIABLE(self
->debugger
) ? HAS_VARIABLE
: 0;
557 /* No plugin selected */
563 /* IAnjutaDebugger callback
564 *---------------------------------------------------------------------------*/
567 on_dma_debugger_ready (DmaDebuggerQueue
*self
, IAnjutaDebuggerState state
)
569 DEBUG_PRINT ("From debugger: receive debugger ready %d", state
);
571 dma_debugger_queue_complete (self
, state
);
575 on_dma_debugger_started (DmaDebuggerQueue
*self
)
577 DEBUG_PRINT ("%s", "From debugger: receive debugger started");
578 dma_queue_emit_debugger_state (self
, IANJUTA_DEBUGGER_STARTED
, NULL
);
582 on_dma_debugger_stopped (DmaDebuggerQueue
*self
, GError
*err
)
584 IAnjutaDebuggerState state
;
586 DEBUG_PRINT ("From debugger: receive debugger stopped with error %p", err
);
587 dma_queue_emit_debugger_state (self
, IANJUTA_DEBUGGER_STOPPED
, err
);
589 /* Reread debugger state, could have changed while emitting signal */
590 state
= ianjuta_debugger_get_state (self
->debugger
, NULL
);
591 dma_debugger_queue_complete (self
, state
);
595 on_dma_program_loaded (DmaDebuggerQueue
*self
)
597 DEBUG_PRINT ("%s", "From debugger: receive program loaded");
598 dma_queue_emit_debugger_state (self
, IANJUTA_DEBUGGER_PROGRAM_LOADED
, NULL
);
602 on_dma_program_running (DmaDebuggerQueue
*self
)
604 DEBUG_PRINT ("%s", "From debugger: debugger_program_running");
605 dma_queue_emit_debugger_state (self
, IANJUTA_DEBUGGER_PROGRAM_RUNNING
, NULL
);
609 on_dma_program_stopped (DmaDebuggerQueue
*self
)
611 DEBUG_PRINT ("%s", "From debugger: receive program stopped");
612 dma_queue_emit_debugger_state (self
, IANJUTA_DEBUGGER_PROGRAM_STOPPED
, NULL
);
616 on_dma_program_exited (DmaDebuggerQueue
*self
)
618 DEBUG_PRINT ("%s", "From debugger: receive program exited");
619 dma_queue_emit_debugger_state (self
, IANJUTA_DEBUGGER_PROGRAM_LOADED
, NULL
);
623 on_dma_program_moved (DmaDebuggerQueue
*self
, guint pid
, gint tid
, gulong address
, const gchar
* src_path
, guint line
)
625 DEBUG_PRINT ("%s", "From debugger: program moved");
626 self
->insert_command
= g_list_prepend (self
->insert_command
, g_queue_peek_head_link (self
->queue
));
627 g_signal_emit_by_name (self
->plugin
, "program-moved", pid
, tid
, address
, src_path
, line
);
628 self
->insert_command
= g_list_delete_link (self
->insert_command
, self
->insert_command
);
632 on_dma_frame_changed (DmaDebuggerQueue
*self
, guint frame
, gint thread
)
634 DEBUG_PRINT ("%s", "From debugger: frame changed");
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
, "frame-changed", frame
, thread
);
637 self
->insert_command
= g_list_delete_link (self
->insert_command
, self
->insert_command
);
641 on_dma_signal_received (DmaDebuggerQueue
*self
, const gchar
* name
, const gchar
* description
)
643 DEBUG_PRINT ("%s", "From debugger: signal received");
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
, "signal-received", name
, description
);
646 self
->insert_command
= g_list_delete_link (self
->insert_command
, self
->insert_command
);
650 on_dma_sharedlib_event (DmaDebuggerQueue
*self
)
652 DEBUG_PRINT ("%s", "From debugger: shared lib event");
653 self
->stop_on_sharedlib
= TRUE
;
654 dma_debugger_queue_complete (self
, IANJUTA_DEBUGGER_PROGRAM_STOPPED
);
655 self
->insert_command
= g_list_prepend (self
->insert_command
, g_queue_peek_head_link (self
->queue
));
656 g_signal_emit_by_name (self
->plugin
, "sharedlib-event");
657 self
->insert_command
= g_list_delete_link (self
->insert_command
, self
->insert_command
);
658 dma_queue_run (self
);
662 *---------------------------------------------------------------------------*/
664 /* Command callback will add their commands at the beginning of the queue */
666 dma_debugger_queue_command_callback (const gpointer data
, gpointer user_data
, GError
* err
)
668 DmaDebuggerQueue
*self
= (DmaDebuggerQueue
*)user_data
;
670 g_return_if_fail (self
->last
!= NULL
);
672 self
->insert_command
= g_list_prepend (self
->insert_command
, g_queue_peek_head_link (self
->queue
));
673 if (self
->queue_state
!= IANJUTA_DEBUGGER_STOPPED
)
675 dma_command_callback (self
->last
, data
, err
);
677 self
->insert_command
= g_list_delete_link (self
->insert_command
, self
->insert_command
);
681 dma_debugger_queue_append (DmaDebuggerQueue
*self
, DmaQueueCommand
*cmd
)
683 DEBUG_PRINT("append cmd %x prepend %p", dma_command_get_type (cmd
), self
->insert_command
);
684 DEBUG_PRINT("current %x", self
->last
== NULL
? 0 : dma_command_get_type (self
->last
));
685 DEBUG_PRINT("queue %x", self
->queue
->head
== NULL
? 0 : dma_command_get_type (self
->queue
->head
->data
));
687 if ((self
->debugger
!= NULL
) && dma_queue_check_state(self
, cmd
))
689 /* If command is asynchronous stop current command */
690 if (dma_command_has_flag (cmd
, ASYNCHRONOUS
))
692 IAnjutaDebuggerState state
;
694 state
= dma_command_is_going_to_state (cmd
);
695 if (state
!= IANJUTA_DEBUGGER_BUSY
)
697 /* Command is changing debugger state */
698 dma_queue_cancel_unexpected (self
, state
);
701 /* Append command at the beginning */
702 g_queue_push_head (self
->queue
, cmd
);
704 /* We must not interrupt command having callback, as the command
705 * will be removed, the callback when emitted will be redirected to
706 * the handler of the next command */
707 if ((state
== IANJUTA_DEBUGGER_STOPPED
) || (self
->debugger_state
== IANJUTA_DEBUGGER_PROGRAM_RUNNING
))
709 dma_debugger_queue_complete (self
, self
->debugger_state
);
712 else if (dma_command_has_flag (cmd
, HIGH_PRIORITY
))
714 IAnjutaDebuggerState state
;
716 state
= dma_command_is_going_to_state (cmd
);
717 if (state
!= IANJUTA_DEBUGGER_BUSY
)
719 /* Command is changing debugger state */
720 dma_queue_cancel_unexpected (self
, state
);
723 /* Prepend command at the beginning */
724 g_queue_push_head (self
->queue
, cmd
);
726 else if ((self
->insert_command
!= NULL
) && (self
->insert_command
->data
!= NULL
))
728 IAnjutaDebuggerState state
;
730 state
= dma_command_is_going_to_state (cmd
);
731 if (state
!= IANJUTA_DEBUGGER_BUSY
)
733 /* Command is changing debugger state */
734 dma_queue_cancel_unexpected (self
, state
);
737 /* Insert command in the beginning */
738 g_queue_insert_before (self
->queue
, (GList
*)self
->insert_command
->data
, cmd
);
742 /* Append command at the end (in the queue) */
743 IAnjutaDebuggerState state
;
745 g_queue_push_tail (self
->queue
, cmd
);
747 state
= dma_command_is_going_to_state (cmd
);
748 if (state
!= IANJUTA_DEBUGGER_BUSY
)
750 self
->queue_state
= state
;
754 dma_debugger_queue_execute(self
);
760 dma_command_free (cmd
);
767 dma_debugger_queue_stop (DmaDebuggerQueue
*self
)
769 /* Disconnect signal */
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
;
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
))
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
);
820 dma_queue_enable_log (self
, self
->log
);
824 return self
->debugger
!= NULL
;
828 dma_queue_enable_log (DmaDebuggerQueue
*self
, IAnjutaMessageView
*log
)
831 if (self
->debugger
!= NULL
)
833 ianjuta_debugger_enable_log (self
->debugger
, self
->log
, NULL
);
838 dma_queue_disable_log (DmaDebuggerQueue
*self
)
841 if (self
->debugger
!= NULL
)
843 ianjuta_debugger_disable_log (self
->debugger
, NULL
);
848 dma_debugger_queue_get_state (DmaDebuggerQueue
*self
)
850 return self
->queue_state
;
854 dma_debugger_queue_is_supported (DmaDebuggerQueue
*self
, DmaDebuggerCapability capability
)
856 return self
->support
& capability
? TRUE
: FALSE
;
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.*/
871 dma_debugger_queue_dispose (GObject
*obj
)
873 DmaDebuggerQueue
*self
= DMA_DEBUGGER_QUEUE (obj
);
875 dma_debugger_queue_clear (self
);
877 G_OBJECT_CLASS (parent_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
885 dma_debugger_queue_finalize (GObject
*obj
)
887 DmaDebuggerQueue
*self
= DMA_DEBUGGER_QUEUE (obj
);
889 g_queue_free (self
->queue
);
891 G_OBJECT_CLASS (parent_class
)->finalize (obj
);
894 /* instance_init is the constructor. All functions should work after this
898 dma_debugger_queue_instance_init (DmaDebuggerQueue
*self
)
901 self
->debugger
= NULL
;
903 self
->queue
= g_queue_new ();
906 self
->insert_command
= NULL
;
907 self
->debugger_state
= IANJUTA_DEBUGGER_STOPPED
;
908 self
->queue_state
= IANJUTA_DEBUGGER_STOPPED
;
912 /* class_init intialize the class itself not the instance */
915 dma_debugger_queue_class_init (DmaDebuggerQueueClass
* klass
)
917 GObjectClass
*object_class
;
919 g_return_if_fail (klass
!= NULL
);
920 object_class
= G_OBJECT_CLASS (klass
);
922 parent_class
= g_type_class_peek_parent (klass
);
924 object_class
->dispose
= dma_debugger_queue_dispose
;
925 object_class
->finalize
= dma_debugger_queue_finalize
;
929 dma_debugger_queue_get_type (void)
931 static GType type
= 0;
935 static const GTypeInfo type_info
=
937 sizeof (DmaDebuggerQueueClass
),
938 (GBaseInitFunc
) NULL
,
939 (GBaseFinalizeFunc
) NULL
,
940 (GClassInitFunc
) dma_debugger_queue_class_init
,
941 (GClassFinalizeFunc
) NULL
,
942 NULL
, /* class_data */
943 sizeof (DmaDebuggerQueue
),
945 (GInstanceInitFunc
) dma_debugger_queue_instance_init
,
946 NULL
/* value_table */
949 type
= g_type_register_static (G_TYPE_OBJECT
,
950 "DmaDebuggerQueue", &type_info
, 0);
956 /* Creation and Destruction
957 *---------------------------------------------------------------------------*/
960 dma_debugger_queue_new (AnjutaPlugin
*plugin
)
962 DmaDebuggerQueue
*self
;
964 self
= g_object_new (DMA_DEBUGGER_QUEUE_TYPE
, NULL
);
965 self
->plugin
= plugin
;
971 dma_debugger_queue_free (DmaDebuggerQueue
*self
)
973 dma_debugger_queue_stop (self
);
974 g_object_unref (self
);