diff --git a/bindings/matrix-sdk-ffi/src/room.rs b/bindings/matrix-sdk-ffi/src/room.rs index 30787048d88..5fb3abad596 100644 --- a/bindings/matrix-sdk-ffi/src/room.rs +++ b/bindings/matrix-sdk-ffi/src/room.rs @@ -818,6 +818,30 @@ impl Room { })) } + pub fn send_voice_message( + self: Arc, + url: String, + audio_info: AudioInfo, + waveform: Vec, + progress_watcher: Option>, + ) -> Arc { + SendAttachmentJoinHandle::new(RUNTIME.spawn(async move { + let mime_str = + audio_info.mimetype.as_ref().ok_or(RoomError::InvalidAttachmentMimeType)?; + let mime_type = + mime_str.parse::().map_err(|_| RoomError::InvalidAttachmentMimeType)?; + + let base_audio_info: BaseAudioInfo = BaseAudioInfo::try_from(&audio_info) + .map_err(|_| RoomError::InvalidAttachmentData)?; + + let attachment_info = + AttachmentInfo::Voice { audio_info: base_audio_info, waveform: Some(waveform) }; + let attachment_config = AttachmentConfig::new().info(attachment_info); + + self.send_attachment(url, mime_type, attachment_config, progress_watcher).await + })) + } + pub fn send_file( self: Arc, url: String, diff --git a/crates/matrix-sdk/Cargo.toml b/crates/matrix-sdk/Cargo.toml index 72d9421206c..58aff2835d1 100644 --- a/crates/matrix-sdk/Cargo.toml +++ b/crates/matrix-sdk/Cargo.toml @@ -88,7 +88,7 @@ matrix-sdk-sqlite = { version = "0.1.0", path = "../matrix-sdk-sqlite", default- mime = "0.3.16" mime2ext = "0.1.52" rand = { version = "0.8.5", optional = true } -ruma = { workspace = true, features = ["rand", "unstable-msc2448", "unstable-msc2965", "unstable-msc3930"] } +ruma = { workspace = true, features = ["rand", "unstable-msc2448", "unstable-msc2965", "unstable-msc3930", "unstable-msc3245-v1-compat"] } serde = { workspace = true } serde_html_form = { workspace = true } serde_json = { workspace = true } diff --git a/crates/matrix-sdk/src/attachment.rs b/crates/matrix-sdk/src/attachment.rs index 0dc1addc639..9a3b1b59b5d 100644 --- a/crates/matrix-sdk/src/attachment.rs +++ b/crates/matrix-sdk/src/attachment.rs @@ -87,6 +87,13 @@ pub enum AttachmentInfo { Audio(BaseAudioInfo), /// The metadata of a file. File(BaseFileInfo), + /// The metadata of a voice message + Voice { + /// The audio info + audio_info: BaseAudioInfo, + /// The waveform of the voice message + waveform: Option>, + }, } impl From for ImageInfo { @@ -125,6 +132,10 @@ impl From for AudioInfo { duration: info.duration, size: info.size, }), + AttachmentInfo::Voice { audio_info, .. } => assign!(AudioInfo::new(), { + duration: audio_info.duration, + size: audio_info.size, + }), _ => AudioInfo::new(), } } diff --git a/crates/matrix-sdk/src/encryption/mod.rs b/crates/matrix-sdk/src/encryption/mod.rs index db763adb884..2802ba82362 100644 --- a/crates/matrix-sdk/src/encryption/mod.rs +++ b/crates/matrix-sdk/src/encryption/mod.rs @@ -45,8 +45,8 @@ use ruma::{ assign, events::room::{ message::{ - AudioInfo, AudioMessageEventContent, FileInfo, FileMessageEventContent, - ImageMessageEventContent, MessageType, VideoInfo, VideoMessageEventContent, + AudioMessageEventContent, FileInfo, FileMessageEventContent, ImageMessageEventContent, + MessageType, VideoInfo, VideoMessageEventContent, }, ImageInfo, MediaSource, ThumbnailInfo, }, @@ -202,13 +202,13 @@ impl Client { MessageType::Image(content) } mime::AUDIO => { - let info = assign!(info.map(AudioInfo::from).unwrap_or_default(), { - mimetype: Some(content_type.as_ref().to_owned()), - }); - let content = assign!(AudioMessageEventContent::encrypted(body.to_owned(), file), { - info: Some(Box::new(info)) - }); - MessageType::Audio(content) + let audio_message_event_content = + AudioMessageEventContent::encrypted(body.to_owned(), file); + MessageType::Audio(crate::media::update_audio_message_event( + audio_message_event_content, + content_type, + info, + )) } mime::VIDEO => { let info = assign!(info.map(VideoInfo::from).unwrap_or_default(), { diff --git a/crates/matrix-sdk/src/media.rs b/crates/matrix-sdk/src/media.rs index 0aa992627a8..9e04f8c938e 100644 --- a/crates/matrix-sdk/src/media.rs +++ b/crates/matrix-sdk/src/media.rs @@ -32,8 +32,9 @@ use ruma::{ assign, events::room::{ message::{ - self, AudioInfo, FileInfo, FileMessageEventContent, ImageMessageEventContent, - MessageType, VideoInfo, VideoMessageEventContent, + self, AudioInfo, AudioMessageEventContent, FileInfo, FileMessageEventContent, + ImageMessageEventContent, MessageType, UnstableAudioDetailsContentBlock, + UnstableVoiceContentBlock, VideoInfo, VideoMessageEventContent, }, ImageInfo, MediaSource, ThumbnailInfo, }, @@ -438,13 +439,13 @@ impl Media { ) } mime::AUDIO => { - let info = assign!(info.map(AudioInfo::from).unwrap_or_default(), { - mimetype: Some(content_type.as_ref().to_owned()), - }); - MessageType::Audio( - message::AudioMessageEventContent::plain(body.to_owned(), url) - .info(Box::new(info)), - ) + let audio_message_event_content = + message::AudioMessageEventContent::plain(body.to_owned(), url); + MessageType::Audio(update_audio_message_event( + audio_message_event_content, + content_type, + info, + )) } mime::VIDEO => { let info = assign!(info.map(VideoInfo::from).unwrap_or_default(), { @@ -495,3 +496,21 @@ impl Media { } } } + +pub(crate) fn update_audio_message_event( + mut audio_message_event_content: AudioMessageEventContent, + content_type: &Mime, + info: Option, +) -> AudioMessageEventContent { + if let Some(AttachmentInfo::Voice { audio_info, waveform: Some(waveform_vec) }) = &info { + if let Some(duration) = audio_info.duration { + let waveform = waveform_vec.iter().map(|v| (*v).into()).collect(); + audio_message_event_content.audio = + Some(UnstableAudioDetailsContentBlock::new(duration, waveform)); + } + audio_message_event_content.voice = Some(UnstableVoiceContentBlock::new()); + } + + let audio_info = assign!(info.map(AudioInfo::from).unwrap_or_default(), {mimetype: Some(content_type.as_ref().to_owned()), }); + audio_message_event_content.info(Box::new(audio_info)) +}