diff --git a/DroidStar.pro b/DroidStar.pro
index b35ced5..ea0ba14 100644
--- a/DroidStar.pro
+++ b/DroidStar.pro
@@ -1,7 +1,6 @@
QT += quick quickcontrols2 network multimedia
android:QT += androidextras
-linux:QT += serialport
-unix:QT += serialport
+unix:!ios:QT += serialport
CONFIG += c++11
LFLAGS +=
android:INCLUDEPATH += $$(HOME)/Android/android-build/include
@@ -15,7 +14,6 @@ win32:QMAKE_LFLAGS += -static
QMAKE_LFLAGS_WINDOWS += --enable-stdcall-fixup
RC_ICONS = images/droidstar.ico
ICON = images/droidstar.icns
-macx:QT += serialport
macx::INCLUDEPATH += /usr/local/include
macx:LIBS += -L/usr/local/lib -framework AVFoundation
macx:QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.14
@@ -24,6 +22,9 @@ ios:LIBS += -lvocoder -framework AVFoundation
ios:QMAKE_TARGET_BUNDLE_PREFIX = com.dudetronics
ios:QMAKE_BUNDLE = droidstar
ios:VERSION = 0.43.20
+ios:Q_ENABLE_BITCODE.name = ENABLE_BITCODE
+ios:Q_ENABLE_BITCODE.value = NO
+ios:QMAKE_MAC_XCODE_SETTINGS += Q_ENABLE_BITCODE
ios:QMAKE_ASSET_CATALOGS += Images.xcassets
ios:QMAKE_INFO_PLIST = Info.plist
VERSION_BUILD='$(shell cd $$PWD;git rev-parse --short HEAD)'
@@ -150,9 +151,10 @@ contains(ANDROID_TARGET_ARCH,arm64-v8a) {
LIBS += -L$$(HOME)/Android/local/lib64
ANDROID_PACKAGE_SOURCE_DIR = $$PWD/android
OTHER_FILES += android/src
+ #ANDROID_ABIS = arm64-v8a
}
-ANDROID_ABIS = armeabi-v7a arm64-v8a
+#ANDROID_ABIS = armeabi-v7a arm64-v8a
contains(DEFINES, USE_FLITE){
LIBS += -lflite_cmu_us_slt -lflite_cmu_us_kal16 -lflite_cmu_us_awb -lflite_cmu_us_rms -lflite_usenglish -lflite_cmulex -lflite -lasound
diff --git a/README.md b/README.md
index cf32d1a..dfb84b3 100644
--- a/README.md
+++ b/README.md
@@ -63,7 +63,7 @@ Port: UDP port of node, usually 4569.
Add DTMF commands like \*3node, \*1node, \*70, etc in the IAX DTMF box and hit send to send the DTMF string. Details on various commands can be found at the AllStar wiki and others.
# General building instructions
-This software is written primarily in C++ on Linux and requires Qt5 >= Qt5.15, and natually the devel packages to build. The imbe_vocoder library is also required. Java, QML (Javascript based), and C# code is also used where necessary. The preferred way to obtain Qt 5.15 is to use the Qt open source online installer from the Qt website. Run this installer as a user (not root) to keep the Qt installation separate from your system libs. Select the option as shown in this pic https://imgur.com/i0WuFCY which will install everything under ~/Qt.
+This software is written primarily in C++ on Linux and requires Qt5 >= Qt5.15 or Qt6 >= Qt6.3, and natually the devel packages to build. The imbe_vocoder library is also required. Java, QML (Javascript based), and C# code is also used where necessary. The preferred way to obtain Qt 5.15 is to use the Qt open source online installer from the Qt website. Run this installer as a user (not root) to keep the Qt installation separate from your system libs. Select the option as shown in this pic https://imgur.com/i0WuFCY which will install everything under ~/Qt.
The imbe_vocoder library is a prerequisite: https://github.com/nostar/imbe_vocoder
diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml
index c077f73..5ec4085 100644
--- a/android/AndroidManifest.xml
+++ b/android/AndroidManifest.xml
@@ -1,6 +1,6 @@
-
+
@@ -41,8 +41,6 @@
-
-
@@ -78,8 +76,5 @@
-
-
-
-
+
diff --git a/android/build.gradle b/android/build.gradle
index 3087d08..7f78543 100644
--- a/android/build.gradle
+++ b/android/build.gradle
@@ -5,7 +5,7 @@ buildscript {
}
dependencies {
- classpath 'com.android.tools.build:gradle:3.5.0'
+ classpath 'com.android.tools.build:gradle:4.1.0'
}
}
diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties
index 4b7e1f3..186b715 100644
--- a/android/gradle/wrapper/gradle-wrapper.properties
+++ b/android/gradle/wrapper/gradle-wrapper.properties
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-5.5.1-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-all.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
diff --git a/androidserialport.cpp b/androidserialport.cpp
index 8996938..6729c42 100644
--- a/androidserialport.cpp
+++ b/androidserialport.cpp
@@ -14,7 +14,7 @@
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
-
+#include
#include "androidserialport.h"
#ifdef Q_OS_ANDROID
@@ -41,7 +41,11 @@ QStringList AndroidSerialPort::discover_devices()
QStringList l;
l.clear();
qDebug() << "AndroidSerialPort::discover_devices()";
+#if QT_VERSION < QT_VERSION_CHECK(6, 3, 0)
QAndroidJniObject d = serialJavaObject.callObjectMethod("discover_devices", "(Landroid/content/Context;)[Ljava/lang/String;", QtAndroid::androidContext().object());
+#else
+ QAndroidJniObject d = serialJavaObject.callObjectMethod("discover_devices", "(Landroid/content/Context;)[Ljava/lang/String;", QNativeInterface::QAndroidApplication::context());
+#endif
jobjectArray devices = d.object();
int size = env->GetArrayLength(devices);
@@ -54,7 +58,11 @@ QStringList AndroidSerialPort::discover_devices()
int AndroidSerialPort::open(int p)
{
+#if QT_VERSION < QT_VERSION_CHECK(6, 3, 0)
qDebug() << serialJavaObject.callObjectMethod("setup_serial", "(Landroid/content/Context;)Ljava/lang/String;", QtAndroid::androidContext().object()).toString();
+#else
+ serialJavaObject.callObjectMethod("setup_serial", "(Landroid/content/Context;)Ljava/lang/String;", QNativeInterface::QAndroidApplication::context());
+#endif
return p;
}
diff --git a/androidserialport.h b/androidserialport.h
index 52368d5..7734434 100644
--- a/androidserialport.h
+++ b/androidserialport.h
@@ -20,7 +20,12 @@
#include
#ifdef Q_OS_ANDROID
+#if QT_VERSION < QT_VERSION_CHECK(6, 3, 0)
#include
+#else
+#include
+#include
+#endif
class AndroidSerialPort : public QObject
{
@@ -51,7 +56,13 @@ signals:
private:
explicit AndroidSerialPort(QObject * parent = nullptr);
static void java_data_received(JNIEnv *env, jobject t, jbyteArray data);
+#if QT_VERSION < QT_VERSION_CHECK(6, 3, 0)
QAndroidJniObject serialJavaObject;
+#else
+ QJniObject serialJavaObject;
+ typedef QJniObject QAndroidJniObject;
+ typedef QJniEnvironment QAndroidJniEnvironment;
+#endif
QByteArray m_received;
};
#endif
diff --git a/audioengine.cpp b/audioengine.cpp
index b35acbd..2f0caba 100644
--- a/audioengine.cpp
+++ b/audioengine.cpp
@@ -44,6 +44,7 @@ AudioEngine::~AudioEngine()
{
}
+#if QT_VERSION < QT_VERSION_CHECK(6, 3, 0)
QStringList AudioEngine::discover_audio_devices(uint8_t d)
{
QStringList list;
@@ -151,6 +152,112 @@ void AudioEngine::init()
fprintf(stderr, "Capture device: %s SR: %d resample factor: %f\n", info.deviceName().toStdString().c_str(), sr, m_srm);fflush(stderr);
}
}
+#else
+QStringList AudioEngine::discover_audio_devices(uint8_t d)
+{
+ QStringList list;
+ QList devices;
+
+ if(d){
+ devices = QMediaDevices::audioOutputs();
+ }
+ else{
+ devices = QMediaDevices::audioInputs();
+ }
+
+ for (QList::ConstIterator it = devices.constBegin(); it != devices.constEnd(); ++it ) {
+ //fprintf(stderr, "Playback device name = %s\n", (*it).deviceName().toStdString().c_str());fflush(stderr);
+ list.append((*it).description());
+ }
+
+ return list;
+}
+
+void AudioEngine::init()
+{
+ QAudioFormat format;
+ QAudioFormat tempformat;
+ format.setSampleRate(8000);
+ format.setChannelCount(1);
+ format.setSampleFormat(QAudioFormat::Int16);
+ //format.setSampleSize(16);
+ //format.setCodec("audio/pcm");
+ //format.setByteOrder(QAudioFormat::LittleEndian);
+ //format.setSampleType(QAudioFormat::SignedInt);
+
+ m_agc = true;
+
+ QList devices = QMediaDevices::audioOutputs();
+ if(devices.size() == 0){
+ fprintf(stderr, "No audio playback hardware found\n");fflush(stderr);
+ }
+ else{
+ QAudioDevice device(QMediaDevices::defaultAudioOutput());
+ for (QList::ConstIterator it = devices.constBegin(); it != devices.constEnd(); ++it ) {
+ if(MACHAK){
+ qDebug() << "Playback device name = " << (*it).description();
+ qDebug() << (*it).supportedSampleFormats();
+ qDebug() << (*it).preferredFormat();
+ }
+ if((*it).description() == m_outputdevice){
+ device = *it;
+ }
+ }
+ if (!device.isFormatSupported(format)) {
+ qWarning() << "Raw audio format not supported by backend, trying nearest format.";
+ //tempformat = device.nearestFormat(format);
+ //qWarning() << "Format now set to " << format.sampleRate() << ":" << format.sampleSize();
+ }
+ else{
+ tempformat = format;
+ }
+ fprintf(stderr, "Using playback device %s\n", device.description().toStdString().c_str());fflush(stderr);
+
+ m_out = new QAudioSink(device, tempformat, this);
+ m_out->setBufferSize(1280);
+ connect(m_out, SIGNAL(stateChanged(QAudio::State)), this, SLOT(handleStateChanged(QAudio::State)));
+ //m_outdev = m_out->start();
+ }
+
+ devices = QMediaDevices::audioInputs();
+
+ if(devices.size() == 0){
+ fprintf(stderr, "No audio recording hardware found\n");fflush(stderr);
+ }
+ else{
+ QAudioDevice device(QMediaDevices::defaultAudioInput());
+ for (QList::ConstIterator it = devices.constBegin(); it != devices.constEnd(); ++it ) {
+ if(MACHAK){
+ qDebug() << "Playback device name = " << (*it).description();
+ qDebug() << (*it).supportedSampleFormats();
+ qDebug() << (*it).preferredFormat();
+ }
+ if((*it).description() == m_inputdevice){
+ device = *it;
+ }
+ }
+ if (!device.isFormatSupported(format)) {
+ qWarning() << "Raw audio format not supported by backend, trying nearest format.";
+ //tempformat = device.nearestFormat(format);
+ //qWarning() << "Format now set to " << format.sampleRate() << ":" << format.sampleSize();
+ }
+ else{
+ tempformat = format;
+ }
+
+ int sr = 8000;
+ if(MACHAK){
+ sr = device.preferredFormat().sampleRate();
+ m_srm = (float)sr / 8000.0;
+ }
+ format.setSampleRate(sr);
+ m_in = new QAudioSource(device, format, this);
+ fprintf(stderr, "Capture device: %s SR: %d resample factor: %f\n", device.description().toStdString().c_str(), sr, m_srm);fflush(stderr);
+ }
+
+ //start_playback();
+}
+#endif
void AudioEngine::start_capture()
{
@@ -184,12 +291,9 @@ void AudioEngine::stop_playback()
void AudioEngine::input_data_received()
{
- QByteArray data;
- qint64 len = m_in->bytesReady();
+ QByteArray data = m_indev->readAll();
- if (len > 0){
- data.resize(len);
- m_indev->read(data.data(), len);
+ if (data.size() > 0){
/*
fprintf(stderr, "AUDIOIN: ");
for(int i = 0; i < len; ++i){
@@ -200,15 +304,15 @@ void AudioEngine::input_data_received()
*/
if(MACHAK){
std::vector samples;
- for(int i = 0; i < len; i += 2){
+ for(int i = 0; i < data.size(); i += 2){
samples.push_back(((data.data()[i+1] << 8) & 0xff00) | (data.data()[i] & 0xff));
}
- for(float i = 0; i < (float)len/2; i += m_srm){
+ for(float i = 0; i < (float)data.size()/2; i += m_srm){
m_audioinq.enqueue(samples[i]);
}
}
else{
- for(int i = 0; i < len; i += (2 * m_srm)){
+ for(int i = 0; i < data.size(); i += (2 * m_srm)){
m_audioinq.enqueue(((data.data()[i+1] << 8) & 0xff00) | (data.data()[i] & 0xff));
}
}
diff --git a/audioengine.h b/audioengine.h
index 2ac6db4..b294984 100644
--- a/audioengine.h
+++ b/audioengine.h
@@ -19,10 +19,17 @@
#define AUDIOENGINE_H
#include
+#if QT_VERSION < QT_VERSION_CHECK(6, 3, 0)
#include
#include
-#include
#include
+#else
+#include
+#include
+#include
+#include
+#endif
+#include
#include
#define AUDIO_OUT 1
@@ -56,8 +63,13 @@ signals:
private:
QString m_outputdevice;
QString m_inputdevice;
+#if QT_VERSION < QT_VERSION_CHECK(6, 3, 0)
QAudioOutput *m_out;
QAudioInput *m_in;
+#else
+ QAudioSink *m_out;
+ QAudioSource *m_in;
+#endif
QIODevice *m_outdev;
QIODevice *m_indev;
QQueue m_audioinq;
diff --git a/droidstar.cpp b/droidstar.cpp
index d621668..270b895 100644
--- a/droidstar.cpp
+++ b/droidstar.cpp
@@ -18,7 +18,12 @@
#include "droidstar.h"
#include "httpmanager.h"
#ifdef Q_OS_ANDROID
+#if QT_VERSION < QT_VERSION_CHECK(6, 3, 0)
#include
+#else
+#include
+#include
+#endif
#endif
#ifdef Q_OS_IOS
#include "micpermission.h"
@@ -52,15 +57,7 @@ DroidStar::DroidStar(QObject *parent) :
#endif
#if defined(Q_OS_ANDROID)
keepScreenOn();
- const QString permission("android.permission.READ_EXTERNAL_STORAGE");
- if(QtAndroid::checkPermission(permission) != QtAndroid::PermissionResult::Granted){
- auto resultHash = QtAndroid::requestPermissionsSync(QStringList({permission}));
- if(resultHash[permission] == QtAndroid::PermissionResult::Denied){
- qDebug() << "Storage read permissions denied";
- }
- }
#endif
-
check_host_files();
discover_devices();
process_settings();
@@ -81,6 +78,7 @@ DroidStar::~DroidStar()
}
#ifdef Q_OS_ANDROID
+#if QT_VERSION < QT_VERSION_CHECK(6, 3, 0)
void DroidStar::keepScreenOn()
{
char const * const action = "addFlags";
@@ -95,7 +93,22 @@ void DroidStar::keepScreenOn()
}
}});
}
+#else
+void DroidStar::keepScreenOn()
+{
+ char const * const action = "addFlags";
+ QNativeInterface::QAndroidApplication::runOnAndroidMainThread([action](){
+ QJniObject activity = QNativeInterface::QAndroidApplication::context();
+ if (activity.isValid()) {
+ QJniObject window = activity.callObjectMethod("getWindow", "()Landroid/view/Window;");
+ if (window.isValid()) {
+ const int FLAG_KEEP_SCREEN_ON = 128;
+ window.callMethod("addFlags", "(I)V", FLAG_KEEP_SCREEN_ON);
+ }
+ }});
+}
+#endif
void DroidStar::reset_connect_status()
{
if(connect_status == Mode::CONNECTED_RW){
@@ -1267,6 +1280,7 @@ void DroidStar::update_data(Mode::MODEINFO info)
}
else{
emit update_log("Vocoder plugin not loaded");
+ emit open_vocoder_dialog();
}
}
diff --git a/micpermission.mm b/micpermission.mm
index 6dfd4af..f219e3f 100755
--- a/micpermission.mm
+++ b/micpermission.mm
@@ -18,9 +18,15 @@
#include "micpermission.h"
//#import
//#import
+#ifdef Q_OS_IOS
+#import
+#endif
#import
int MicPermission::check_permission()
{
+#ifdef Q_OS_IOS
+ [UIApplication sharedApplication].idleTimerDisabled = YES;
+#endif
[UIApplication sharedApplication].idleTimerDisabled = YES;
AVAuthorizationStatus status = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeAudio];
if(status != AVAuthorizationStatusAuthorized){
diff --git a/serialambe.cpp b/serialambe.cpp
index fe54bbb..49a5d41 100755
--- a/serialambe.cpp
+++ b/serialambe.cpp
@@ -80,13 +80,9 @@ QMap SerialAMBE::discover_devices()
+ "Manufacturer: " + (!serialPortInfo.manufacturer().isEmpty() ? serialPortInfo.manufacturer() : blankString) + ENDLINE
+ "Serial number: " + (!serialPortInfo.serialNumber().isEmpty() ? serialPortInfo.serialNumber() : blankString) + ENDLINE
+ "Vendor Identifier: " + (serialPortInfo.hasVendorIdentifier() ? QByteArray::number(serialPortInfo.vendorIdentifier(), 16) : blankString) + ENDLINE
- + "Product Identifier: " + (serialPortInfo.hasProductIdentifier() ? QByteArray::number(serialPortInfo.productIdentifier(), 16) : blankString) + ENDLINE
- + "Busy: " + (serialPortInfo.isBusy() ? "Yes" : "No") + ENDLINE;
+ + "Product Identifier: " + (serialPortInfo.hasProductIdentifier() ? QByteArray::number(serialPortInfo.productIdentifier(), 16) : blankString) + ENDLINE;
fprintf(stderr, "%s", out.toStdString().c_str());fflush(stderr);
- if(!serialPortInfo.isBusy()){
- //devlist[serialPortInfo.systemLocation()] = serialPortInfo.portName() + " - " + serialPortInfo.manufacturer() + " " + serialPortInfo.description() + " - " + serialPortInfo.serialNumber();
- devlist[serialPortInfo.systemLocation()] = serialPortInfo.description() + ":" + serialPortInfo.systemLocation();
- }
+ devlist[serialPortInfo.systemLocation()] = serialPortInfo.description() + ":" + serialPortInfo.systemLocation();
}
}
#else
@@ -113,8 +109,7 @@ void SerialAMBE::connect_to_serial(QString p)
+ "Manufacturer: " + (!info.manufacturer().isEmpty() ? info.manufacturer() : blankString) + ENDLINE
+ "Serial number: " + (!info.serialNumber().isEmpty() ? info.serialNumber() : blankString) + ENDLINE
+ "Vendor Identifier: " + (info.hasVendorIdentifier() ? QByteArray::number(info.vendorIdentifier(), 16) : blankString) + ENDLINE
- + "Product Identifier: " + (info.hasProductIdentifier() ? QByteArray::number(info.productIdentifier(), 16) : blankString) + ENDLINE
- + "Busy: " + (info.isBusy() ? "Yes" : "No") + ENDLINE;
+ + "Product Identifier: " + (info.hasProductIdentifier() ? QByteArray::number(info.productIdentifier(), 16) : blankString) + ENDLINE;
fprintf(stderr, "%s", out.toStdString().c_str());fflush(stderr);
m_description = info.description();
@@ -457,7 +452,6 @@ bool SerialAMBE::get_audio(int16_t *audio)
m_serialdata.dequeue();
m_serialdata.dequeue();
m_serialdata.dequeue();
- //qDebug() << "Found header, deleting.....................................................................";
for(int i = 0; i < 160; i++){
//Byte swap BE to LE
audio[i] = ((m_serialdata.dequeue() << 8) & 0xff00) | (m_serialdata.dequeue() & 0xff);
@@ -466,7 +460,6 @@ bool SerialAMBE::get_audio(int16_t *audio)
r = true;
}
else{
- qDebug() << "Header not found..............................................................................." ;
while( (m_serialdata.size() > 5) && (
((uint8_t)m_serialdata[0] != header[0]) ||
((uint8_t)m_serialdata[1] != header[1]) ||
@@ -475,7 +468,6 @@ bool SerialAMBE::get_audio(int16_t *audio)
((uint8_t)m_serialdata[4] != header[4]) ||
((uint8_t)m_serialdata[5] != header[5]))){
m_serialdata.dequeue();
- //qDebug() << "Finding start of audio frame";
}
}
}