Compare commits

..

9 Commits

Author SHA1 Message Date
Roberto Viola
47a3c24b03 2.18.9 2024-12-03 14:23:06 +01:00
Roberto Viola
40579fd376 improving safety on mediabuttonreceiver 2024-12-03 14:22:11 +01:00
Roberto Viola
bb17c1cc1a Inclination Gain implementation in QZ for Elite Suito/Rouvy #2850 (#2858) 2024-12-03 11:21:51 +01:00
Roberto Viola
1cc8862a04 proform carbon TL PFTL59722c.0 (Issue #2806) 2024-12-03 10:32:23 +01:00
Roberto Viola
ff4606caa4 Yosuda RC-Max #2861 2024-12-03 08:58:37 +01:00
Roberto Viola
aff12a0462 Bowflex T9 #2860 2024-12-03 08:56:55 +01:00
Roberto Viola
3c5054acbd App not displaying metrics #2835 2024-12-02 14:37:18 +01:00
Roberto Viola
9a854f7810 Buggy behaviour on Raspberry pi 4 and Zwift #2810 2024-12-02 11:39:04 +01:00
Roberto Viola
1e731f7cbe Zwo warmup not fully elapsed in terms of time in running workouts #2847 2024-12-02 08:36:23 +01:00
15 changed files with 111 additions and 59 deletions

View File

@@ -1,5 +1,5 @@
<?xml version="1.0"?>
<manifest package="org.cagnulen.qdomyoszwift" xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:versionName="2.18.8" android:versionCode="952" android:installLocation="auto">
<manifest package="org.cagnulen.qdomyoszwift" xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:versionName="2.18.9" android:versionCode="953" android:installLocation="auto">
<!-- 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. -->
<!-- %%INSERT_PERMISSIONS -->

View File

@@ -29,18 +29,39 @@ public class MediaButtonReceiver extends BroadcastReceiver {
private native void nativeOnMediaButtonEvent(int prev, int current, int max);
public static void registerReceiver(Context context) {
if (instance == null) {
instance = new MediaButtonReceiver();
try {
if (instance == null) {
instance = new MediaButtonReceiver();
}
IntentFilter filter = new IntentFilter("android.media.VOLUME_CHANGED_ACTION");
if (context == null) {
Log.e("MediaButtonReceiver", "Context is null, cannot register receiver");
return;
}
if (Build.VERSION.SDK_INT >= 34) {
try {
context.registerReceiver(instance, filter, Context.RECEIVER_EXPORTED);
} catch (SecurityException se) {
Log.e("MediaButtonReceiver", "Security exception while registering receiver: " + se.getMessage());
}
} else {
try {
context.registerReceiver(instance, filter);
} catch (SecurityException se) {
Log.e("MediaButtonReceiver", "Security exception while registering receiver: " + se.getMessage());
}
}
Log.d("MediaButtonReceiver", "Receiver registered successfully");
} catch (IllegalArgumentException e) {
Log.e("MediaButtonReceiver", "Invalid arguments for receiver registration: " + e.getMessage());
} catch (Exception e) {
Log.e("MediaButtonReceiver", "Unexpected error while registering receiver: " + e.getMessage());
}
IntentFilter filter = new IntentFilter("android.media.VOLUME_CHANGED_ACTION");
if (Build.VERSION.SDK_INT >= 34) {
context.registerReceiver(instance, filter, Context.RECEIVER_EXPORTED);
} else {
context.registerReceiver(instance, filter);
}
Log.d("MediaButtonReceiver", "registerReceiver");
}
public static void unregisterReceiver(Context context) {
if (instance != null) {
context.unregisterReceiver(instance);

View File

@@ -128,12 +128,11 @@ public class InAppPurchase implements PurchasesUpdatedListener
@Override
public void onBillingSetupFinished(BillingResult billingResult) {
Log.w(TAG, "onBillingSetupFinished");
return;
/* if (billingResult.getResponseCode() == RESULT_OK) {
if (billingResult.getResponseCode() == RESULT_OK) {
purchasedProductsQueried(m_nativePointer);
} else {
Log.w(TAG, "onBillingSetupFinished error!" + billingResult.getResponseCode());
}*/
}
}
@Override

View File

@@ -1350,7 +1350,8 @@ void bluetooth::deviceDiscovered(const QBluetoothDeviceInfo &device) {
b.name().toUpper().startsWith(QStringLiteral("WELLFIT TM")) ||
b.name().toUpper().startsWith(QStringLiteral("XTERRA TR")) ||
b.name().toUpper().startsWith(QStringLiteral("T118_")) ||
b.name().toUpper().startsWith(QStringLiteral("RUNN ")) ||
b.name().toUpper().startsWith(QStringLiteral("RUNN ")) ||
b.name().toUpper().startsWith(QStringLiteral("BFX_T9_")) ||
b.name().toUpper().startsWith(QStringLiteral("TF04-")) || // Sport Synology Z5 Treadmill #2415
b.name().toUpper().startsWith(QStringLiteral("FIT-")) || // FIT-1596
b.name().toUpper().startsWith(QStringLiteral("LJJ-")) || // LJJ-02351A
@@ -1563,6 +1564,7 @@ void bluetooth::deviceDiscovered(const QBluetoothDeviceInfo &device) {
(b.name().toUpper().startsWith("JUSTO")) ||
(b.name().toUpper().startsWith("MYCYCLE ")) ||
(b.name().toUpper().startsWith("T2 ")) ||
(b.name().toUpper().startsWith("RC-MAX-")) ||
(b.name().toUpper().startsWith("NEO BIKE SMART")) ||
(b.name().toUpper().startsWith("ZDRIVE")) ||
(b.name().toUpper().startsWith("T300P_")) ||

View File

@@ -1031,6 +1031,11 @@ void ftmsbike::ftmsCharacteristicChanged(const QLowEnergyCharacteristic &charact
// handling gears
if (b.at(0) == FTMS_SET_INDOOR_BIKE_SIMULATION_PARAMS && (zwiftPlayService == nullptr || !gears_zwift_ratio)) {
double min_inclination = settings.value(QZSettings::min_inclination, QZSettings::default_min_inclination).toDouble();
double offset =
settings.value(QZSettings::zwift_inclination_offset, QZSettings::default_zwift_inclination_offset).toDouble();
double gain =
settings.value(QZSettings::zwift_inclination_gain, QZSettings::default_zwift_inclination_gain).toDouble();
lastPacketFromFTMS.clear();
for(int i=0; i<b.length(); i++)
lastPacketFromFTMS.append(b.at(i));
@@ -1045,6 +1050,9 @@ void ftmsbike::ftmsCharacteristicChanged(const QLowEnergyCharacteristic &charact
qDebug() << "grade override due to min_inclination " << min_inclination;
}
slope *= gain;
slope += (offset * 100);
b[3] = slope & 0xFF;
b[4] = slope >> 8;

View File

@@ -5445,7 +5445,7 @@ void proformtreadmill::btinit() {
uint8_t initData7[] = {0xff, 0x0a, 0x02, 0x04, 0x02, 0x06, 0x02, 0x06, 0x84, 0x00, 0x00, 0x8c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
uint8_t initData8[] = {0xff, 0x08, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x95, 0x9b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
uint8_t initData9[] = {0xfe, 0x02, 0x2c, 0x04};
uint8_t initData10[] = {0x00, 0x12, 0x02, 0x04, 0x02, 0x28, 0x04, 0x28, 0x90, 0x04, 0x00, 0xe1, 0xd8, 0xdd, 0xd0, 0xd1, 0xd0, 0xd5, 0xe8, 0xe1};
uint8_t initData10[] = {0x00, 0x12, 0x02, 0x04, 0x02, 0x28, 0x04, 0x28, 0x90, 0x07, 0x01, 0xe1, 0xd8, 0xdd, 0xd0, 0xd1, 0xd0, 0xd5, 0xe8, 0xe1};
uint8_t initData11[] = {0x01, 0x12, 0xf8, 0x0d, 0x00, 0x11, 0x20, 0x55, 0x48, 0x61, 0x98, 0xbd, 0xd0, 0xf1, 0x10, 0x35, 0x48, 0x61, 0xb8, 0xcd};
uint8_t initData12[] = {0xff, 0x08, 0xe0, 0x31, 0x40, 0x98, 0x02, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
uint8_t noOpData1[] = {0xfe, 0x02, 0x19, 0x03};
@@ -5458,11 +5458,11 @@ void proformtreadmill::btinit() {
uint8_t noOpData8[] = {0x00, 0x12, 0x02, 0x04, 0x02, 0x15, 0x04, 0x15, 0x02, 0x00, 0x0f, 0x00, 0x10, 0x00, 0xd8, 0x1c, 0x48, 0x00, 0x00, 0xe0};
uint8_t noOpData9[] = {0xff, 0x07, 0x00, 0x00, 0x00, 0x10, 0x00, 0x08, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
uint8_t noOpData10[] = {0xfe, 0x02, 0x19, 0x03};
uint8_t noOpData11[] = {0x00, 0x12, 0x02, 0x04, 0x02, 0x15, 0x04, 0x15, 0x02, 0x00, 0x0f, 0x92, 0x18, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
uint8_t noOpData12[] = {0xff, 0x07, 0x00, 0x00, 0x00, 0x80, 0x00, 0x10, 0xd4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
uint8_t noOpData11[] = {0x00, 0x12, 0x02, 0x04, 0x02, 0x13, 0x04, 0x13, 0x02, 0x00, 0x0d, 0x13, 0x96, 0x31, 0x00, 0x00, 0x40, 0x10, 0x00, 0x80};
uint8_t noOpData12[] = {0xff, 0x05, 0x18, 0x00, 0x00, 0x01, 0xe9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
uint8_t noOpData13[] = {0xfe, 0x02, 0x17, 0x03};
uint8_t noOpData14[] = {0x00, 0x12, 0x02, 0x04, 0x02, 0x13, 0x04, 0x13, 0x02, 0x00, 0x0d, 0x01, 0x86, 0x01, 0x00, 0x00, 0x40, 0x10, 0x00, 0x80};
uint8_t noOpData15[] = {0xff, 0x05, 0x18, 0x00, 0x00, 0x01, 0x97, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
uint8_t noOpData14[] = {0x00, 0x12, 0x02, 0x04, 0x02, 0x15, 0x04, 0x15, 0x02, 0x00, 0x0f, 0x80, 0x08, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
uint8_t noOpData15[] = {0xff, 0x07, 0x00, 0x00, 0x00, 0x80, 0x00, 0x10, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
writeCharacteristic(initData1, sizeof(initData1), QStringLiteral("init"), false, false);
QThread::msleep(sleepms);
@@ -5514,13 +5514,13 @@ void proformtreadmill::btinit() {
QThread::msleep(sleepms);
writeCharacteristic(noOpData9, sizeof(noOpData9), QStringLiteral("init"), false, false);
QThread::msleep(sleepms);
writeCharacteristic(noOpData10, sizeof(noOpData10), QStringLiteral("init"), false, false);
writeCharacteristic(noOpData13, sizeof(noOpData13), QStringLiteral("init"), false, false);
QThread::msleep(sleepms);
writeCharacteristic(noOpData11, sizeof(noOpData11), QStringLiteral("init"), false, false);
QThread::msleep(sleepms);
writeCharacteristic(noOpData12, sizeof(noOpData12), QStringLiteral("init"), false, false);
QThread::msleep(sleepms);
writeCharacteristic(noOpData13, sizeof(noOpData13), QStringLiteral("init"), false, false);
writeCharacteristic(noOpData10, sizeof(noOpData10), QStringLiteral("init"), false, false);
QThread::msleep(sleepms);
writeCharacteristic(noOpData14, sizeof(noOpData14), QStringLiteral("init"), false, false);
QThread::msleep(sleepms);

View File

@@ -126,7 +126,7 @@ void trxappgateusbbike::update() {
bool toorx30 = settings.value(QZSettings::toorx_3_0, QZSettings::default_toorx_3_0).toBool();
if (toorx30 == false &&
(bike_type == TYPE::IRUNNING || bike_type == TYPE::IRUNNING_2 || bike_type == TYPE::ICONSOLE || bike_type == TYPE::ICONSOLE_2 ||
bike_type == TYPE::HERTZ_XR_770 || bike_type == TYPE::HERTZ_XR_770_2)) {
bike_type == TYPE::HERTZ_XR_770 || bike_type == TYPE::HERTZ_XR_770_2 || bike_type == PASYOU)) {
const uint8_t noOpData[] = {0xf0, 0xa2, 0x01, 0x01, 0x94};
writeCharacteristic((uint8_t *)noOpData, sizeof(noOpData), QStringLiteral("noOp"), false, true);
@@ -220,7 +220,7 @@ void trxappgateusbbike::characteristicChanged(const QLowEnergyCharacteristic &ch
lastPacket = newValue;
if ((newValue.length() != 21 && (bike_type != JLL_IC400 && bike_type != ASVIVA && bike_type != FYTTER_RI08 &&
bike_type != TUNTURI && bike_type != TUNTURI_2 && bike_type != TOORX_SRX_500)) ||
(newValue.length() != 19 && (bike_type == JLL_IC400 || bike_type == ASVIVA || bike_type == FYTTER_RI08)) ||
(newValue.length() != 19 && (bike_type == JLL_IC400 || bike_type == ASVIVA || bike_type == FYTTER_RI08 || bike_type == PASYOU)) ||
(newValue.length() != 20 && newValue.length() != 21 &&
(bike_type == TUNTURI || bike_type == TYPE::TUNTURI_2))) {
return;
@@ -453,7 +453,7 @@ void trxappgateusbbike::btinit(bool startTape) {
bool toorx30 = settings.value(QZSettings::toorx_3_0, QZSettings::default_toorx_3_0).toBool();
if (toorx30 == false &&
(bike_type == TYPE::IRUNNING || bike_type == TYPE::IRUNNING_2 || bike_type == TYPE::ICONSOLE || bike_type == TYPE::ICONSOLE_2)) {
(bike_type == TYPE::IRUNNING || bike_type == TYPE::IRUNNING_2 || bike_type == TYPE::ICONSOLE || bike_type == TYPE::ICONSOLE_2 || bike_type == PASYOU)) {
const uint8_t initData1[] = {0xf0, 0xa0, 0x01, 0x01, 0x92};
const uint8_t initData2[] = {0xf0, 0xa1, 0x01, 0x01, 0x93};
@@ -462,23 +462,23 @@ void trxappgateusbbike::btinit(bool startTape) {
const uint8_t initData5[] = {0xf0, 0xa6, 0x01, 0x01, 0x06, 0x9e};
writeCharacteristic((uint8_t *)initData1, sizeof(initData1), QStringLiteral("init"), false, true);
if (bike_type == TYPE::IRUNNING || bike_type == TYPE::IRUNNING_2) {
if (bike_type == TYPE::IRUNNING || bike_type == TYPE::IRUNNING_2 || bike_type == PASYOU) {
QThread::msleep(400);
}
writeCharacteristic((uint8_t *)initData2, sizeof(initData2), QStringLiteral("init"), false, true);
if (bike_type == TYPE::IRUNNING || bike_type == TYPE::IRUNNING_2) {
if (bike_type == TYPE::IRUNNING || bike_type == TYPE::IRUNNING_2 || bike_type == PASYOU) {
QThread::msleep(400);
}
writeCharacteristic((uint8_t *)initData3, sizeof(initData3), QStringLiteral("init"), false, true);
if (bike_type == TYPE::IRUNNING || bike_type == TYPE::IRUNNING_2) {
if (bike_type == TYPE::IRUNNING || bike_type == TYPE::IRUNNING_2 || bike_type == PASYOU) {
QThread::msleep(400);
}
writeCharacteristic((uint8_t *)initData4, sizeof(initData4), QStringLiteral("init"), false, true);
if (bike_type == TYPE::IRUNNING || bike_type == TYPE::IRUNNING_2) {
if (bike_type == TYPE::IRUNNING || bike_type == TYPE::IRUNNING_2 || bike_type == PASYOU) {
QThread::msleep(400);
}
writeCharacteristic((uint8_t *)initData5, sizeof(initData5), QStringLiteral("init"), false, true);
if (bike_type == TYPE::IRUNNING || bike_type == TYPE::IRUNNING_2) {
if (bike_type == TYPE::IRUNNING || bike_type == TYPE::IRUNNING_2 || bike_type == PASYOU) {
QThread::msleep(400);
}
} else if (bike_type == TYPE::HOP_SPORT_HS_090H) {
@@ -1158,6 +1158,10 @@ void trxappgateusbbike::deviceDiscovered(const QBluetoothDeviceInfo &device) {
bike_type = TYPE::BIKZU;
qDebug() << QStringLiteral("BIKZU bike found");
} else if (device.name().toUpper().startsWith(QStringLiteral("PASYOU-"))) {
bike_type = TYPE::PASYOU;
qDebug() << QStringLiteral("PASYOU bike found");
}
bluetoothDevice = device;

View File

@@ -113,6 +113,7 @@ class trxappgateusbbike : public bike {
BIKZU = 24,
TOORX_SRX_500 = 25,
IRUNNING_2 = 26,
PASYOU = 27,
} TYPE;
TYPE bike_type = TRXAPPGATE;

View File

@@ -595,7 +595,7 @@ homeform::homeform(QQmlApplicationEngine *engine, bluetooth *bl) {
}
#endif
//m_speech.setLocale(QLocale::English);
m_speech.setLocale(QLocale::English);
#if defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)
QBluetoothDeviceInfo b;
@@ -3721,8 +3721,8 @@ void homeform::Start_inner(bool send_event_to_device) {
m_overridePower = false;
/*if (settings.value(QZSettings::tts_enabled, QZSettings::default_tts_enabled).toBool())
m_speech.say("Start pressed");*/
if (settings.value(QZSettings::tts_enabled, QZSettings::default_tts_enabled).toBool())
m_speech.say("Start pressed");
if (!paused && !stopped) {
paused = true;
@@ -3846,8 +3846,8 @@ void homeform::Stop() {
this->innerTemplateManager->reinit();
#endif
/*if (settings.value(QZSettings::tts_enabled, QZSettings::default_tts_enabled).toBool())
m_speech.say("Stop pressed");*/
if (settings.value(QZSettings::tts_enabled, QZSettings::default_tts_enabled).toBool())
m_speech.say("Stop pressed");
if (bluetoothManager->device()) {
@@ -5588,7 +5588,7 @@ void homeform::update() {
setToastRequested("AutoLap " + QString::number(settings.value(QZSettings::autolap_distance, QZSettings::default_autolap_distance).toDouble(), 'f', 1));
}
}
/*
if (settings.value(QZSettings::tts_enabled, QZSettings::default_tts_enabled).toBool()) {
static double tts_speed_played = 0;
bool description =
@@ -5637,7 +5637,7 @@ void homeform::update() {
if (settings.value(QZSettings::tts_avg_cadence, QZSettings::default_tts_avg_cadence).toBool())
s.append((description ? tr(", Average cadence ") : ",") +
QString::number(bluetoothManager->device()->currentCadence().average(), 'f', 0));
if (settings.value(QZSettings::tts_max_cadence, QZSettings::default_tts_max_cadence)
if (settings.value(QZSettings::tts_max_cadence, QZSettings::default_tts_max_cadence /* true */)
.toBool())
s.append((description ? tr(", Max cadence ") : ",") +
QString::number(bluetoothManager->device()->currentCadence().max()));
@@ -5703,7 +5703,7 @@ void homeform::update() {
if (settings.value(QZSettings::tts_max_watt, QZSettings::default_tts_max_watt).toBool())
s.append((description ? tr(", max watt ") : ",") +
QString::number(bluetoothManager->device()->wattsMetric().max(), 'f', 0));
if (settings.value(QZSettings::tts_act_ftp, QZSettings::default_tts_act_ftp )
if (settings.value(QZSettings::tts_act_ftp, QZSettings::default_tts_act_ftp /* true */)
.toBool())
s.append((description ? tr(", ftp ") : ",") + QString::number(ftpZone, 'f', 1));
if (settings.value(QZSettings::tts_act_heart, QZSettings::default_tts_act_heart).toBool())
@@ -5825,7 +5825,7 @@ void homeform::update() {
m_speech.say(s);
}
}
}*/
}
if(bluetoothManager->device()->currentSpeed().value() > 0 && !isinf(bluetoothManager->device()->currentSpeed().value()))
bluetoothManager->device()->addCurrentDistance1s((bluetoothManager->device()->currentSpeed().value() / 3600.0));

View File

@@ -769,7 +769,7 @@ class homeform : public QObject {
bool getLap();
void Start_inner(bool send_event_to_device);
//QTextToSpeech m_speech;
QTextToSpeech m_speech;
int tts_summary_count = 0;
#if defined(Q_OS_WIN) || (defined(Q_OS_MAC) && !defined(Q_OS_IOS)) || (defined(Q_OS_ANDROID) && defined(LICENSE))

View File

@@ -73,6 +73,7 @@ bool reebok_fr30_treadmill = false;
bool zwift_play = false;
bool zwift_click = false;
bool zwift_play_emulator = false;
bool virtual_device_bluetooth = true;
QString eventGearDevice = QStringLiteral("");
QString trainProgram;
QString deviceName = QLatin1String("");
@@ -109,6 +110,8 @@ QCoreApplication *createApplication(int &argc, char *argv[]) {
noConsole = true;
if (!qstrcmp(argv[i], "-test-resistance"))
testResistance = true;
if (!qstrcmp(argv[i], "-no-virtual-device-bluetooth"))
virtual_device_bluetooth = false;
if (!qstrcmp(argv[i], "-no-log"))
logs = false;
if (!qstrcmp(argv[i], "-no-write-resistance"))
@@ -406,6 +409,7 @@ int main(int argc, char *argv[]) {
settings.setValue(QZSettings::zwift_click, zwift_click);
settings.setValue(QZSettings::zwift_play, zwift_play);
settings.setValue(QZSettings::zwift_play_emulator, zwift_play_emulator);
settings.setValue(QZSettings::virtual_device_bluetooth, virtual_device_bluetooth);
}
#endif

View File

@@ -777,7 +777,7 @@ ApplicationWindow {
}
ItemDelegate {
text: "version 2.18.8"
text: "version 2.18.9"
width: parent.width
}

View File

@@ -57,14 +57,12 @@
QT_USE_NAMESPACE
static void purchasedProductsQueried(JNIEnv *, jclass, jlong nativePointer) {
return;
AndroidInAppPurchaseBackend *backend = reinterpret_cast<AndroidInAppPurchaseBackend *>(nativePointer);
QMetaObject::invokeMethod(backend, "registerReady", Qt::AutoConnection);
}
static void registerProduct(JNIEnv *, jclass, jlong nativePointer, jstring productId, jstring price, jstring title,
jstring description) {
return;
AndroidInAppPurchaseBackend *backend = reinterpret_cast<AndroidInAppPurchaseBackend *>(nativePointer);
QMetaObject::invokeMethod(
backend, "registerProduct", Qt::AutoConnection, Q_ARG(QString, QAndroidJniObject(productId).toString()),
@@ -74,7 +72,6 @@ static void registerProduct(JNIEnv *, jclass, jlong nativePointer, jstring produ
static void registerPurchased(JNIEnv *, jclass, jlong nativePointer, jstring identifier, jstring signature,
jstring data, jstring purchaseToken, jstring orderId, jlong timestamp) {
return;
QDateTime dateTime = QDateTime::fromMSecsSinceEpoch(qint64(timestamp));
dateTime.setTimeSpec(Qt::LocalTime);
@@ -88,7 +85,6 @@ static void registerPurchased(JNIEnv *, jclass, jlong nativePointer, jstring ide
static void purchaseSucceeded(JNIEnv *, jclass, jlong nativePointer, jint requestCode, jstring signature, jstring data,
jstring purchaseToken, jstring orderId, jlong timestamp) {
return;
QDateTime dateTime = QDateTime::fromMSecsSinceEpoch(qint64(timestamp));
dateTime.setTimeSpec(Qt::LocalTime);
@@ -102,7 +98,6 @@ static void purchaseSucceeded(JNIEnv *, jclass, jlong nativePointer, jint reques
static void purchaseFailed(JNIEnv *, jclass, jlong nativePointer, jint requestCode, jint failureReason,
jstring errorString) {
return;
AndroidInAppPurchaseBackend *backend = reinterpret_cast<AndroidInAppPurchaseBackend *>(nativePointer);
QMetaObject::invokeMethod(backend, "purchaseFailed", Qt::AutoConnection, Q_ARG(int, int(requestCode)),
Q_ARG(int, int(failureReason)),
@@ -121,7 +116,6 @@ static JNINativeMethod methods[] = {
{"purchaseFailed", "(JIILjava/lang/String;)V", (void *)purchaseFailed}};
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *) {
return JNI_VERSION_1_6;
static bool initialized = false;
if (initialized) {
return JNI_VERSION_1_6;

View File

@@ -1,5 +1,5 @@
include(../defaults.pri)
QT += bluetooth widgets xml positioning quick networkauth websockets location multimedia
QT += bluetooth widgets xml positioning quick networkauth websockets texttospeech location multimedia
QTPLUGIN += qavfmediaplayer
QT+= charts core-private
@@ -910,4 +910,4 @@ INCLUDEPATH += purchasing/inapp
WINRT_MANIFEST = AppxManifest.xml
VERSION = 2.18.8
VERSION = 2.18.9

View File

@@ -129,26 +129,45 @@ void zwiftworkout::convertTag(double thresholdSecPerKm, const QString &sportType
if (sportType.toLower().contains(QStringLiteral("run")) && !durationAsDistance(sportType, durationType)) {
double speed = speedFromPace(Pace);
int speedDelta = qAbs(qCeil((((60.0 / speed) * 60.0) * (PowerHigh - PowerLow)) * 10)) + 1;
// Ensure we don't divide by zero
speedDelta = qMax(1, speedDelta);
// Calculate base duration step and remaining seconds
int durationStep = Duration / speedDelta;
int spareSeconds = Duration - (durationStep * speedDelta);
int spareSum = 0;
int remainingSeconds = Duration % speedDelta;
int totalElapsed = 0;
for (int i = 0; i < speedDelta; i++) {
trainrow row;
int spare = 0;
if (spareSeconds)
spare = (i % spareSeconds == 0 && i > 0) ? 1 : 0;
spareSum += spare;
row.duration = QTime(0, 0, 0, 0).addSecs(durationStep + spare);
row.rampElapsed = QTime(0, 0, 0, 0).addSecs((durationStep * i) + spareSum);
row.rampDuration = QTime(0, 0, 0, 0).addSecs(Duration - (durationStep * i) - spareSum);
// Distribute remaining seconds evenly across iterations
int extraSecond = (i < remainingSeconds) ? 1 : 0;
int currentStepDuration = durationStep + extraSecond;
// Set row duration
row.duration = QTime(0, 0, 0, 0).addSecs(currentStepDuration);
row.rampElapsed = QTime(0, 0, 0, 0).addSecs(totalElapsed);
row.rampDuration = QTime(0, 0, 0, 0).addSecs(Duration - totalElapsed);
// Update total elapsed time
totalElapsed += currentStepDuration;
row.forcespeed = 1;
// Calculate speed based on tag type
if (!qstricmp(tag, "Ramp") || !qstricmp(tag, "Warmup")) {
row.speed = (double)qFloor(((((60.0 / speed) * 60.0) * (PowerLow)) + (0.1 * i)) * 10.0) / 10.0;
} else {
row.speed = (double)qFloor(((((60.0 / speed) * 60.0) * (PowerLow)) - (0.1 * i)) * 10.0) / 10.0;
}
if(Incline != -100)
// Set inclination if provided
if (Incline != -100) {
row.inclination = Incline * 100;
}
qDebug() << "TrainRow" << row.toString();
list.append(row);
}