mirror of
https://github.com/daveallie/crosspoint-reader.git
synced 2026-02-05 15:17:37 +03:00
add autoopen
This commit is contained in:
parent
6473689e3e
commit
2a1f7873f7
@ -24,11 +24,24 @@
|
|||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
void BluetoothActivity::taskTrampoline(void* param) {
|
void BluetoothActivity::displayTaskTrampoline(void* param) {
|
||||||
auto* self = static_cast<BluetoothActivity*>(param);
|
auto* self = static_cast<BluetoothActivity*>(param);
|
||||||
self->displayTaskLoop();
|
self->displayTaskLoop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BluetoothActivity::reportTaskTrampoline(void* param) {
|
||||||
|
auto* self = static_cast<BluetoothActivity*>(param);
|
||||||
|
self->report();
|
||||||
|
vTaskDelete(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BluetoothActivity::report() {
|
||||||
|
if (state != STATE_DONE) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
onFileReceived(OUTPUT_DIRECTORY "/" + filename);
|
||||||
|
}
|
||||||
|
|
||||||
void BluetoothActivity::startAdvertising() {
|
void BluetoothActivity::startAdvertising() {
|
||||||
NimBLEDevice::startAdvertising();
|
NimBLEDevice::startAdvertising();
|
||||||
}
|
}
|
||||||
@ -65,7 +78,7 @@ void BluetoothActivity::onEnter() {
|
|||||||
state = STATE_INITIALIZING;
|
state = STATE_INITIALIZING;
|
||||||
intoState(STATE_WAITING);
|
intoState(STATE_WAITING);
|
||||||
|
|
||||||
xTaskCreate(&BluetoothActivity::taskTrampoline, "BluetoothTask",
|
xTaskCreate(&BluetoothActivity::displayTaskTrampoline, "BluetoothTask",
|
||||||
// TODO: figure out how much stack we actually need
|
// TODO: figure out how much stack we actually need
|
||||||
4096, // Stack size
|
4096, // Stack size
|
||||||
this, // Parameters
|
this, // Parameters
|
||||||
@ -89,6 +102,16 @@ void BluetoothActivity::intoState(State newState) {
|
|||||||
// caller sets filename, totalBytes, file, txnId
|
// caller sets filename, totalBytes, file, txnId
|
||||||
receivedBytes = 0;
|
receivedBytes = 0;
|
||||||
break;
|
break;
|
||||||
|
case STATE_DONE:
|
||||||
|
// we cannot call onFileReceived here directly because it might cause onExit to be called,
|
||||||
|
// which calls NimBLEDevice::deinit, which cannot be called from inside a NimBLE callback.
|
||||||
|
xTaskCreate(&BluetoothActivity::reportTaskTrampoline, "BluetoothReportTask",
|
||||||
|
2048, // Stack size
|
||||||
|
this, // Parameters
|
||||||
|
1, // Priority,
|
||||||
|
nullptr
|
||||||
|
);
|
||||||
|
break;
|
||||||
case STATE_ERROR:
|
case STATE_ERROR:
|
||||||
{
|
{
|
||||||
// caller sets errorMessage
|
// caller sets errorMessage
|
||||||
@ -131,7 +154,7 @@ void BluetoothActivity::loop() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state == STATE_ERROR) {
|
if (state == STATE_ERROR || state == STATE_DONE) {
|
||||||
if (mappedInput.wasPressed(MappedInputManager::Button::Confirm)) {
|
if (mappedInput.wasPressed(MappedInputManager::Button::Confirm)) {
|
||||||
// restart
|
// restart
|
||||||
intoState(STATE_WAITING);
|
intoState(STATE_WAITING);
|
||||||
@ -207,7 +230,7 @@ void BluetoothActivity::render() const {
|
|||||||
// Draw help text at bottom
|
// Draw help text at bottom
|
||||||
const auto labels = mappedInput.mapLabels(
|
const auto labels = mappedInput.mapLabels(
|
||||||
"« Back",
|
"« Back",
|
||||||
(state == STATE_ERROR) ? "Restart" : "",
|
(state == STATE_ERROR || state == STATE_DONE) ? "Restart" : "",
|
||||||
"",
|
"",
|
||||||
""
|
""
|
||||||
);
|
);
|
||||||
@ -227,8 +250,9 @@ void BluetoothActivity::ServerCallbacks::onDisconnect(NimBLEServer* pServer, Nim
|
|||||||
}
|
}
|
||||||
|
|
||||||
void BluetoothActivity::onConnected(bool isConnected) {
|
void BluetoothActivity::onConnected(bool isConnected) {
|
||||||
if (state == STATE_ERROR) {
|
if (state == STATE_ERROR || state == STATE_DONE) {
|
||||||
// stay in error state so the user can read the error message even after disconnect
|
// stay in error state so the user can read the error message even after disconnect.
|
||||||
|
// stay in done state so the user can see the transfer complete message.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -310,7 +334,6 @@ void BluetoothActivity::onRequest(lfbt_message* msg, size_t msg_len) {
|
|||||||
if (receivedBytes >= totalBytes) {
|
if (receivedBytes >= totalBytes) {
|
||||||
PROTOCOL_ASSERT(receivedBytes == totalBytes, "Got more bytes than expected: %zu > %zu", receivedBytes, totalBytes);
|
PROTOCOL_ASSERT(receivedBytes == totalBytes, "Got more bytes than expected: %zu > %zu", receivedBytes, totalBytes);
|
||||||
PROTOCOL_ASSERT(file.close(), "Couldn't finalize writing the file");
|
PROTOCOL_ASSERT(file.close(), "Couldn't finalize writing the file");
|
||||||
// TODO: automatically open file in reader
|
|
||||||
intoState(STATE_DONE);
|
intoState(STATE_DONE);
|
||||||
} else {
|
} else {
|
||||||
intoState(STATE_RECEIVING);
|
intoState(STATE_RECEIVING);
|
||||||
|
|||||||
@ -45,17 +45,22 @@ typedef struct __attribute__((packed)) {
|
|||||||
* BluetoothActivity receives files over a custom BLE protocol and stores them on the SD card.
|
* BluetoothActivity receives files over a custom BLE protocol and stores them on the SD card.
|
||||||
*
|
*
|
||||||
* The onCancel callback is called if the user presses back.
|
* The onCancel callback is called if the user presses back.
|
||||||
|
* onFileReceived is called when a file is successfully received with the path to the file.
|
||||||
*/
|
*/
|
||||||
class BluetoothActivity final : public Activity {
|
class BluetoothActivity final : public Activity {
|
||||||
TaskHandle_t displayTaskHandle = nullptr;
|
TaskHandle_t displayTaskHandle = nullptr;
|
||||||
SemaphoreHandle_t renderingMutex = nullptr;
|
SemaphoreHandle_t renderingMutex = nullptr;
|
||||||
bool updateRequired = false;
|
bool updateRequired = false;
|
||||||
const std::function<void()> onCancel;
|
const std::function<void()> onCancel;
|
||||||
|
const std::function<void(const std::string&)> onFileReceived;
|
||||||
|
|
||||||
static void taskTrampoline(void* param);
|
static void displayTaskTrampoline(void* param);
|
||||||
[[noreturn]] void displayTaskLoop();
|
[[noreturn]] void displayTaskLoop();
|
||||||
void render() const;
|
void render() const;
|
||||||
|
|
||||||
|
static void reportTaskTrampoline(void* param);
|
||||||
|
void report();
|
||||||
|
|
||||||
void onConnected(bool isConnected);
|
void onConnected(bool isConnected);
|
||||||
void onRequest(lfbt_message *msg, size_t msg_len);
|
void onRequest(lfbt_message *msg, size_t msg_len);
|
||||||
|
|
||||||
@ -113,8 +118,9 @@ class BluetoothActivity final : public Activity {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
explicit BluetoothActivity(GfxRenderer& renderer, MappedInputManager& mappedInput,
|
explicit BluetoothActivity(GfxRenderer& renderer, MappedInputManager& mappedInput,
|
||||||
const std::function<void()>& onCancel)
|
const std::function<void()>& onCancel,
|
||||||
: Activity("Bluetooth", renderer, mappedInput), onCancel(onCancel),
|
const std::function<void(const std::string&)>& onFileReceived)
|
||||||
|
: Activity("Bluetooth", renderer, mappedInput), onCancel(onCancel), onFileReceived(onFileReceived),
|
||||||
serverCallbacks(this), requestCallbacks(this) {}
|
serverCallbacks(this), requestCallbacks(this) {}
|
||||||
void onEnter() override;
|
void onEnter() override;
|
||||||
void onExit() override;
|
void onExit() override;
|
||||||
|
|||||||
13
src/main.cpp
13
src/main.cpp
@ -26,6 +26,7 @@
|
|||||||
#include "activities/settings/SettingsActivity.h"
|
#include "activities/settings/SettingsActivity.h"
|
||||||
#include "activities/util/FullScreenMessageActivity.h"
|
#include "activities/util/FullScreenMessageActivity.h"
|
||||||
#include "fontIds.h"
|
#include "fontIds.h"
|
||||||
|
#include "util/StringUtils.h"
|
||||||
|
|
||||||
#define SPI_FQ 40000000
|
#define SPI_FQ 40000000
|
||||||
// Display SPI pins (custom pins for XteinkX4, not hardware SPI defaults)
|
// Display SPI pins (custom pins for XteinkX4, not hardware SPI defaults)
|
||||||
@ -229,7 +230,17 @@ void onGoToFileTransfer() {
|
|||||||
|
|
||||||
void onGoToBluetooth() {
|
void onGoToBluetooth() {
|
||||||
exitActivity();
|
exitActivity();
|
||||||
enterNewActivity(new BluetoothActivity(renderer, mappedInputManager, onGoHome));
|
enterNewActivity(new BluetoothActivity(
|
||||||
|
renderer,
|
||||||
|
mappedInputManager,
|
||||||
|
onGoHome,
|
||||||
|
[](const std::string& filepath) {
|
||||||
|
Serial.printf("[%lu] [ ] File received over Bluetooth: %s\n", millis(), filepath.c_str());
|
||||||
|
if (StringUtils::readableFileExtension(filepath)) {
|
||||||
|
onGoToReader(filepath, MyLibraryActivity::Tab::Recent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
void onGoToSettings() {
|
void onGoToSettings() {
|
||||||
|
|||||||
@ -61,6 +61,11 @@ bool checkFileExtension(const String& fileName, const char* extension) {
|
|||||||
return localFile.endsWith(localExtension);
|
return localFile.endsWith(localExtension);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool readableFileExtension(const std::string& fileName) {
|
||||||
|
return (StringUtils::checkFileExtension(fileName, ".epub") || StringUtils::checkFileExtension(fileName, ".xtch") ||
|
||||||
|
StringUtils::checkFileExtension(fileName, ".xtc") || StringUtils::checkFileExtension(fileName, ".txt"));
|
||||||
|
}
|
||||||
|
|
||||||
std::pair<std::string, std::string> splitFileName(const std::string& name) {
|
std::pair<std::string, std::string> splitFileName(const std::string& name) {
|
||||||
size_t lastDot = name.find_last_of('.');
|
size_t lastDot = name.find_last_of('.');
|
||||||
if (lastDot == std::string::npos) {
|
if (lastDot == std::string::npos) {
|
||||||
|
|||||||
@ -19,6 +19,11 @@ std::string sanitizeFilename(const std::string& name, size_t maxLength = 100);
|
|||||||
bool checkFileExtension(const std::string& fileName, const char* extension);
|
bool checkFileExtension(const std::string& fileName, const char* extension);
|
||||||
bool checkFileExtension(const String& fileName, const char* extension);
|
bool checkFileExtension(const String& fileName, const char* extension);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the given filename ends with an extension we can open.
|
||||||
|
*/
|
||||||
|
bool readableFileExtension(const std::string& fileName);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Split a filename into base name and extension.
|
* Split a filename into base name and extension.
|
||||||
* If there is no extension, the second element of the pair will be an empty string.
|
* If there is no extension, the second element of the pair will be an empty string.
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user