mirror of
https://github.com/moonlight-stream/moonlight-chrome.git
synced 2025-08-17 00:26:56 +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 \
|
||||
input.cpp \
|
||||
gamepad.cpp \
|
||||
connectionlistener.cpp \
|
||||
|
||||
# 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) {
|
||||
switch (event.GetType()) {
|
||||
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);
|
||||
|
||||
LiSendMouseButtonEvent(ConvertPPButtonToLiButton(mouseEvent.GetButton()), BUTTON_ACTION_PRESS);
|
||||
LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, ConvertPPButtonToLiButton(mouseEvent.GetButton()));
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -39,7 +55,7 @@ bool MoonlightInstance::HandleInputEvent(const pp::InputEvent& event) {
|
||||
case PP_INPUTEVENT_TYPE_MOUSEUP: {
|
||||
pp::MouseInputEvent mouseEvent(event);
|
||||
|
||||
LiSendMouseButtonEvent(ConvertPPButtonToLiButton(mouseEvent.GetButton()), BUTTON_ACTION_RELEASE);
|
||||
LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, ConvertPPButtonToLiButton(mouseEvent.GetButton()));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
85
main.cpp
85
main.cpp
@ -1,5 +1,15 @@
|
||||
#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() {}
|
||||
|
||||
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 {
|
||||
Module* CreateModule() {
|
||||
return new MoonlightModule();
|
||||
|
@ -1,14 +1,23 @@
|
||||
#include "ppapi/cpp/instance.h"
|
||||
#include "ppapi/cpp/module.h"
|
||||
#include "ppapi/cpp/var.h"
|
||||
#include "ppapi/cpp/mouse_lock.h"
|
||||
|
||||
#include "ppapi/c/ppb_gamepad.h"
|
||||
|
||||
#include "ppapi/utility/completion_callback_factory.h"
|
||||
|
||||
#include "nacl_io/nacl_io.h"
|
||||
|
||||
class MoonlightInstance : public pp::Instance {
|
||||
#include <Limelight.h>
|
||||
|
||||
class MoonlightInstance : public pp::Instance, public pp::MouseLock {
|
||||
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!)
|
||||
nacl_io_init_ppapi(pp_instance(), pp::Module::Get()->get_browser_interface());
|
||||
|
||||
@ -17,11 +26,42 @@ class MoonlightInstance : public pp::Instance {
|
||||
|
||||
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);
|
||||
|
||||
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:
|
||||
double m_LastPadTimestamps[4];
|
||||
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