[FL-878] Gui: screen streaming (#337)
* GUI: canvas streaming * Fix right status bar icon alignment
This commit is contained in:
parent
b835d7a451
commit
23f66c2cdd
@ -11,6 +11,8 @@ typedef struct {
|
|||||||
FuriThread* thread;
|
FuriThread* thread;
|
||||||
ViewPort* view_port;
|
ViewPort* view_port;
|
||||||
const FlipperApplication* current_app;
|
const FlipperApplication* current_app;
|
||||||
|
Cli* cli;
|
||||||
|
Gui* gui;
|
||||||
} AppLoaderState;
|
} AppLoaderState;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -73,8 +75,8 @@ static void app_loader_cli_callback(string_t args, void* _ctx) {
|
|||||||
|
|
||||||
printf("Press any key to kill application");
|
printf("Press any key to kill application");
|
||||||
|
|
||||||
char c;
|
cli_getc(ctx->state->cli);
|
||||||
cli_read(&c, 1);
|
|
||||||
furi_thread_terminate(ctx->state->thread);
|
furi_thread_terminate(ctx->state->thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,10 +101,10 @@ int32_t app_loader(void* p) {
|
|||||||
view_port_input_callback_set(state.view_port, app_loader_input_callback, &state);
|
view_port_input_callback_set(state.view_port, app_loader_input_callback, &state);
|
||||||
|
|
||||||
ValueMutex* menu_mutex = furi_record_open("menu");
|
ValueMutex* menu_mutex = furi_record_open("menu");
|
||||||
Cli* cli = furi_record_open("cli");
|
state.cli = furi_record_open("cli");
|
||||||
Gui* gui = furi_record_open("gui");
|
state.gui = furi_record_open("gui");
|
||||||
|
|
||||||
gui_add_view_port(gui, state.view_port, GuiLayerFullscreen);
|
gui_add_view_port(state.gui, state.view_port, GuiLayerFullscreen);
|
||||||
|
|
||||||
// Main menu
|
// Main menu
|
||||||
with_value_mutex(
|
with_value_mutex(
|
||||||
@ -124,7 +126,8 @@ int32_t app_loader(void* p) {
|
|||||||
string_t cli_name;
|
string_t cli_name;
|
||||||
string_init_set_str(cli_name, "app_");
|
string_init_set_str(cli_name, "app_");
|
||||||
string_cat_str(cli_name, FLIPPER_APPS[i].name);
|
string_cat_str(cli_name, FLIPPER_APPS[i].name);
|
||||||
cli_add_command(cli, string_get_cstr(cli_name), app_loader_cli_callback, ctx);
|
cli_add_command(
|
||||||
|
state.cli, string_get_cstr(cli_name), app_loader_cli_callback, ctx);
|
||||||
string_clear(cli_name);
|
string_clear(cli_name);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -170,7 +173,8 @@ int32_t app_loader(void* p) {
|
|||||||
string_t cli_name;
|
string_t cli_name;
|
||||||
string_init_set_str(cli_name, "app_");
|
string_init_set_str(cli_name, "app_");
|
||||||
string_cat_str(cli_name, FLIPPER_PLUGINS[i].name);
|
string_cat_str(cli_name, FLIPPER_PLUGINS[i].name);
|
||||||
cli_add_command(cli, string_get_cstr(cli_name), app_loader_cli_callback, ctx);
|
cli_add_command(
|
||||||
|
state.cli, string_get_cstr(cli_name), app_loader_cli_callback, ctx);
|
||||||
string_clear(cli_name);
|
string_clear(cli_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,8 +40,12 @@ void cli_stdout_callback(void* _cookie, const char* data, size_t size) {
|
|||||||
api_hal_vcp_tx((const uint8_t*)data, size);
|
api_hal_vcp_tx((const uint8_t*)data, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cli_read(char* buffer, size_t size) {
|
void cli_write(Cli* cli, uint8_t* buffer, size_t size) {
|
||||||
api_hal_vcp_rx((uint8_t*)buffer, size);
|
return api_hal_vcp_tx(buffer, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t cli_read(Cli* cli, uint8_t* buffer, size_t size) {
|
||||||
|
return api_hal_vcp_rx(buffer, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cli_print_version() {
|
void cli_print_version() {
|
||||||
|
@ -27,12 +27,29 @@ typedef void (*CliCallback)(string_t args, void* context);
|
|||||||
*/
|
*/
|
||||||
void cli_add_command(Cli* cli, const char* name, CliCallback callback, void* context);
|
void cli_add_command(Cli* cli, const char* name, CliCallback callback, void* context);
|
||||||
|
|
||||||
/* Read terminal input.
|
/* Read from terminal
|
||||||
* Do it only from inside of callback.
|
* Do it only from inside of cli call.
|
||||||
* @param buffer - buffer pointer to char buffer
|
* @param cli - Cli instance
|
||||||
|
* @param buffer - pointer to buffer
|
||||||
* @param size - size of buffer in bytes
|
* @param size - size of buffer in bytes
|
||||||
|
* @return bytes written
|
||||||
*/
|
*/
|
||||||
void cli_read(char* buffer, size_t size);
|
size_t cli_read(Cli* cli, uint8_t* buffer, size_t size);
|
||||||
|
|
||||||
|
/* Write to terminal
|
||||||
|
* Do it only from inside of cli call.
|
||||||
|
* @param cli - Cli instance
|
||||||
|
* @param buffer - pointer to buffer
|
||||||
|
* @param size - size of buffer in bytes
|
||||||
|
* @return bytes written
|
||||||
|
*/
|
||||||
|
void cli_write(Cli* cli, uint8_t* buffer, size_t size);
|
||||||
|
|
||||||
|
/* Read character
|
||||||
|
* @param cli - Cli instance
|
||||||
|
* @return char
|
||||||
|
*/
|
||||||
|
char cli_getc(Cli* cli);
|
||||||
|
|
||||||
/* New line
|
/* New line
|
||||||
* Send new ine sequence
|
* Send new ine sequence
|
||||||
|
@ -38,6 +38,5 @@ Cli* cli_alloc();
|
|||||||
void cli_free(Cli* cli);
|
void cli_free(Cli* cli);
|
||||||
void cli_reset_state(Cli* cli);
|
void cli_reset_state(Cli* cli);
|
||||||
void cli_print_version();
|
void cli_print_version();
|
||||||
char cli_getc(Cli* cli);
|
|
||||||
void cli_putc(char c);
|
void cli_putc(char c);
|
||||||
void cli_stdout_callback(void* _cookie, const char* data, size_t size);
|
void cli_stdout_callback(void* _cookie, const char* data, size_t size);
|
||||||
|
@ -39,6 +39,16 @@ void canvas_commit(Canvas* canvas) {
|
|||||||
u8g2_SendBuffer(&canvas->fb);
|
u8g2_SendBuffer(&canvas->fb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8_t* canvas_get_buffer(Canvas* canvas) {
|
||||||
|
furi_assert(canvas);
|
||||||
|
return u8g2_GetBufferPtr(&canvas->fb);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t canvas_get_buffer_size(Canvas* canvas) {
|
||||||
|
furi_assert(canvas);
|
||||||
|
return u8g2_GetBufferTileWidth(&canvas->fb) * u8g2_GetBufferTileHeight(&canvas->fb) * 8;
|
||||||
|
}
|
||||||
|
|
||||||
void canvas_frame_set(
|
void canvas_frame_set(
|
||||||
Canvas* canvas,
|
Canvas* canvas,
|
||||||
uint8_t offset_x,
|
uint8_t offset_x,
|
||||||
|
@ -31,6 +31,18 @@ void canvas_reset(Canvas* canvas);
|
|||||||
*/
|
*/
|
||||||
void canvas_commit(Canvas* canvas);
|
void canvas_commit(Canvas* canvas);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get canvas buffer.
|
||||||
|
* @return pointer to buffer
|
||||||
|
*/
|
||||||
|
uint8_t* canvas_get_buffer(Canvas* canvas);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get canvas buffer size.
|
||||||
|
* @return size of canvas in bytes
|
||||||
|
*/
|
||||||
|
size_t canvas_get_buffer_size(Canvas* canvas);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set drawing region relative to real screen buffer
|
* Set drawing region relative to real screen buffer
|
||||||
*/
|
*/
|
||||||
|
@ -59,7 +59,7 @@ void gui_redraw_status_bar(Gui* gui) {
|
|||||||
uint8_t width;
|
uint8_t width;
|
||||||
ViewPort* view_port;
|
ViewPort* view_port;
|
||||||
// Right side
|
// Right side
|
||||||
x = 128;
|
x = GUI_DISPLAY_WIDTH + 2;
|
||||||
ViewPortArray_it(it, gui->layers[GuiLayerStatusBarRight]);
|
ViewPortArray_it(it, gui->layers[GuiLayerStatusBarRight]);
|
||||||
while(!ViewPortArray_end_p(it) && x_used < GUI_STATUS_BAR_WIDTH) {
|
while(!ViewPortArray_end_p(it) && x_used < GUI_STATUS_BAR_WIDTH) {
|
||||||
// Render view_port;
|
// Render view_port;
|
||||||
@ -127,6 +127,12 @@ void gui_redraw(Gui* gui) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
canvas_commit(gui->canvas);
|
canvas_commit(gui->canvas);
|
||||||
|
if(gui->canvas_callback) {
|
||||||
|
gui->canvas_callback(
|
||||||
|
canvas_get_buffer(gui->canvas),
|
||||||
|
canvas_get_buffer_size(gui->canvas),
|
||||||
|
gui->canvas_callback_context);
|
||||||
|
}
|
||||||
gui_unlock(gui);
|
gui_unlock(gui);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -159,6 +165,27 @@ void gui_unlock(Gui* gui) {
|
|||||||
furi_check(osMutexRelease(gui->mutex) == osOK);
|
furi_check(osMutexRelease(gui->mutex) == osOK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void gui_cli_screen_stream_callback(uint8_t* data, size_t size, void* context) {
|
||||||
|
furi_assert(data);
|
||||||
|
furi_assert(size == 1024);
|
||||||
|
furi_assert(context);
|
||||||
|
|
||||||
|
Gui* gui = context;
|
||||||
|
uint8_t magic[] = {0xF0, 0xE1, 0xD2, 0xC3};
|
||||||
|
cli_write(gui->cli, magic, sizeof(magic));
|
||||||
|
cli_write(gui->cli, data, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void gui_cli_screen_stream(string_t args, void* context) {
|
||||||
|
furi_assert(context);
|
||||||
|
Gui* gui = context;
|
||||||
|
gui_set_framebuffer_callback_context(gui, gui);
|
||||||
|
gui_set_framebuffer_callback(gui, gui_cli_screen_stream_callback);
|
||||||
|
cli_getc(gui->cli);
|
||||||
|
gui_set_framebuffer_callback(gui, NULL);
|
||||||
|
gui_set_framebuffer_callback_context(gui, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
void gui_add_view_port(Gui* gui, ViewPort* view_port, GuiLayer layer) {
|
void gui_add_view_port(Gui* gui, ViewPort* view_port, GuiLayer layer) {
|
||||||
furi_assert(gui);
|
furi_assert(gui);
|
||||||
furi_assert(view_port);
|
furi_assert(view_port);
|
||||||
@ -256,6 +283,16 @@ void gui_send_view_port_back(Gui* gui, ViewPort* view_port) {
|
|||||||
gui_unlock(gui);
|
gui_unlock(gui);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void gui_set_framebuffer_callback(Gui* gui, GuiCanvasCommitCallback callback) {
|
||||||
|
furi_assert(gui);
|
||||||
|
gui->canvas_callback = callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
void gui_set_framebuffer_callback_context(Gui* gui, void* context) {
|
||||||
|
furi_assert(gui);
|
||||||
|
gui->canvas_callback_context = context;
|
||||||
|
}
|
||||||
|
|
||||||
Gui* gui_alloc() {
|
Gui* gui_alloc() {
|
||||||
Gui* gui = furi_alloc(sizeof(Gui));
|
Gui* gui = furi_alloc(sizeof(Gui));
|
||||||
// Thread ID
|
// Thread ID
|
||||||
@ -276,6 +313,9 @@ Gui* gui_alloc() {
|
|||||||
gui->input_events = furi_record_open("input_events");
|
gui->input_events = furi_record_open("input_events");
|
||||||
furi_check(gui->input_events);
|
furi_check(gui->input_events);
|
||||||
subscribe_pubsub(gui->input_events, gui_input_events_callback, gui);
|
subscribe_pubsub(gui->input_events, gui_input_events_callback, gui);
|
||||||
|
// Cli
|
||||||
|
gui->cli = furi_record_open("cli");
|
||||||
|
cli_add_command(gui->cli, "screen_stream", gui_cli_screen_stream, gui);
|
||||||
|
|
||||||
return gui;
|
return gui;
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Gui layers */
|
||||||
typedef enum {
|
typedef enum {
|
||||||
GuiLayerNone, /* Special layer for internal use only */
|
GuiLayerNone, /* Special layer for internal use only */
|
||||||
|
|
||||||
@ -18,6 +19,9 @@ typedef enum {
|
|||||||
GuiLayerMAX /* Don't use or move, special value */
|
GuiLayerMAX /* Don't use or move, special value */
|
||||||
} GuiLayer;
|
} GuiLayer;
|
||||||
|
|
||||||
|
/* Gui frame buffer callback */
|
||||||
|
typedef void (*GuiCanvasCommitCallback)(uint8_t* data, size_t size, void* context);
|
||||||
|
|
||||||
typedef struct Gui Gui;
|
typedef struct Gui Gui;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -34,18 +38,32 @@ void gui_remove_view_port(Gui* gui, ViewPort* view_port);
|
|||||||
|
|
||||||
/* Send ViewPort to the front
|
/* Send ViewPort to the front
|
||||||
* Places selected ViewPort to the top of the drawing stack
|
* Places selected ViewPort to the top of the drawing stack
|
||||||
* @param gui, Gui instance
|
* @param gui - Gui instance
|
||||||
* @param view_port, ViewPort instance
|
* @param view_port - ViewPort instance
|
||||||
*/
|
*/
|
||||||
void gui_send_view_port_front(Gui* gui, ViewPort* view_port);
|
void gui_send_view_port_front(Gui* gui, ViewPort* view_port);
|
||||||
|
|
||||||
/* Send ViewPort to the back
|
/* Send ViewPort to the back
|
||||||
* Places selected ViewPort to the bottom of the drawing stack
|
* Places selected ViewPort to the bottom of the drawing stack
|
||||||
* @param gui, Gui instance
|
* @param gui - Gui instance
|
||||||
* @param view_port, ViewPort instance
|
* @param view_port - ViewPort instance
|
||||||
*/
|
*/
|
||||||
void gui_send_view_port_back(Gui* gui, ViewPort* view_port);
|
void gui_send_view_port_back(Gui* gui, ViewPort* view_port);
|
||||||
|
|
||||||
|
/* Set gui canvas commit callback
|
||||||
|
* This callback will be called upon Canvas commit
|
||||||
|
* Callback dispatched from GUI thread and is time critical
|
||||||
|
* @param gui - Gui instance
|
||||||
|
* @param callback - GuiCanvasCommitCallback
|
||||||
|
*/
|
||||||
|
void gui_set_framebuffer_callback(Gui* gui, GuiCanvasCommitCallback callback);
|
||||||
|
|
||||||
|
/* Set gui canvas commit callback context
|
||||||
|
* @param gui - Gui instance
|
||||||
|
* @param context - pointer to context
|
||||||
|
*/
|
||||||
|
void gui_set_framebuffer_callback_context(Gui* gui, void* context);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
#include <m-array.h>
|
#include <m-array.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <cli/cli.h>
|
||||||
#include "canvas.h"
|
#include "canvas.h"
|
||||||
#include "canvas_i.h"
|
#include "canvas_i.h"
|
||||||
#include "view_port.h"
|
#include "view_port.h"
|
||||||
@ -38,9 +39,13 @@ struct Gui {
|
|||||||
// Layers and Canvas
|
// Layers and Canvas
|
||||||
ViewPortArray_t layers[GuiLayerMAX];
|
ViewPortArray_t layers[GuiLayerMAX];
|
||||||
Canvas* canvas;
|
Canvas* canvas;
|
||||||
|
GuiCanvasCommitCallback canvas_callback;
|
||||||
|
void* canvas_callback_context;
|
||||||
// Input
|
// Input
|
||||||
osMessageQueueId_t input_queue;
|
osMessageQueueId_t input_queue;
|
||||||
PubSub* input_events;
|
PubSub* input_events;
|
||||||
|
// Cli
|
||||||
|
Cli* cli;
|
||||||
};
|
};
|
||||||
|
|
||||||
ViewPort* gui_view_port_find_enabled(ViewPortArray_t array);
|
ViewPort* gui_view_port_find_enabled(ViewPortArray_t array);
|
||||||
@ -58,3 +63,7 @@ void gui_input_events_callback(const void* value, void* ctx);
|
|||||||
void gui_lock(Gui* gui);
|
void gui_lock(Gui* gui);
|
||||||
|
|
||||||
void gui_unlock(Gui* gui);
|
void gui_unlock(Gui* gui);
|
||||||
|
|
||||||
|
void gui_cli_screen_stream_callback(uint8_t* data, size_t size, void* context);
|
||||||
|
|
||||||
|
void gui_cli_screen_stream(string_t args, void* context);
|
Loading…
x
Reference in New Issue
Block a user