File indexing completed on 2024-05-12 16:27:14
0001 /* 0002 SPDX-FileCopyrightText: 2023-2024 Laurent Montel <montel.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "createsoundmessagewidget.h" 0008 #include <KConfigGroup> 0009 #include <KLocalizedString> 0010 #include <KMessageWidget> 0011 #include <KSharedConfig> 0012 #include <QAudioDevice> 0013 #include <QAudioInput> 0014 #include <QComboBox> 0015 #include <QDir> 0016 #include <QHBoxLayout> 0017 #include <QLabel> 0018 #include <QMediaDevices> 0019 #include <QTemporaryFile> 0020 #include <QToolButton> 0021 0022 namespace 0023 { 0024 const char mySoundGroupName[] = "Message Sound"; 0025 } 0026 0027 CreateSoundMessageWidget::CreateSoundMessageWidget(QWidget *parent) 0028 : QWidget{parent} 0029 , mRecordButton(new QToolButton(this)) 0030 , mPauseButton(new QToolButton(this)) 0031 , mStopButton(new QToolButton(this)) 0032 , mLabelDuration(new QLabel(this)) 0033 , mAudioRecorder(new QMediaRecorder(this)) 0034 , mDeviceComboBox(new QComboBox(this)) 0035 , mMessageWidget(new KMessageWidget(this)) 0036 { 0037 mCaptureSession.setRecorder(mAudioRecorder); 0038 mCaptureSession.setAudioInput(new QAudioInput(this)); 0039 0040 auto mainLayout = new QVBoxLayout(this); 0041 mainLayout->setObjectName(QStringLiteral("mainLayout")); 0042 mainLayout->setContentsMargins({}); 0043 0044 mMessageWidget->setObjectName(QStringLiteral("mMessageWidget")); 0045 mainLayout->addWidget(mMessageWidget); 0046 mMessageWidget->setVisible(false); 0047 mMessageWidget->setCloseButtonVisible(false); 0048 mMessageWidget->setMessageType(KMessageWidget::Information); 0049 mMessageWidget->setWordWrap(true); 0050 0051 mDeviceComboBox->setObjectName(QStringLiteral("mDeviceComboBox")); 0052 mainLayout->addWidget(mDeviceComboBox); 0053 0054 auto soundWidgetLayout = new QHBoxLayout; 0055 soundWidgetLayout->setObjectName(QStringLiteral("mainLayout")); 0056 mainLayout->addLayout(soundWidgetLayout); 0057 0058 mStopButton->setObjectName(QStringLiteral("mStopButton")); 0059 mStopButton->setIcon(QIcon::fromTheme(QStringLiteral("media-playback-stop"))); 0060 soundWidgetLayout->addWidget(mStopButton); 0061 connect(mStopButton, &QToolButton::clicked, this, &CreateSoundMessageWidget::stop); 0062 0063 mPauseButton->setObjectName(QStringLiteral("mPauseButton")); 0064 mPauseButton->setIcon(QIcon::fromTheme(QStringLiteral("media-playback-pause"))); 0065 soundWidgetLayout->addWidget(mPauseButton); 0066 connect(mPauseButton, &QToolButton::clicked, this, &CreateSoundMessageWidget::pause); 0067 0068 mRecordButton->setObjectName(QStringLiteral("mRecordButton")); 0069 mRecordButton->setIcon(QIcon::fromTheme(QStringLiteral("media-record"))); 0070 soundWidgetLayout->addWidget(mRecordButton); 0071 connect(mRecordButton, &QToolButton::clicked, this, &CreateSoundMessageWidget::record); 0072 0073 mLabelDuration->setObjectName(QStringLiteral("mLabelDuration")); 0074 mLabelDuration->setTextFormat(Qt::PlainText); 0075 soundWidgetLayout->addWidget(mLabelDuration); 0076 0077 connect(mAudioRecorder, &QMediaRecorder::durationChanged, this, &CreateSoundMessageWidget::updateRecordTime); 0078 connect(mAudioRecorder, &QMediaRecorder::recorderStateChanged, this, &CreateSoundMessageWidget::updateRecorderState); 0079 connect(mAudioRecorder, &QMediaRecorder::errorChanged, this, &CreateSoundMessageWidget::displayRecorderError); 0080 initializeInput(); 0081 updateRecorderState(mAudioRecorder->recorderState()); 0082 } 0083 0084 CreateSoundMessageWidget::~CreateSoundMessageWidget() 0085 { 0086 delete mTemporaryFile; 0087 } 0088 0089 void CreateSoundMessageWidget::loadSettings() 0090 { 0091 KConfigGroup group(KSharedConfig::openConfig(), QLatin1String(mySoundGroupName)); 0092 const QByteArray deviceIdentifier = group.readEntry("SoundDevice", QByteArray()); 0093 if (!deviceIdentifier.isEmpty()) { 0094 for (int i = 0; i < mDeviceComboBox->count(); ++i) { 0095 const QAudioDevice audioDevice = mDeviceComboBox->itemData(i).value<QAudioDevice>(); 0096 if (audioDevice.id() == deviceIdentifier) { 0097 mDeviceComboBox->setCurrentIndex(i); 0098 break; 0099 } 0100 } 0101 } 0102 } 0103 0104 void CreateSoundMessageWidget::saveSettings() 0105 { 0106 KConfigGroup group(KSharedConfig::openConfig(), QLatin1String(mySoundGroupName)); 0107 const auto device = mDeviceComboBox->itemData(mDeviceComboBox->currentIndex()).value<QAudioDevice>(); 0108 if (!device.isNull()) { 0109 const QByteArray deviceIdentifier = device.id(); 0110 group.writeEntry("SoundDevice", deviceIdentifier); 0111 } 0112 } 0113 0114 void CreateSoundMessageWidget::displayRecorderError() 0115 { 0116 if (mAudioRecorder->error() != QMediaRecorder::NoError) { 0117 mMessageWidget->setText(mAudioRecorder->errorString()); 0118 mMessageWidget->animatedShow(); 0119 } 0120 } 0121 0122 void CreateSoundMessageWidget::initializeInput() 0123 { 0124 mDeviceComboBox->addItem(i18n("Default"), QVariant(QString())); 0125 for (const auto &device : QMediaDevices::audioInputs()) { 0126 const auto name = device.description(); 0127 mDeviceComboBox->addItem(name, QVariant::fromValue(device)); 0128 } 0129 0130 mTemporaryFile = new QTemporaryFile(QDir::tempPath() + QLatin1String("/ruqola_XXXXXX")); // TODO fix extension 0131 mTemporaryFile->setAutoRemove(false); 0132 mTemporaryFile->open(); 0133 // QMediaFormat format; 0134 // format.setFileFormat(QMediaFormat::FileFormat::AVI); 0135 // mMediaRecorder->setMediaFormat(format); 0136 // Define url temporary file. 0137 mAudioRecorder->setOutputLocation(QUrl::fromLocalFile(mTemporaryFile->fileName())); 0138 // qDebug() << " store " << mTemporaryFile->fileName(); 0139 } 0140 0141 void CreateSoundMessageWidget::updateRecordTime(qint64 duration) 0142 { 0143 const QString str = i18n("Recorded %1 sec", duration / 1000); 0144 mLabelDuration->setText(str); 0145 } 0146 0147 QUrl CreateSoundMessageWidget::temporaryFilePath() const 0148 { 0149 // qDebug() << "output location" << mMediaRecorder->outputLocation() << " dd " << mMediaRecorder->actualLocation(); 0150 return mAudioRecorder->actualLocation(); 0151 } 0152 0153 void CreateSoundMessageWidget::stop() 0154 { 0155 mAudioRecorder->stop(); 0156 Q_EMIT recordDone(); 0157 } 0158 0159 void CreateSoundMessageWidget::record() 0160 { 0161 mCaptureSession.audioInput()->setDevice(mDeviceComboBox->itemData(mDeviceComboBox->currentIndex()).value<QAudioDevice>()); 0162 mAudioRecorder->record(); 0163 } 0164 0165 void CreateSoundMessageWidget::pause() 0166 { 0167 mAudioRecorder->pause(); 0168 } 0169 0170 void CreateSoundMessageWidget::updateRecorderState(QMediaRecorder::RecorderState state) 0171 { 0172 switch (state) { 0173 case QMediaRecorder::StoppedState: 0174 mRecordButton->setEnabled(true); 0175 mPauseButton->setEnabled(true); 0176 mStopButton->setEnabled(false); 0177 break; 0178 case QMediaRecorder::PausedState: 0179 mRecordButton->setEnabled(true); 0180 mPauseButton->setEnabled(false); 0181 mStopButton->setEnabled(true); 0182 break; 0183 case QMediaRecorder::RecordingState: 0184 mRecordButton->setEnabled(false); 0185 mPauseButton->setEnabled(true); 0186 mStopButton->setEnabled(true); 0187 break; 0188 } 0189 } 0190 0191 #include "moc_createsoundmessagewidget.cpp"