mirror of
https://github.com/moonlight-stream/moonlight-chrome.git
synced 2025-08-17 16:46:31 +00:00
Basic streaming and mouse input works
This commit is contained in:
parent
27fa24cfbc
commit
7ea534c692
1
Makefile
1
Makefile
@ -22,6 +22,7 @@ SOURCES = \
|
|||||||
main.cpp \
|
main.cpp \
|
||||||
input.cpp \
|
input.cpp \
|
||||||
gamepad.cpp \
|
gamepad.cpp \
|
||||||
|
connectionlistener.cpp \
|
||||||
|
|
||||||
# Build rules generated by macros from common.mk:
|
# Build rules generated by macros from common.mk:
|
||||||
|
|
||||||
|
49
connectionlistener.cpp
Normal file
49
connectionlistener.cpp
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
#include "moonlight.hpp"
|
||||||
|
|
||||||
|
#include "ppapi/c/ppb_input_event.h"
|
||||||
|
|
||||||
|
#include "ppapi/cpp/input_event.h"
|
||||||
|
#include "ppapi/cpp/mouse_lock.h"
|
||||||
|
|
||||||
|
void MoonlightInstance::ClStageStarting(int stage) {
|
||||||
|
pp::Var response(std::string("Starting ") + std::string(LiGetStageName(stage)) + std::string("..."));
|
||||||
|
g_Instance->PostMessage(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MoonlightInstance::ClStageFailed(int stage, long errorCode) {
|
||||||
|
pp::Var response(std::string("Starting ") + std::string(LiGetStageName(stage)) + std::string("failed"));
|
||||||
|
g_Instance->PostMessage(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MoonlightInstance::ClConnectionStarted(void) {
|
||||||
|
pp::Module::Get()->core()->CallOnMainThread(0,
|
||||||
|
g_Instance->m_CallbackFactory.NewCallback(&MoonlightInstance::OnConnectionStarted));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MoonlightInstance::ClConnectionTerminated(long errorCode) {
|
||||||
|
pp::Module::Get()->core()->CallOnMainThread(0,
|
||||||
|
g_Instance->m_CallbackFactory.NewCallback(&MoonlightInstance::OnConnectionStopped), (uint32_t)errorCode);
|
||||||
|
|
||||||
|
pp::Var response("Connection terminated");
|
||||||
|
g_Instance->PostMessage(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MoonlightInstance::ClDisplayMessage(char* message) {
|
||||||
|
pp::Var response(message);
|
||||||
|
g_Instance->PostMessage(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MoonlightInstance::ClDisplayTransientMessage(char* message) {
|
||||||
|
pp::Var response(message);
|
||||||
|
g_Instance->PostMessage(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
CONNECTION_LISTENER_CALLBACKS MoonlightInstance::s_ClCallbacks = {
|
||||||
|
MoonlightInstance::ClStageStarting,
|
||||||
|
NULL,
|
||||||
|
MoonlightInstance::ClStageFailed,
|
||||||
|
MoonlightInstance::ClConnectionStarted,
|
||||||
|
MoonlightInstance::ClConnectionTerminated,
|
||||||
|
MoonlightInstance::ClDisplayMessage,
|
||||||
|
MoonlightInstance::ClDisplayTransientMessage
|
||||||
|
};
|
20
input.cpp
20
input.cpp
@ -19,12 +19,28 @@ static int ConvertPPButtonToLiButton(PP_InputEvent_MouseButton ppButton) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MoonlightInstance::DidLockMouse(int32_t result) {
|
||||||
|
m_MouseLocked = (result == PP_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MoonlightInstance::MouseLockLost() {
|
||||||
|
m_MouseLocked = false;
|
||||||
|
}
|
||||||
|
|
||||||
bool MoonlightInstance::HandleInputEvent(const pp::InputEvent& event) {
|
bool MoonlightInstance::HandleInputEvent(const pp::InputEvent& event) {
|
||||||
switch (event.GetType()) {
|
switch (event.GetType()) {
|
||||||
case PP_INPUTEVENT_TYPE_MOUSEDOWN: {
|
case PP_INPUTEVENT_TYPE_MOUSEDOWN: {
|
||||||
|
// Lock the mouse cursor when the user clicks on the stream
|
||||||
|
if (!m_MouseLocked) {
|
||||||
|
g_Instance->LockMouse(g_Instance->m_CallbackFactory.NewCallback(&MoonlightInstance::DidLockMouse));
|
||||||
|
|
||||||
|
// Assume it worked until we get a callback telling us otherwise
|
||||||
|
m_MouseLocked = true;
|
||||||
|
}
|
||||||
|
|
||||||
pp::MouseInputEvent mouseEvent(event);
|
pp::MouseInputEvent mouseEvent(event);
|
||||||
|
|
||||||
LiSendMouseButtonEvent(ConvertPPButtonToLiButton(mouseEvent.GetButton()), BUTTON_ACTION_PRESS);
|
LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, ConvertPPButtonToLiButton(mouseEvent.GetButton()));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,7 +55,7 @@ bool MoonlightInstance::HandleInputEvent(const pp::InputEvent& event) {
|
|||||||
case PP_INPUTEVENT_TYPE_MOUSEUP: {
|
case PP_INPUTEVENT_TYPE_MOUSEUP: {
|
||||||
pp::MouseInputEvent mouseEvent(event);
|
pp::MouseInputEvent mouseEvent(event);
|
||||||
|
|
||||||
LiSendMouseButtonEvent(ConvertPPButtonToLiButton(mouseEvent.GetButton()), BUTTON_ACTION_RELEASE);
|
LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, ConvertPPButtonToLiButton(mouseEvent.GetButton()));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
85
main.cpp
85
main.cpp
@ -1,5 +1,15 @@
|
|||||||
#include "moonlight.hpp"
|
#include "moonlight.hpp"
|
||||||
|
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "ppapi/cpp/input_event.h"
|
||||||
|
|
||||||
|
static char s_Host[256];
|
||||||
|
static STREAM_CONFIGURATION s_StreamConfig;
|
||||||
|
|
||||||
|
MoonlightInstance* g_Instance;
|
||||||
|
|
||||||
MoonlightInstance::~MoonlightInstance() {}
|
MoonlightInstance::~MoonlightInstance() {}
|
||||||
|
|
||||||
class MoonlightModule : public pp::Module {
|
class MoonlightModule : public pp::Module {
|
||||||
@ -12,6 +22,81 @@ class MoonlightModule : public pp::Module {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void MoonlightInstance::OnConnectionStarted(uint32_t unused) {
|
||||||
|
printf("Connection started\n");
|
||||||
|
|
||||||
|
// Start receiving input events
|
||||||
|
g_Instance->RequestInputEvents(PP_INPUTEVENT_CLASS_MOUSE);
|
||||||
|
g_Instance->RequestFilteringInputEvents(PP_INPUTEVENT_CLASS_WHEEL | PP_INPUTEVENT_CLASS_KEYBOARD);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MoonlightInstance::OnConnectionStopped(uint32_t error) {
|
||||||
|
// Stop receiving input events
|
||||||
|
g_Instance->ClearInputEventRequest(PP_INPUTEVENT_CLASS_MOUSE | PP_INPUTEVENT_CLASS_WHEEL | PP_INPUTEVENT_CLASS_KEYBOARD);
|
||||||
|
|
||||||
|
// Unlock the mouse
|
||||||
|
g_Instance->UnlockMouse();
|
||||||
|
}
|
||||||
|
|
||||||
|
void* MoonlightInstance::ConnectionThreadFunc(void* context) {
|
||||||
|
MoonlightInstance* me = (MoonlightInstance*)context;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
err = LiStartConnection(s_Host,
|
||||||
|
&s_StreamConfig,
|
||||||
|
&MoonlightInstance::s_ClCallbacks,
|
||||||
|
NULL, NULL,
|
||||||
|
NULL, 0, 4);
|
||||||
|
if (err != 0) {
|
||||||
|
pp::Var response("Starting connection failed");
|
||||||
|
g_Instance->PostMessage(response);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
me->PollGamepads();
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MoonlightInstance::HandleMessage(const pp::Var& var_message) {
|
||||||
|
// Ignore the message if it is not a string.
|
||||||
|
if (!var_message.is_string())
|
||||||
|
return;
|
||||||
|
|
||||||
|
std::string host = var_message.AsString();
|
||||||
|
|
||||||
|
// Populate the stream configuration
|
||||||
|
LiInitializeStreamConfiguration(&s_StreamConfig);
|
||||||
|
s_StreamConfig.width = 1280;
|
||||||
|
s_StreamConfig.height = 720;
|
||||||
|
s_StreamConfig.fps = 30;
|
||||||
|
s_StreamConfig.bitrate = 10; // megabits per second
|
||||||
|
s_StreamConfig.packetSize = 1024;
|
||||||
|
s_StreamConfig.streamingRemotely = 0;
|
||||||
|
s_StreamConfig.audioConfiguration = AUDIO_CONFIGURATION_STEREO;
|
||||||
|
|
||||||
|
// Store the host
|
||||||
|
host = host.substr(host.find(":") + 1);
|
||||||
|
strcpy(s_Host, host.c_str());
|
||||||
|
|
||||||
|
// Post a status update before we begin
|
||||||
|
pp::Var response("Starting connection...");
|
||||||
|
PostMessage(response);
|
||||||
|
|
||||||
|
// Start the worker thread to establish the connection
|
||||||
|
pthread_t t;
|
||||||
|
pthread_create(&t, NULL, MoonlightInstance::ConnectionThreadFunc, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MoonlightInstance::Init(uint32_t argc,
|
||||||
|
const char* argn[],
|
||||||
|
const char* argv[]) {
|
||||||
|
g_Instance = this;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
namespace pp {
|
namespace pp {
|
||||||
Module* CreateModule() {
|
Module* CreateModule() {
|
||||||
return new MoonlightModule();
|
return new MoonlightModule();
|
||||||
|
@ -1,14 +1,23 @@
|
|||||||
#include "ppapi/cpp/instance.h"
|
#include "ppapi/cpp/instance.h"
|
||||||
#include "ppapi/cpp/module.h"
|
#include "ppapi/cpp/module.h"
|
||||||
#include "ppapi/cpp/var.h"
|
#include "ppapi/cpp/var.h"
|
||||||
|
#include "ppapi/cpp/mouse_lock.h"
|
||||||
|
|
||||||
#include "ppapi/c/ppb_gamepad.h"
|
#include "ppapi/c/ppb_gamepad.h"
|
||||||
|
|
||||||
|
#include "ppapi/utility/completion_callback_factory.h"
|
||||||
|
|
||||||
#include "nacl_io/nacl_io.h"
|
#include "nacl_io/nacl_io.h"
|
||||||
|
|
||||||
class MoonlightInstance : public pp::Instance {
|
#include <Limelight.h>
|
||||||
|
|
||||||
|
class MoonlightInstance : public pp::Instance, public pp::MouseLock {
|
||||||
public:
|
public:
|
||||||
explicit MoonlightInstance(PP_Instance instance) : pp::Instance(instance) {
|
explicit MoonlightInstance(PP_Instance instance) :
|
||||||
|
pp::Instance(instance),
|
||||||
|
pp::MouseLock(this),
|
||||||
|
m_CallbackFactory(this),
|
||||||
|
m_MouseLocked(false) {
|
||||||
// This function MUST be used otherwise sockets don't work (nacl_io_init() doesn't work!)
|
// This function MUST be used otherwise sockets don't work (nacl_io_init() doesn't work!)
|
||||||
nacl_io_init_ppapi(pp_instance(), pp::Module::Get()->get_browser_interface());
|
nacl_io_init_ppapi(pp_instance(), pp::Module::Get()->get_browser_interface());
|
||||||
|
|
||||||
@ -17,11 +26,42 @@ class MoonlightInstance : public pp::Instance {
|
|||||||
|
|
||||||
virtual ~MoonlightInstance();
|
virtual ~MoonlightInstance();
|
||||||
|
|
||||||
|
bool Init(uint32_t argc, const char* argn[], const char* argv[]);
|
||||||
|
|
||||||
|
void HandleMessage(const pp::Var& var_message);
|
||||||
|
|
||||||
bool HandleInputEvent(const pp::InputEvent& event);
|
bool HandleInputEvent(const pp::InputEvent& event);
|
||||||
|
|
||||||
void PollGamepads();
|
void PollGamepads();
|
||||||
|
|
||||||
|
void DidLockMouse(int32_t result);
|
||||||
|
|
||||||
|
void MouseLockLost();
|
||||||
|
|
||||||
|
void OnConnectionStopped(uint32_t unused);
|
||||||
|
|
||||||
|
void OnConnectionStarted(uint32_t error);
|
||||||
|
|
||||||
|
static void* ConnectionThreadFunc(void* context);
|
||||||
|
|
||||||
|
static void ClStageStarting(int stage);
|
||||||
|
|
||||||
|
static void ClStageFailed(int stage, long errorCode);
|
||||||
|
|
||||||
|
static void ClConnectionStarted(void);
|
||||||
|
|
||||||
|
static void ClConnectionTerminated(long errorCode);
|
||||||
|
|
||||||
|
static void ClDisplayMessage(char* message);
|
||||||
|
|
||||||
|
static void ClDisplayTransientMessage(char* message);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
double m_LastPadTimestamps[4];
|
double m_LastPadTimestamps[4];
|
||||||
const PPB_Gamepad* m_GamepadApi;
|
const PPB_Gamepad* m_GamepadApi;
|
||||||
|
static CONNECTION_LISTENER_CALLBACKS s_ClCallbacks;
|
||||||
|
pp::CompletionCallbackFactory<MoonlightInstance> m_CallbackFactory;
|
||||||
|
bool m_MouseLocked;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
extern MoonlightInstance* g_Instance;
|
Loading…
x
Reference in New Issue
Block a user