Dark Mode & Stream Overlay [macOS] (#315)

* dark mode & stream overlay

* removed all redundant imports

* update for the new xcode version with fixes for the new 'implicitly retains self warning'

* reworked the overlay view

* cleaning up unused variables

* small corrections
This commit is contained in:
Felix Kratz
2018-04-22 06:44:22 +02:00
committed by Cameron Gutman
parent 74283a6763
commit f759f719e6
50 changed files with 358 additions and 146 deletions

View File

@@ -160,32 +160,37 @@ void onButtonUp(struct Gamepad_device * device, unsigned int buttonID, double ti
void onAxisMoved(struct Gamepad_device * device, unsigned int axisID, float value, float lastValue, double timestamp, void * context) {
if (fabsf(lastValue - value) > 0.01) {
_controller = [_controllers objectForKey:[NSNumber numberWithInteger:device->deviceID]];
// The dualshock controller has much more than these axis because of the motion axis, so it
// is better to call the updateFinished in the cases, because otherwise all of these
// motion axis will also trigger an updateFinished event.
switch (axisID) {
case LEFT_X:
_controller = [_controllers objectForKey:[NSNumber numberWithInteger:device->deviceID]];
_controller.lastLeftStickX = value * 0X7FFE;
[_controllerSupport updateFinished:_controller];
break;
case LEFT_Y:
_controller = [_controllers objectForKey:[NSNumber numberWithInteger:device->deviceID]];
_controller.lastLeftStickY = -value * 0X7FFE;
[_controllerSupport updateFinished:_controller];
break;
case RIGHT_X:
_controller = [_controllers objectForKey:[NSNumber numberWithInteger:device->deviceID]];
_controller.lastRightStickX = value * 0X7FFE;
[_controllerSupport updateFinished:_controller];
break;
case RIGHT_Y:
_controller = [_controllers objectForKey:[NSNumber numberWithInteger:device->deviceID]];
_controller.lastRightStickY = -value * 0X7FFE;
[_controllerSupport updateFinished:_controller];
break;
case LT:
_controller = [_controllers objectForKey:[NSNumber numberWithInteger:device->deviceID]];
_controller.lastLeftTrigger = value * 0xFF;
[_controllerSupport updateFinished:_controller];
break;
case RT:
_controller = [_controllers objectForKey:[NSNumber numberWithInteger:device->deviceID]];
_controller.lastRightTrigger = value * 0xFF;
[_controllerSupport updateFinished:_controller];
break;
@@ -208,11 +213,11 @@ void onDeviceRemoved(struct Gamepad_device * device, void * context) {
void initGamepad(ControllerSupport* controllerSupport) {
_controllerSupport = controllerSupport;
_controller = [[Controller alloc] init];
Gamepad_deviceAttachFunc(onDeviceAttached, NULL);
Gamepad_deviceRemoveFunc(onDeviceRemoved, NULL);
Gamepad_buttonDownFunc(onButtonDown, NULL);
Gamepad_buttonUpFunc(onButtonUp, NULL);
Gamepad_axisMoveFunc(onAxisMoved, NULL);
Gamepad_init();
_controller = [[Controller alloc] init];
}

View File

@@ -0,0 +1,16 @@
//
// OverlayView.h
// Moonlight macOS
//
// Created by Felix Kratz on 01.04.18.
// Copyright © 2018 Felix Kratz. All rights reserved.
//
#import <Cocoa/Cocoa.h>
@interface OverlayView : NSView
- (id)initWithFrame:(NSRect)frame sender:(StreamView*)sender;
- (void)toggleOverlay:(int)codec;
@end

View File

@@ -0,0 +1,98 @@
//
// OverlayView.m
// Moonlight macOS
//
// Created by Felix Kratz on 01.04.18.
// Copyright © 2018 Felix Kratz. All rights reserved.
//
#import "StreamView.h"
#import "OverlayView.h"
#import "NetworkTraffic.h"
@implementation OverlayView {
StreamView* _streamView;
bool statsDisplayed;
unsigned long lastNetworkDown;
unsigned long lastNetworkUp;
NSTextField* _textFieldIncomingBitrate;
NSTextField* _textFieldOutgoingBitrate;
NSTextField* _textFieldCodec;
NSTextField* _textFieldFramerate;
NSTextField* _stageLabel;
NSTimer* _statTimer;
}
- (id)initWithFrame:(NSRect)frame sender:(StreamView*)sender
{
self = [super initWithFrame:frame];
if (self) {
_streamView = sender;
}
return self;
}
- (void)initStats {
_textFieldCodec = [[NSTextField alloc] initWithFrame:NSMakeRect(5, NSScreen.mainScreen.frame.size.height - 22, 200, 17)];
_textFieldIncomingBitrate = [[NSTextField alloc] initWithFrame:NSMakeRect(5, 5, 250, 17)];
_textFieldOutgoingBitrate = [[NSTextField alloc] initWithFrame:NSMakeRect(5, 5 + 20, 250, 17)];
_textFieldFramerate = [[NSTextField alloc] initWithFrame:NSMakeRect(NSScreen.mainScreen.frame.size.width - 50, NSScreen.mainScreen.frame.size.height - 22, 50, 17)];
[self setupTextField:_textFieldOutgoingBitrate];
[self setupTextField:_textFieldIncomingBitrate];
[self setupTextField:_textFieldCodec];
[self setupTextField:_textFieldFramerate];
}
- (void)setupTextField:(NSTextField*)textField {
textField.drawsBackground = false;
textField.bordered = false;
textField.editable = false;
textField.alignment = NSTextAlignmentLeft;
textField.textColor = [NSColor whiteColor];
[self addSubview:textField];
}
- (void)toggleOverlay:(int)codec {
statsDisplayed = !statsDisplayed;
if (statsDisplayed) {
_streamView.frameCount = 0;
if (_textFieldIncomingBitrate == nil || _textFieldCodec == nil || _textFieldOutgoingBitrate == nil || _textFieldFramerate == nil) {
[self initStats];
}
_statTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(statTimerTick) userInfo:nil repeats:true];
NSLog(@"display stats");
if (codec == 1) {
_textFieldCodec.stringValue = @"Codec: H.264";
}
else if (codec == 256) {
_textFieldCodec.stringValue = @"Codec: HEVC/H.265";
}
else {
_textFieldCodec.stringValue = @"Codec: Unknown";
}
[self statTimerTick];
}
else {
[_statTimer invalidate];
_textFieldCodec.stringValue = @"";
_textFieldIncomingBitrate.stringValue = @"";
_textFieldOutgoingBitrate.stringValue = @"";
_textFieldFramerate.stringValue = @"";
}
}
- (void)statTimerTick {
_textFieldFramerate.stringValue = [NSString stringWithFormat:@"%i fps", _streamView.frameCount];
_streamView.frameCount = 0;
unsigned long currentNetworkDown = getBytesDown();
_textFieldIncomingBitrate.stringValue = [NSString stringWithFormat:@"Incoming Bitrate (System): %lu kbps", (currentNetworkDown - lastNetworkDown)*8 / 1000];
lastNetworkDown = currentNetworkDown;
unsigned long currentNetworkUp = getBytesUp();
_textFieldOutgoingBitrate.stringValue = [NSString stringWithFormat:@"Outgoing Bitrate (System): %lu kbps", (currentNetworkUp - lastNetworkUp)*8 / 1000];
lastNetworkUp = currentNetworkUp;
}
@end

View File

@@ -8,5 +8,10 @@
@interface StreamView : NSView
- (void)drawMessage:(NSString*)message;
@property int codec;
@property unsigned short frameCount;
@end

View File

@@ -11,26 +11,27 @@
#import "DataManager.h"
#include <ApplicationServices/ApplicationServices.h>
#include "keyboardTranslation.h"
#import "OverlayView.h"
@implementation StreamView {
BOOL isDragging;
NSTrackingArea *trackingArea;
bool isDragging;
NSTrackingArea* _trackingArea;
OverlayView* _overlay;
NSTextField* _stageLabel;
}
- (void) updateTrackingAreas {
// This will be the area used to track the mouse movement
if (trackingArea != nil) {
[self removeTrackingArea:trackingArea];
if (_trackingArea != nil) {
[self removeTrackingArea:_trackingArea];
}
NSTrackingAreaOptions options = (NSTrackingActiveAlways | NSTrackingInVisibleRect |
NSTrackingMouseEnteredAndExited | NSTrackingMouseMoved);
trackingArea = [[NSTrackingArea alloc] initWithRect:[self bounds]
_trackingArea = [[NSTrackingArea alloc] initWithRect:[self bounds]
options:options
owner:self
userInfo:nil];
[self addTrackingArea:trackingArea];
[self addTrackingArea:_trackingArea];
}
-(void)mouseDragged:(NSEvent *)event {
@@ -59,24 +60,20 @@
- (void)mouseDown:(NSEvent *)mouseEvent {
LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, BUTTON_LEFT);
[self setNeedsDisplay:YES];
}
- (void)mouseUp:(NSEvent *)mouseEvent {
isDragging = false;
LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_LEFT);
[self setNeedsDisplay:YES];
}
- (void)rightMouseUp:(NSEvent *)mouseEvent {
isDragging = false;
LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_RIGHT);
[self setNeedsDisplay:YES];
}
- (void)rightMouseDown:(NSEvent *)mouseEvent {
LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, BUTTON_RIGHT);
[self setNeedsDisplay:YES];
}
- (void)mouseMoved:(NSEvent *)mouseEvent {
@@ -85,22 +82,24 @@
-(void)keyDown:(NSEvent *)event {
unsigned char keyChar = keyCharFromKeyCode(event.keyCode);
printf("DOWN: KeyCode: %hu, keyChar: %d, keyModifier: %lu \n", event.keyCode, keyChar, event.modifierFlags);
NSLog(@"DOWN: KeyCode: %hu, keyChar: %d, keyModifier: %lu \n", event.keyCode, keyChar, event.modifierFlags);
LiSendKeyboardEvent(keyChar, KEY_ACTION_DOWN, modifierFlagForKeyModifier(event.modifierFlags));
if (event.modifierFlags & kCGEventFlagMaskCommand && event.keyCode == kVK_ANSI_I) {
[self toggleStats];
}
}
-(void)keyUp:(NSEvent *)event {
unsigned char keyChar = keyCharFromKeyCode(event.keyCode);
printf("UP: KeyChar: %d \n", keyChar);
NSLog(@"UP: KeyChar: %d \n", keyChar);
LiSendKeyboardEvent(keyChar, KEY_ACTION_UP, modifierFlagForKeyModifier(event.modifierFlags));
}
- (void)flagsChanged:(NSEvent *)event
{
- (void)flagsChanged:(NSEvent *)event {
unsigned char keyChar = keyCodeFromModifierKey(event.modifierFlags);
if(keyChar) {
printf("DOWN: FlagChanged: %hhu \n", keyChar);
NSLog(@"DOWN: FlagChanged: %hhu \n", keyChar);
LiSendKeyboardEvent(keyChar, KEY_ACTION_DOWN, 0x00);
}
else {
@@ -108,6 +107,33 @@
}
}
- (void)initStageLabel {
_stageLabel = [[NSTextField alloc] initWithFrame:NSMakeRect(NSScreen.mainScreen.frame.size.width/2 - 100, NSScreen.mainScreen.frame.size.height/2 - 8, 200, 17)];
_stageLabel.drawsBackground = false;
_stageLabel.bordered = false;
_stageLabel.alignment = NSTextAlignmentCenter;
_stageLabel.textColor = [NSColor blackColor];
[self addSubview:_stageLabel];
}
- (void)toggleStats {
if (_overlay == nil) {
_overlay = [[OverlayView alloc] initWithFrame:self.frame sender:self];
[self addSubview:_overlay];
}
[_overlay toggleOverlay:_codec];
}
- (void)drawMessage:(NSString*)message {
dispatch_async(dispatch_get_main_queue(), ^{
if (self->_stageLabel == nil) {
[self initStageLabel];
}
self->_stageLabel.stringValue = message;
});
}
- (BOOL)acceptsFirstResponder {
return YES;
}