Browse Source

audio-history-viewer: Add ability to listen to audio

merge-requests/1327/merge
Marco Melorio 4 years ago committed by Kévin Commaille
parent
commit
93015294ed
  1. 3
      data/resources/ui/content-audio-history-viewer-row.ui
  2. 92
      src/session/content/room_details/history_viewer/audio_row.rs

3
data/resources/ui/content-audio-history-viewer-row.ui

@ -5,7 +5,8 @@
<object class="GtkBox">
<property name="spacing">12</property>
<child>
<object class="GtkButton">
<object class="GtkButton" id="play_button">
<property name="action-name">audio-row.toggle-play</property>
<property name="icon-name">media-playback-start-symbolic</property>
<property name="valign">center</property>
<style>

92
src/session/content/room_details/history_viewer/audio_row.rs

@ -1,9 +1,17 @@
use adw::{prelude::*, subclass::prelude::*};
use gettextrs::gettext;
use gtk::{glib, CompositeTemplate};
use matrix_sdk::ruma::events::{room::message::MessageType, AnyMessageLikeEventContent};
use crate::session::content::room_details::history_viewer::HistoryViewerEvent;
use glib::clone;
use gtk::{gio, glib, CompositeTemplate};
use log::warn;
use matrix_sdk::ruma::events::{
room::message::{AudioMessageEventContent, MessageType},
AnyMessageLikeEventContent,
};
use crate::{
session::{content::room_details::history_viewer::HistoryViewerEvent, Session},
spawn, spawn_tokio,
};
mod imp {
use std::cell::RefCell;
@ -17,6 +25,9 @@ mod imp {
#[template(resource = "/org/gnome/Fractal/content-audio-history-viewer-row.ui")]
pub struct AudioRow {
pub event: RefCell<Option<HistoryViewerEvent>>,
pub media_file: RefCell<Option<gtk::MediaFile>>,
#[template_child]
pub play_button: TemplateChild<gtk::Button>,
#[template_child]
pub title_label: TemplateChild<gtk::Label>,
#[template_child]
@ -31,6 +42,10 @@ mod imp {
fn class_init(klass: &mut Self::Class) {
Self::bind_template(klass);
klass.install_action("audio-row.toggle-play", None, move |widget, _, _| {
widget.toggle_play();
});
}
fn instance_init(obj: &InitializingObject<Self>) {
@ -89,7 +104,7 @@ impl AudioRow {
if let MessageType::Audio(audio) = content.msgtype {
imp.title_label.set_label(&audio.body);
if let Some(duration) = audio.info.and_then(|i| i.duration) {
if let Some(duration) = audio.info.as_ref().and_then(|i| i.duration) {
let duration_secs = duration.as_secs();
let secs = duration_secs % 60;
let mins = (duration_secs % (60 * 60)) / 60;
@ -105,6 +120,11 @@ impl AudioRow {
} else {
imp.duration_label.set_label(&gettext("Unknown duration"));
}
let session = event.room().unwrap().session();
spawn!(clone!(@weak self as obj => async move {
obj.download_audio(audio, &session).await;
}));
}
}
}
@ -116,4 +136,66 @@ impl AudioRow {
pub fn event(&self) -> Option<HistoryViewerEvent> {
self.imp().event.borrow().clone()
}
async fn download_audio(&self, audio: AudioMessageEventContent, session: &Session) {
let client = session.client();
let handle = spawn_tokio!(async move { client.media().get_file(audio, true).await });
match handle.await.unwrap() {
Ok(Some(data)) => {
// The GStreamer backend doesn't work with input streams so
// we need to store the file.
// See: https://gitlab.gnome.org/GNOME/gtk/-/issues/4062
let (file, _) = gio::File::new_tmp(Option::<String>::None).unwrap();
file.replace_contents(
&data,
None,
false,
gio::FileCreateFlags::REPLACE_DESTINATION,
gio::Cancellable::NONE,
)
.unwrap();
self.prepare_audio(file);
}
Ok(None) => {
warn!("Could not retrieve invalid audio file");
}
Err(error) => {
warn!("Could not retrieve audio file: {error}");
}
}
}
fn prepare_audio(&self, file: gio::File) {
let media_file = gtk::MediaFile::for_file(&file);
media_file.connect_error_notify(clone!(@weak self as obj => move |media_file| {
if let Some(error) = media_file.error() {
warn!("Error reading audio file: {}", error);
}
}));
media_file.connect_ended_notify(clone!(@weak self as obj => move |media_file| {
if media_file.is_ended() {
obj.imp().play_button.set_icon_name("media-playback-start-symbolic");
}
}));
self.imp().media_file.replace(Some(media_file));
}
fn toggle_play(&self) {
let imp = self.imp();
if let Some(media_file) = self.imp().media_file.borrow().as_ref() {
if media_file.is_playing() {
media_file.pause();
imp.play_button
.set_icon_name("media-playback-start-symbolic");
} else {
media_file.play();
imp.play_button
.set_icon_name("media-playback-pause-symbolic");
}
}
}
}

Loading…
Cancel
Save