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