Recording Vorbis files works & connected to UI
This commit is contained in:
parent
fd0d188030
commit
d38f56b9fe
17 changed files with 555 additions and 12 deletions
|
@ -16,7 +16,7 @@ CONFIG += sailfishapp sailfishapp_i18n
|
||||||
|
|
||||||
PKGCONFIG += nemonotifications-qt5 zlib
|
PKGCONFIG += nemonotifications-qt5 zlib
|
||||||
|
|
||||||
QT += core dbus sql
|
QT += core dbus sql multimedia
|
||||||
|
|
||||||
DEFINES += QT_STATICPLUGIN
|
DEFINES += QT_STATICPLUGIN
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright (C) 2020 Sebastian J. Wolf and other contributors
|
Copyright (C) 2020-21 Sebastian J. Wolf and other contributors
|
||||||
|
|
||||||
This file is part of Fernschreiber.
|
This file is part of Fernschreiber.
|
||||||
|
|
||||||
|
@ -18,13 +18,74 @@
|
||||||
*/
|
*/
|
||||||
import QtQuick 2.6
|
import QtQuick 2.6
|
||||||
import Sailfish.Silica 1.0
|
import Sailfish.Silica 1.0
|
||||||
|
import WerkWolf.Fernschreiber 1.0
|
||||||
import "../components"
|
import "../components"
|
||||||
import "../js/twemoji.js" as Emoji
|
import "../js/twemoji.js" as Emoji
|
||||||
|
import "../js/debug.js" as Debug
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: voiceNoteOverlayItem
|
id: voiceNoteOverlayItem
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
|
||||||
|
property int recordingState: fernschreiberUtils.getVoiceNoteRecordingState();
|
||||||
|
property int recordingDuration: 0;
|
||||||
|
|
||||||
|
function handleRecordingState() {
|
||||||
|
switch (recordingState) {
|
||||||
|
case FernschreiberUtilities.Unavailable:
|
||||||
|
recordingStateLabel.text = qsTr("Unavailable");
|
||||||
|
break;
|
||||||
|
case FernschreiberUtilities.Stopped:
|
||||||
|
recordingStateLabel.text = qsTr("Stopped");
|
||||||
|
break;
|
||||||
|
case FernschreiberUtilities.Starting:
|
||||||
|
recordingStateLabel.text = qsTr("Starting");
|
||||||
|
break;
|
||||||
|
case FernschreiberUtilities.Recording:
|
||||||
|
recordingStateLabel.text = qsTr("Recording");
|
||||||
|
break;
|
||||||
|
case FernschreiberUtilities.Stopping:
|
||||||
|
recordingStateLabel.text = qsTr("Stopping");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getTwoDigitString(numberToBeConverted) {
|
||||||
|
var numberString = "00";
|
||||||
|
if (numberToBeConverted > 0 && numberToBeConverted < 10) {
|
||||||
|
numberString = "0" + String(numberToBeConverted);
|
||||||
|
}
|
||||||
|
if (numberToBeConverted >= 10) {
|
||||||
|
numberString = String(numberToBeConverted);
|
||||||
|
}
|
||||||
|
return numberString;
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleRecordingDuration() {
|
||||||
|
var minutes = Math.floor(recordingDuration / 60);
|
||||||
|
var seconds = recordingDuration % 60;
|
||||||
|
recordingDurationLabel.text = getTwoDigitString(minutes) + ":" + getTwoDigitString(seconds);
|
||||||
|
}
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
handleRecordingState();
|
||||||
|
handleRecordingDuration();
|
||||||
|
}
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: fernschreiberUtils
|
||||||
|
onVoiceNoteDurationChanged: {
|
||||||
|
Debug.log("New duration received: " + duration);
|
||||||
|
recordingDuration = Math.round(duration / 1000);
|
||||||
|
handleRecordingDuration();
|
||||||
|
}
|
||||||
|
onVoiceNoteRecordingStateChanged: {
|
||||||
|
Debug.log("New state received: " + state);
|
||||||
|
recordingState = state;
|
||||||
|
handleRecordingState();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: stickerPickerOverlayBackground
|
id: stickerPickerOverlayBackground
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
@ -52,17 +113,85 @@ Item {
|
||||||
text: qsTr("Record a Voice Note")
|
text: qsTr("Record a Voice Note")
|
||||||
}
|
}
|
||||||
|
|
||||||
Image {
|
Label {
|
||||||
id: recorderImage
|
wrapMode: Text.Wrap
|
||||||
source: "image://theme/icon-l-recorder"
|
width: parent.width - ( 2 * Theme.horizontalPageMargin )
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
text: qsTr("Press the button to start recording")
|
||||||
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
anchors {
|
anchors {
|
||||||
horizontalCenter: parent.horizontalCenter
|
horizontalCenter: parent.horizontalCenter
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fillMode: Image.PreserveAspectFit
|
Item {
|
||||||
asynchronous: true
|
width: Theme.iconSizeExtraLarge
|
||||||
width: Theme.itemSizeLarge
|
height: Theme.iconSizeExtraLarge
|
||||||
height: Theme.itemSizeLarge
|
anchors {
|
||||||
|
horizontalCenter: parent.horizontalCenter
|
||||||
|
}
|
||||||
|
Rectangle {
|
||||||
|
color: Theme.primaryColor
|
||||||
|
opacity: Theme.opacityOverlay
|
||||||
|
width: Theme.iconSizeExtraLarge
|
||||||
|
height: Theme.iconSizeExtraLarge
|
||||||
|
anchors.centerIn: parent
|
||||||
|
radius: width / 2
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: recordButton
|
||||||
|
color: "red"
|
||||||
|
width: Theme.iconSizeExtraLarge * 0.6
|
||||||
|
height: Theme.iconSizeExtraLarge * 0.6
|
||||||
|
anchors.centerIn: parent
|
||||||
|
radius: width / 2
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
onClicked: {
|
||||||
|
recordButton.visible = false;
|
||||||
|
fernschreiberUtils.startRecordingVoiceNote();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: stopButton
|
||||||
|
visible: !recordButton.visible
|
||||||
|
color: Theme.overlayBackgroundColor
|
||||||
|
width: Theme.iconSizeExtraLarge * 0.4
|
||||||
|
height: Theme.iconSizeExtraLarge * 0.4
|
||||||
|
anchors.centerIn: parent
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
onClicked: {
|
||||||
|
recordButton.visible = true;
|
||||||
|
fernschreiberUtils.stopRecordingVoiceNote();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
id: recordingStateLabel
|
||||||
|
wrapMode: Text.Wrap
|
||||||
|
width: parent.width - ( 2 * Theme.horizontalPageMargin )
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
|
anchors {
|
||||||
|
horizontalCenter: parent.horizontalCenter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
id: recordingDurationLabel
|
||||||
|
wrapMode: Text.Wrap
|
||||||
|
width: parent.width - ( 2 * Theme.horizontalPageMargin )
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
font.pixelSize: Theme.fontSizeMedium
|
||||||
|
anchors {
|
||||||
|
horizontalCenter: parent.horizontalCenter
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1145,6 +1145,11 @@ Page {
|
||||||
width: parent.width
|
width: parent.width
|
||||||
height: active ? parent.height : 0
|
height: active ? parent.height : 0
|
||||||
source: "../components/VoiceNoteOverlay.qml"
|
source: "../components/VoiceNoteOverlay.qml"
|
||||||
|
onActiveChanged: {
|
||||||
|
if (!active) {
|
||||||
|
fernschreiberUtils.stopRecordingVoiceNote();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,57 @@
|
||||||
#include "fernschreiberutils.h"
|
/*
|
||||||
|
Copyright (C) 2020-21 Sebastian J. Wolf and other contributors
|
||||||
|
|
||||||
|
This file is part of Fernschreiber.
|
||||||
|
|
||||||
|
Fernschreiber is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
Fernschreiber 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with Fernschreiber. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "fernschreiberutils.h"
|
||||||
#include <QMap>
|
#include <QMap>
|
||||||
#include <QVariant>
|
#include <QVariant>
|
||||||
|
#include <QAudioEncoderSettings>
|
||||||
|
#include <QStandardPaths>
|
||||||
|
#include <QDir>
|
||||||
|
#include <QFile>
|
||||||
|
#include <QUrl>
|
||||||
|
|
||||||
|
#define DEBUG_MODULE FernschreiberUtils
|
||||||
|
#include "debuglog.h"
|
||||||
|
|
||||||
FernschreiberUtils::FernschreiberUtils(QObject *parent) : QObject(parent)
|
FernschreiberUtils::FernschreiberUtils(QObject *parent) : QObject(parent)
|
||||||
{
|
{
|
||||||
|
LOG("Initializing audio recorder...");
|
||||||
|
|
||||||
|
QString temporaryDirectoryPath = QStandardPaths::writableLocation(QStandardPaths::TempLocation) + + "/harbour-fernschreiber";
|
||||||
|
QDir temporaryDirectory(temporaryDirectoryPath);
|
||||||
|
if (!temporaryDirectory.exists()) {
|
||||||
|
temporaryDirectory.mkpath(temporaryDirectoryPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
QAudioEncoderSettings encoderSettings;
|
||||||
|
encoderSettings.setCodec("audio/vorbis");
|
||||||
|
encoderSettings.setChannelCount(1);
|
||||||
|
encoderSettings.setQuality(QMultimedia::LowQuality);
|
||||||
|
this->audioRecorder.setEncodingSettings(encoderSettings);
|
||||||
|
this->audioRecorder.setContainerFormat("ogg");
|
||||||
|
this->audioRecorder.setOutputLocation(QUrl::fromLocalFile(temporaryDirectoryPath + "/voicenote.ogg"));
|
||||||
|
|
||||||
|
QMediaRecorder::Status audioRecorderStatus = this->audioRecorder.status();
|
||||||
|
this->handleAudioRecorderStatusChanged(audioRecorderStatus);
|
||||||
|
|
||||||
|
connect(&audioRecorder, SIGNAL(durationChanged(qlonglong)), this, SIGNAL(voiceNoteDurationChanged(qlonglong)));
|
||||||
|
connect(&audioRecorder, SIGNAL(statusChanged(QMediaRecorder::Status)), this, SLOT(handleAudioRecorderStatusChanged(QMediaRecorder::Status)));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,3 +175,58 @@ QString FernschreiberUtils::getUserName(const QVariantMap &userInformation)
|
||||||
const QString lastName = userInformation.value("last_name").toString();
|
const QString lastName = userInformation.value("last_name").toString();
|
||||||
return QString(firstName + " " + lastName).trimmed();
|
return QString(firstName + " " + lastName).trimmed();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FernschreiberUtils::startRecordingVoiceNote()
|
||||||
|
{
|
||||||
|
LOG("Start recording voice note...");
|
||||||
|
QString voiceNotePath = this->voiceNotePath();
|
||||||
|
LOG("Using temporary file at " << voiceNotePath);
|
||||||
|
if (QFile::exists(voiceNotePath)) {
|
||||||
|
LOG("Removing old temporary file...");
|
||||||
|
QFile::remove(voiceNotePath);
|
||||||
|
}
|
||||||
|
this->audioRecorder.setVolume(1);
|
||||||
|
this->audioRecorder.record();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FernschreiberUtils::stopRecordingVoiceNote()
|
||||||
|
{
|
||||||
|
LOG("Stop recording voice note...");
|
||||||
|
this->audioRecorder.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString FernschreiberUtils::voiceNotePath()
|
||||||
|
{
|
||||||
|
return this->audioRecorder.outputLocation().toLocalFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
FernschreiberUtils::VoiceNoteRecordingState FernschreiberUtils::getVoiceNoteRecordingState()
|
||||||
|
{
|
||||||
|
return this->voiceNoteRecordingState;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FernschreiberUtils::handleAudioRecorderStatusChanged(QMediaRecorder::Status status)
|
||||||
|
{
|
||||||
|
LOG("Audio recorder status changed:" << status);
|
||||||
|
switch (status) {
|
||||||
|
case QMediaRecorder::UnavailableStatus:
|
||||||
|
case QMediaRecorder::UnloadedStatus:
|
||||||
|
case QMediaRecorder::LoadingStatus:
|
||||||
|
this->voiceNoteRecordingState = VoiceNoteRecordingState::Unavailable;
|
||||||
|
break;
|
||||||
|
case QMediaRecorder::LoadedStatus:
|
||||||
|
case QMediaRecorder::PausedStatus:
|
||||||
|
this->voiceNoteRecordingState = VoiceNoteRecordingState::Stopped;
|
||||||
|
break;
|
||||||
|
case QMediaRecorder::StartingStatus:
|
||||||
|
this->voiceNoteRecordingState = VoiceNoteRecordingState::Starting;
|
||||||
|
break;
|
||||||
|
case QMediaRecorder::FinalizingStatus:
|
||||||
|
this->voiceNoteRecordingState = VoiceNoteRecordingState::Stopping;
|
||||||
|
break;
|
||||||
|
case QMediaRecorder::RecordingStatus:
|
||||||
|
this->voiceNoteRecordingState = VoiceNoteRecordingState::Recording;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
emit voiceNoteRecordingStateChanged(this->voiceNoteRecordingState);
|
||||||
|
}
|
||||||
|
|
|
@ -1,7 +1,27 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2020-21 Sebastian J. Wolf and other contributors
|
||||||
|
|
||||||
|
This file is part of Fernschreiber.
|
||||||
|
|
||||||
|
Fernschreiber is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
Fernschreiber 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with Fernschreiber. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
#ifndef FERNSCHREIBERUTILS_H
|
#ifndef FERNSCHREIBERUTILS_H
|
||||||
#define FERNSCHREIBERUTILS_H
|
#define FERNSCHREIBERUTILS_H
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
#include <QAudioRecorder>
|
||||||
#include "tdlibwrapper.h"
|
#include "tdlibwrapper.h"
|
||||||
|
|
||||||
class FernschreiberUtils : public QObject
|
class FernschreiberUtils : public QObject
|
||||||
|
@ -10,12 +30,34 @@ class FernschreiberUtils : public QObject
|
||||||
public:
|
public:
|
||||||
explicit FernschreiberUtils(QObject *parent = nullptr);
|
explicit FernschreiberUtils(QObject *parent = nullptr);
|
||||||
|
|
||||||
|
enum VoiceNoteRecordingState {
|
||||||
|
Unavailable,
|
||||||
|
Stopped,
|
||||||
|
Starting,
|
||||||
|
Recording,
|
||||||
|
Stopping
|
||||||
|
};
|
||||||
|
Q_ENUM(VoiceNoteRecordingState)
|
||||||
|
|
||||||
static QString getMessageShortText(TDLibWrapper *tdLibWrapper, const QVariantMap &messageContent, const bool isChannel, const qlonglong currentUserId, const QVariantMap &messageSender);
|
static QString getMessageShortText(TDLibWrapper *tdLibWrapper, const QVariantMap &messageContent, const bool isChannel, const qlonglong currentUserId, const QVariantMap &messageSender);
|
||||||
static QString getUserName(const QVariantMap &userInformation);
|
static QString getUserName(const QVariantMap &userInformation);
|
||||||
|
|
||||||
signals:
|
Q_INVOKABLE void startRecordingVoiceNote();
|
||||||
|
Q_INVOKABLE void stopRecordingVoiceNote();
|
||||||
|
Q_INVOKABLE QString voiceNotePath();
|
||||||
|
Q_INVOKABLE VoiceNoteRecordingState getVoiceNoteRecordingState();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void voiceNoteDurationChanged(qlonglong duration);
|
||||||
|
void voiceNoteRecordingStateChanged(VoiceNoteRecordingState state);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void handleAudioRecorderStatusChanged(QMediaRecorder::Status status);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QAudioRecorder audioRecorder;
|
||||||
|
VoiceNoteRecordingState voiceNoteRecordingState;
|
||||||
|
|
||||||
public slots:
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // FERNSCHREIBERUTILS_H
|
#endif // FERNSCHREIBERUTILS_H
|
||||||
|
|
|
@ -82,6 +82,7 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
FernschreiberUtils *fernschreiberUtils = new FernschreiberUtils(view.data());
|
FernschreiberUtils *fernschreiberUtils = new FernschreiberUtils(view.data());
|
||||||
context->setContextProperty("fernschreiberUtils", fernschreiberUtils);
|
context->setContextProperty("fernschreiberUtils", fernschreiberUtils);
|
||||||
|
qmlRegisterUncreatableType<FernschreiberUtils>(uri, 1, 0, "FernschreiberUtilities", QString());
|
||||||
|
|
||||||
DBusAdaptor *dBusAdaptor = tdLibWrapper->getDBusAdaptor();
|
DBusAdaptor *dBusAdaptor = tdLibWrapper->getDBusAdaptor();
|
||||||
context->setContextProperty("dBusAdaptor", dBusAdaptor);
|
context->setContextProperty("dBusAdaptor", dBusAdaptor);
|
||||||
|
|
|
@ -1438,6 +1438,30 @@
|
||||||
<source>Record a Voice Note</source>
|
<source>Record a Voice Note</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Press the button to start recording</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Unavailable</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Stopped</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Starting</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Recording</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Stopping</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>WebPagePreview</name>
|
<name>WebPagePreview</name>
|
||||||
|
|
|
@ -1438,6 +1438,30 @@
|
||||||
<source>Record a Voice Note</source>
|
<source>Record a Voice Note</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Press the button to start recording</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Unavailable</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Stopped</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Starting</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Recording</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Stopping</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>WebPagePreview</name>
|
<name>WebPagePreview</name>
|
||||||
|
|
|
@ -1417,6 +1417,30 @@
|
||||||
<source>Record a Voice Note</source>
|
<source>Record a Voice Note</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Press the button to start recording</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Unavailable</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Stopped</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Starting</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Recording</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Stopping</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>WebPagePreview</name>
|
<name>WebPagePreview</name>
|
||||||
|
|
|
@ -1439,6 +1439,30 @@
|
||||||
<source>Record a Voice Note</source>
|
<source>Record a Voice Note</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Press the button to start recording</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Unavailable</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Stopped</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Starting</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Recording</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Stopping</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>WebPagePreview</name>
|
<name>WebPagePreview</name>
|
||||||
|
|
|
@ -1417,6 +1417,30 @@
|
||||||
<source>Record a Voice Note</source>
|
<source>Record a Voice Note</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Press the button to start recording</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Unavailable</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Stopped</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Starting</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Recording</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Stopping</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>WebPagePreview</name>
|
<name>WebPagePreview</name>
|
||||||
|
|
|
@ -1438,6 +1438,30 @@
|
||||||
<source>Record a Voice Note</source>
|
<source>Record a Voice Note</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Press the button to start recording</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Unavailable</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Stopped</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Starting</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Recording</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Stopping</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>WebPagePreview</name>
|
<name>WebPagePreview</name>
|
||||||
|
|
|
@ -1459,6 +1459,30 @@
|
||||||
<source>Record a Voice Note</source>
|
<source>Record a Voice Note</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Press the button to start recording</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Unavailable</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Stopped</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Starting</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Recording</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Stopping</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>WebPagePreview</name>
|
<name>WebPagePreview</name>
|
||||||
|
|
|
@ -1459,6 +1459,30 @@
|
||||||
<source>Record a Voice Note</source>
|
<source>Record a Voice Note</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Press the button to start recording</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Unavailable</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Stopped</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Starting</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Recording</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Stopping</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>WebPagePreview</name>
|
<name>WebPagePreview</name>
|
||||||
|
|
|
@ -1438,6 +1438,30 @@
|
||||||
<source>Record a Voice Note</source>
|
<source>Record a Voice Note</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Press the button to start recording</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Unavailable</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Stopped</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Starting</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Recording</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Stopping</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>WebPagePreview</name>
|
<name>WebPagePreview</name>
|
||||||
|
|
|
@ -1417,6 +1417,30 @@
|
||||||
<source>Record a Voice Note</source>
|
<source>Record a Voice Note</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Press the button to start recording</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Unavailable</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Stopped</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Starting</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Recording</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Stopping</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>WebPagePreview</name>
|
<name>WebPagePreview</name>
|
||||||
|
|
|
@ -1438,6 +1438,30 @@
|
||||||
<source>Record a Voice Note</source>
|
<source>Record a Voice Note</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Press the button to start recording</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Unavailable</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Stopped</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Starting</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Recording</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<source>Stopping</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>WebPagePreview</name>
|
<name>WebPagePreview</name>
|
||||||
|
|
Loading…
Reference in a new issue