15976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org/*
25976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * libjingle
35976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * Copyright 2012, Google Inc.
45976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *
55976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * Redistribution and use in source and binary forms, with or without
65976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * modification, are permitted provided that the following conditions are met:
75976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *
85976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *  1. Redistributions of source code must retain the above copyright notice,
95976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *     this list of conditions and the following disclaimer.
105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *  2. Redistributions in binary form must reproduce the above copyright notice,
115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *     this list of conditions and the following disclaimer in the documentation
125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *     and/or other materials provided with the distribution.
135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *  3. The name of the author may not be used to endorse or promote products
145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *     derived from this software without specific prior written permission.
155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *
165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org */
275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/examples/peerconnection/client/linux/main_wnd.h"
305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include <gdk/gdkkeysyms.h>
325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include <gtk/gtk.h>
335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include <stddef.h>
345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/examples/peerconnection/client/defaults.h"
365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/base/common.h"
375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/base/logging.h"
385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/base/stringutils.h"
395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgusing talk_base::sprintfn;
415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgnamespace {
435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org//
455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// Simple static functions that simply forward the callback to the
465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// GtkMainWnd instance.
475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org//
485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orggboolean OnDestroyedCallback(GtkWidget* widget, GdkEvent* event,
505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                             gpointer data) {
515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  reinterpret_cast<GtkMainWnd*>(data)->OnDestroyed(widget, event);
525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return FALSE;
535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid OnClickedCallback(GtkWidget* widget, gpointer data) {
565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  reinterpret_cast<GtkMainWnd*>(data)->OnClicked(widget);
575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orggboolean SimulateButtonClick(gpointer button) {
605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  g_signal_emit_by_name(button, "clicked");
615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return false;
625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orggboolean OnKeyPressCallback(GtkWidget* widget, GdkEventKey* key,
655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                            gpointer data) {
665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  reinterpret_cast<GtkMainWnd*>(data)->OnKeyPress(widget, key);
675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return false;
685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid OnRowActivatedCallback(GtkTreeView* tree_view, GtkTreePath* path,
715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                            GtkTreeViewColumn* column, gpointer data) {
725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  reinterpret_cast<GtkMainWnd*>(data)->OnRowActivated(tree_view, path, column);
735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orggboolean SimulateLastRowActivated(gpointer data) {
765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  GtkTreeView* tree_view = reinterpret_cast<GtkTreeView*>(data);
775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  GtkTreeModel* model = gtk_tree_view_get_model(tree_view);
785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // "if iter is NULL, then the number of toplevel nodes is returned."
805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  int rows = gtk_tree_model_iter_n_children(model, NULL);
815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  GtkTreePath* lastpath = gtk_tree_path_new_from_indices(rows - 1, -1);
825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // Select the last item in the list
845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  GtkTreeSelection* selection = gtk_tree_view_get_selection(tree_view);
855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  gtk_tree_selection_select_path(selection, lastpath);
865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // Our TreeView only has one column, so it is column 0.
885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  GtkTreeViewColumn* column = gtk_tree_view_get_column(tree_view, 0);
895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  gtk_tree_view_row_activated(tree_view, lastpath, column);
915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  gtk_tree_path_free(lastpath);
935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return false;
945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// Creates a tree view, that we use to display the list of peers.
975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid InitializeList(GtkWidget* list) {
985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  GtkCellRenderer* renderer = gtk_cell_renderer_text_new();
995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  GtkTreeViewColumn* column = gtk_tree_view_column_new_with_attributes(
1005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      "List Items", renderer, "text", 0, NULL);
1015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  gtk_tree_view_append_column(GTK_TREE_VIEW(list), column);
1025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  GtkListStore* store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_INT);
1035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  gtk_tree_view_set_model(GTK_TREE_VIEW(list), GTK_TREE_MODEL(store));
1045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  g_object_unref(store);
1055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
1065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// Adds an entry to a tree view.
1085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid AddToList(GtkWidget* list, const gchar* str, int value) {
1095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  GtkListStore* store = GTK_LIST_STORE(
1105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      gtk_tree_view_get_model(GTK_TREE_VIEW(list)));
1115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  GtkTreeIter iter;
1135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  gtk_list_store_append(store, &iter);
1145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  gtk_list_store_set(store, &iter, 0, str, 1, value, -1);
1155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
1165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgstruct UIThreadCallbackData {
1185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  explicit UIThreadCallbackData(MainWndCallback* cb, int id, void* d)
1195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      : callback(cb), msg_id(id), data(d) {}
1205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  MainWndCallback* callback;
1215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  int msg_id;
1225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  void* data;
1235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org};
1245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orggboolean HandleUIThreadCallback(gpointer data) {
1265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  UIThreadCallbackData* cb_data = reinterpret_cast<UIThreadCallbackData*>(data);
1275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  cb_data->callback->UIThreadCallback(cb_data->msg_id, cb_data->data);
1285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  delete cb_data;
1295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return false;
1305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
1315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orggboolean Redraw(gpointer data) {
1335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  GtkMainWnd* wnd = reinterpret_cast<GtkMainWnd*>(data);
1345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  wnd->OnRedraw();
1355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return false;
1365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
1375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}  // end anonymous
1385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org//
1405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// GtkMainWnd implementation.
1415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org//
1425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgGtkMainWnd::GtkMainWnd(const char* server, int port, bool autoconnect,
1445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                       bool autocall)
1455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    : window_(NULL), draw_area_(NULL), vbox_(NULL), server_edit_(NULL),
1465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      port_edit_(NULL), peer_list_(NULL), callback_(NULL),
1475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      server_(server), autoconnect_(autoconnect), autocall_(autocall) {
1485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  char buffer[10];
1495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  sprintfn(buffer, sizeof(buffer), "%i", port);
1505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  port_ = buffer;
1515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
1525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgGtkMainWnd::~GtkMainWnd() {
1545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  ASSERT(!IsWindow());
1555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
1565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid GtkMainWnd::RegisterObserver(MainWndCallback* callback) {
1585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  callback_ = callback;
1595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
1605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgbool GtkMainWnd::IsWindow() {
1625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return window_ != NULL && GTK_IS_WINDOW(window_);
1635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
1645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid GtkMainWnd::MessageBox(const char* caption, const char* text,
1665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                            bool is_error) {
1675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  GtkWidget* dialog = gtk_message_dialog_new(GTK_WINDOW(window_),
1685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      GTK_DIALOG_DESTROY_WITH_PARENT,
1695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      is_error ? GTK_MESSAGE_ERROR : GTK_MESSAGE_INFO,
1705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      GTK_BUTTONS_CLOSE, "%s", text);
1715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  gtk_window_set_title(GTK_WINDOW(dialog), caption);
1725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  gtk_dialog_run(GTK_DIALOG(dialog));
1735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  gtk_widget_destroy(dialog);
1745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
1755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgMainWindow::UI GtkMainWnd::current_ui() {
1775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (vbox_)
1785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return CONNECT_TO_SERVER;
1795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (peer_list_)
1815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return LIST_PEERS;
1825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return STREAMING;
1845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
1855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid GtkMainWnd::StartLocalRenderer(webrtc::VideoTrackInterface* local_video) {
1885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  local_renderer_.reset(new VideoRenderer(this, local_video));
1895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
1905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid GtkMainWnd::StopLocalRenderer() {
1925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  local_renderer_.reset();
1935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
1945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid GtkMainWnd::StartRemoteRenderer(webrtc::VideoTrackInterface* remote_video) {
1965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  remote_renderer_.reset(new VideoRenderer(this, remote_video));
1975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
1985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid GtkMainWnd::StopRemoteRenderer() {
2005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  remote_renderer_.reset();
2015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
2025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid GtkMainWnd::QueueUIThreadCallback(int msg_id, void* data) {
2045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  g_idle_add(HandleUIThreadCallback,
2055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org             new UIThreadCallbackData(callback_, msg_id, data));
2065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
2075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgbool GtkMainWnd::Create() {
2095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  ASSERT(window_ == NULL);
2105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  window_ = gtk_window_new(GTK_WINDOW_TOPLEVEL);
2125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (window_) {
2135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    gtk_window_set_position(GTK_WINDOW(window_), GTK_WIN_POS_CENTER);
2145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    gtk_window_set_default_size(GTK_WINDOW(window_), 640, 480);
2155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    gtk_window_set_title(GTK_WINDOW(window_), "PeerConnection client");
2165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    g_signal_connect(G_OBJECT(window_), "delete-event",
2175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                     G_CALLBACK(&OnDestroyedCallback), this);
2185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    g_signal_connect(window_, "key-press-event", G_CALLBACK(OnKeyPressCallback),
2195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                     this);
2205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    SwitchToConnectUI();
2225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
2235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return window_ != NULL;
2255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
2265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgbool GtkMainWnd::Destroy() {
2285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!IsWindow())
2295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return false;
2305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  gtk_widget_destroy(window_);
2325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  window_ = NULL;
2335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return true;
2355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
2365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid GtkMainWnd::SwitchToConnectUI() {
2385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  LOG(INFO) << __FUNCTION__;
2395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  ASSERT(IsWindow());
2415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  ASSERT(vbox_ == NULL);
2425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  gtk_container_set_border_width(GTK_CONTAINER(window_), 10);
2445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (peer_list_) {
2465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    gtk_widget_destroy(peer_list_);
2475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    peer_list_ = NULL;
2485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
2495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  vbox_ = gtk_vbox_new(FALSE, 5);
2515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  GtkWidget* valign = gtk_alignment_new(0, 1, 0, 0);
2525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  gtk_container_add(GTK_CONTAINER(vbox_), valign);
2535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  gtk_container_add(GTK_CONTAINER(window_), vbox_);
2545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  GtkWidget* hbox = gtk_hbox_new(FALSE, 5);
2565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  GtkWidget* label = gtk_label_new("Server");
2585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  gtk_container_add(GTK_CONTAINER(hbox), label);
2595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  server_edit_ = gtk_entry_new();
2615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  gtk_entry_set_text(GTK_ENTRY(server_edit_), server_.c_str());
2625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  gtk_widget_set_size_request(server_edit_, 400, 30);
2635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  gtk_container_add(GTK_CONTAINER(hbox), server_edit_);
2645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  port_edit_ = gtk_entry_new();
2665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  gtk_entry_set_text(GTK_ENTRY(port_edit_), port_.c_str());
2675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  gtk_widget_set_size_request(port_edit_, 70, 30);
2685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  gtk_container_add(GTK_CONTAINER(hbox), port_edit_);
2695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  GtkWidget* button = gtk_button_new_with_label("Connect");
2715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  gtk_widget_set_size_request(button, 70, 30);
2725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  g_signal_connect(button, "clicked", G_CALLBACK(OnClickedCallback), this);
2735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  gtk_container_add(GTK_CONTAINER(hbox), button);
2745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  GtkWidget* halign = gtk_alignment_new(1, 0, 0, 0);
2765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  gtk_container_add(GTK_CONTAINER(halign), hbox);
2775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  gtk_box_pack_start(GTK_BOX(vbox_), halign, FALSE, FALSE, 0);
2785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  gtk_widget_show_all(window_);
2805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (autoconnect_)
2825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    g_idle_add(SimulateButtonClick, button);
2835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
2845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid GtkMainWnd::SwitchToPeerList(const Peers& peers) {
2865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  LOG(INFO) << __FUNCTION__;
2875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!peer_list_) {
2895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    gtk_container_set_border_width(GTK_CONTAINER(window_), 0);
2905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    if (vbox_) {
2915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      gtk_widget_destroy(vbox_);
2925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      vbox_ = NULL;
2935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      server_edit_ = NULL;
2945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      port_edit_ = NULL;
2955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    } else if (draw_area_) {
2965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      gtk_widget_destroy(draw_area_);
2975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      draw_area_ = NULL;
2985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      draw_buffer_.reset();
2995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    }
3005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
3015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    peer_list_ = gtk_tree_view_new();
3025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    g_signal_connect(peer_list_, "row-activated",
3035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                     G_CALLBACK(OnRowActivatedCallback), this);
3045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(peer_list_), FALSE);
3055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    InitializeList(peer_list_);
3065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    gtk_container_add(GTK_CONTAINER(window_), peer_list_);
3075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    gtk_widget_show_all(window_);
3085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  } else {
3095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    GtkListStore* store =
3105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(peer_list_)));
3115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    gtk_list_store_clear(store);
3125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
3135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
3145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  AddToList(peer_list_, "List of currently connected peers:", -1);
3155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  for (Peers::const_iterator i = peers.begin(); i != peers.end(); ++i)
3165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    AddToList(peer_list_, i->second.c_str(), i->first);
3175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
3185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (autocall_ && peers.begin() != peers.end())
3195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    g_idle_add(SimulateLastRowActivated, peer_list_);
3205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
3215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
3225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid GtkMainWnd::SwitchToStreamingUI() {
3235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  LOG(INFO) << __FUNCTION__;
3245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
3255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  ASSERT(draw_area_ == NULL);
3265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
3275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  gtk_container_set_border_width(GTK_CONTAINER(window_), 0);
3285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (peer_list_) {
3295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    gtk_widget_destroy(peer_list_);
3305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    peer_list_ = NULL;
3315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
3325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
3335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  draw_area_ = gtk_drawing_area_new();
3345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  gtk_container_add(GTK_CONTAINER(window_), draw_area_);
3355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
3365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  gtk_widget_show_all(window_);
3375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
3385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
3395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid GtkMainWnd::OnDestroyed(GtkWidget* widget, GdkEvent* event) {
3405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  callback_->Close();
3415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  window_ = NULL;
3425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  draw_area_ = NULL;
3435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  vbox_ = NULL;
3445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  server_edit_ = NULL;
3455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  port_edit_ = NULL;
3465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  peer_list_ = NULL;
3475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
3485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
3495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid GtkMainWnd::OnClicked(GtkWidget* widget) {
3505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // Make the connect button insensitive, so that it cannot be clicked more than
3515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // once.  Now that the connection includes auto-retry, it should not be
3525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // necessary to click it more than once.
3535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  gtk_widget_set_sensitive(widget, false);
3545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  server_ = gtk_entry_get_text(GTK_ENTRY(server_edit_));
3555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  port_ = gtk_entry_get_text(GTK_ENTRY(port_edit_));
3565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  int port = port_.length() ? atoi(port_.c_str()) : 0;
3575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  callback_->StartLogin(server_, port);
3585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
3595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
3605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid GtkMainWnd::OnKeyPress(GtkWidget* widget, GdkEventKey* key) {
3615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (key->type == GDK_KEY_PRESS) {
3625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    switch (key->keyval) {
3635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org     case GDK_Escape:
3645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org       if (draw_area_) {
3655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org         callback_->DisconnectFromCurrentPeer();
3665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org       } else if (peer_list_) {
3675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org         callback_->DisconnectFromServer();
3685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org       }
3695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org       break;
3705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
3715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org     case GDK_KP_Enter:
3725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org     case GDK_Return:
3735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org       if (vbox_) {
3745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org         OnClicked(NULL);
3755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org       } else if (peer_list_) {
3765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org         // OnRowActivated will be called automatically when the user
3775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org         // presses enter.
3785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org       }
3795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org       break;
3805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
3815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org     default:
3825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org       break;
3835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    }
3845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
3855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
3865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
3875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid GtkMainWnd::OnRowActivated(GtkTreeView* tree_view, GtkTreePath* path,
3885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                                GtkTreeViewColumn* column) {
3895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  ASSERT(peer_list_ != NULL);
3905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  GtkTreeIter iter;
3915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  GtkTreeModel* model;
3925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  GtkTreeSelection* selection =
3935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      gtk_tree_view_get_selection(GTK_TREE_VIEW(tree_view));
3945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (gtk_tree_selection_get_selected(selection, &model, &iter)) {
3955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org     char* text;
3965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org     int id = -1;
3975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org     gtk_tree_model_get(model, &iter, 0, &text, 1, &id,  -1);
3985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org     if (id != -1)
3995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org       callback_->ConnectToPeer(id);
4005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org     g_free(text);
4015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
4025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
4035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
4045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid GtkMainWnd::OnRedraw() {
4055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  gdk_threads_enter();
4065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
4075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  VideoRenderer* remote_renderer = remote_renderer_.get();
4085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (remote_renderer && remote_renderer->image() != NULL &&
4095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      draw_area_ != NULL) {
4105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    int width = remote_renderer->width();
4115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    int height = remote_renderer->height();
4125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
4135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    if (!draw_buffer_.get()) {
4145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      draw_buffer_size_ = (width * height * 4) * 4;
4155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      draw_buffer_.reset(new uint8[draw_buffer_size_]);
4165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      gtk_widget_set_size_request(draw_area_, width * 2, height * 2);
4175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    }
4185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
4195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    const uint32* image = reinterpret_cast<const uint32*>(
4205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        remote_renderer->image());
4215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    uint32* scaled = reinterpret_cast<uint32*>(draw_buffer_.get());
4225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    for (int r = 0; r < height; ++r) {
4235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      for (int c = 0; c < width; ++c) {
4245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        int x = c * 2;
4255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        scaled[x] = scaled[x + 1] = image[c];
4265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      }
4275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
4285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      uint32* prev_line = scaled;
4295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      scaled += width * 2;
4305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      memcpy(scaled, prev_line, (width * 2) * 4);
4315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
4325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      image += width;
4335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      scaled += width * 2;
4345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    }
4355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
4365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    VideoRenderer* local_renderer = local_renderer_.get();
4375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    if (local_renderer && local_renderer->image()) {
4385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      image = reinterpret_cast<const uint32*>(local_renderer->image());
4395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      scaled = reinterpret_cast<uint32*>(draw_buffer_.get());
4405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      // Position the local preview on the right side.
4415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      scaled += (width * 2) - (local_renderer->width() / 2);
4425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      // right margin...
4435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      scaled -= 10;
4445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      // ... towards the bottom.
4455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      scaled += (height * width * 4) -
4465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                ((local_renderer->height() / 2) *
4475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                 (local_renderer->width() / 2) * 4);
4485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      // bottom margin...
4495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      scaled -= (width * 2) * 5;
4505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      for (int r = 0; r < local_renderer->height(); r += 2) {
4515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        for (int c = 0; c < local_renderer->width(); c += 2) {
4525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org          scaled[c / 2] = image[c + r * local_renderer->width()];
4535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        }
4545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        scaled += width * 2;
4555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      }
4565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    }
4575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
4585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    gdk_draw_rgb_32_image(draw_area_->window,
4595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                          draw_area_->style->fg_gc[GTK_STATE_NORMAL],
4605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                          0,
4615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                          0,
4625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                          width * 2,
4635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                          height * 2,
4645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                          GDK_RGB_DITHER_MAX,
4655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                          draw_buffer_.get(),
4665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                          (width * 2) * 4);
4675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
4685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
4695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  gdk_threads_leave();
4705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
4715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
4725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgGtkMainWnd::VideoRenderer::VideoRenderer(
4735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    GtkMainWnd* main_wnd,
4745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    webrtc::VideoTrackInterface* track_to_render)
4755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    : width_(0),
4765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      height_(0),
4775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      main_wnd_(main_wnd),
4785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      rendered_track_(track_to_render) {
4795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  rendered_track_->AddRenderer(this);
4805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
4815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
4825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgGtkMainWnd::VideoRenderer::~VideoRenderer() {
4835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  rendered_track_->RemoveRenderer(this);
4845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
4855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
4865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid GtkMainWnd::VideoRenderer::SetSize(int width, int height) {
4875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  gdk_threads_enter();
4885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  width_ = width;
4895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  height_ = height;
4905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  image_.reset(new uint8[width * height * 4]);
4915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  gdk_threads_leave();
4925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
4935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
4945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid GtkMainWnd::VideoRenderer::RenderFrame(const cricket::VideoFrame* frame) {
4955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  gdk_threads_enter();
4965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
4975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  int size = width_ * height_ * 4;
4985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // TODO: Convert directly to RGBA
4995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  frame->ConvertToRgbBuffer(cricket::FOURCC_ARGB,
5005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                            image_.get(),
5015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                            size,
5025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                            width_ * 4);
5035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // Convert the B,G,R,A frame to R,G,B,A, which is accepted by GTK.
5045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // The 'A' is just padding for GTK, so we can use it as temp.
5055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  uint8* pix = image_.get();
5065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  uint8* end = image_.get() + size;
5075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  while (pix < end) {
5085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    pix[3] = pix[0];     // Save B to A.
5095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    pix[0] = pix[2];  // Set Red.
5105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    pix[2] = pix[3];  // Set Blue.
5115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    pix[3] = 0xFF;     // Fixed Alpha.
5125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    pix += 4;
5135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
5145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
5155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  gdk_threads_leave();
5165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
5175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  g_idle_add(Redraw, main_wnd_);
5185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
5195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
5205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
521