diff --git a/syncplay_chat.c b/syncplay_chat.c new file mode 100644 index 0000000..1a8ee98 --- /dev/null +++ b/syncplay_chat.c @@ -0,0 +1,228 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +/* VLC core API headers */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +const int64_t KEY_ACTION_MASK_ON = 0x7FFFFFFFFFFFFFFF; +const int64_t KEY_ACTION_MASK_OFF = 0; + +vlc_thread_t th; +input_thread_t *input = NULL; +vlc_mutex_t lock; +bool writing = false; +int port = 0; + +char message[200]; +int message_size = 0; + +static int GetPort(vlc_object_t* libvlc) { + char* lua_config = var_GetNonEmptyString(libvlc, "lua-config"); + if (!lua_config) return 0; + + char* config = malloc(strlen(lua_config) + 1); + strcpy(config, lua_config); + + char* prt = strstr(config, "port=") + 6; + if (!prt) return 0; + + *strchr(prt, '"') = '\0'; + int port = atoi(prt); + + free(config); + return port; +} + +// Changes the minimum and maximum value for the key-action thought simulating disabling the keyboard actions +static void SetKeyActionMask(vlc_object_t* libvlc, int64_t *max) { + int64_t min = 0; + var_Change( libvlc, "key-action", VLC_VAR_SETMINMAX, &min, max); +} + + +// Detect playlist change event and aquire the input +static int PlaylistEvent( vlc_object_t *p_this, char const *psz_var, + vlc_value_t oldval, vlc_value_t val, void *p_data ) +{ + input = val.p_address; + msg_Info(p_this, "Playlist state changed"); + port = GetPort(p_this->obj.libvlc); + return VLC_SUCCESS; +} + +// Updates OSD indirectly to avoid an unknown bug +static void ShowText(vlc_object_t* libvlc) { + var_SetInteger(libvlc, "syncplay-text", message_size); +} + +// Hides the text +static void HideText(vlc_object_t* libvlc) { + message_size = 0; + ShowText(libvlc); +} + +// Thread that currently draws the bliking cursor +static void *RunIntf(void*data) { + vlc_object_t* libvlc = data; + while(writing) { + // SHOW CURSOR + message[message_size] = '|'; + message[message_size + 1] = 0; + if (input != NULL) { + vout_OSDText(input_GetVout(input), 1, VOUT_ALIGN_TOP | VOUT_ALIGN_LEFT, 0xfffffffffff, message); + } + + for (int i=0; i < 10; i++) { + if (!writing) return; // REMOVE LATENCY -- Don't forget this is a thread + msleep(50000); + } + + // HIDE CURSOR + message[message_size] = 0; + if (input != NULL) { + vout_OSDText(input_GetVout(input), 1, VOUT_ALIGN_TOP | VOUT_ALIGN_LEFT, 0xfffffffffff, message); + } + for (int i=0; i < 10; i++) { + if (!writing) return; // REMOVE LATENCY -- Don't forget this is a thread + msleep(50000); + } + } +} + +// Display OSD text +static int SynplayText( vlc_object_t *libvlc, char const *psz_var, + vlc_value_t oldval, vlc_value_t newval, void *p_data ) +{ + if (input != NULL) { + message[message_size] = 0; + vout_OSDText(input_GetVout(input), 1, VOUT_ALIGN_TOP | VOUT_ALIGN_LEFT, 0xfffffffffff, message); + } + return 0; +} + +// Handle key events +static int KeyPressed( vlc_object_t *libvlc, char const *psz_var, + vlc_value_t oldval, vlc_value_t newval, void *p_data ) +{ + intf_thread_t *intf = (intf_thread_t *)p_data; + + msg_Info(intf, "Synclpay: keypressed"); + + int key_code = var_GetInteger(libvlc, "key-pressed"); + + int key = key_code & 0xffff; + int sup_key = (key_code >> 16) & 0xffff; + + // Some debug messages for ... debugging + + msg_Info(intf, "key Code: %d", key_code); + msg_Info(intf, "Key: %d", key); + msg_Info(intf, "Sup key: %d", sup_key); + msg_Info(intf, "config: %s", var_GetNonEmptyString(libvlc, "lua-config")); + msg_Info(intf, "port: %d", port); + + if (writing) { + switch(key) { + case KEY_BACKSPACE: + message_size > 0 ? message_size-- : 0; + break; + + case KEY_ENTER: + case KEY_ESC: + writing=false; + SetKeyActionMask(libvlc, &KEY_ACTION_MASK_ON); + break; + + default: + if (key <= 127) { + if (key == 32 && message_size > 0 && message[message_size - 1] != 32 || key != 32) { + char ch = key; + if (sup_key == 512 && isalpha(ch)) ch -= 0x20; + message[message_size++] = ch; + } + } + break; + } + + switch(key) { + case KEY_ENTER: + { + // Stops the thread + vlc_cancel(th); + + msg_Info(intf, "message: %s", message); + var_SetString(intf->obj.libvlc, "chat-message", message); + + } + case KEY_ESC: + HideText(libvlc); + break; + default: + ShowText(libvlc); + } + } else { + switch(key) { + case KEY_ENTER: + SetKeyActionMask(libvlc, &KEY_ACTION_MASK_OFF); + writing = true; + // Starts the thread + vlc_clone(&th, RunIntf, intf->obj.libvlc, VLC_THREAD_PRIORITY_LOW); + break; + } + } + + return VLC_SUCCESS; +} + +static int Open(vlc_object_t *obj) +{ + intf_thread_t *intf = (intf_thread_t *)obj; + + vlc_mutex_init(&lock); + + var_Create( intf->obj.libvlc, "syncplay-text", VLC_VAR_INTEGER); + var_Create(intf->obj.libvlc, "chat-message", VLC_VAR_STRING); + var_AddCallback(intf->obj.libvlc, "syncplay-text", SynplayText, intf ); + var_AddCallback( intf->obj.libvlc, "key-pressed", KeyPressed, intf ); + var_AddCallback( pl_Get(intf), "input-current", PlaylistEvent, intf ); + + msg_Info(intf, "Synclpay"); + + // Returns error even tho no error ? It's working so don't tuch it + return 1; +} + + +static void Close(vlc_object_t *obj) +{ + intf_thread_t *intf = (intf_thread_t *)obj; +} + +vlc_module_begin() + set_shortname(N_("Syncplay Chat")) + set_description(N_("Syncplay Chat")) + set_capability("interface", 200) + set_callbacks(Open, Close) + set_category(CAT_INTERFACE) + set_subcategory(SUBCAT_INTERFACE_CONTROL) +vlc_module_end () \ No newline at end of file