Add Qt6 support

pull/4/head
Doug McLain 1 year ago
parent a612323d23
commit 357ae4db19

@ -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

@ -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

@ -1,6 +1,6 @@
<?xml version="1.0"?>
<manifest package="org.dudetronics.droidstar" xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="-- %%INSERT_VERSION_NAME%% --" android:versionCode="68" android:installLocation="auto">
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="30"/>
<!-- The following comment will be replaced upon deployment with default permissions based on the dependencies of the application.
Remove the comment if you do not require these default permissions. -->
@ -41,8 +41,6 @@
<!-- Used to specify custom system library path to run with local system libs -->
<!-- <meta-data android:name="android.app.system_libs_prefix" android:value="/system/lib/"/> -->
<!-- Messages maps -->
<meta-data android:value="@string/ministro_not_found_msg" android:name="android.app.ministro_not_found_msg"/>
<meta-data android:value="@string/ministro_needed_msg" android:name="android.app.ministro_needed_msg"/>
<meta-data android:value="@string/fatal_error_msg" android:name="android.app.fatal_error_msg"/>
<meta-data android:value="@string/unsupported_android_version" android:name="android.app.unsupported_android_version"/>
<!-- Messages maps -->
@ -78,8 +76,5 @@
</activity>
<!-- For adding service(s) please check: https://wiki.qt.io/AndroidServices -->
</application>
<uses-sdk android:targetSdkVersion="31"/>
</manifest>

@ -5,7 +5,7 @@ buildscript {
}
dependencies {
classpath 'com.android.tools.build:gradle:3.5.0'
classpath 'com.android.tools.build:gradle:4.1.0'
}
}

@ -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

@ -14,7 +14,7 @@
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <QDebug>
#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<jobjectArray>();
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;
}

@ -20,7 +20,12 @@
#include <QObject>
#ifdef Q_OS_ANDROID
#if QT_VERSION < QT_VERSION_CHECK(6, 3, 0)
#include <QtAndroidExtras>
#else
#include <QCoreApplication>
#include <QJniObject>
#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

@ -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<QAudioDevice> devices;
if(d){
devices = QMediaDevices::audioOutputs();
}
else{
devices = QMediaDevices::audioInputs();
}
for (QList<QAudioDevice>::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<QAudioDevice> devices = QMediaDevices::audioOutputs();
if(devices.size() == 0){
fprintf(stderr, "No audio playback hardware found\n");fflush(stderr);
}
else{
QAudioDevice device(QMediaDevices::defaultAudioOutput());
for (QList<QAudioDevice>::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<QAudioDevice>::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<int16_t> 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));
}
}

@ -19,10 +19,17 @@
#define AUDIOENGINE_H
#include <QObject>
#if QT_VERSION < QT_VERSION_CHECK(6, 3, 0)
#include <QAudio>
#include <QAudioFormat>
#include <QAudioOutput>
#include <QAudioInput>
#else
#include <QAudioDevice>
#include <QAudioSink>
#include <QAudioSource>
#include <QMediaDevices>
#endif
#include <QAudioOutput>
#include <QQueue>
#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<int16_t> m_audioinq;

@ -18,7 +18,12 @@
#include "droidstar.h"
#include "httpmanager.h"
#ifdef Q_OS_ANDROID
#if QT_VERSION < QT_VERSION_CHECK(6, 3, 0)
#include <QtAndroidExtras>
#else
#include <QCoreApplication>
#include <QJniObject>
#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<void>("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();
}
}

@ -18,9 +18,15 @@
#include "micpermission.h"
//#import <Foundation/NSUserNotification.h>
//#import <Foundation/NSString.h>
#ifdef Q_OS_IOS
#import <UIKit/UIKit.h>
#endif
#import <AVFoundation/AVCaptureDevice.h>
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){

@ -80,13 +80,9 @@ QMap<QString, QString> 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";
}
}
}

Loading…
Cancel
Save