1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
|
using Dino.Entities;
using Gtk;
using Pango;
public class Dino.Ui.CallBottomBar : Gtk.Box {
public signal void hang_up();
public bool audio_enabled { get; set; }
public bool video_enabled { get; set; }
public string counterpart_display_name { get; set; }
private Button audio_button = new Button() { height_request=45, width_request=45, halign=Align.START, valign=Align.START };
private Overlay audio_button_overlay = new Overlay();
private Image audio_image = new Image() { pixel_size=22 };
private MenuButton audio_settings_button = new MenuButton() { halign=Align.END, valign=Align.END };
public AudioSettingsPopover? audio_settings_popover;
private Button video_button = new Button() { height_request=45, width_request=45, halign=Align.START, valign=Align.START };
private Overlay video_button_overlay = new Overlay();
private Image video_image = new Image() { pixel_size=22 };
private MenuButton video_settings_button = new MenuButton() { halign=Align.END, valign=Align.END };
public VideoSettingsPopover? video_settings_popover;
private Label label = new Label("") { halign=Align.CENTER, valign=Align.CENTER, wrap=true, wrap_mode=Pango.WrapMode.WORD_CHAR, hexpand=true };
private Stack stack = new Stack();
public CallBottomBar() {
Object(orientation:Orientation.HORIZONTAL, spacing:0);
Box main_buttons = new Box(Orientation.HORIZONTAL, 20) { margin_start=40, margin_end=40, margin_bottom=20, margin_top=20, halign=Align.CENTER, hexpand=true };
audio_button.set_child(audio_image);
audio_button.add_css_class("call-button");
audio_button.clicked.connect(() => { audio_enabled = !audio_enabled; });
audio_button.margin_end = audio_button.margin_bottom = 5; // space for the small settings button
audio_button_overlay.set_child(audio_button);
audio_button_overlay.add_overlay(audio_settings_button);
menu_button_set_icon_with_size(audio_settings_button, "go-up-symbolic", 10);
audio_settings_button.add_css_class("call-mediadevice-settings-button");
main_buttons.append(audio_button_overlay);
video_button.set_child(video_image);
video_button.add_css_class("call-button");
video_button.clicked.connect(() => { video_enabled = !video_enabled; });
video_button.margin_end = video_button.margin_bottom = 5;
video_button_overlay.set_child(video_button);
video_button_overlay.add_overlay(video_settings_button);
menu_button_set_icon_with_size(video_settings_button, "go-up-symbolic", 10);
video_settings_button.add_css_class("call-mediadevice-settings-button");
main_buttons.append(video_button_overlay);
Button button_hang = new Button() { height_request=45, width_request=45, halign=Align.START, valign=Align.START };
button_hang.set_child(new Image() { icon_name="dino-phone-hangup-symbolic", pixel_size=22 });
button_hang.add_css_class("call-button");
button_hang.add_css_class("destructive-action");
button_hang.clicked.connect(() => hang_up());
main_buttons.append(button_hang);
label.add_css_class("text-no-controls");
stack.add_named(main_buttons, "control-buttons");
stack.add_named(label, "label");
this.append(stack);
this.notify["audio-enabled"].connect(on_audio_enabled_changed);
this.notify["video-enabled"].connect(on_video_enabled_changed);
audio_enabled = true;
video_enabled = false;
on_audio_enabled_changed();
on_video_enabled_changed();
this.add_css_class("call-bottom-bar");
}
private static void menu_button_set_icon_with_size(MenuButton menu_button, string icon_name, int pixel_size) {
#if GTK_4_6
menu_button.set_child(new Image.from_icon_name(icon_name) { pixel_size=pixel_size });
#else
menu_button.set_icon_name(icon_name);
var button = menu_button.get_first_child() as Button;
if (button == null) return;
var box = button.child as Box;
if (box == null) return;
var image = box.get_first_child() as Image;
if (image == null) return;
image.pixel_size = pixel_size;
#endif
}
public AudioSettingsPopover? show_audio_device_choices(bool show) {
audio_settings_button.visible = show;
if (audio_settings_popover != null) audio_settings_popover.visible = false;
if (!show) return null;
audio_settings_popover = new AudioSettingsPopover();
audio_settings_button.popover = audio_settings_popover;
audio_settings_popover.microphone_selected.connect(() => { audio_settings_button.popdown(); });
audio_settings_popover.speaker_selected.connect(() => { audio_settings_button.popdown(); });
return audio_settings_popover;
}
public void show_audio_device_error() {
audio_settings_button.set_icon_name("dialog-warning-symbolic");
Util.force_error_color(audio_settings_button);
}
public VideoSettingsPopover? show_video_device_choices(bool show) {
video_settings_button.visible = show;
if (video_settings_popover != null) video_settings_popover.visible = false;
if (!show) return null;
video_settings_popover = new VideoSettingsPopover();
video_settings_button.popover = video_settings_popover;
video_settings_popover.camera_selected.connect(() => { video_settings_button.popdown(); });
return video_settings_popover;
}
public void show_video_device_error() {
video_settings_button.set_icon_name("dialog-warning-symbolic");
Util.force_error_color(video_settings_button);
}
public void on_audio_enabled_changed() {
if (audio_enabled) {
audio_image.icon_name = "dino-microphone-symbolic";
audio_button.add_css_class("white-button");
audio_button.remove_css_class("transparent-white-button");
} else {
audio_image.icon_name = "dino-microphone-off-symbolic";
audio_button.remove_css_class("white-button");
audio_button.add_css_class("transparent-white-button");
}
}
public void on_video_enabled_changed() {
if (video_enabled) {
video_image.icon_name = "dino-video-symbolic";
video_button.add_css_class("white-button");
video_button.remove_css_class("transparent-white-button");
} else {
video_image.icon_name = "dino-video-off-symbolic";
video_button.remove_css_class("white-button");
video_button.add_css_class("transparent-white-button");
}
}
public void show_counterpart_ended(string text) {
stack.set_visible_child_name("label");
label.label = text;
}
public bool is_menu_active() {
return (video_settings_button.popover != null && video_settings_button.popover.visible) ||
(audio_settings_button.popover != null && audio_settings_button.popover.visible);
}
}
|