mirror of
https://github.com/DarkFlippers/unleashed-firmware
synced 2024-11-27 15:00:46 +00:00
Youtube shorts remote, swap tiktok control buttons
This commit is contained in:
parent
bd199c63ab
commit
3191b32708
6 changed files with 312 additions and 8 deletions
19
applications/external/hid_app/hid.c
vendored
19
applications/external/hid_app/hid.c
vendored
|
@ -10,6 +10,7 @@ enum HidDebugSubmenuIndex {
|
|||
HidSubmenuIndexKeyboard,
|
||||
HidSubmenuIndexMedia,
|
||||
HidSubmenuIndexTikTok,
|
||||
HidSubmenuIndexYTShorts,
|
||||
HidSubmenuIndexMouse,
|
||||
HidSubmenuIndexMouseJiggler,
|
||||
};
|
||||
|
@ -32,6 +33,9 @@ static void hid_submenu_callback(void* context, uint32_t index) {
|
|||
} else if(index == HidSubmenuIndexTikTok) {
|
||||
app->view_id = BtHidViewTikTok;
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, BtHidViewTikTok);
|
||||
} else if(index == HidSubmenuIndexYTShorts) {
|
||||
app->view_id = BtHidViewYTShorts;
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, BtHidViewYTShorts);
|
||||
} else if(index == HidSubmenuIndexMouseJiggler) {
|
||||
app->view_id = HidViewMouseJiggler;
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, HidViewMouseJiggler);
|
||||
|
@ -55,6 +59,7 @@ static void bt_hid_connection_status_changed_callback(BtStatus status, void* con
|
|||
hid_mouse_set_connected_status(hid->hid_mouse, connected);
|
||||
hid_mouse_jiggler_set_connected_status(hid->hid_mouse_jiggler, connected);
|
||||
hid_tiktok_set_connected_status(hid->hid_tiktok, connected);
|
||||
hid_ytshorts_set_connected_status(hid->hid_ytshorts, connected);
|
||||
}
|
||||
|
||||
static void hid_dialog_callback(DialogExResult result, void* context) {
|
||||
|
@ -113,6 +118,12 @@ Hid* hid_alloc(HidTransport transport) {
|
|||
HidSubmenuIndexTikTok,
|
||||
hid_submenu_callback,
|
||||
app);
|
||||
submenu_add_item(
|
||||
app->device_type_submenu,
|
||||
"YT Shorts Controller",
|
||||
HidSubmenuIndexYTShorts,
|
||||
hid_submenu_callback,
|
||||
app);
|
||||
}
|
||||
submenu_add_item(
|
||||
app->device_type_submenu,
|
||||
|
@ -166,6 +177,12 @@ Hid* hid_app_alloc_view(void* context) {
|
|||
view_dispatcher_add_view(
|
||||
app->view_dispatcher, BtHidViewTikTok, hid_tiktok_get_view(app->hid_tiktok));
|
||||
|
||||
// YTShorts view
|
||||
app->hid_ytshorts = hid_ytshorts_alloc(app);
|
||||
view_set_previous_callback(hid_ytshorts_get_view(app->hid_ytshorts), hid_exit_confirm_view);
|
||||
view_dispatcher_add_view(
|
||||
app->view_dispatcher, BtHidViewYTShorts, hid_ytshorts_get_view(app->hid_ytshorts));
|
||||
|
||||
// Mouse view
|
||||
app->hid_mouse = hid_mouse_alloc(app);
|
||||
view_set_previous_callback(hid_mouse_get_view(app->hid_mouse), hid_exit_confirm_view);
|
||||
|
@ -209,6 +226,8 @@ void hid_free(Hid* app) {
|
|||
hid_mouse_jiggler_free(app->hid_mouse_jiggler);
|
||||
view_dispatcher_remove_view(app->view_dispatcher, BtHidViewTikTok);
|
||||
hid_tiktok_free(app->hid_tiktok);
|
||||
view_dispatcher_remove_view(app->view_dispatcher, BtHidViewYTShorts);
|
||||
hid_ytshorts_free(app->hid_ytshorts);
|
||||
view_dispatcher_free(app->view_dispatcher);
|
||||
|
||||
// Close records
|
||||
|
|
2
applications/external/hid_app/hid.h
vendored
2
applications/external/hid_app/hid.h
vendored
|
@ -22,6 +22,7 @@
|
|||
#include "views/hid_mouse.h"
|
||||
#include "views/hid_mouse_jiggler.h"
|
||||
#include "views/hid_tiktok.h"
|
||||
#include "views/hid_ytshorts.h"
|
||||
|
||||
#define HID_BT_KEYS_STORAGE_NAME ".bt_hid.keys"
|
||||
|
||||
|
@ -45,6 +46,7 @@ struct Hid {
|
|||
HidMouse* hid_mouse;
|
||||
HidMouseJiggler* hid_mouse_jiggler;
|
||||
HidTikTok* hid_tiktok;
|
||||
HidYTShorts* hid_ytshorts;
|
||||
|
||||
HidTransport transport;
|
||||
uint32_t view_id;
|
||||
|
|
1
applications/external/hid_app/views.h
vendored
1
applications/external/hid_app/views.h
vendored
|
@ -6,5 +6,6 @@ typedef enum {
|
|||
HidViewMouse,
|
||||
HidViewMouseJiggler,
|
||||
BtHidViewTikTok,
|
||||
BtHidViewYTShorts,
|
||||
HidViewExitConfirm,
|
||||
} HidView;
|
16
applications/external/hid_app/views/hid_tiktok.c
vendored
16
applications/external/hid_app/views/hid_tiktok.c
vendored
|
@ -187,20 +187,20 @@ static bool hid_tiktok_input_callback(InputEvent* event, void* context) {
|
|||
consumed = true;
|
||||
} else if(event->key == InputKeyDown) {
|
||||
// Swipe to new video
|
||||
hid_hal_mouse_scroll(hid_tiktok->hid, -6);
|
||||
hid_hal_mouse_scroll(hid_tiktok->hid, -12);
|
||||
hid_hal_mouse_scroll(hid_tiktok->hid, -19);
|
||||
hid_hal_mouse_scroll(hid_tiktok->hid, -12);
|
||||
hid_hal_mouse_scroll(hid_tiktok->hid, -6);
|
||||
consumed = true;
|
||||
} else if(event->key == InputKeyUp) {
|
||||
// Swipe to previous video
|
||||
hid_hal_mouse_scroll(hid_tiktok->hid, 6);
|
||||
hid_hal_mouse_scroll(hid_tiktok->hid, 12);
|
||||
hid_hal_mouse_scroll(hid_tiktok->hid, 19);
|
||||
hid_hal_mouse_scroll(hid_tiktok->hid, 12);
|
||||
hid_hal_mouse_scroll(hid_tiktok->hid, 6);
|
||||
consumed = true;
|
||||
} else if(event->key == InputKeyUp) {
|
||||
// Swipe to previous video
|
||||
hid_hal_mouse_scroll(hid_tiktok->hid, -6);
|
||||
hid_hal_mouse_scroll(hid_tiktok->hid, -12);
|
||||
hid_hal_mouse_scroll(hid_tiktok->hid, -19);
|
||||
hid_hal_mouse_scroll(hid_tiktok->hid, -12);
|
||||
hid_hal_mouse_scroll(hid_tiktok->hid, -6);
|
||||
consumed = true;
|
||||
} else if(event->key == InputKeyBack) {
|
||||
// Pause
|
||||
hid_hal_mouse_press(hid_tiktok->hid, HID_MOUSE_BTN_RIGHT);
|
||||
|
|
268
applications/external/hid_app/views/hid_ytshorts.c
vendored
Normal file
268
applications/external/hid_app/views/hid_ytshorts.c
vendored
Normal file
|
@ -0,0 +1,268 @@
|
|||
#include "hid_ytshorts.h"
|
||||
#include "../hid.h"
|
||||
#include <gui/elements.h>
|
||||
|
||||
#include "hid_icons.h"
|
||||
|
||||
#define TAG "HidYTShorts"
|
||||
|
||||
struct HidYTShorts {
|
||||
View* view;
|
||||
Hid* hid;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
bool left_pressed;
|
||||
bool up_pressed;
|
||||
bool right_pressed;
|
||||
bool down_pressed;
|
||||
bool ok_pressed;
|
||||
bool connected;
|
||||
bool is_cursor_set;
|
||||
bool back_mouse_pressed;
|
||||
HidTransport transport;
|
||||
} HidYTShortsModel;
|
||||
|
||||
static void hid_ytshorts_draw_callback(Canvas* canvas, void* context) {
|
||||
furi_assert(context);
|
||||
HidYTShortsModel* model = context;
|
||||
|
||||
// Header
|
||||
if(model->transport == HidTransportBle) {
|
||||
if(model->connected) {
|
||||
canvas_draw_icon(canvas, 0, 0, &I_Ble_connected_15x15);
|
||||
} else {
|
||||
canvas_draw_icon(canvas, 0, 0, &I_Ble_disconnected_15x15);
|
||||
}
|
||||
}
|
||||
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
elements_multiline_text_aligned(canvas, 17, 3, AlignLeft, AlignTop, "Shorts");
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
|
||||
// Keypad circles
|
||||
canvas_draw_icon(canvas, 66, 8, &I_Circles_47x47);
|
||||
|
||||
// Pause
|
||||
if(model->back_mouse_pressed) {
|
||||
canvas_set_bitmap_mode(canvas, 1);
|
||||
canvas_draw_icon(canvas, 106, 46, &I_Pressed_Button_13x13);
|
||||
canvas_set_bitmap_mode(canvas, 0);
|
||||
canvas_set_color(canvas, ColorWhite);
|
||||
}
|
||||
canvas_draw_icon(canvas, 108, 48, &I_Pause_icon_9x9);
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
|
||||
// Up
|
||||
if(model->up_pressed) {
|
||||
canvas_set_bitmap_mode(canvas, 1);
|
||||
canvas_draw_icon(canvas, 83, 9, &I_Pressed_Button_13x13);
|
||||
canvas_set_bitmap_mode(canvas, 0);
|
||||
canvas_set_color(canvas, ColorWhite);
|
||||
}
|
||||
canvas_draw_icon(canvas, 86, 11, &I_Arr_up_7x9);
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
|
||||
// Down
|
||||
if(model->down_pressed) {
|
||||
canvas_set_bitmap_mode(canvas, 1);
|
||||
canvas_draw_icon(canvas, 83, 41, &I_Pressed_Button_13x13);
|
||||
canvas_set_bitmap_mode(canvas, 0);
|
||||
canvas_set_color(canvas, ColorWhite);
|
||||
}
|
||||
canvas_draw_icon(canvas, 86, 44, &I_Arr_dwn_7x9);
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
|
||||
// Left
|
||||
if(model->left_pressed) {
|
||||
canvas_set_bitmap_mode(canvas, 1);
|
||||
canvas_draw_icon(canvas, 67, 25, &I_Pressed_Button_13x13);
|
||||
canvas_set_bitmap_mode(canvas, 0);
|
||||
canvas_set_color(canvas, ColorWhite);
|
||||
}
|
||||
canvas_draw_icon(canvas, 71, 29, &I_Voldwn_6x6);
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
|
||||
// Right
|
||||
if(model->right_pressed) {
|
||||
canvas_set_bitmap_mode(canvas, 1);
|
||||
canvas_draw_icon(canvas, 99, 25, &I_Pressed_Button_13x13);
|
||||
canvas_set_bitmap_mode(canvas, 0);
|
||||
canvas_set_color(canvas, ColorWhite);
|
||||
}
|
||||
canvas_draw_icon(canvas, 101, 29, &I_Volup_8x6);
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
|
||||
// Ok
|
||||
if(model->ok_pressed) {
|
||||
canvas_draw_icon(canvas, 81, 23, &I_Like_pressed_17x17);
|
||||
} else {
|
||||
canvas_draw_icon(canvas, 84, 27, &I_Like_def_11x9);
|
||||
}
|
||||
// Exit
|
||||
canvas_draw_icon(canvas, 0, 54, &I_Pin_back_arrow_10x8);
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
elements_multiline_text_aligned(canvas, 13, 62, AlignLeft, AlignBottom, "Hold to exit");
|
||||
}
|
||||
|
||||
static void hid_ytshorts_reset_cursor(HidYTShorts* hid_ytshorts) {
|
||||
// Set cursor to the phone's left up corner
|
||||
// Delays to guarantee one packet per connection interval
|
||||
for(size_t i = 0; i < 8; i++) {
|
||||
hid_hal_mouse_move(hid_ytshorts->hid, -127, -127);
|
||||
furi_delay_ms(50);
|
||||
}
|
||||
// Move cursor from the corner
|
||||
hid_hal_mouse_move(hid_ytshorts->hid, 40, 120);
|
||||
hid_hal_mouse_move(hid_ytshorts->hid, 0, 120);
|
||||
furi_delay_ms(50);
|
||||
}
|
||||
|
||||
static void hid_ytshorts_process_press(
|
||||
HidYTShorts* hid_ytshorts,
|
||||
HidYTShortsModel* model,
|
||||
InputEvent* event) {
|
||||
if(event->key == InputKeyUp) {
|
||||
model->up_pressed = true;
|
||||
} else if(event->key == InputKeyDown) {
|
||||
model->down_pressed = true;
|
||||
} else if(event->key == InputKeyLeft) {
|
||||
model->left_pressed = true;
|
||||
hid_hal_consumer_key_press(hid_ytshorts->hid, HID_CONSUMER_VOLUME_DECREMENT);
|
||||
} else if(event->key == InputKeyRight) {
|
||||
model->right_pressed = true;
|
||||
hid_hal_consumer_key_press(hid_ytshorts->hid, HID_CONSUMER_VOLUME_INCREMENT);
|
||||
} else if(event->key == InputKeyOk) {
|
||||
model->ok_pressed = true;
|
||||
} else if(event->key == InputKeyBack) {
|
||||
model->back_mouse_pressed = true;
|
||||
}
|
||||
}
|
||||
|
||||
static void hid_ytshorts_process_release(
|
||||
HidYTShorts* hid_ytshorts,
|
||||
HidYTShortsModel* model,
|
||||
InputEvent* event) {
|
||||
if(event->key == InputKeyUp) {
|
||||
model->up_pressed = false;
|
||||
} else if(event->key == InputKeyDown) {
|
||||
model->down_pressed = false;
|
||||
} else if(event->key == InputKeyLeft) {
|
||||
model->left_pressed = false;
|
||||
hid_hal_consumer_key_release(hid_ytshorts->hid, HID_CONSUMER_VOLUME_DECREMENT);
|
||||
} else if(event->key == InputKeyRight) {
|
||||
model->right_pressed = false;
|
||||
hid_hal_consumer_key_release(hid_ytshorts->hid, HID_CONSUMER_VOLUME_INCREMENT);
|
||||
} else if(event->key == InputKeyOk) {
|
||||
model->ok_pressed = false;
|
||||
} else if(event->key == InputKeyBack) {
|
||||
model->back_mouse_pressed = false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool hid_ytshorts_input_callback(InputEvent* event, void* context) {
|
||||
furi_assert(context);
|
||||
HidYTShorts* hid_ytshorts = context;
|
||||
bool consumed = false;
|
||||
|
||||
with_view_model(
|
||||
hid_ytshorts->view,
|
||||
HidYTShortsModel * model,
|
||||
{
|
||||
if(event->type == InputTypePress) {
|
||||
hid_ytshorts_process_press(hid_ytshorts, model, event);
|
||||
if(model->connected && !model->is_cursor_set) {
|
||||
hid_ytshorts_reset_cursor(hid_ytshorts);
|
||||
model->is_cursor_set = true;
|
||||
}
|
||||
consumed = true;
|
||||
} else if(event->type == InputTypeRelease) {
|
||||
hid_ytshorts_process_release(hid_ytshorts, model, event);
|
||||
consumed = true;
|
||||
} else if(event->type == InputTypeShort) {
|
||||
if(event->key == InputKeyOk) {
|
||||
hid_hal_mouse_press(hid_ytshorts->hid, HID_MOUSE_BTN_LEFT);
|
||||
furi_delay_ms(50);
|
||||
hid_hal_mouse_release(hid_ytshorts->hid, HID_MOUSE_BTN_LEFT);
|
||||
furi_delay_ms(50);
|
||||
hid_hal_mouse_press(hid_ytshorts->hid, HID_MOUSE_BTN_LEFT);
|
||||
furi_delay_ms(50);
|
||||
hid_hal_mouse_release(hid_ytshorts->hid, HID_MOUSE_BTN_LEFT);
|
||||
consumed = true;
|
||||
} else if(event->key == InputKeyDown) {
|
||||
// Swipe to new video
|
||||
hid_hal_mouse_scroll(hid_ytshorts->hid, 6);
|
||||
hid_hal_mouse_scroll(hid_ytshorts->hid, 8);
|
||||
hid_hal_mouse_scroll(hid_ytshorts->hid, 10);
|
||||
hid_hal_mouse_scroll(hid_ytshorts->hid, 8);
|
||||
hid_hal_mouse_scroll(hid_ytshorts->hid, 6);
|
||||
consumed = true;
|
||||
} else if(event->key == InputKeyUp) {
|
||||
// Swipe to previous video
|
||||
hid_hal_mouse_scroll(hid_ytshorts->hid, -6);
|
||||
hid_hal_mouse_scroll(hid_ytshorts->hid, -8);
|
||||
hid_hal_mouse_scroll(hid_ytshorts->hid, -10);
|
||||
hid_hal_mouse_scroll(hid_ytshorts->hid, -8);
|
||||
hid_hal_mouse_scroll(hid_ytshorts->hid, -6);
|
||||
consumed = true;
|
||||
} else if(event->key == InputKeyBack) {
|
||||
// Pause
|
||||
hid_hal_mouse_press(hid_ytshorts->hid, HID_MOUSE_BTN_LEFT);
|
||||
furi_delay_ms(50);
|
||||
hid_hal_mouse_release(hid_ytshorts->hid, HID_MOUSE_BTN_LEFT);
|
||||
furi_delay_ms(50);
|
||||
consumed = true;
|
||||
}
|
||||
} else if(event->type == InputTypeLong) {
|
||||
if(event->key == InputKeyBack) {
|
||||
hid_hal_consumer_key_release_all(hid_ytshorts->hid);
|
||||
model->is_cursor_set = false;
|
||||
consumed = false;
|
||||
}
|
||||
}
|
||||
},
|
||||
true);
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
HidYTShorts* hid_ytshorts_alloc(Hid* bt_hid) {
|
||||
HidYTShorts* hid_ytshorts = malloc(sizeof(HidYTShorts));
|
||||
hid_ytshorts->hid = bt_hid;
|
||||
hid_ytshorts->view = view_alloc();
|
||||
view_set_context(hid_ytshorts->view, hid_ytshorts);
|
||||
view_allocate_model(hid_ytshorts->view, ViewModelTypeLocking, sizeof(HidYTShortsModel));
|
||||
view_set_draw_callback(hid_ytshorts->view, hid_ytshorts_draw_callback);
|
||||
view_set_input_callback(hid_ytshorts->view, hid_ytshorts_input_callback);
|
||||
|
||||
with_view_model(
|
||||
hid_ytshorts->view,
|
||||
HidYTShortsModel * model,
|
||||
{ model->transport = bt_hid->transport; },
|
||||
true);
|
||||
|
||||
return hid_ytshorts;
|
||||
}
|
||||
|
||||
void hid_ytshorts_free(HidYTShorts* hid_ytshorts) {
|
||||
furi_assert(hid_ytshorts);
|
||||
view_free(hid_ytshorts->view);
|
||||
free(hid_ytshorts);
|
||||
}
|
||||
|
||||
View* hid_ytshorts_get_view(HidYTShorts* hid_ytshorts) {
|
||||
furi_assert(hid_ytshorts);
|
||||
return hid_ytshorts->view;
|
||||
}
|
||||
|
||||
void hid_ytshorts_set_connected_status(HidYTShorts* hid_ytshorts, bool connected) {
|
||||
furi_assert(hid_ytshorts);
|
||||
with_view_model(
|
||||
hid_ytshorts->view,
|
||||
HidYTShortsModel * model,
|
||||
{
|
||||
model->connected = connected;
|
||||
model->is_cursor_set = false;
|
||||
},
|
||||
true);
|
||||
}
|
14
applications/external/hid_app/views/hid_ytshorts.h
vendored
Normal file
14
applications/external/hid_app/views/hid_ytshorts.h
vendored
Normal file
|
@ -0,0 +1,14 @@
|
|||
#pragma once
|
||||
|
||||
#include <gui/view.h>
|
||||
|
||||
typedef struct Hid Hid;
|
||||
typedef struct HidYTShorts HidYTShorts;
|
||||
|
||||
HidYTShorts* hid_ytshorts_alloc(Hid* bt_hid);
|
||||
|
||||
void hid_ytshorts_free(HidYTShorts* hid_ytshorts);
|
||||
|
||||
View* hid_ytshorts_get_view(HidYTShorts* hid_ytshorts);
|
||||
|
||||
void hid_ytshorts_set_connected_status(HidYTShorts* hid_ytshorts, bool connected);
|
Loading…
Reference in a new issue