Re: How does one pipe output from process to text buffer? <-- FIXED



Thanks everyone, I have this working now :-)  Special thanks to Tomas!

The program still freezes for a very brief moment, but then it comes
quickly back to life with wonderful data spilling onto the notebook
pages. 


Here's the target function:


void on_confirm_okbutton_clicked (GtkWidget *widget, gpointer data)
{
        gchar *tmp_ssh_command;
        gchar **ssh_command;
        gint i = 0;
        gint count = g_strv_length(serverlist);
                        
        /* remove any existing notebook pages */
        remove_notebook_pages(GTK_NOTEBOOK(notebook1));
        
        /* start a process for each server */
        for (i=0; i<count; i++ ) {
                tmp_ssh_command=g_strjoin(" ", SSH_PROGRAM, serverlist[i], 
                                          MAINSCRIPT_PROGRAM, command, 
                                          serverlist[i], NULL);
                ssh_command = g_strsplit(tmp_ssh_command, " ", -1);
                
                /* create notebook page with textview for this process */
                GtkWidget *textview;
                GtkWidget *scroller;
                GtkTextBuffer *buffer = gtk_text_buffer_new(NULL);
                GtkWidget *label = gtk_label_new(serverlist[i]);
                textview = gtk_text_view_new_with_buffer(buffer);
                
                scroller = gtk_scrolled_window_new(NULL, NULL);
                gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroller),
                                     GTK_POLICY_AUTOMATIC,
                                     GTK_POLICY_AUTOMATIC);
                
                gtk_container_add(GTK_CONTAINER(scroller), textview);
                
                gtk_notebook_insert_page(GTK_NOTEBOOK(notebook1), 
                                         scroller, label, i);
                
                gtk_widget_show_all(notebook1);
                
                /* spawn off the process */
                GPid pid;
                gint stdout;
                GIOChannel *gioout;
                g_spawn_async_with_pipes( NULL, 
                        ssh_command, 
                        NULL, 
                        G_SPAWN_SEARCH_PATH,
                        NULL,
                        NULL,
                        &pid,
                        NULL, &stdout, NULL,
                        NULL );
                gioout = g_io_channel_unix_new(stdout);
                g_io_add_watch_full(gioout, 
                        G_PRIORITY_DEFAULT,
                        (GIOCondition)(G_IO_IN|G_IO_PRI|G_IO_ERR|G_IO_HUP|G_IO_NVAL), 
                        (GIOFunc)watch_out_callback, 
                        textview,
                        NULL);
                g_io_channel_unref(gioout);
                g_free(tmp_ssh_command);
        }
        
        gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook1), 0);
        
        gtk_widget_show(progressdialog);
        gtk_widget_hide(confirmdialog);
}


And here is the callback function.  The new item I added that I think
helped stop the program from freezing is the addtion of an iter and 
a call to 'gtk_text_buffer_get_end_iter'.  


gboolean watch_out_callback (GIOChannel *channel, 
                        GIOCondition condition, 
                        gpointer data)
{
        GIOStatus status = G_IO_STATUS_NORMAL;
        GtkTextView *textview;
        GtkTextBuffer *buffer;
        GtkTextIter iter;
        GtkTextMark *mark;
        gchar buf[512];
        gsize bytes_read;
        
        /* set up pointers to our textbuffer */
        textview = GTK_TEXT_VIEW((GtkWidget *)data);
        buffer = gtk_text_view_get_buffer(textview);
        gtk_text_buffer_get_end_iter(buffer, &iter);
        
        /* send ssh output to our gui */
        status = g_io_channel_read_chars(channel, buf, sizeof(buf), &bytes_read, NULL);
        if (bytes_read) {
                gtk_text_buffer_insert(buffer, &iter, buf, bytes_read);
        }
        
        /* decide if we should close the channel */
        switch (status) {
                case G_IO_STATUS_NORMAL:
                        return TRUE;
                default:
                        return FALSE;
        }
}


Thanks for helping me get through this.  It sure was the most difficult part of this 
program.  I still have a lot to do, but mainly cosmetic compared to this.

Thanks!


-- Tony





[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]