diff --git a/core/debug.cpp b/core/debug.cpp index 38a27094..aef97886 100644 --- a/core/debug.cpp +++ b/core/debug.cpp @@ -357,7 +357,16 @@ int process_debug_cmd(char *cmdline) { if (*(file + len - 1) == '"') *(file + len - 1) = '\0'; usblink_connect(); - usblink_queue_put_file(std::string(file), std::string(ln_target_folder), nullptr, nullptr); + + const char *file_name = file; + for (const char *p = file; *p; p++) + if (*p == ':' || *p == '/' || *p == '\\') + file_name = p + 1; + + if (ln_target_folder.length() < 1 || *ln_target_folder.rbegin() != '/') + ln_target_folder += '/'; + + usblink_queue_put_file(std::string(file), ln_target_folder + std::string(file_name), nullptr, nullptr); } } else if (!strcasecmp(ln_cmd, "st")) { char *dir = strtok(NULL, " \n\r"); diff --git a/core/usblink.c b/core/usblink.c index 8a0e9a40..f4b89577 100644 --- a/core/usblink.c +++ b/core/usblink.c @@ -278,7 +278,8 @@ void put_file_next(struct packet *in) { teardown: throttle_timer_on(); put_file_state = 0; - fclose(put_file); + if (put_file) + fclose(put_file); put_file = NULL; } @@ -524,10 +525,10 @@ void usblink_received_packet(const uint8_t *data, uint32_t size) { } } -bool usblink_put_file(const char *filepath, const char *folder, usblink_progress_cb callback, void *user_data) { +bool usblink_put_file(const char *local, const char *remote, usblink_progress_cb callback, void *user_data) { mode = File_Send; - char *dot = strrchr(filepath, '.'); + char *dot = local ? strrchr(local, '.') : NULL; // TODO (thanks for the reminder, Excale :P) : Filter depending on which model is being emulated if (dot && (!strcmp(dot, ".tno") || !strcmp(dot, ".tnc") || !strcmp(dot, ".tco") || !strcmp(dot, ".tcc") @@ -535,37 +536,30 @@ bool usblink_put_file(const char *filepath, const char *folder, usblink_progress || !strcmp(dot, ".tco2") || !strcmp(dot, ".tcc2") || !strcmp(dot, ".tct2")) ) { emuprintf("File is an OS, calling usblink_send_os\n"); - usblink_send_os(filepath, callback, user_data); + usblink_send_os(local, callback, user_data); return 1; } current_user_data = user_data; current_file_callback = callback; - const char *filename = filepath; - // Hack for android content:// urls - if(strncmp(filepath, "content://", 10) == 0) { - for (const char *p = filepath; *p; p++) - if (strncasecmp(p, "%2F", 3) == 0) - filename = p + 3; - } - else { - for (const char *p = filepath; *p; p++) - if (*p == ':' || *p == '/' || *p == '\\') - filename = p + 1; - } - - FILE *f = fopen_utf8(filepath, "rb"); - if (!f) { - gui_perror(filepath); - return 0; - } if (put_file) fclose(put_file); - put_file = f; - fseek(f, 0, SEEK_END); - put_file_size_orig = put_file_size = ftell(f); - fseek(f, 0, SEEK_SET); + + if (local && local[0] != '\0') { + put_file = fopen_utf8(local, "rb"); + if (!put_file) { + gui_perror(local); + return 0; + } + fseek(put_file, 0, SEEK_END); + put_file_size_orig = put_file_size = ftell(put_file); + fseek(put_file, 0, SEEK_SET); + } else { + put_file = NULL; + put_file_size_orig = put_file_size = 0; + } + put_file_state = SENDING_03; /* Send the first packet */ @@ -577,7 +571,7 @@ bool usblink_put_file(const char *filepath, const char *folder, usblink_progress uint8_t *data = out->data; *data++ = File_Put; *data++ = 1; - data += sprintf((char *)data, "%s/%s", folder, filename) + 1; + data += sprintf((char *)data, "%s", remote) + 1; *(uint32_t *)data = BSWAP32(put_file_size); data += 4; out->data_size = data - out->data; usblink_send_packet(); diff --git a/core/usblink.h b/core/usblink.h index 7a81567c..6b998fdd 100644 --- a/core/usblink.h +++ b/core/usblink.h @@ -27,7 +27,8 @@ typedef void (*usblink_progress_cb)(int progress, void *user_data); void usblink_delete(const char *path, bool is_dir, usblink_progress_cb callback, void *user_data); void usblink_dirlist(const char *path, usblink_dirlist_cb callback, void *user_data); bool usblink_get_file(const char *path, const char *dest, usblink_progress_cb callback, void *user_data); -bool usblink_put_file(const char *filepath, const char *folder, usblink_progress_cb callback, void *user_data); +/* local = NULL or empty creates an empty file */ +bool usblink_put_file(const char *local, const char *remote, usblink_progress_cb callback, void *user_data); void usblink_new_dir(const char *path, usblink_progress_cb callback, void *user_data); void usblink_move(const char *old_path, const char *new_path, usblink_progress_cb callback, void *user_data); bool usblink_send_os(const char *filepath, usblink_progress_cb callback, void *user_data); diff --git a/core/usblink_queue.cpp b/core/usblink_queue.cpp index 7af90a7a..fab99287 100644 --- a/core/usblink_queue.cpp +++ b/core/usblink_queue.cpp @@ -19,8 +19,8 @@ struct usblink_queue_action { } action; //Members only used if the appropriate action is set - std::string filepath; - std::string path; + std::string local; + std::string remote; usblink_progress_cb progress_callback = nullptr; usblink_dirlist_cb dirlist_callback = nullptr; void *user_data; @@ -81,36 +81,36 @@ void usblink_queue_do() switch(action.action) { case usblink_queue_action::PUT_FILE: - if(!usblink_put_file(action.filepath.c_str(), action.path.c_str(), progress_callback, action.user_data)) + if(!usblink_put_file(action.local.c_str(), action.remote.c_str(), progress_callback, action.user_data)) { progress_callback(-1, action.user_data); busy = false; } break; case usblink_queue_action::SEND_OS: - if(!usblink_send_os(action.filepath.c_str(), progress_callback, action.user_data)) + if(!usblink_send_os(action.local.c_str(), progress_callback, action.user_data)) { progress_callback(-1, action.user_data); busy = false; } break; case usblink_queue_action::DIRLIST: - usblink_dirlist(action.path.c_str(), dirlist_callback, action.user_data); + usblink_dirlist(action.remote.c_str(), dirlist_callback, action.user_data); break; case usblink_queue_action::MOVE: - usblink_move(action.filepath.c_str(), action.path.c_str(), progress_callback, action.user_data); + usblink_move(action.local.c_str(), action.remote.c_str(), progress_callback, action.user_data); break; case usblink_queue_action::NEW_DIR: - usblink_new_dir(action.path.c_str(), progress_callback, action.user_data); + usblink_new_dir(action.remote.c_str(), progress_callback, action.user_data); break; case usblink_queue_action::DEL_DIR: - usblink_delete(action.path.c_str(), true, progress_callback, action.user_data); + usblink_delete(action.remote.c_str(), true, progress_callback, action.user_data); break; case usblink_queue_action::DEL_FILE: - usblink_delete(action.path.c_str(), false, progress_callback, action.user_data); + usblink_delete(action.remote.c_str(), false, progress_callback, action.user_data); break; case usblink_queue_action::GET_FILE: - if(!usblink_get_file(action.path.c_str(), action.filepath.c_str(), progress_callback, action.user_data)) + if(!usblink_get_file(action.remote.c_str(), action.local.c_str(), progress_callback, action.user_data)) { progress_callback(-1, action.user_data); busy = false; @@ -150,7 +150,7 @@ void usblink_queue_delete(std::string path, bool is_dir, usblink_progress_cb cal usblink_queue_action action; action.action = is_dir ? usblink_queue_action::DEL_DIR : usblink_queue_action::DEL_FILE; action.user_data = user_data; - action.path = path; + action.remote = path; action.progress_callback = callback; usblink_queue_add(action); @@ -161,7 +161,7 @@ void usblink_queue_dirlist(std::string path, usblink_dirlist_cb callback, void * usblink_queue_action action; action.action = usblink_queue_action::DIRLIST; action.user_data = user_data; - action.path = path; + action.remote = path; action.dirlist_callback = callback; usblink_queue_add(action); @@ -172,20 +172,20 @@ void usblink_queue_download(std::string path, std::string destpath, usblink_prog usblink_queue_action action; action.action = usblink_queue_action::GET_FILE; action.user_data = user_data; - action.filepath = destpath; - action.path = path; + action.local = destpath; + action.remote = path; action.progress_callback = callback; usblink_queue_add(action); } -void usblink_queue_put_file(std::string filepath, std::string folder, usblink_progress_cb callback, void *user_data) +void usblink_queue_put_file(std::string local, std::string remote, usblink_progress_cb callback, void *user_data) { usblink_queue_action action; action.action = usblink_queue_action::PUT_FILE; action.user_data = user_data; - action.filepath = filepath; - action.path = folder; + action.local = local; + action.remote = remote; action.progress_callback = callback; usblink_queue_add(action); @@ -196,7 +196,7 @@ void usblink_queue_send_os(std::string filepath, usblink_progress_cb callback, v usblink_queue_action action; action.action = usblink_queue_action::SEND_OS; action.user_data = user_data; - action.filepath = filepath; + action.local = filepath; action.progress_callback = callback; usblink_queue_add(action); @@ -207,7 +207,7 @@ void usblink_queue_new_dir(std::string path, usblink_progress_cb callback, void usblink_queue_action action; action.action = usblink_queue_action::NEW_DIR; action.user_data = user_data; - action.path = path; + action.remote = path; action.progress_callback = callback, usblink_queue_add(action); @@ -218,8 +218,8 @@ void usblink_queue_move(std::string old_path, std::string new_path, usblink_prog usblink_queue_action action; action.action = usblink_queue_action::MOVE; action.user_data = user_data; - action.filepath = old_path; - action.path = new_path; + action.local = old_path; + action.remote = new_path; action.progress_callback = callback, usblink_queue_add(action); diff --git a/core/usblink_queue.h b/core/usblink_queue.h index 45dad052..cf8df3e2 100644 --- a/core/usblink_queue.h +++ b/core/usblink_queue.h @@ -13,7 +13,7 @@ void usblink_queue_delete(std::string path, bool is_dir, usblink_progress_cb callback, void *user_data); void usblink_queue_dirlist(std::string path, usblink_dirlist_cb callback, void *user_data); void usblink_queue_download(std::string path, std::string destpath, usblink_progress_cb callback, void *user_data); -void usblink_queue_put_file(std::string filepath, std::string folder, usblink_progress_cb callback, void *user_data); +void usblink_queue_put_file(std::string local, std::string remote, usblink_progress_cb callback, void *user_data); void usblink_queue_move(std::string old_path, std::string new_path, usblink_progress_cb callback, void *user_data); void usblink_queue_new_dir(std::string path, usblink_progress_cb callback, void *user_data); void usblink_queue_send_os(std::string filepath, usblink_progress_cb callback, void *user_data); diff --git a/mainwindow.cpp b/mainwindow.cpp index 7e42a95c..1a8a577d 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -98,6 +98,7 @@ MainWindow::MainWindow(QWidget *parent) : connect(&lcd, SIGNAL(closed()), ui->actionLCD_Window, SLOT(toggle())); connect(ui->actionXModem, SIGNAL(triggered()), this, SLOT(xmodemSend())); connect(ui->actionSwitch_to_Mobile_UI, SIGNAL(triggered()), this, SLOT(switchToMobileUI())); + connect(ui->actionLeavePTT, &QAction::triggered, the_qml_bridge, &QMLBridge::sendExitPTT); ui->actionConnect->setShortcut(QKeySequence(Qt::Key_F10)); ui->actionConnect->setAutoRepeat(false); @@ -288,8 +289,9 @@ void MainWindow::dropEvent(QDropEvent *e) for(auto &&url : mime_data->urls()) { - auto local = QDir::toNativeSeparators(url.toLocalFile()).toStdString(); - usblink_queue_put_file(local, the_qml_bridge->getUSBDir().toStdString(), usblink_progress_callback, this); + auto local = QDir::toNativeSeparators(url.toLocalFile()); + auto remote = the_qml_bridge->getUSBDir() + QLatin1Char('/') + QFileInfo(local).fileName(); + usblink_queue_put_file(local.toStdString(), remote.toStdString(), usblink_progress_callback, this); } } @@ -494,6 +496,7 @@ void MainWindow::updateUIActionState(bool emulation_running) ui->actionConnect->setEnabled(emulation_running); ui->actionDebugger->setEnabled(emulation_running); ui->actionXModem->setEnabled(emulation_running); + ui->actionLeavePTT->setEnabled(emulation_running); ui->actionSuspend->setEnabled(emulation_running); ui->actionSuspend_to_file->setEnabled(emulation_running); diff --git a/mainwindow.ui b/mainwindow.ui index 2daea3ba..ddda493c 100644 --- a/mainwindow.ui +++ b/mainwindow.ui @@ -451,6 +451,7 @@ + @@ -662,6 +663,11 @@ Switch to Mobile UI + + + Leave &PTT + + diff --git a/qml/ConfigPageFileTransfer.qml b/qml/ConfigPageFileTransfer.qml index b20a1480..0b0b77ea 100644 --- a/qml/ConfigPageFileTransfer.qml +++ b/qml/ConfigPageFileTransfer.qml @@ -61,11 +61,13 @@ ColumnLayout { } } - ProgressBar { - id: transferProgress - Layout.fillWidth: true - minimumValue: 0 - maximumValue: 100 + Button { + text: qsTr("Leave Press-to-Test mode") + Layout.topMargin: 5 + Layout.bottomMargin: 5 + onClicked: { + Emu.sendExitPTT(); + } } } @@ -86,10 +88,11 @@ ColumnLayout { Connections { target: Emu function onUsblinkProgressChanged(percent) { - if(percent < 0) + if(percent < 0) { transferStatus.text = qsTr("Failed!"); - else - { + transferProgress.value = 0; + transferProgress.indeterminate = false; + } else { transferStatus.text = (percent >= 100) ? qsTr("Done!") : (percent + "%"); transferProgress.value = percent; transferProgress.indeterminate = false; @@ -98,6 +101,13 @@ ColumnLayout { } } + ProgressBar { + id: transferProgress + Layout.fillWidth: true + minimumValue: 0 + maximumValue: 100 + } + FBLabel { text: qsTr("Target Directory") font.pixelSize: TextMetrics.title2Size diff --git a/qmlbridge.cpp b/qmlbridge.cpp index f1233f9e..d0c11b1c 100644 --- a/qmlbridge.cpp +++ b/qmlbridge.cpp @@ -278,7 +278,15 @@ bool QMLBridge::isMobile() void QMLBridge::sendFile(QUrl url, QString dir) { - usblink_queue_put_file(toLocalFile(url).toStdString(), dir.toStdString(), QMLBridge::usblink_progress_changed, this); + auto local = toLocalFile(url); + auto remote = dir + QLatin1Char('/') + basename(local); + usblink_queue_put_file(local.toStdString(), remote.toStdString(), QMLBridge::usblink_progress_changed, this); +} + +void QMLBridge::sendExitPTT() +{ + usblink_queue_new_dir("/Press-to-Test", nullptr, nullptr); + usblink_queue_put_file(std::string(), "/Press-to-Test/Exit Test Mode.tns", QMLBridge::usblink_progress_changed, this); } QString QMLBridge::basename(QString path) diff --git a/qmlbridge.h b/qmlbridge.h index bac8576d..606a2ada 100644 --- a/qmlbridge.h +++ b/qmlbridge.h @@ -86,6 +86,7 @@ class QMLBridge : public QObject Q_INVOKABLE bool isMobile(); Q_INVOKABLE void sendFile(QUrl url, QString dir); + Q_INVOKABLE void sendExitPTT(); // Various utility functions Q_INVOKABLE QString basename(QString path); diff --git a/usblinktreewidget.cpp b/usblinktreewidget.cpp index 14231c24..4ec58e47 100644 --- a/usblinktreewidget.cpp +++ b/usblinktreewidget.cpp @@ -174,11 +174,12 @@ bool USBLinkTreeWidget::dropMimeData(QTreeWidgetItem *parent, int index, const Q (void) index; (void) action; - auto parentDir = usblink_path_item(parent).toStdString(); + auto parentDir = usblink_path_item(parent); for(auto &&url : data->urls()) { - auto local = QDir::toNativeSeparators(url.toLocalFile()).toStdString(); - usblink_queue_put_file(local, parentDir, usblink_upload_callback, this); + auto local = QDir::toNativeSeparators(url.toLocalFile()); + auto remote = parentDir + QLatin1Char('/') + QFileInfo(local).fileName(); + usblink_queue_put_file(local.toStdString(), parentDir.toStdString(), usblink_upload_callback, this); } return true;