diff --git a/ACKNOWLEDGMENTS.md b/ACKNOWLEDGMENTS.md new file mode 100644 index 0000000000000000000000000000000000000000..881daa96c6462d7b9f925fe25fc534176bd1f8e4 --- /dev/null +++ b/ACKNOWLEDGMENTS.md @@ -0,0 +1,4 @@ +# Acknowledgments + +For notifications, Briar Desktop uses a [sound file](https://freesound.org/people/yfjesse/sounds/235911/) +published on freesound under the [Creative Commons 0 License](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/notification/linux/LibnotifyNotificationProvider.kt b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/notification/linux/LibnotifyNotificationProvider.kt index cb5617ac2f1ee9e62e1c403f3937f05219aa6196..d35590a82622b7d1b0783de2bdedc398fc397878 100644 --- a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/notification/linux/LibnotifyNotificationProvider.kt +++ b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/notification/linux/LibnotifyNotificationProvider.kt @@ -22,23 +22,36 @@ import com.sun.jna.Native import com.sun.jna.Pointer import mu.KotlinLogging import org.briarproject.briar.desktop.notification.NotificationProvider +import org.briarproject.briar.desktop.utils.AudioUtils.loadAudioFromResource +import org.briarproject.briar.desktop.utils.AudioUtils.play import org.briarproject.briar.desktop.utils.InternationalizationUtils.i18n import org.briarproject.briar.desktop.utils.InternationalizationUtils.i18nP import org.briarproject.briar.desktop.utils.KLoggerUtils.e import org.briarproject.briar.desktop.utils.KLoggerUtils.i +import javax.sound.sampled.Clip object LibnotifyNotificationProvider : NotificationProvider { private val LOG = KotlinLogging.logger {} - private var isAvailable: Boolean = false + private var libNotifyAvailable: Boolean = false + private var soundAvailable: Boolean = false private lateinit var libNotify: LibNotify + private lateinit var sound: Clip + override val available: Boolean - get() = isAvailable + get() = libNotifyAvailable override fun init() { + try { + sound = loadAudioFromResource("/audio/notification.wav") ?: throw Exception() // NON-NLS + soundAvailable = true + } catch (ex: Exception) { + LOG.e(ex) { "Error while loading notification sound" } + } + try { libNotify = Native.load("libnotify.so.4", LibNotify::class.java) // NON-NLS } catch (err: UnsatisfiedLinkError) { @@ -46,8 +59,8 @@ object LibnotifyNotificationProvider : NotificationProvider { return } - isAvailable = libNotify.notify_init(i18n("main.title")) - if (!isAvailable) { + libNotifyAvailable = libNotify.notify_init(i18n("main.title")) + if (!libNotifyAvailable) { LOG.e { "unable to initialize libnotify" } return } @@ -63,14 +76,22 @@ object LibnotifyNotificationProvider : NotificationProvider { } override fun uninit() { - if (!isAvailable) return - - libNotify.notify_uninit() - isAvailable = false + if (libNotifyAvailable) { + libNotify.notify_uninit() + libNotifyAvailable = false + } + if (soundAvailable) { + sound.close() + soundAvailable = false + } } override fun notifyPrivateMessages(num: Int) { - if (!isAvailable) return + if (!libNotifyAvailable) { + // play sound even if libnotify unavailable + if (soundAvailable) sound.play() + return + } /** * summary @@ -115,6 +136,8 @@ object LibnotifyNotificationProvider : NotificationProvider { // todo: error handling LOG.e { "error while sending notification via libnotify" } } + + sound.play() } /** diff --git a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/notification/linux/TestNativeNotifications.kt b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/notification/linux/TestNativeNotifications.kt index 3f145ae5ae4850442e1145cfe2877ecc2779639b..c04b5b00d169af7eead34ae0345219003898226f 100644 --- a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/notification/linux/TestNativeNotifications.kt +++ b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/notification/linux/TestNativeNotifications.kt @@ -23,6 +23,10 @@ fun main() { notifyPrivateMessages(9) + Thread.sleep(100) + + notifyPrivateMessages(10) + uninit() } } diff --git a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/utils/AudioUtils.kt b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/utils/AudioUtils.kt new file mode 100644 index 0000000000000000000000000000000000000000..8dac0004af6cae62abc8c84b719c7ac57ac0878d --- /dev/null +++ b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/utils/AudioUtils.kt @@ -0,0 +1,45 @@ +/* + * Briar Desktop + * Copyright (C) 2021-2022 The Briar Project + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package org.briarproject.briar.desktop.utils + +import org.briarproject.briar.desktop.utils.ResourceUtils.getResourceAsStream +import javax.sound.sampled.AudioSystem +import javax.sound.sampled.Clip + +object AudioUtils { + + fun loadAudioFromResource(name: String): Clip? { + val resourceStream = getResourceAsStream(name) ?: return null + val audioInputStream = AudioSystem.getAudioInputStream(resourceStream) + val sound = AudioSystem.getClip() + sound.open(audioInputStream) + return sound + } + + /** + * Play audio from the beginning. + * If it is currently played, it is stopped and restarted. + */ + fun Clip.play() = this.apply { + stop() + flush() + framePosition = 0 + start() + } +} diff --git a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/utils/ResourceUtils.kt b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/utils/ResourceUtils.kt new file mode 100644 index 0000000000000000000000000000000000000000..18fa0be455626313bdb1fa2dff1584df3fed918b --- /dev/null +++ b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/utils/ResourceUtils.kt @@ -0,0 +1,26 @@ +/* + * Briar Desktop + * Copyright (C) 2021-2022 The Briar Project + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package org.briarproject.briar.desktop.utils + +import java.io.InputStream + +object ResourceUtils { + + fun getResourceAsStream(name: String): InputStream? = this::class.java.getResourceAsStream(name) +} diff --git a/briar-desktop/src/main/resources/audio/notification.wav b/briar-desktop/src/main/resources/audio/notification.wav new file mode 100644 index 0000000000000000000000000000000000000000..571fecf098e1e2fb0a5204b7057d8552ffee2861 Binary files /dev/null and b/briar-desktop/src/main/resources/audio/notification.wav differ