1 /** \file   uinetplay_new.c
2  * \brief   GTK3 Netplay UI
3  *
4  * \author  Bas Wassink <b.wassink@ziggo.nl>
5  */
6 
7 /*
8  * $VICERES NetworkServerName           -vsid
9  * $VICERES NetworkServerPort           -vsid
10  * $VICERES NetworkServerBindAddress    -vsid
11  *
12  * Not sure about this one (TODO):
13  * $VICERES NetworkControl              -vsid
14  */
15 
16 /*
17  * This file is part of VICE, the Versatile Commodore Emulator.
18  * See README for copyright notice.
19  *
20  *  This program is free software; you can redistribute it and/or modify
21  *  it under the terms of the GNU General Public License as published by
22  *  the Free Software Foundation; either version 2 of the License, or
23  *  (at your option) any later version.
24  *
25  *  This program is distributed in the hope that it will be useful,
26  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
27  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
28  *  GNU General Public License for more details.
29  *
30  *  You should have received a copy of the GNU General Public License
31  *  along with this program; if not, write to the Free Software
32  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
33  *  02111-1307  USA.
34  */
35 
36 #include "vice.h"
37 
38 #include <gtk/gtk.h>
39 #include <stdio.h>
40 #include <stdlib.h>
41 
42 #include "basewidgets.h"
43 #include "debug_gtk3.h"
44 #include "lib.h"
45 #include "network.h"
46 #include "ui.h"
47 #include "widgethelpers.h"
48 
49 #include "uinetplay_new.h"
50 
51 
52 static GtkWidget *server_addr = NULL;
53 static GtkWidget *server_port = NULL;
54 static GtkWidget *bind_enable = NULL;
55 static GtkWidget *status_widget = NULL;
56 
57 
58 static const char *net_modes[] = {
59     "Idle",
60     "Server listening",
61     "Connected server",
62     "Connected client"
63 };
64 
65 
create_indented_label(const char * text)66 static GtkWidget *create_indented_label(const char *text)
67 {
68     GtkWidget *label = gtk_label_new(text);
69     gtk_widget_set_halign(label, GTK_ALIGN_START);
70     g_object_set(label, "margin-left", 16, NULL);
71     return label;
72 }
73 
74 
on_server_enable_toggled(GtkSwitch * widget,gpointer data)75 static void on_server_enable_toggled(GtkSwitch *widget, gpointer data)
76 {
77     int state = gtk_switch_get_active(widget);
78     debug_gtk3("Server %s requested.", state ? "ENABLE" : "DISABLE");
79 
80     gtk_widget_set_sensitive(bind_enable, state ? FALSE : TRUE);
81     gtk_widget_set_sensitive(server_addr, state ? FALSE : TRUE);
82     gtk_widget_set_sensitive(server_port, state ? FALSE : TRUE);
83 }
84 
85 
on_client_enable_toggled(GtkSwitch * widget,gpointer data)86 static void on_client_enable_toggled(GtkSwitch *widget, gpointer data)
87 {
88 #ifdef HAVE_DEBUG_GTK3UI
89     int state = gtk_switch_get_active(widget);
90 #endif
91     debug_gtk3("Client %s requested.", state ? "CONNECT" : "DISCONNECT");
92 }
93 
94 
95 
create_server_enable_widget(void)96 static GtkWidget *create_server_enable_widget(void)
97 {
98     GtkWidget *widget;
99 
100     widget = gtk_switch_new();
101     gtk_widget_set_halign(widget, GTK_ALIGN_START);
102     g_signal_connect(widget, "notify::active",
103             G_CALLBACK(on_server_enable_toggled), NULL);
104     return widget;
105 }
106 
107 
create_client_enable_widget(void)108 static GtkWidget *create_client_enable_widget(void)
109 {
110     GtkWidget *widget;
111 
112     widget = gtk_switch_new();
113     gtk_widget_set_halign(widget, GTK_ALIGN_START);
114     g_signal_connect(widget, "notify::active",
115             G_CALLBACK(on_client_enable_toggled), NULL);
116     return widget;
117 }
118 
119 
120 
121 /** \brief  Handler for the "response" event of the dialog
122  *
123  * \param[in,out]   dialog      dialog
124  * \param[in]       response_id response ID
125  * \param[in]       extra event data (unused)
126  */
on_response(GtkWidget * dialog,gint response_id,gpointer data)127 static void on_response(GtkWidget *dialog, gint response_id, gpointer data)
128 {
129     switch (response_id) {
130         case GTK_RESPONSE_DELETE_EVENT:
131             gtk_widget_destroy(dialog);
132             break;
133         default:
134             debug_gtk3("unknown response ID %d, ignoring.", response_id);
135             break;
136     }
137 }
138 
139 
netplay_update_status(void)140 static void netplay_update_status(void)
141 {
142     const char *text = NULL;
143     char *temp;
144     int mode = network_get_mode();
145 
146     if (mode < 0 || mode >= (int)(sizeof net_modes / sizeof net_modes[0])) {
147         text = "invalid";
148     } else {
149         text = net_modes[mode];
150     }
151 
152     temp = lib_msprintf("<b>%s</b>", text);
153     gtk_label_set_markup(GTK_LABEL(status_widget), temp);
154     lib_free(temp);
155 }
156 
157 
158 
159 /** \brief  Create the 'content' widget for the dialog
160  *
161  * This creates the content of the dialog, holding all controls
162  *
163  * \return  GtkGrid
164  */
create_content_widget(void)165 static GtkWidget *create_content_widget(void)
166 {
167     GtkWidget *grid;
168     GtkWidget *label;
169     GtkWidget *server_enable;
170     GtkWidget *bind_addr;
171     int row;
172 
173     grid = gtk_grid_new();
174     gtk_grid_set_column_spacing(GTK_GRID(grid), 16);
175     gtk_grid_set_row_spacing(GTK_GRID(grid), 8);
176 
177     row = 0;
178 
179     label = gtk_label_new(NULL);
180     gtk_label_set_markup(GTK_LABEL(label), "<b>Server</b>");
181     gtk_widget_set_halign(label, GTK_ALIGN_START);
182     gtk_grid_attach(GTK_GRID(grid), label, 0, row, 4, 1);
183     row++;
184 
185     label = create_indented_label("Server IP address");
186     server_addr = vice_gtk3_resource_entry_full_new("NetworkServerName");
187     gtk_widget_set_hexpand(server_addr, TRUE);
188     gtk_grid_attach(GTK_GRID(grid), label, 0, row, 1, 1);
189     gtk_grid_attach(GTK_GRID(grid), server_addr, 1, row, 1, 1);
190 
191     server_port = vice_gtk3_resource_spin_int_new("NetworkServerPort",
192             1, 65535, 1);
193     gtk_grid_attach(GTK_GRID(grid), server_port, 2, row, 1, 1);
194     server_enable = create_server_enable_widget();
195 
196     gtk_grid_attach(GTK_GRID(grid), server_enable, 3, row, 1, 1);
197     row++;
198 
199     label = gtk_label_new(NULL);
200     gtk_label_set_markup(GTK_LABEL(label), "<b>Client</b>");
201     gtk_widget_set_halign(label, GTK_ALIGN_START);
202     gtk_grid_attach(GTK_GRID(grid), label, 0, row, 4, 1);
203     row++;
204 
205     label = create_indented_label("Bind IP address");
206     bind_addr = vice_gtk3_resource_entry_full_new(
207             "NetworkServerBindAddress");
208     gtk_grid_attach(GTK_GRID(grid), label, 0, row, 1, 1);
209     gtk_grid_attach(GTK_GRID(grid), bind_addr, 1, row, 1, 1);
210 
211     bind_enable = create_client_enable_widget();
212     gtk_grid_attach(GTK_GRID(grid), bind_enable, 3, row, 2, 1);
213     row++;
214 
215     label = gtk_label_new(NULL);
216     gtk_label_set_markup(GTK_LABEL(label), "<b>Network status</b>");
217     gtk_widget_set_halign(label, GTK_ALIGN_START);
218     gtk_grid_attach(GTK_GRID(grid), label, 0, row, 4, 1);
219 
220     row++;
221     status_widget = create_indented_label("");
222     gtk_grid_attach(GTK_GRID(grid), status_widget, 0, row, 4, 1);
223 
224     gtk_widget_show_all(grid);
225     return grid;
226 }
227 
228 
229 
230 /** \brief  Show Netplay dialog
231  *
232  * \param[in]   parent  parent widget
233  * \param[in]   data    extra data (unused)
234  */
ui_netplay_dialog_new(GtkWidget * parent,gpointer data)235 void ui_netplay_dialog_new(GtkWidget *parent, gpointer data)
236 {
237     GtkWidget *dialog;
238     GtkWidget *content;
239 
240     dialog = gtk_dialog_new_with_buttons("Netplay",
241             ui_get_active_window(),
242             GTK_DIALOG_MODAL,
243             "Close", GTK_RESPONSE_DELETE_EVENT,
244             NULL);
245 
246     content = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
247     gtk_container_add(GTK_CONTAINER(content), create_content_widget());
248     netplay_update_status();
249 
250     g_signal_connect(dialog, "response", G_CALLBACK(on_response), NULL);
251 
252     gtk_widget_show_all(dialog);
253 }
254