128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org/*
2a8736448970fedd82f051c6b2cc89185b755ddf3Donald E Curtis *  Copyright 2012 The WebRTC Project Authors. All rights reserved.
328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org *
4a8736448970fedd82f051c6b2cc89185b755ddf3Donald E Curtis *  Use of this source code is governed by a BSD-style license
5a8736448970fedd82f051c6b2cc89185b755ddf3Donald E Curtis *  that can be found in the LICENSE file in the root of the source
6a8736448970fedd82f051c6b2cc89185b755ddf3Donald E Curtis *  tree. An additional intellectual property rights grant can be found
7a8736448970fedd82f051c6b2cc89185b755ddf3Donald E Curtis *  in the file PATENTS.  All contributing project authors may
8a8736448970fedd82f051c6b2cc89185b755ddf3Donald E Curtis *  be found in the AUTHORS file in the root of the source tree.
928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org */
1028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
11a8736448970fedd82f051c6b2cc89185b755ddf3Donald E Curtis#include "webrtc/examples/peerconnection/client/linux/main_wnd.h"
1228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
1328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org#include <gdk/gdkkeysyms.h>
1428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org#include <gtk/gtk.h>
1528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org#include <stddef.h>
1628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
17a8736448970fedd82f051c6b2cc89185b755ddf3Donald E Curtis#include "webrtc/examples/peerconnection/client/defaults.h"
18d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org#include "webrtc/base/common.h"
19d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org#include "webrtc/base/logging.h"
20d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org#include "webrtc/base/stringutils.h"
2128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
22d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.orgusing rtc::sprintfn;
2328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
2428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgnamespace {
2528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
2628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org//
2728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// Simple static functions that simply forward the callback to the
2828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// GtkMainWnd instance.
2928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org//
3028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
3128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orggboolean OnDestroyedCallback(GtkWidget* widget, GdkEvent* event,
3228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org                             gpointer data) {
3328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  reinterpret_cast<GtkMainWnd*>(data)->OnDestroyed(widget, event);
3428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  return FALSE;
3528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
3628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
3728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgvoid OnClickedCallback(GtkWidget* widget, gpointer data) {
3828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  reinterpret_cast<GtkMainWnd*>(data)->OnClicked(widget);
3928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
4028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
4128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orggboolean SimulateButtonClick(gpointer button) {
4228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  g_signal_emit_by_name(button, "clicked");
4328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  return false;
4428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
4528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
4628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orggboolean OnKeyPressCallback(GtkWidget* widget, GdkEventKey* key,
4728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org                            gpointer data) {
4828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  reinterpret_cast<GtkMainWnd*>(data)->OnKeyPress(widget, key);
4928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  return false;
5028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
5128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
5228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgvoid OnRowActivatedCallback(GtkTreeView* tree_view, GtkTreePath* path,
5328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org                            GtkTreeViewColumn* column, gpointer data) {
5428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  reinterpret_cast<GtkMainWnd*>(data)->OnRowActivated(tree_view, path, column);
5528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
5628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
5728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orggboolean SimulateLastRowActivated(gpointer data) {
5828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  GtkTreeView* tree_view = reinterpret_cast<GtkTreeView*>(data);
5928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  GtkTreeModel* model = gtk_tree_view_get_model(tree_view);
6028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
6128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  // "if iter is NULL, then the number of toplevel nodes is returned."
6228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  int rows = gtk_tree_model_iter_n_children(model, NULL);
6328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  GtkTreePath* lastpath = gtk_tree_path_new_from_indices(rows - 1, -1);
6428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
6528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  // Select the last item in the list
6628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  GtkTreeSelection* selection = gtk_tree_view_get_selection(tree_view);
6728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  gtk_tree_selection_select_path(selection, lastpath);
6828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
6928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  // Our TreeView only has one column, so it is column 0.
7028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  GtkTreeViewColumn* column = gtk_tree_view_get_column(tree_view, 0);
7128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
7228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  gtk_tree_view_row_activated(tree_view, lastpath, column);
7328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
7428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  gtk_tree_path_free(lastpath);
7528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  return false;
7628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
7728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
7828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// Creates a tree view, that we use to display the list of peers.
7928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgvoid InitializeList(GtkWidget* list) {
8028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  GtkCellRenderer* renderer = gtk_cell_renderer_text_new();
8128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  GtkTreeViewColumn* column = gtk_tree_view_column_new_with_attributes(
8228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      "List Items", renderer, "text", 0, NULL);
8328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  gtk_tree_view_append_column(GTK_TREE_VIEW(list), column);
8428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  GtkListStore* store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_INT);
8528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  gtk_tree_view_set_model(GTK_TREE_VIEW(list), GTK_TREE_MODEL(store));
8628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  g_object_unref(store);
8728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
8828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
8928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// Adds an entry to a tree view.
9028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgvoid AddToList(GtkWidget* list, const gchar* str, int value) {
9128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  GtkListStore* store = GTK_LIST_STORE(
9228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      gtk_tree_view_get_model(GTK_TREE_VIEW(list)));
9328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
9428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  GtkTreeIter iter;
9528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  gtk_list_store_append(store, &iter);
9628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  gtk_list_store_set(store, &iter, 0, str, 1, value, -1);
9728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
9828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
9928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgstruct UIThreadCallbackData {
10028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  explicit UIThreadCallbackData(MainWndCallback* cb, int id, void* d)
10128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      : callback(cb), msg_id(id), data(d) {}
10228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  MainWndCallback* callback;
10328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  int msg_id;
10428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  void* data;
10528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org};
10628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
10728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orggboolean HandleUIThreadCallback(gpointer data) {
10828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  UIThreadCallbackData* cb_data = reinterpret_cast<UIThreadCallbackData*>(data);
10928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  cb_data->callback->UIThreadCallback(cb_data->msg_id, cb_data->data);
11028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  delete cb_data;
11128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  return false;
11228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
11328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
11428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orggboolean Redraw(gpointer data) {
11528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  GtkMainWnd* wnd = reinterpret_cast<GtkMainWnd*>(data);
11628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  wnd->OnRedraw();
11728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  return false;
11828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
11970625e5bf3c91c57bf704d380bcc9df86575f08ajbauch
12070625e5bf3c91c57bf704d380bcc9df86575f08ajbauch}  // namespace
12128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
12228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org//
12328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// GtkMainWnd implementation.
12428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org//
12528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
12628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgGtkMainWnd::GtkMainWnd(const char* server, int port, bool autoconnect,
12728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org                       bool autocall)
12828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    : window_(NULL), draw_area_(NULL), vbox_(NULL), server_edit_(NULL),
12928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      port_edit_(NULL), peer_list_(NULL), callback_(NULL),
13028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      server_(server), autoconnect_(autoconnect), autocall_(autocall) {
13128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  char buffer[10];
13228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  sprintfn(buffer, sizeof(buffer), "%i", port);
13328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  port_ = buffer;
13428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
13528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
13628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgGtkMainWnd::~GtkMainWnd() {
13728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  ASSERT(!IsWindow());
13828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
13928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
14028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgvoid GtkMainWnd::RegisterObserver(MainWndCallback* callback) {
14128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  callback_ = callback;
14228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
14328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
14428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgbool GtkMainWnd::IsWindow() {
14528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  return window_ != NULL && GTK_IS_WINDOW(window_);
14628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
14728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
14828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgvoid GtkMainWnd::MessageBox(const char* caption, const char* text,
14928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org                            bool is_error) {
15028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  GtkWidget* dialog = gtk_message_dialog_new(GTK_WINDOW(window_),
15128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      GTK_DIALOG_DESTROY_WITH_PARENT,
15228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      is_error ? GTK_MESSAGE_ERROR : GTK_MESSAGE_INFO,
15328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      GTK_BUTTONS_CLOSE, "%s", text);
15428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  gtk_window_set_title(GTK_WINDOW(dialog), caption);
15528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  gtk_dialog_run(GTK_DIALOG(dialog));
15628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  gtk_widget_destroy(dialog);
15728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
15828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
15928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgMainWindow::UI GtkMainWnd::current_ui() {
16028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  if (vbox_)
16128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    return CONNECT_TO_SERVER;
16228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
16328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  if (peer_list_)
16428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    return LIST_PEERS;
16528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
16628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  return STREAMING;
16728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
16828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
16928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
17028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgvoid GtkMainWnd::StartLocalRenderer(webrtc::VideoTrackInterface* local_video) {
17128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  local_renderer_.reset(new VideoRenderer(this, local_video));
17228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
17328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
17428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgvoid GtkMainWnd::StopLocalRenderer() {
17528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  local_renderer_.reset();
17628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
17728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
17870625e5bf3c91c57bf704d380bcc9df86575f08ajbauchvoid GtkMainWnd::StartRemoteRenderer(
17970625e5bf3c91c57bf704d380bcc9df86575f08ajbauch    webrtc::VideoTrackInterface* remote_video) {
18028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  remote_renderer_.reset(new VideoRenderer(this, remote_video));
18128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
18228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
18328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgvoid GtkMainWnd::StopRemoteRenderer() {
18428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  remote_renderer_.reset();
18528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
18628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
18728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgvoid GtkMainWnd::QueueUIThreadCallback(int msg_id, void* data) {
18828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  g_idle_add(HandleUIThreadCallback,
18928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org             new UIThreadCallbackData(callback_, msg_id, data));
19028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
19128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
19228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgbool GtkMainWnd::Create() {
19328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  ASSERT(window_ == NULL);
19428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
19528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  window_ = gtk_window_new(GTK_WINDOW_TOPLEVEL);
19628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  if (window_) {
19728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    gtk_window_set_position(GTK_WINDOW(window_), GTK_WIN_POS_CENTER);
19828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    gtk_window_set_default_size(GTK_WINDOW(window_), 640, 480);
19928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    gtk_window_set_title(GTK_WINDOW(window_), "PeerConnection client");
20028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    g_signal_connect(G_OBJECT(window_), "delete-event",
20128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org                     G_CALLBACK(&OnDestroyedCallback), this);
20228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    g_signal_connect(window_, "key-press-event", G_CALLBACK(OnKeyPressCallback),
20328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org                     this);
20428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
20528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    SwitchToConnectUI();
20628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  }
20728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
20828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  return window_ != NULL;
20928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
21028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
21128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgbool GtkMainWnd::Destroy() {
21228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  if (!IsWindow())
21328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    return false;
21428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
21528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  gtk_widget_destroy(window_);
21628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  window_ = NULL;
21728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
21828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  return true;
21928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
22028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
22128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgvoid GtkMainWnd::SwitchToConnectUI() {
22228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  LOG(INFO) << __FUNCTION__;
22328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
22428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  ASSERT(IsWindow());
22528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  ASSERT(vbox_ == NULL);
22628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
22728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  gtk_container_set_border_width(GTK_CONTAINER(window_), 10);
22828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
22928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  if (peer_list_) {
23028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    gtk_widget_destroy(peer_list_);
23128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    peer_list_ = NULL;
23228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  }
23328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
23428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  vbox_ = gtk_vbox_new(FALSE, 5);
23528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  GtkWidget* valign = gtk_alignment_new(0, 1, 0, 0);
23628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  gtk_container_add(GTK_CONTAINER(vbox_), valign);
23728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  gtk_container_add(GTK_CONTAINER(window_), vbox_);
23828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
23928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  GtkWidget* hbox = gtk_hbox_new(FALSE, 5);
24028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
24128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  GtkWidget* label = gtk_label_new("Server");
24228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  gtk_container_add(GTK_CONTAINER(hbox), label);
24328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
24428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  server_edit_ = gtk_entry_new();
24528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  gtk_entry_set_text(GTK_ENTRY(server_edit_), server_.c_str());
24628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  gtk_widget_set_size_request(server_edit_, 400, 30);
24728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  gtk_container_add(GTK_CONTAINER(hbox), server_edit_);
24828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
24928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  port_edit_ = gtk_entry_new();
25028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  gtk_entry_set_text(GTK_ENTRY(port_edit_), port_.c_str());
25128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  gtk_widget_set_size_request(port_edit_, 70, 30);
25228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  gtk_container_add(GTK_CONTAINER(hbox), port_edit_);
25328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
25428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  GtkWidget* button = gtk_button_new_with_label("Connect");
25528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  gtk_widget_set_size_request(button, 70, 30);
25628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  g_signal_connect(button, "clicked", G_CALLBACK(OnClickedCallback), this);
25728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  gtk_container_add(GTK_CONTAINER(hbox), button);
25828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
25928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  GtkWidget* halign = gtk_alignment_new(1, 0, 0, 0);
26028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  gtk_container_add(GTK_CONTAINER(halign), hbox);
26128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  gtk_box_pack_start(GTK_BOX(vbox_), halign, FALSE, FALSE, 0);
26228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
26328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  gtk_widget_show_all(window_);
26428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
26528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  if (autoconnect_)
26628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    g_idle_add(SimulateButtonClick, button);
26728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
26828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
26928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgvoid GtkMainWnd::SwitchToPeerList(const Peers& peers) {
27028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  LOG(INFO) << __FUNCTION__;
27128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
27228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  if (!peer_list_) {
27328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    gtk_container_set_border_width(GTK_CONTAINER(window_), 0);
27428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    if (vbox_) {
27528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      gtk_widget_destroy(vbox_);
27628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      vbox_ = NULL;
27728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      server_edit_ = NULL;
27828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      port_edit_ = NULL;
27928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    } else if (draw_area_) {
28028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      gtk_widget_destroy(draw_area_);
28128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      draw_area_ = NULL;
28228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      draw_buffer_.reset();
28328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    }
28428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
28528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    peer_list_ = gtk_tree_view_new();
28628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    g_signal_connect(peer_list_, "row-activated",
28728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org                     G_CALLBACK(OnRowActivatedCallback), this);
28828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(peer_list_), FALSE);
28928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    InitializeList(peer_list_);
29028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    gtk_container_add(GTK_CONTAINER(window_), peer_list_);
29128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    gtk_widget_show_all(window_);
29228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  } else {
29328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    GtkListStore* store =
29428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org        GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(peer_list_)));
29528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    gtk_list_store_clear(store);
29628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  }
29728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
29828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  AddToList(peer_list_, "List of currently connected peers:", -1);
29928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  for (Peers::const_iterator i = peers.begin(); i != peers.end(); ++i)
30028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    AddToList(peer_list_, i->second.c_str(), i->first);
30128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
30228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  if (autocall_ && peers.begin() != peers.end())
30328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    g_idle_add(SimulateLastRowActivated, peer_list_);
30428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
30528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
30628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgvoid GtkMainWnd::SwitchToStreamingUI() {
30728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  LOG(INFO) << __FUNCTION__;
30828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
30928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  ASSERT(draw_area_ == NULL);
31028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
31128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  gtk_container_set_border_width(GTK_CONTAINER(window_), 0);
31228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  if (peer_list_) {
31328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    gtk_widget_destroy(peer_list_);
31428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    peer_list_ = NULL;
31528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  }
31628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
31728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  draw_area_ = gtk_drawing_area_new();
31828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  gtk_container_add(GTK_CONTAINER(window_), draw_area_);
31928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
32028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  gtk_widget_show_all(window_);
32128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
32228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
32328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgvoid GtkMainWnd::OnDestroyed(GtkWidget* widget, GdkEvent* event) {
32428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  callback_->Close();
32528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  window_ = NULL;
32628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  draw_area_ = NULL;
32728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  vbox_ = NULL;
32828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  server_edit_ = NULL;
32928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  port_edit_ = NULL;
33028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  peer_list_ = NULL;
33128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
33228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
33328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgvoid GtkMainWnd::OnClicked(GtkWidget* widget) {
33428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  // Make the connect button insensitive, so that it cannot be clicked more than
33528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  // once.  Now that the connection includes auto-retry, it should not be
33628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  // necessary to click it more than once.
33728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  gtk_widget_set_sensitive(widget, false);
33828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  server_ = gtk_entry_get_text(GTK_ENTRY(server_edit_));
33928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  port_ = gtk_entry_get_text(GTK_ENTRY(port_edit_));
34028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  int port = port_.length() ? atoi(port_.c_str()) : 0;
34128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  callback_->StartLogin(server_, port);
34228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
34328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
34428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgvoid GtkMainWnd::OnKeyPress(GtkWidget* widget, GdkEventKey* key) {
34528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  if (key->type == GDK_KEY_PRESS) {
34628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    switch (key->keyval) {
34728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org     case GDK_Escape:
34828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org       if (draw_area_) {
34928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org         callback_->DisconnectFromCurrentPeer();
35028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org       } else if (peer_list_) {
35128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org         callback_->DisconnectFromServer();
35228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org       }
35328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org       break;
35428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
35528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org     case GDK_KP_Enter:
35628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org     case GDK_Return:
35728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org       if (vbox_) {
35828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org         OnClicked(NULL);
35928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org       } else if (peer_list_) {
36028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org         // OnRowActivated will be called automatically when the user
36128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org         // presses enter.
36228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org       }
36328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org       break;
36428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
36528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org     default:
36628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org       break;
36728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    }
36828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  }
36928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
37028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
37128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgvoid GtkMainWnd::OnRowActivated(GtkTreeView* tree_view, GtkTreePath* path,
37228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org                                GtkTreeViewColumn* column) {
37328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  ASSERT(peer_list_ != NULL);
37428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  GtkTreeIter iter;
37528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  GtkTreeModel* model;
37628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  GtkTreeSelection* selection =
37728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      gtk_tree_view_get_selection(GTK_TREE_VIEW(tree_view));
37828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  if (gtk_tree_selection_get_selected(selection, &model, &iter)) {
37928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org     char* text;
38028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org     int id = -1;
38128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org     gtk_tree_model_get(model, &iter, 0, &text, 1, &id,  -1);
38228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org     if (id != -1)
38328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org       callback_->ConnectToPeer(id);
38428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org     g_free(text);
38528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  }
38628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
38728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
38828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgvoid GtkMainWnd::OnRedraw() {
38928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  gdk_threads_enter();
39028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
39128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  VideoRenderer* remote_renderer = remote_renderer_.get();
39228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  if (remote_renderer && remote_renderer->image() != NULL &&
39328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      draw_area_ != NULL) {
39428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    int width = remote_renderer->width();
39528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    int height = remote_renderer->height();
39628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
39728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    if (!draw_buffer_.get()) {
39828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      draw_buffer_size_ = (width * height * 4) * 4;
3990c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström      draw_buffer_.reset(new uint8_t[draw_buffer_size_]);
40028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      gtk_widget_set_size_request(draw_area_, width * 2, height * 2);
40128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    }
40228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
4030c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    const uint32_t* image =
4040c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström        reinterpret_cast<const uint32_t*>(remote_renderer->image());
4050c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    uint32_t* scaled = reinterpret_cast<uint32_t*>(draw_buffer_.get());
40628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    for (int r = 0; r < height; ++r) {
40728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      for (int c = 0; c < width; ++c) {
40828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org        int x = c * 2;
40928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org        scaled[x] = scaled[x + 1] = image[c];
41028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      }
41128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
4120c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström      uint32_t* prev_line = scaled;
41328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      scaled += width * 2;
41428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      memcpy(scaled, prev_line, (width * 2) * 4);
41528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
41628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      image += width;
41728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      scaled += width * 2;
41828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    }
41928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
42028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    VideoRenderer* local_renderer = local_renderer_.get();
42128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    if (local_renderer && local_renderer->image()) {
4220c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström      image = reinterpret_cast<const uint32_t*>(local_renderer->image());
4230c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström      scaled = reinterpret_cast<uint32_t*>(draw_buffer_.get());
42428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      // Position the local preview on the right side.
42528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      scaled += (width * 2) - (local_renderer->width() / 2);
42628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      // right margin...
42728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      scaled -= 10;
42828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      // ... towards the bottom.
42928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      scaled += (height * width * 4) -
43028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org                ((local_renderer->height() / 2) *
43128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org                 (local_renderer->width() / 2) * 4);
43228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      // bottom margin...
43328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      scaled -= (width * 2) * 5;
43428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      for (int r = 0; r < local_renderer->height(); r += 2) {
43528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org        for (int c = 0; c < local_renderer->width(); c += 2) {
43628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org          scaled[c / 2] = image[c + r * local_renderer->width()];
43728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org        }
43828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org        scaled += width * 2;
43928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      }
44028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    }
44128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
44228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    gdk_draw_rgb_32_image(draw_area_->window,
44328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org                          draw_area_->style->fg_gc[GTK_STATE_NORMAL],
44428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org                          0,
44528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org                          0,
44628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org                          width * 2,
44728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org                          height * 2,
44828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org                          GDK_RGB_DITHER_MAX,
44928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org                          draw_buffer_.get(),
45028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org                          (width * 2) * 4);
45128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  }
45228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
45328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  gdk_threads_leave();
45428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
45528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
45628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgGtkMainWnd::VideoRenderer::VideoRenderer(
45728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    GtkMainWnd* main_wnd,
45828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    webrtc::VideoTrackInterface* track_to_render)
45928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    : width_(0),
46028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      height_(0),
46128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      main_wnd_(main_wnd),
46228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      rendered_track_(track_to_render) {
46328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  rendered_track_->AddRenderer(this);
46428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
46528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
46628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgGtkMainWnd::VideoRenderer::~VideoRenderer() {
46728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  rendered_track_->RemoveRenderer(this);
46828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
46928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
47028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgvoid GtkMainWnd::VideoRenderer::SetSize(int width, int height) {
47128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  gdk_threads_enter();
47200c509ad1c94805b3332f2ce876c04705abf8ef5guoweis@webrtc.org
47300c509ad1c94805b3332f2ce876c04705abf8ef5guoweis@webrtc.org  if (width_ == width && height_ == height) {
47400c509ad1c94805b3332f2ce876c04705abf8ef5guoweis@webrtc.org    return;
47500c509ad1c94805b3332f2ce876c04705abf8ef5guoweis@webrtc.org  }
47600c509ad1c94805b3332f2ce876c04705abf8ef5guoweis@webrtc.org
47728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  width_ = width;
47828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  height_ = height;
4790c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  image_.reset(new uint8_t[width * height * 4]);
48028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  gdk_threads_leave();
48128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
48228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
48300c509ad1c94805b3332f2ce876c04705abf8ef5guoweis@webrtc.orgvoid GtkMainWnd::VideoRenderer::RenderFrame(
48400c509ad1c94805b3332f2ce876c04705abf8ef5guoweis@webrtc.org    const cricket::VideoFrame* video_frame) {
48528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  gdk_threads_enter();
48628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
48700c509ad1c94805b3332f2ce876c04705abf8ef5guoweis@webrtc.org  const cricket::VideoFrame* frame = video_frame->GetCopyWithRotationApplied();
48800c509ad1c94805b3332f2ce876c04705abf8ef5guoweis@webrtc.org
48900c509ad1c94805b3332f2ce876c04705abf8ef5guoweis@webrtc.org  SetSize(static_cast<int>(frame->GetWidth()),
49000c509ad1c94805b3332f2ce876c04705abf8ef5guoweis@webrtc.org          static_cast<int>(frame->GetHeight()));
49100c509ad1c94805b3332f2ce876c04705abf8ef5guoweis@webrtc.org
49228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  int size = width_ * height_ * 4;
49370625e5bf3c91c57bf704d380bcc9df86575f08ajbauch  // TODO(henrike): Convert directly to RGBA
49428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  frame->ConvertToRgbBuffer(cricket::FOURCC_ARGB,
49528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org                            image_.get(),
49628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org                            size,
49728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org                            width_ * 4);
49828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  // Convert the B,G,R,A frame to R,G,B,A, which is accepted by GTK.
49928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  // The 'A' is just padding for GTK, so we can use it as temp.
5000c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  uint8_t* pix = image_.get();
5010c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  uint8_t* end = image_.get() + size;
50228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  while (pix < end) {
50328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    pix[3] = pix[0];     // Save B to A.
50428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    pix[0] = pix[2];  // Set Red.
50528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    pix[2] = pix[3];  // Set Blue.
50628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    pix[3] = 0xFF;     // Fixed Alpha.
50728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    pix += 4;
50828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  }
50928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
51028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  gdk_threads_leave();
51128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
51228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  g_idle_add(Redraw, main_wnd_);
51328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
51428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
51528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
516