@@ -9,6 +9,7 @@ const adw = @import("adw");
9
9
const gtk = @import ("gtk" );
10
10
const gio = @import ("gio" );
11
11
const gobject = @import ("gobject" );
12
+ const glib = @import ("glib" );
12
13
13
14
const Allocator = std .mem .Allocator ;
14
15
const build_config = @import ("../../build_config.zig" );
@@ -1239,6 +1240,67 @@ pub fn showDesktopNotification(
1239
1240
c .g_application_send_notification (g_app , body .ptr , notification );
1240
1241
}
1241
1242
1243
+ /// Handle bell features.
1244
+ pub fn bell (self : * Surface ) void {
1245
+ if (self .app .config .@"bell-features" .system ) system : {
1246
+ // Handle "system" beep by calling the GTK "beep" API.
1247
+
1248
+ // FIXME: when surface is converted to zig-gobject
1249
+ const native = gtk .Widget .getNative (@ptrCast (@alignCast (self .overlay ))) orelse break :system ;
1250
+ const surface = native .getSurface () orelse break :system ;
1251
+ surface .beep ();
1252
+ }
1253
+ if (self .app .config .@"bell-features" .audio ) audio : {
1254
+ // Play a user-specified audio file.
1255
+
1256
+ const pathname , const optional = switch (self .app .config .@"bell-audio" .value orelse break :audio ) {
1257
+ .optional = > | path | .{ path , true },
1258
+ .required = > | path | .{ path , false },
1259
+ };
1260
+ std .debug .assert (std .fs .path .isAbsolute (pathname ));
1261
+ const media_file = gtk .MediaFile .newForFilename (pathname );
1262
+ const media_stream = media_file .as (gtk .MediaStream );
1263
+
1264
+ if (! optional ) {
1265
+ _ = gobject .Object .signals .notify .connect (
1266
+ media_stream ,
1267
+ ? * anyopaque ,
1268
+ gtkStreamError ,
1269
+ null ,
1270
+ .{ .detail = "error" },
1271
+ );
1272
+ }
1273
+ _ = gobject .Object .signals .notify .connect (
1274
+ media_stream ,
1275
+ ? * anyopaque ,
1276
+ gtkStreamEnded ,
1277
+ null ,
1278
+ .{ .detail = "ended" },
1279
+ );
1280
+
1281
+ media_stream .setVolume (1.0 );
1282
+ media_stream .play ();
1283
+ }
1284
+ }
1285
+
1286
+ /// Handle a stream that is in an error state.
1287
+ fn gtkStreamError (media_stream : * gtk.MediaStream , _ : * gobject.ParamSpec , _ : ? * anyopaque ) callconv (.C ) void {
1288
+ const media_file = gobject .ext .cast (gtk .MediaFile , media_stream ) orelse return ;
1289
+ const file = media_file .getFile () orelse return ;
1290
+ const path = file .getPath () orelse return ;
1291
+ defer glib .free (path );
1292
+
1293
+ const err = media_stream .getError ();
1294
+
1295
+ if (err ) | e |
1296
+ log .warn ("error playing bell from {s}: {s} {d} {s}" , .{ path , glib .quarkToString (e .f_domain ), e .f_code , e .f_message orelse "" });
1297
+ }
1298
+
1299
+ /// Stream is finished, release the memory.
1300
+ fn gtkStreamEnded (media_stream : * gtk.MediaStream , _ : * gobject.ParamSpec , _ : ? * anyopaque ) callconv (.C ) void {
1301
+ media_stream .unref ();
1302
+ }
1303
+
1242
1304
fn gtkRealize (area : * c.GtkGLArea , ud : ? * anyopaque ) callconv (.C ) void {
1243
1305
log .debug ("gl surface realized" , .{});
1244
1306
0 commit comments