auto play voice recording message

This commit is contained in:
Gaelle Braud 2025-07-10 12:26:05 +02:00
parent 4c08c28bd5
commit e8feb1c0dc
12 changed files with 63 additions and 7 deletions

View file

@ -65,6 +65,10 @@ QString EventLogCore::getEventLogId() {
QSharedPointer<ChatMessageCore> EventLogCore::getChatMessageCore() { QSharedPointer<ChatMessageCore> EventLogCore::getChatMessageCore() {
return mChatMessageCore; return mChatMessageCore;
} }
ChatMessageGui *EventLogCore::getChatMessageGui() {
return mChatMessageCore ? new ChatMessageGui(mChatMessageCore) : nullptr;
}
QSharedPointer<CallHistoryCore> EventLogCore::getCallHistoryCore() { QSharedPointer<CallHistoryCore> EventLogCore::getCallHistoryCore() {
return mCallHistoryCore; return mCallHistoryCore;
} }

View file

@ -35,12 +35,13 @@
#include <linphone++/linphone.hh> #include <linphone++/linphone.hh>
class ChatMessageCore; class ChatMessageCore;
class ChatMessageGui;
class EventLogCore : public QObject, public AbstractObject { class EventLogCore : public QObject, public AbstractObject {
Q_OBJECT Q_OBJECT
Q_PROPERTY(LinphoneEnums::EventLogType type MEMBER mEventLogType CONSTANT) Q_PROPERTY(LinphoneEnums::EventLogType type MEMBER mEventLogType CONSTANT)
Q_PROPERTY(ChatMessageCore *chatMessage READ getChatMessageCorePointer CONSTANT) Q_PROPERTY(ChatMessageGui *chatMessageGui READ getChatMessageGui CONSTANT)
// Q_PROPERTY(NotifyCore *notification MEMBER mNotifyCore CONSTANT) // Q_PROPERTY(NotifyCore *notification MEMBER mNotifyCore CONSTANT)
Q_PROPERTY(CallHistoryCore *callLog READ getCallHistoryCorePointer CONSTANT) Q_PROPERTY(CallHistoryCore *callLog READ getCallHistoryCorePointer CONSTANT)
Q_PROPERTY(bool important MEMBER mImportant CONSTANT) Q_PROPERTY(bool important MEMBER mImportant CONSTANT)
@ -55,6 +56,7 @@ public:
void setSelf(QSharedPointer<EventLogCore> me); void setSelf(QSharedPointer<EventLogCore> me);
QString getEventLogId(); QString getEventLogId();
QSharedPointer<ChatMessageCore> getChatMessageCore(); QSharedPointer<ChatMessageCore> getChatMessageCore();
ChatMessageGui *getChatMessageGui();
QSharedPointer<CallHistoryCore> getCallHistoryCore(); QSharedPointer<CallHistoryCore> getCallHistoryCore();
bool isHandled() const { bool isHandled() const {
return mHandled; return mHandled;

View file

@ -105,6 +105,9 @@ void SoundPlayerCore::buildInternalPlayer(QSharedPointer<SoundPlayerCore> me) {
mSoundPlayerModelConnection->makeConnectToCore(&SoundPlayerCore::lPlay, [this]() { mSoundPlayerModelConnection->makeConnectToCore(&SoundPlayerCore::lPlay, [this]() {
mSoundPlayerModelConnection->invokeToModel([this] { mSoundPlayerModel->play(mSource); }); mSoundPlayerModelConnection->invokeToModel([this] { mSoundPlayerModel->play(mSource); });
}); });
mSoundPlayerModelConnection->makeConnectToCore(&SoundPlayerCore::lRestart, [this]() {
mSoundPlayerModelConnection->invokeToModel([this] { mSoundPlayerModel->play(mSource, true); });
});
mSoundPlayerModelConnection->makeConnectToCore(&SoundPlayerCore::lSeek, [this](int offset) { mSoundPlayerModelConnection->makeConnectToCore(&SoundPlayerCore::lSeek, [this](int offset) {
mSoundPlayerModelConnection->invokeToModel([this, offset] { mSoundPlayerModel->seek(mSource, offset); }); mSoundPlayerModelConnection->invokeToModel([this, offset] { mSoundPlayerModel->seek(mSource, offset); });
}); });
@ -150,6 +153,7 @@ void SoundPlayerCore::handleEof() {
if (mForceClose) { if (mForceClose) {
mForceClose = false; mForceClose = false;
lStop(); lStop();
emit eofReached();
} }
} }

View file

@ -71,6 +71,7 @@ signals:
bool lOpen(); bool lOpen();
void lPause(); void lPause();
bool lPlay(); bool lPlay();
bool lRestart();
void lStop(bool force = false); void lStop(bool force = false);
void lSeek(int offset); void lSeek(int offset);
void lRefreshPosition(); void lRefreshPosition();
@ -79,6 +80,7 @@ signals:
void playing(); void playing();
void stopped(); void stopped();
void errorChanged(QString error); void errorChanged(QString error);
void eofReached();
void sourceChanged(const QString &source); void sourceChanged(const QString &source);
void playbackStateChanged(LinphoneEnums::PlaybackState playbackState); void playbackStateChanged(LinphoneEnums::PlaybackState playbackState);

View file

@ -30,6 +30,7 @@ SoundPlayerGui::SoundPlayerGui(QObject *parent) : QObject(parent) {
if (mCore) connect(mCore.get(), &SoundPlayerCore::stopped, this, &SoundPlayerGui::stopped); if (mCore) connect(mCore.get(), &SoundPlayerCore::stopped, this, &SoundPlayerGui::stopped);
if (mCore) connect(mCore.get(), &SoundPlayerCore::positionChanged, this, &SoundPlayerGui::positionChanged); if (mCore) connect(mCore.get(), &SoundPlayerCore::positionChanged, this, &SoundPlayerGui::positionChanged);
if (mCore) connect(mCore.get(), &SoundPlayerCore::errorChanged, this, &SoundPlayerGui::errorChanged); if (mCore) connect(mCore.get(), &SoundPlayerCore::errorChanged, this, &SoundPlayerGui::errorChanged);
if (mCore) connect(mCore.get(), &SoundPlayerCore::eofReached, this, &SoundPlayerGui::eofReached);
} }
SoundPlayerGui::SoundPlayerGui(QSharedPointer<SoundPlayerCore> core) { SoundPlayerGui::SoundPlayerGui(QSharedPointer<SoundPlayerCore> core) {
App::getInstance()->mEngine->setObjectOwnership(this, QQmlEngine::JavaScriptOwnership); App::getInstance()->mEngine->setObjectOwnership(this, QQmlEngine::JavaScriptOwnership);

View file

@ -45,6 +45,7 @@ signals:
void stopped(); void stopped();
void positionChanged(); void positionChanged();
void errorChanged(QString error); void errorChanged(QString error);
void eofReached();
private: private:
DECLARE_ABSTRACT_OBJECT DECLARE_ABSTRACT_OBJECT

View file

@ -78,8 +78,9 @@ bool SoundPlayerModel::open(QString source) {
// return false; // return false;
} }
bool SoundPlayerModel::play(QString source) { bool SoundPlayerModel::play(QString source, bool fromStart) {
if (source == "") return false; if (source == "") return false;
if (fromStart) stop();
if (!open(source)) { if (!open(source)) {
qWarning() << QStringLiteral("Unable to open: `%1`").arg(source); qWarning() << QStringLiteral("Unable to open: `%1`").arg(source);
//: Unable to open: `%1` //: Unable to open: `%1`

View file

@ -44,7 +44,7 @@ public:
bool open(QString source); bool open(QString source);
void pause(); void pause();
bool play(QString source); bool play(QString source, bool fromStart = false);
void stop(bool force = false); void stop(bool force = false);
void seek(QString source, int offset); void seek(QString source, int offset);

View file

@ -10,6 +10,7 @@ import UtilsCpp
Item { Item {
id: mainItem id: mainItem
property ChatMessageContentGui chatMessageContentGui property ChatMessageContentGui chatMessageContentGui
// used for creating a voice recording message
property var chatMessageObj property var chatMessageObj
property ChatMessageGui chatMessage: chatMessageObj && chatMessageObj.value || null property ChatMessageGui chatMessage: chatMessageObj && chatMessageObj.value || null
property bool isPlaying : soudPlayerLoader.item && soudPlayerLoader.item.core.playbackState === LinphoneEnums.PlaybackState.PlayingState property bool isPlaying : soudPlayerLoader.item && soudPlayerLoader.item.core.playbackState === LinphoneEnums.PlaybackState.PlayingState
@ -19,6 +20,13 @@ Item {
signal voiceRecordingMessageCreationRequested(RecorderGui recorderGui) signal voiceRecordingMessageCreationRequested(RecorderGui recorderGui)
signal stopRecording() signal stopRecording()
signal endOfFileReached()
// auto play if follows a voice recording
function requestPlaying() {
if(soudPlayerLoader.item) {
soudPlayerLoader.item.play(true)
}
}
function createVoiceMessageInChat(chat) { function createVoiceMessageInChat(chat) {
if (recorderLoader.item) { if (recorderLoader.item) {
@ -44,9 +52,11 @@ Item {
id: soundPlayerGui id: soundPlayerGui
source: mainItem.chatMessageContentGui && mainItem.chatMessageContentGui.core.filePath source: mainItem.chatMessageContentGui && mainItem.chatMessageContentGui.core.filePath
function play(){ function play(restartIfPlaying){
if(mainItem.isPlaying){// Pause the play if(mainItem.isPlaying && (restartIfPlaying === undefined || !restartIfPlaying)){// Pause the play
soundPlayerGui.core.lPause() soundPlayerGui.core.lPause()
} else if (restartIfPlaying) { //Play from scratch
soundPlayerGui.core.lRestart()
} else {// Play the audio } else {// Play the audio
soundPlayerGui.core.lPlay() soundPlayerGui.core.lPlay()
} }
@ -67,6 +77,9 @@ Item {
//: Error //: Error
UtilsCpp.showInformationPopup(qsTr("information_popup_error_title"), error, false) UtilsCpp.showInformationPopup(qsTr("information_popup_error_title"), error, false)
} }
onEofReached: {
mainItem.endOfFileReached()
}
} }
} }

View file

@ -37,6 +37,9 @@ Control.Control {
signal showImdnStatusForMessageRequested() signal showImdnStatusForMessageRequested()
signal replyToMessageRequested() signal replyToMessageRequested()
signal forwardMessageRequested() signal forwardMessageRequested()
signal endOfVoiceRecordingReached()
signal requestAutoPlayVoiceRecording()
onRequestAutoPlayVoiceRecording: chatBubbleContent.requestAutoPlayVoiceRecording()
Timer { Timer {
id: hightlightTimer id: hightlightTimer
@ -254,6 +257,7 @@ Control.Control {
onMouseEvent: (event) => { onMouseEvent: (event) => {
mainItem.handleDefaultMouseEvent(event) mainItem.handleDefaultMouseEvent(event)
} }
onEndOfVoiceRecordingReached: mainItem.endOfVoiceRecordingReached()
} }
RowLayout { RowLayout {
Layout.preferredHeight: childrenRect.height Layout.preferredHeight: childrenRect.height

View file

@ -17,6 +17,8 @@ ColumnLayout {
signal lastSelectedTextChanged(string selectedText) signal lastSelectedTextChanged(string selectedText)
// signal conferenceIcsCopied() // signal conferenceIcsCopied()
signal mouseEvent(MouseEvent event) signal mouseEvent(MouseEvent event)
signal endOfVoiceRecordingReached()
signal requestAutoPlayVoiceRecording()
property string selectedText property string selectedText
property color textColor property color textColor
@ -36,11 +38,19 @@ ColumnLayout {
chatMessageGui: mainItem.chatMessageGui chatMessageGui: mainItem.chatMessageGui
} }
delegate: ChatAudioContent { delegate: ChatAudioContent {
id: audioContent
// Layout.fillWidth: true // Layout.fillWidth: true
width: Math.round(269 * DefaultStyle.dp) width: Math.round(269 * DefaultStyle.dp)
height: Math.round(48 * DefaultStyle.dp) height: Math.round(48 * DefaultStyle.dp)
Layout.preferredHeight: height Layout.preferredHeight: height
chatMessageContentGui: modelData chatMessageContentGui: modelData
onEndOfFileReached: mainItem.endOfVoiceRecordingReached()
Connections {
target: mainItem
function onRequestAutoPlayVoiceRecording() {
audioContent.requestPlaying()
}
}
// width: conferenceList.width // width: conferenceList.width
// onMouseEvent: (event) => mainItem.mouseEvent(event) // onMouseEvent: (event) => mainItem.mouseEvent(event)
} }

View file

@ -17,6 +17,7 @@ ListView {
signal replyToMessageRequested(ChatMessageGui chatMessage) signal replyToMessageRequested(ChatMessageGui chatMessage)
signal forwardMessageRequested(ChatMessageGui chatMessage) signal forwardMessageRequested(ChatMessageGui chatMessage)
signal requestHighlight(int indexToHighlight) signal requestHighlight(int indexToHighlight)
signal requestAutoPlayVoiceRecording(int indexToPlay)
property string filterText property string filterText
onFilterTextChanged: { onFilterTextChanged: {
@ -174,6 +175,11 @@ ListView {
} }
width: mainItem.width width: mainItem.width
property var previousIndex: index - 1 property var previousIndex: index - 1
property ChatMessageGui nextChatMessage: index >= (mainItem.count - 1)
? null
: eventLogProxy.getEventAtIndex(index+1)
? eventLogProxy.getEventAtIndex(index+1).core.chatMessageGui
: null
property var previousFromAddress: eventLogProxy.getEventAtIndex(index-1)?.core.chatMessage?.fromAddress property var previousFromAddress: eventLogProxy.getEventAtIndex(index-1)?.core.chatMessage?.fromAddress
backgroundColor: isRemoteMessage ? DefaultStyle.main2_100 : DefaultStyle.main1_100 backgroundColor: isRemoteMessage ? DefaultStyle.main2_100 : DefaultStyle.main1_100
isFirstMessage: !previousFromAddress || previousFromAddress !== modelData.core.fromAddress isFirstMessage: !previousFromAddress || previousFromAddress !== modelData.core.fromAddress
@ -186,6 +192,9 @@ ListView {
onShowImdnStatusForMessageRequested: mainItem.showImdnStatusForMessageRequested(modelData) onShowImdnStatusForMessageRequested: mainItem.showImdnStatusForMessageRequested(modelData)
onReplyToMessageRequested: mainItem.replyToMessageRequested(modelData) onReplyToMessageRequested: mainItem.replyToMessageRequested(modelData)
onForwardMessageRequested: mainItem.forwardMessageRequested(modelData) onForwardMessageRequested: mainItem.forwardMessageRequested(modelData)
onEndOfVoiceRecordingReached: {
if (nextChatMessage && nextChatMessage.core.isVoiceRecording) mainItem.requestAutoPlayVoiceRecording(index + 1)
}
Connections { Connections {
target: mainItem target: mainItem
function onRequestHighlight(indexToHighlight) { function onRequestHighlight(indexToHighlight) {
@ -193,6 +202,11 @@ ListView {
requestHighlight() requestHighlight()
} }
} }
function onRequestAutoPlayVoiceRecording(indexToPlay) {
if (indexToPlay === index) {
chatMessageDelegate.requestAutoPlayVoiceRecording()
}
}
} }
} }
} }