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 AnjutaStatus
* status
;
331 status
= anjuta_shell_get_status(ANJUTA_PLUGIN (self
->plugin
)->shell
, NULL
);
336 static void dma_debugger_queue_execute (DmaDebuggerQueue
*self
);
338 /* Call when debugger has completed the current command */
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
);
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 */
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
;
397 cmd
= (DmaQueueCommand
*)g_queue_pop_head(self
->queue
);
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
))
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
);
419 /* Display error message to user */
422 if (err
->message
!= NULL
)
424 anjuta_util_dialog_error (GTK_WINDOW (ANJUTA_PLUGIN (self
->plugin
)->shell
), err
->message
);
432 dma_queue_emit_debugger_ready (self
);
436 dma_queue_check_state (DmaDebuggerQueue
*self
, DmaQueueCommand
* cmd
)
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
;
457 state
= self
->debugger_state
;
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
))
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
);
488 dma_debugger_activate_plugin (DmaDebuggerQueue
* self
, const gchar
*mime_type
)
490 AnjutaPluginManager
*plugin_manager
;
491 AnjutaPluginDescription
*plugin
;
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
);
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
,
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
);
520 else if (g_list_length (descs
) == 1)
522 /* Only one plugin found, use it */
523 plugin
= (AnjutaPluginDescription
*)descs
->data
;
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"),
536 /* Get debugger location */
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
);
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;
566 /* No plugin selected */
572 /* IAnjutaDebugger callback
573 *---------------------------------------------------------------------------*/
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
671 *---------------------------------------------------------------------------*/
673 /* Command callback will add their commands at the beginning of the queue */
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
);
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
);
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
);
769 dma_command_free (cmd
);
776 dma_debugger_queue_stop (DmaDebuggerQueue
*self
)
778 /* Disconnect signal */
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
;
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
))
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
);
829 dma_queue_enable_log (self
, self
->log
);
833 return self
->debugger
!= NULL
;
837 dma_queue_enable_log (DmaDebuggerQueue
*self
, IAnjutaMessageView
*log
)
840 if (self
->debugger
!= NULL
)
842 ianjuta_debugger_enable_log (self
->debugger
, self
->log
, NULL
);
847 dma_queue_disable_log (DmaDebuggerQueue
*self
)
850 if (self
->debugger
!= NULL
)
852 ianjuta_debugger_disable_log (self
->debugger
, NULL
);
857 dma_debugger_queue_get_state (DmaDebuggerQueue
*self
)
859 return self
->queue_state
;
863 dma_debugger_queue_is_supported (DmaDebuggerQueue
*self
, DmaDebuggerCapability capability
)
865 return self
->support
& capability
? TRUE
: FALSE
;
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.*/
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
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
907 dma_debugger_queue_instance_init (DmaDebuggerQueue
*self
)
910 self
->debugger
= NULL
;
912 self
->queue
= g_queue_new ();
915 self
->insert_command
= NULL
;
916 self
->debugger_state
= IANJUTA_DEBUGGER_STOPPED
;
917 self
->queue_state
= IANJUTA_DEBUGGER_STOPPED
;
921 /* class_init intialize the class itself not the instance */
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
;
938 dma_debugger_queue_get_type (void)
940 static GType type
= 0;
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
),
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);
965 /* Creation and Destruction
966 *---------------------------------------------------------------------------*/
969 dma_debugger_queue_new (AnjutaPlugin
*plugin
)
971 DmaDebuggerQueue
*self
;
973 self
= g_object_new (DMA_DEBUGGER_QUEUE_TYPE
, NULL
);
974 self
->plugin
= plugin
;
980 dma_debugger_queue_free (DmaDebuggerQueue
*self
)
982 dma_debugger_queue_stop (self
);
983 g_object_unref (self
);