From 578181940499b9360324d505e3bde70917bcb671 Mon Sep 17 00:00:00 2001 From: semvis123 Date: Wed, 28 Oct 2020 21:38:06 +0100 Subject: [PATCH 01/55] added macos base, not working Gui is working and semi disabled because the bleutooth connector isn't working. --- Client/macos/MacOSBluetoothConnector.h | 32 +++ Client/macos/MacOSBluetoothConnector.mm | 164 ++++++++++++++++ Client/macos/MacOSGUI.cpp | 247 ++++++++++++++++++++++++ Client/macos/MacOSGUI.h | 43 +++++ Client/macos/info.plist | 18 ++ Client/macos/main.mm | 109 +++++++++++ Client/macos/makefile | 63 ++++++ 7 files changed, 676 insertions(+) create mode 100644 Client/macos/MacOSBluetoothConnector.h create mode 100644 Client/macos/MacOSBluetoothConnector.mm create mode 100644 Client/macos/MacOSGUI.cpp create mode 100644 Client/macos/MacOSGUI.h create mode 100644 Client/macos/info.plist create mode 100644 Client/macos/main.mm create mode 100644 Client/macos/makefile diff --git a/Client/macos/MacOSBluetoothConnector.h b/Client/macos/MacOSBluetoothConnector.h new file mode 100644 index 0000000..36cf918 --- /dev/null +++ b/Client/macos/MacOSBluetoothConnector.h @@ -0,0 +1,32 @@ +#pragma once +#include +#include +#include +#include "../IBluetoothConnector.h" +#include "IOBluetooth/IOBluetooth.h" +#include +#include "ByteMagic.h" +#include +class MacOSBluetoothConnector final : public IBluetoothConnector +{ +public: + MacOSBluetoothConnector(); + + ~MacOSBluetoothConnector(); + + virtual void connect(const std::string& addrStr) noexcept(false); + virtual int send(char* buf, size_t length) noexcept(false); + virtual int recv(char* buf, size_t length) noexcept(false); + virtual void disconnect() noexcept; + virtual bool isConnected() noexcept; + + virtual std::vector getConnectedDevices() noexcept(false); + +private: + std::vector _findDevicesInRadio(); + std::string _wstringToUtf8(const std::wstring& wstr); + + // SOCKET _socket = INVALID_SOCKET; + std::atomic _connected = false; + void _initSocket(); +}; \ No newline at end of file diff --git a/Client/macos/MacOSBluetoothConnector.mm b/Client/macos/MacOSBluetoothConnector.mm new file mode 100644 index 0000000..1b715f6 --- /dev/null +++ b/Client/macos/MacOSBluetoothConnector.mm @@ -0,0 +1,164 @@ +#include "MacOSBluetoothConnector.h" + +// don't know if this is needed +void WSAStartupWrapper() +{ + // int iResult; + // WSADATA wsaData; + // iResult = WSAStartup(MAKEWORD(2, 2), &wsaData); + // if (iResult != 0) { + // throw std::runtime_error("WSAStartup failed: " + std::to_string(iResult)); + // } +} + +MacOSBluetoothConnector::MacOSBluetoothConnector() +{ + // static bool startedUp = false; + // if (!startedUp) + // { + // ::WSAStartupWrapper(); + // startedUp = true; + // } +} + +MacOSBluetoothConnector::~MacOSBluetoothConnector() +{ + // if (this->_socket != INVALID_SOCKET) + // { + // ::closesocket(this->_socket); + // } +} + +// generates error +void MacOSBluetoothConnector::connect(const std::string& addrStr) +{ + // convert mac adress to nsstring + NSString *addressNSString = [NSString stringWithCString:addrStr.c_str() encoding:[NSString defaultCStringEncoding]]; + // get device based on mac adress + IOBluetoothDevice *device = [IOBluetoothDevice deviceWithAddressString:addressNSString]; + // create new channel + IOBluetoothRFCOMMChannel *channel = [[IOBluetoothRFCOMMChannel alloc] init]; + if ([device openRFCOMMChannelSync: &channel withChannelID:1 delegate: nil] == kIOReturnSuccess) { + const int connectResult = kIOReturnSuccess; + printf("%d", connectResult); + this->_connected = true; + } +} + +int MacOSBluetoothConnector::send(char* buf, size_t length) +{ + // auto bytesSent = ::send(this->_socket, buf, length, 0); + // if (bytesSent == SOCKET_ERROR) + // { + // throw RecoverableException("Couldn't send (" + std::to_string(WSAGetLastError()) + ")", true); + // } + // return bytesSent; +} + +int MacOSBluetoothConnector::recv(char* buf, size_t length) +{ + // auto bytesReceived = ::recv(this->_socket, buf, length, 0); + // if (bytesReceived == SOCKET_ERROR) + // { + // throw RecoverableException("Couldn't recv (" + std::to_string(WSAGetLastError()) + ")", true); + // } + // return bytesReceived; +} + +// currently working +std::vector MacOSBluetoothConnector::getConnectedDevices() +{ + // create the output vector + std::vector res; + // loop through the paired devices (also includes non paired devices for some reason) + for (IOBluetoothDevice* device in [IOBluetoothDevice pairedDevices]) { + // check if device is connected + if ([device isConnected]) { + BluetoothDevice dev; + // save the mac address and name + dev.mac = [[device addressString]UTF8String]; + dev.name = [[device name] UTF8String]; + // add device to the connected devices vector + res.push_back(dev); + } + } + + return res; +} + +void MacOSBluetoothConnector::disconnect() noexcept +{ + // if (this->_socket != INVALID_SOCKET) + // { + // this->_connected = false; + // shutdown(this->_socket, SD_BOTH); + // closesocket(this->_socket); + // this->_socket = INVALID_SOCKET; + // } +} + +bool MacOSBluetoothConnector::isConnected() noexcept +{ + return this->_connected; +} + +// probably don't need this function (right?) +void MacOSBluetoothConnector::_initSocket() +{ + // SOCKET sock = ::socket(AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM); + // if (sock == INVALID_SOCKET) + // { + // throw std::runtime_error("Couldn't create socket: " + std::to_string(WSAGetLastError())); + // } + + // ULONG enable = TRUE; + // if (::setsockopt(sock, SOL_RFCOMM, SO_BTH_AUTHENTICATE, reinterpret_cast(&enable), sizeof(enable))) + // { + // throw std::runtime_error("Couldn't set SO_BTH_AUTHENTICATE: " + std::to_string(WSAGetLastError())); + // } + + // if (::setsockopt(sock, SOL_RFCOMM, SO_BTH_ENCRYPT, reinterpret_cast(&enable), sizeof(enable))) + // { + // throw std::runtime_error("Couldn't set SO_BTH_ENCRYPT: " + std::to_string(WSAGetLastError())); + // } + + // this->_socket = sock; +} + +// probably don't need this function (right?) +std::string MacOSBluetoothConnector::_wstringToUtf8(const std::wstring& wstr) +{ + // std::string strTo; + // const int num_chars = WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), wstr.length(), NULL, 0, NULL, NULL); + + // if (num_chars > 0) + // { + // strTo.resize(num_chars); + // WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), wstr.length(), &strTo[0], num_chars, NULL, NULL); + // } + // return strTo; +} + + +// probably don't need this function (right?) +std::vector MacOSBluetoothConnector::_findDevicesInRadio() +{ + // std::vector res; + + // for (IOBluetoothDevice* device in [IOBluetoothDevice pairedDevices]) { + // BluetoothDevice dev; + // dev.mac = [[device addressString]UTF8String] + // dev.name = [[device name] UTF8String] + // printf("%s - ",[[device addressString]UTF8String]); + // printf("%s - ",[[device name] UTF8String]); + // if ([device isConnected]) { + // printf("connected device"); + // res.append(dev) + // }else{ + // printf("disconnected device"); + // } + // printf("\n"); + // } + + // return res; +} diff --git a/Client/macos/MacOSGUI.cpp b/Client/macos/MacOSGUI.cpp new file mode 100644 index 0000000..191cf17 --- /dev/null +++ b/Client/macos/MacOSGUI.cpp @@ -0,0 +1,247 @@ +#include "MacOSGUI.h" + +bool MacOSGUI::performGUIPass() +{ + ImGui::NewFrame(); + + static bool isConnected = false; + + bool open = true; + + ImGui::SetNextWindowPos({ 0,0 }); + + { + //TODO: Figure out how to get rid of the Windows window, make everything transparent, and just use ImGui for everything. + //TODO: ImGuiWindowFlags_AlwaysAutoResize causes some flickering. Figure out how to stop it + ImGui::Begin("Sony Headphones", &open, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar); + + //Legal disclaimer + ImGui::Text("! This product is not affiliated with Sony. Use at your own risk. !"); + ImGui::Text("Source: https://github.com/Plutoberth/SonyHeadphonesClient"); + ImGui::Spacing(); + + this->_drawErrors(); + this->_drawDeviceDiscovery(); + + if (this->_bt.isConnected()) + { + ImGui::Spacing(); + this->_drawASMControls(); + } + } + + ImGui::End(); + + return open; +} + +void MacOSGUI::_drawErrors() +{ + //There's a slight race condition here but I don't care, it'd only be for one frame. + if (this->_mq.begin() != this->_mq.end()) + { + ImGui::Text("Errors"); + ImGui::Text("----------------------------"); + for (auto&& message : this->_mq) + { + ImGui::Text(message.message.c_str()); + } + //TODO: add a better ending separator + ImGui::Text("----------------------------"); + } +} + + +void MacOSGUI::_drawDeviceDiscovery() +{ + if (ImGui::CollapsingHeader("Device Discovery ", ImGuiTreeNodeFlags_DefaultOpen)) + { + static std::vector connectedDevices; + static int selectedDevice = -1; + + if (this->_bt.isConnected()) + { + ImGui::Text("Connected to %s", this->_connectedDevice.name.c_str()); + if (ImGui::Button("Disconnect")) + { + selectedDevice = -1; + this->_bt.disconnect(); + } + } + else + { + ImGui::Text("Select from one of the available devices: "); + + int temp = 0; + for (auto device : connectedDevices) + { + ImGui::RadioButton(device.name.c_str(), &selectedDevice, temp++); + } + + ImGui::Spacing(); + + if (this->_connectFuture.valid()) + { + if (this->_connectFuture.ready()) + { + try + { + this->_connectFuture.get(); + } + catch (const RecoverableException& exc) + { + if (exc.shouldDisconnect) + { + this->_bt.disconnect(); + } + this->_mq.addMessage(exc.what()); + } + } + else + { + ImGui::Text("Connecting %c", "|/-\\"[(int)(ImGui::GetTime() / 0.05f) & 3]); + } + } + else + { + if (ImGui::Button("Connect")) + { + if (selectedDevice != -1) + { + this->_connectedDevice = connectedDevices[selectedDevice]; + this->_connectFuture.setFromAsync([this]() { this->_bt.connect(this->_connectedDevice.mac); }); + } + } + } + + ImGui::SameLine(); + + if (this->_connectedDevicesFuture.valid()) + { + if (this->_connectedDevicesFuture.ready()) + { + try + { + connectedDevices = this->_connectedDevicesFuture.get(); + } + catch (const RecoverableException& exc) + { + if (exc.shouldDisconnect) + { + this->_bt.disconnect(); + } + this->_mq.addMessage(exc.what()); + } + } + else + { + ImGui::Text("Discovering Devices %c", "|/-\\"[(int)(ImGui::GetTime() / 0.05f) & 3]); + } + } + else + { + if (ImGui::Button("Refresh devices")) + { + selectedDevice = -1; + this->_connectedDevicesFuture.setFromAsync([this]() { return this->_bt.getConnectedDevices(); }); + } + } + } + } +} + + +void MacOSGUI::_drawASMControls() +{ + static bool focusOnVoice = false; + static bool sentFocusOnVoice = focusOnVoice; + static int asmLevel = 0; + static int sentAsmLevel = asmLevel; + //Don't show if the command only takes a few frames to send + static int commandLinger = 0; + + if (ImGui::CollapsingHeader("Ambient Sound Mode ", ImGuiTreeNodeFlags_DefaultOpen)) + { + ImGui::Text("Control ambient sound for your %ss", this->_connectedDevice.name.c_str()); + + ImGui::SliderInt("Ambient Sound Level", &asmLevel, 0, 19); + + bool sliderActive = ImGui::IsItemActive(); + + if (asmLevel >= MINIMUM_VOICE_FOCUS_STEP) + { + ImGui::Checkbox("Focus on Voice", &focusOnVoice); + } + else + { + ImGui::Text("Focus on Voice isn't enabled on this level."); + } + + if (this->_sendCommandFuture.ready()) + { + commandLinger = 0; + try + { + this->_sendCommandFuture.get(); + } + catch (const RecoverableException& exc) + { + std::string excString; + //We kinda have to do it here and not in the wrapper, due to async causing timing issues. To fix it, the messagequeue can be made + //static, but I'm not sure if I wanna do that. + if (exc.shouldDisconnect) + { + this->_bt.disconnect(); + excString = "Disconnected due to: "; + } + this->_mq.addMessage(excString + exc.what()); + } + } + //This means that we're waiting + else if (this->_sendCommandFuture.valid()) + { + if (commandLinger++ > FPS / 10) + { + ImGui::Text("Sending command %c", "|/-\\"[(int)(ImGui::GetTime() / 0.05f) & 3]); + } + } + //We're not waiting, and there's no command in the air, so we can evaluate sending a new command + else if (sentAsmLevel != asmLevel || sentFocusOnVoice != focusOnVoice) + { + auto ncAsmEffect = sliderActive ? NC_ASM_EFFECT::ADJUSTMENT_IN_PROGRESS : NC_ASM_EFFECT::ADJUSTMENT_COMPLETION; + auto asmId = focusOnVoice ? ASM_ID::VOICE : ASM_ID::NORMAL; + + this->_sendCommandFuture.setFromAsync([=]() { + return this->_bt.sendCommand(CommandSerializer::serializeNcAndAsmSetting( + ncAsmEffect, + NC_ASM_SETTING_TYPE::LEVEL_ADJUSTMENT, + ASM_SETTING_TYPE::LEVEL_ADJUSTMENT, + asmId, + asmLevel + )); + }); + sentAsmLevel = asmLevel; + sentFocusOnVoice = focusOnVoice; + } + } +} + +MacOSGUI::MacOSGUI(BluetoothWrapper bt) : _bt(std::move(bt)) +{ + // bt.getConnectedDevices(); + // Setup Dear ImGui style + ImGui::StyleColorsDark(); + ImGuiIO& io = ImGui::GetIO(); (void)io; + + this->_mq = TimedMessageQueue(GUI_MAX_MESSAGES); + this->_connectedDevicesFuture.setFromAsync([this]() { return this->_bt.getConnectedDevices(); }); + + io.IniFilename = nullptr; + io.WantSaveIniSettings = false; + + //AddFontFromMemory will own the pointer, so there's no leak + char* fileData = new char[sizeof(CascadiaCodeTTF)]; + memcpy(fileData, CascadiaCodeTTF, sizeof(CascadiaCodeTTF)); + ImFont* font = io.Fonts->AddFontFromMemoryTTF(reinterpret_cast(fileData), sizeof(CascadiaCodeTTF), 15.0f); + IM_ASSERT(font != NULL); +} diff --git a/Client/macos/MacOSGUI.h b/Client/macos/MacOSGUI.h new file mode 100644 index 0000000..263b402 --- /dev/null +++ b/Client/macos/MacOSGUI.h @@ -0,0 +1,43 @@ +#pragma once + +#include "imgui/imgui.h" +#include "Constants.h" +#include "IBluetoothConnector.h" +#include "BluetoothWrapper.h" +#include "CommandSerializer.h" +#include "Exceptions.h" +#include "TimedMessageQueue.h" +#include "SingleInstanceFuture.h" +#include "CascadiaCodeFont.h" +#include "MacOSBluetoothConnector.h" + +#include + +constexpr auto GUI_MAX_MESSAGES = 10; +constexpr auto FPS = 60; +constexpr auto GUI_HEIGHT = 350; +constexpr auto GUI_WIDTH = 540; + +//This class should be constructed after AFTER the Dear ImGUI context is initialized. +class MacOSGUI +{ +public: + MacOSGUI(BluetoothWrapper bt); + + //Run the GUI code once. This function should be called from a loop from one of the GUI impls (Windows, OSX, Linux...) + //O: true if the user wants to close the window + bool performGUIPass(); +private: + void _drawErrors(); + void _drawDeviceDiscovery(); + void _drawASMControls(); + + BluetoothDevice _connectedDevice; + BluetoothWrapper _bt; + SingleInstanceFuture> _connectedDevicesFuture; + SingleInstanceFuture _sendCommandFuture; + SingleInstanceFuture _connectFuture; + TimedMessageQueue _mq; +}; + + diff --git a/Client/macos/info.plist b/Client/macos/info.plist new file mode 100644 index 0000000..73eaaf4 --- /dev/null +++ b/Client/macos/info.plist @@ -0,0 +1,18 @@ + + + + + CFBundleExecutable + SonyHeadphonesClient + CFBundleIdentifier + com.semvis123.SonyHeadphonesClient + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + SonyHeadphonesClient + CFBundlePackageType + APPL + NSHighResolutionCapable + True + + \ No newline at end of file diff --git a/Client/macos/main.mm b/Client/macos/main.mm new file mode 100644 index 0000000..40af0dc --- /dev/null +++ b/Client/macos/main.mm @@ -0,0 +1,109 @@ +#include "imgui.h" +#include "imgui_impl_glfw.h" +#include "imgui_impl_metal.h" +#include + +#define GLFW_INCLUDE_NONE +#define GLFW_EXPOSE_NATIVE_COCOA +#include +#include + +#import +#import + +#include "Constants.h" +#include "TimedMessageQueue.h" +#include "BluetoothWrapper.h" +#include "MacOSBluetoothConnector.h" +#include "MacOSGUI.h" + +static void glfw_error_callback(int error, const char* description) +{ + fprintf(stderr, "Glfw Error %d: %s\n", error, description); +} + +int main(int, char**) +{ + // Setup Dear ImGui binding + IMGUI_CHECKVERSION(); + ImGui::CreateContext(); + + // init MacOSGUI + std::unique_ptr connector = std::make_unique(); + BluetoothWrapper wrap(std::move(connector)); + MacOSGUI macOSGUI = MacOSGUI(std::move(wrap)); + + // Setup window + glfwSetErrorCallback(glfw_error_callback); + if (!glfwInit()) + return 1; + + // Create window with graphics context + glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); + GLFWwindow* window = glfwCreateWindow(GUI_WIDTH, GUI_HEIGHT, "Sony Headphones App", NULL, NULL); + if (window == NULL) + return 1; + + id device = MTLCreateSystemDefaultDevice();; + id commandQueue = [device newCommandQueue]; + + ImGui_ImplGlfw_InitForOpenGL(window, true); + ImGui_ImplMetal_Init(device); + + NSWindow *nswin = glfwGetCocoaWindow(window); + CAMetalLayer *layer = [CAMetalLayer layer]; + layer.device = device; + layer.pixelFormat = MTLPixelFormatBGRA8Unorm; + nswin.contentView.layer = layer; + nswin.contentView.wantsLayer = YES; + + MTLRenderPassDescriptor *renderPassDescriptor = [MTLRenderPassDescriptor new]; + + float clear_color[4] = {0.45f, 0.55f, 0.60f, 1.00f}; + // Main loop + while (!glfwWindowShouldClose(window)) + { + @autoreleasepool + { + // Poll and handle events (inputs, window resize, etc.) + glfwPollEvents(); + + int width, height; + glfwGetFramebufferSize(window, &width, &height); + layer.drawableSize = CGSizeMake(width, height); + id drawable = [layer nextDrawable]; + + id commandBuffer = [commandQueue commandBuffer]; + renderPassDescriptor.colorAttachments[0].clearColor = MTLClearColorMake(clear_color[0], clear_color[1], clear_color[2], clear_color[3]); + renderPassDescriptor.colorAttachments[0].texture = drawable.texture; + renderPassDescriptor.colorAttachments[0].loadAction = MTLLoadActionClear; + renderPassDescriptor.colorAttachments[0].storeAction = MTLStoreActionStore; + id renderEncoder = [commandBuffer renderCommandEncoderWithDescriptor:renderPassDescriptor]; + + // Start the Dear ImGui frame + ImGui_ImplMetal_NewFrame(renderPassDescriptor); + ImGui_ImplGlfw_NewFrame(); + macOSGUI.performGUIPass(); + + // Rendering + ImGui::Render(); + ImGui_ImplMetal_RenderDrawData(ImGui::GetDrawData(), commandBuffer, renderEncoder); + + [renderEncoder popDebugGroup]; + [renderEncoder endEncoding]; + + [commandBuffer presentDrawable:drawable]; + [commandBuffer commit]; + } + } + + // Cleanup + ImGui_ImplMetal_Shutdown(); + ImGui_ImplGlfw_Shutdown(); + ImGui::DestroyContext(); + + glfwDestroyWindow(window); + glfwTerminate(); + + return 0; +} \ No newline at end of file diff --git a/Client/macos/makefile b/Client/macos/makefile new file mode 100644 index 0000000..8b2bdf1 --- /dev/null +++ b/Client/macos/makefile @@ -0,0 +1,63 @@ +# +# You will need GLFW (http://www.glfw.org): +# brew install glfw +# + +#CXX = g++ +#CXX = clang++ + +EXE = sonyheadphonesclient +SOURCES = main.mm +SOURCES += MacOSGUI.cpp MacOSBluetoothConnector.cpp BluetoothWrapper.cpp +SOURCES += TimedMessageQueue.cpp CascadiaCodeFont.cpp CommandSerializer.cpp +SOURCES += ByteMagic.cpp +SOURCES += ../imgui/examples/imgui_impl_glfw.cpp ../imgui/examples/imgui_impl_metal.mm +SOURCES += ../imgui/imgui.cpp ../imgui/imgui_widgets.cpp ../imgui/imgui_demo.cpp ../imgui/imgui_draw.cpp +OBJS = $(addsuffix .o, $(basename $(notdir $(SOURCES)))) + +LIBS = -framework IOBluetooth -framework Metal -framework MetalKit -framework Cocoa -framework IOKit -framework CoreVideo -framework QuartzCore +LIBS += -L/usr/local/lib -lglfw + +CXXFLAGS = -I../imgui/ -I../imgui/examples/ -I../ -I/usr/local/include +CXXFLAGS += -Wall -Wformat -std=c++17 -stdlib=libc++ +CFLAGS = $(CXXFLAGS) + +%.o:%.cpp + $(CXX) $(CXXFLAGS) -c -o $@ $< +%.o:../%.cpp + $(CXX) $(CXXFLAGS) -c -o $@ $< +%.o:../imgui/examples/%.cpp + $(CXX) $(CXXFLAGS) -c -o $@ $< + +%.o:../imgui/%.cpp + $(CXX) $(CXXFLAGS) -c -o $@ $< + +%.o:../imgui/examples/%.mm + $(CXX) $(CXXFLAGS) -ObjC++ -fobjc-weak -fobjc-arc -c -o $@ $< + +%.o:%.mm + $(CXX) $(CXXFLAGS) -ObjC++ -fobjc-weak -fobjc-arc -c -o $@ $< + +%.o:../%.mm + $(CXX) $(CXXFLAGS) -ObjC++ -fobjc-weak -fobjc-arc -c -o $@ $< + +all: $(EXE) + $(MAKE) clean_app + $(MAKE) package_app + $(MAKE) clean + @echo Build complete + +$(EXE): $(OBJS) + $(CXX) -o $@ $^ $(CXXFLAGS) $(LIBS) + +clean: + rm -f $(EXE) $(OBJS) + +clean_app: + rm -rf "./$(EXE).app/" + +package_app: + mkdir -p "./$(EXE).app"/Contents/{MacOS,Resources} + cp ./Info.plist "./$(EXE).app/Contents/" + sed -e "s/APP_NAME/$(EXE)/g" -i "" "./$(EXE).app/Contents/Info.plist" + cp ./$(EXE) "./$(EXE).app/Contents/MacOS/$(EXE)" \ No newline at end of file From f6ecd6c8bc5cb88b421c667eedb5d4bea053cc41 Mon Sep 17 00:00:00 2001 From: semvis123 Date: Tue, 3 Nov 2020 21:17:38 +0100 Subject: [PATCH 02/55] automaticly generate channelID --- Client/macos/MacOSBluetoothConnector.mm | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/Client/macos/MacOSBluetoothConnector.mm b/Client/macos/MacOSBluetoothConnector.mm index 1b715f6..9ab84af 100644 --- a/Client/macos/MacOSBluetoothConnector.mm +++ b/Client/macos/MacOSBluetoothConnector.mm @@ -29,7 +29,7 @@ void WSAStartupWrapper() // } } -// generates error +// doesn't generate error anymore, but doesn't close connection yet, because the channel is not stored globaly void MacOSBluetoothConnector::connect(const std::string& addrStr) { // convert mac adress to nsstring @@ -38,7 +38,15 @@ void WSAStartupWrapper() IOBluetoothDevice *device = [IOBluetoothDevice deviceWithAddressString:addressNSString]; // create new channel IOBluetoothRFCOMMChannel *channel = [[IOBluetoothRFCOMMChannel alloc] init]; - if ([device openRFCOMMChannelSync: &channel withChannelID:1 delegate: nil] == kIOReturnSuccess) { + // create sppServiceid + IOBluetoothSDPUUID *sppServiceUUID = [IOBluetoothSDPUUID uuid16: kBluetoothSDPUUID16RFCOMM]; + // get sppServiceRecord + IOBluetoothSDPServiceRecord *sppServiceRecord = [device getServiceRecordForUUID:sppServiceUUID]; + // get rfcommChannelID from sppServiceRecord + UInt8 rfcommChannelID; + [sppServiceRecord getRFCOMMChannelID:&rfcommChannelID]; + + if ([device openRFCOMMChannelSync: &channel withChannelID: rfcommChannelID delegate: nil] == kIOReturnSuccess) { const int connectResult = kIOReturnSuccess; printf("%d", connectResult); this->_connected = true; @@ -95,6 +103,7 @@ void WSAStartupWrapper() // closesocket(this->_socket); // this->_socket = INVALID_SOCKET; // } + // [this->channel closeChannel]; } bool MacOSBluetoothConnector::isConnected() noexcept From bec22e449d3be33e8f0109bc4818888da8695bf2 Mon Sep 17 00:00:00 2001 From: semvis123 Date: Wed, 4 Nov 2020 17:58:44 +0100 Subject: [PATCH 03/55] updated bluetoothconnector --- Client/macos/MacOSBluetoothConnector.h | 15 +- Client/macos/MacOSBluetoothConnector.mm | 196 ++++++++++-------------- 2 files changed, 90 insertions(+), 121 deletions(-) diff --git a/Client/macos/MacOSBluetoothConnector.h b/Client/macos/MacOSBluetoothConnector.h index 36cf918..93eb265 100644 --- a/Client/macos/MacOSBluetoothConnector.h +++ b/Client/macos/MacOSBluetoothConnector.h @@ -7,13 +7,15 @@ #include #include "ByteMagic.h" #include + +#include class MacOSBluetoothConnector final : public IBluetoothConnector { public: MacOSBluetoothConnector(); - ~MacOSBluetoothConnector(); - + static void connectToMac(MacOSBluetoothConnector* MacOSBluetoothConnector) noexcept(false); + virtual void dataRec(const char *dataReceived) noexcept(false); virtual void connect(const std::string& addrStr) noexcept(false); virtual int send(char* buf, size_t length) noexcept(false); virtual int recv(char* buf, size_t length) noexcept(false); @@ -23,10 +25,9 @@ class MacOSBluetoothConnector final : public IBluetoothConnector virtual std::vector getConnectedDevices() noexcept(false); private: - std::vector _findDevicesInRadio(); - std::string _wstringToUtf8(const std::wstring& wstr); + void *rfcommDevice; + void *rfcommchannel; + std::thread* uthread = NULL; + int running = 0; - // SOCKET _socket = INVALID_SOCKET; - std::atomic _connected = false; - void _initSocket(); }; \ No newline at end of file diff --git a/Client/macos/MacOSBluetoothConnector.mm b/Client/macos/MacOSBluetoothConnector.mm index 9ab84af..69fa29f 100644 --- a/Client/macos/MacOSBluetoothConnector.mm +++ b/Client/macos/MacOSBluetoothConnector.mm @@ -1,41 +1,61 @@ +// #import #include "MacOSBluetoothConnector.h" +#include -// don't know if this is needed -void WSAStartupWrapper() +MacOSBluetoothConnector::MacOSBluetoothConnector() { - // int iResult; - // WSADATA wsaData; - // iResult = WSAStartup(MAKEWORD(2, 2), &wsaData); - // if (iResult != 0) { - // throw std::runtime_error("WSAStartup failed: " + std::to_string(iResult)); - // } + +} +MacOSBluetoothConnector::~MacOSBluetoothConnector() +{ + //onclose event + disconnect(); } -MacOSBluetoothConnector::MacOSBluetoothConnector() +@interface AsyncCommDelegate : NSObject { + @public + MacOSBluetoothConnector* delegateCPP; +} +@end + +@implementation AsyncCommDelegate { +} + +-(void)rfcommChannelOpenComplete:(IOBluetoothRFCOMMChannel *)rfcommChannel status:(IOReturn)error { - // static bool startedUp = false; - // if (!startedUp) - // { - // ::WSAStartupWrapper(); - // startedUp = true; - // } + + if ( error != kIOReturnSuccess ) { + fprintf(stderr,"Error - could not open the RFCOMM channel. Error code = %08x.\n",error); + return; + } + else{ + fprintf(stderr,"Connected. Yeah!\n"); + } + } -MacOSBluetoothConnector::~MacOSBluetoothConnector() +-(void)rfcommChannelData:(IOBluetoothRFCOMMChannel *)rfcommChannel data:(void *)dataPointer length:(size_t)dataLength { - // if (this->_socket != INVALID_SOCKET) - // { - // ::closesocket(this->_socket); - // } + NSString *message = [[NSString alloc] initWithBytes:dataPointer length:dataLength encoding:NSUTF8StringEncoding]; + delegateCPP->dataRec([message UTF8String]); +} + + +@end + +int MacOSBluetoothConnector::send(char* buf, size_t length) +{ + fprintf(stderr,"Sending Message\n"); + [(__bridge IOBluetoothRFCOMMChannel*)rfcommchannel writeSync:(void*)buf length:length]; + return 1; } // doesn't generate error anymore, but doesn't close connection yet, because the channel is not stored globaly -void MacOSBluetoothConnector::connect(const std::string& addrStr) +void MacOSBluetoothConnector::connectToMac(MacOSBluetoothConnector* MacOSBluetoothConnector) { - // convert mac adress to nsstring - NSString *addressNSString = [NSString stringWithCString:addrStr.c_str() encoding:[NSString defaultCStringEncoding]]; - // get device based on mac adress - IOBluetoothDevice *device = [IOBluetoothDevice deviceWithAddressString:addressNSString]; + MacOSBluetoothConnector->running = 1; + //get device + IOBluetoothDevice *device = (__bridge IOBluetoothDevice *)MacOSBluetoothConnector->rfcommDevice; // create new channel IOBluetoothRFCOMMChannel *channel = [[IOBluetoothRFCOMMChannel alloc] init]; // create sppServiceid @@ -45,32 +65,42 @@ void WSAStartupWrapper() // get rfcommChannelID from sppServiceRecord UInt8 rfcommChannelID; [sppServiceRecord getRFCOMMChannelID:&rfcommChannelID]; - - if ([device openRFCOMMChannelSync: &channel withChannelID: rfcommChannelID delegate: nil] == kIOReturnSuccess) { - const int connectResult = kIOReturnSuccess; - printf("%d", connectResult); - this->_connected = true; + // setup delegate + AsyncCommDelegate* asyncCommDelegate = [[AsyncCommDelegate alloc] init]; + asyncCommDelegate->delegateCPP = MacOSBluetoothConnector; + // try to open channel + if ( [device openRFCOMMChannelAsync:&channel withChannelID:rfcommChannelID delegate:asyncCommDelegate] != kIOReturnSuccess ) { + throw "Error - could not open the rfcomm.\n"; + } + // store the channel + MacOSBluetoothConnector->rfcommchannel = (__bridge void*) channel; + + printf("Successfully connected"); + // keep thread running + while (MacOSBluetoothConnector->running) { + [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:1]]; } } +void MacOSBluetoothConnector::connect(const std::string& addrStr){ + // convert mac adress to nsstring + NSString *addressNSString = [NSString stringWithCString:addrStr.c_str() encoding:[NSString defaultCStringEncoding]]; + // get device based on mac adress + IOBluetoothDevice *device = [IOBluetoothDevice deviceWithAddressString:addressNSString]; + // store the device in an variable + rfcommDevice = (__bridge void*) device; + uthread = new std::thread(MacOSBluetoothConnector::connectToMac, this); +} -int MacOSBluetoothConnector::send(char* buf, size_t length) +void MacOSBluetoothConnector::dataRec(const char *dataReceived) { - // auto bytesSent = ::send(this->_socket, buf, length, 0); - // if (bytesSent == SOCKET_ERROR) - // { - // throw RecoverableException("Couldn't send (" + std::to_string(WSAGetLastError()) + ")", true); - // } - // return bytesSent; + printf("%s\n",dataReceived); // do something more sensible than just printing it! For example establishing a callback here. } int MacOSBluetoothConnector::recv(char* buf, size_t length) { - // auto bytesReceived = ::recv(this->_socket, buf, length, 0); - // if (bytesReceived == SOCKET_ERROR) - // { - // throw RecoverableException("Couldn't recv (" + std::to_string(WSAGetLastError()) + ")", true); - // } - // return bytesReceived; + return 1; + // printf("%s\n",dataReceived); // do something more sensible than just printing it! For example establishing a callback here. + } // currently working @@ -96,78 +126,16 @@ void WSAStartupWrapper() void MacOSBluetoothConnector::disconnect() noexcept { - // if (this->_socket != INVALID_SOCKET) - // { - // this->_connected = false; - // shutdown(this->_socket, SD_BOTH); - // closesocket(this->_socket); - // this->_socket = INVALID_SOCKET; - // } - // [this->channel closeChannel]; + running = 0; + // wait for the thread to finish + uthread->join(); + // get the channel + IOBluetoothRFCOMMChannel *chan = (__bridge IOBluetoothRFCOMMChannel*) rfcommchannel; + // close the channel + [chan closeChannel]; } bool MacOSBluetoothConnector::isConnected() noexcept { - return this->_connected; -} - -// probably don't need this function (right?) -void MacOSBluetoothConnector::_initSocket() -{ - // SOCKET sock = ::socket(AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM); - // if (sock == INVALID_SOCKET) - // { - // throw std::runtime_error("Couldn't create socket: " + std::to_string(WSAGetLastError())); - // } - - // ULONG enable = TRUE; - // if (::setsockopt(sock, SOL_RFCOMM, SO_BTH_AUTHENTICATE, reinterpret_cast(&enable), sizeof(enable))) - // { - // throw std::runtime_error("Couldn't set SO_BTH_AUTHENTICATE: " + std::to_string(WSAGetLastError())); - // } - - // if (::setsockopt(sock, SOL_RFCOMM, SO_BTH_ENCRYPT, reinterpret_cast(&enable), sizeof(enable))) - // { - // throw std::runtime_error("Couldn't set SO_BTH_ENCRYPT: " + std::to_string(WSAGetLastError())); - // } - - // this->_socket = sock; -} - -// probably don't need this function (right?) -std::string MacOSBluetoothConnector::_wstringToUtf8(const std::wstring& wstr) -{ - // std::string strTo; - // const int num_chars = WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), wstr.length(), NULL, 0, NULL, NULL); - - // if (num_chars > 0) - // { - // strTo.resize(num_chars); - // WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), wstr.length(), &strTo[0], num_chars, NULL, NULL); - // } - // return strTo; -} - - -// probably don't need this function (right?) -std::vector MacOSBluetoothConnector::_findDevicesInRadio() -{ - // std::vector res; - - // for (IOBluetoothDevice* device in [IOBluetoothDevice pairedDevices]) { - // BluetoothDevice dev; - // dev.mac = [[device addressString]UTF8String] - // dev.name = [[device name] UTF8String] - // printf("%s - ",[[device addressString]UTF8String]); - // printf("%s - ",[[device name] UTF8String]); - // if ([device isConnected]) { - // printf("connected device"); - // res.append(dev) - // }else{ - // printf("disconnected device"); - // } - // printf("\n"); - // } - - // return res; -} + return running; +} \ No newline at end of file From cee86fa6ce610be6132fc5ca284079750ef364d7 Mon Sep 17 00:00:00 2001 From: semvis123 Date: Wed, 4 Nov 2020 19:43:17 +0100 Subject: [PATCH 04/55] fixed segmentation fault --- Client/macos/MacOSBluetoothConnector.h | 3 ++- Client/macos/MacOSBluetoothConnector.mm | 6 ++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/Client/macos/MacOSBluetoothConnector.h b/Client/macos/MacOSBluetoothConnector.h index 93eb265..72808f2 100644 --- a/Client/macos/MacOSBluetoothConnector.h +++ b/Client/macos/MacOSBluetoothConnector.h @@ -21,7 +21,8 @@ class MacOSBluetoothConnector final : public IBluetoothConnector virtual int recv(char* buf, size_t length) noexcept(false); virtual void disconnect() noexcept; virtual bool isConnected() noexcept; - + virtual void closeConnection(); + virtual std::vector getConnectedDevices() noexcept(false); private: diff --git a/Client/macos/MacOSBluetoothConnector.mm b/Client/macos/MacOSBluetoothConnector.mm index 69fa29f..bd0b777 100644 --- a/Client/macos/MacOSBluetoothConnector.mm +++ b/Client/macos/MacOSBluetoothConnector.mm @@ -129,12 +129,18 @@ -(void)rfcommChannelData:(IOBluetoothRFCOMMChannel *)rfcommChannel data:(void *) running = 0; // wait for the thread to finish uthread->join(); + // close connection + closeConnection(); +} +void MacOSBluetoothConnector::closeConnection() { // get the channel IOBluetoothRFCOMMChannel *chan = (__bridge IOBluetoothRFCOMMChannel*) rfcommchannel; // close the channel [chan closeChannel]; + fprintf(stderr,"closing"); } + bool MacOSBluetoothConnector::isConnected() noexcept { return running; From 07d1b98923c6e3121cac3f3bcba5f8758c102a53 Mon Sep 17 00:00:00 2001 From: semvis123 Date: Wed, 4 Nov 2020 19:53:53 +0100 Subject: [PATCH 05/55] disconnects headphones after disconnect this is used because it won't open the channel if the channel is opened before on the same connection. --- Client/macos/MacOSBluetoothConnector.mm | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/Client/macos/MacOSBluetoothConnector.mm b/Client/macos/MacOSBluetoothConnector.mm index bd0b777..af8fbf8 100644 --- a/Client/macos/MacOSBluetoothConnector.mm +++ b/Client/macos/MacOSBluetoothConnector.mm @@ -9,7 +9,9 @@ MacOSBluetoothConnector::~MacOSBluetoothConnector() { //onclose event - disconnect(); + if (isConnected()){ + disconnect(); + } } @interface AsyncCommDelegate : NSObject { @@ -86,6 +88,10 @@ -(void)rfcommChannelData:(IOBluetoothRFCOMMChannel *)rfcommChannel data:(void *) NSString *addressNSString = [NSString stringWithCString:addrStr.c_str() encoding:[NSString defaultCStringEncoding]]; // get device based on mac adress IOBluetoothDevice *device = [IOBluetoothDevice deviceWithAddressString:addressNSString]; + // if device is not connected + if (![device isConnected]) { + [device openConnection]; + } // store the device in an variable rfcommDevice = (__bridge void*) device; uthread = new std::thread(MacOSBluetoothConnector::connectToMac, this); @@ -137,6 +143,10 @@ -(void)rfcommChannelData:(IOBluetoothRFCOMMChannel *)rfcommChannel data:(void *) IOBluetoothRFCOMMChannel *chan = (__bridge IOBluetoothRFCOMMChannel*) rfcommchannel; // close the channel [chan closeChannel]; + // get the device + IOBluetoothDevice *device =(__bridge IOBluetoothDevice*) rfcommDevice; + // disconnect from the device + [device closeConnection]; fprintf(stderr,"closing"); } From b4e098eaa3a094498bacfde29a8fec445e01ce69 Mon Sep 17 00:00:00 2001 From: semvis123 Date: Wed, 4 Nov 2020 19:57:48 +0100 Subject: [PATCH 06/55] added two empty lines for readability --- Client/macos/MacOSBluetoothConnector.mm | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Client/macos/MacOSBluetoothConnector.mm b/Client/macos/MacOSBluetoothConnector.mm index af8fbf8..48db604 100644 --- a/Client/macos/MacOSBluetoothConnector.mm +++ b/Client/macos/MacOSBluetoothConnector.mm @@ -143,10 +143,12 @@ -(void)rfcommChannelData:(IOBluetoothRFCOMMChannel *)rfcommChannel data:(void *) IOBluetoothRFCOMMChannel *chan = (__bridge IOBluetoothRFCOMMChannel*) rfcommchannel; // close the channel [chan closeChannel]; + // get the device IOBluetoothDevice *device =(__bridge IOBluetoothDevice*) rfcommDevice; // disconnect from the device [device closeConnection]; + fprintf(stderr,"closing"); } From 6e308a25d0d33917afadffa4e62a77275dab9083 Mon Sep 17 00:00:00 2001 From: semvis123 Date: Wed, 4 Nov 2020 20:12:25 +0100 Subject: [PATCH 07/55] added some comments --- Client/macos/MacOSBluetoothConnector.mm | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/Client/macos/MacOSBluetoothConnector.mm b/Client/macos/MacOSBluetoothConnector.mm index 48db604..afd911a 100644 --- a/Client/macos/MacOSBluetoothConnector.mm +++ b/Client/macos/MacOSBluetoothConnector.mm @@ -22,7 +22,7 @@ @interface AsyncCommDelegate : NSObject { @implementation AsyncCommDelegate { } - +// this function fires when the channel is opened -(void)rfcommChannelOpenComplete:(IOBluetoothRFCOMMChannel *)rfcommChannel status:(IOReturn)error { @@ -35,7 +35,7 @@ -(void)rfcommChannelOpenComplete:(IOBluetoothRFCOMMChannel *)rfcommChannel statu } } - +// this function fires when the channel receives data -(void)rfcommChannelData:(IOBluetoothRFCOMMChannel *)rfcommChannel data:(void *)dataPointer length:(size_t)dataLength { NSString *message = [[NSString alloc] initWithBytes:dataPointer length:dataLength encoding:NSUTF8StringEncoding]; @@ -48,11 +48,12 @@ -(void)rfcommChannelData:(IOBluetoothRFCOMMChannel *)rfcommChannel data:(void *) int MacOSBluetoothConnector::send(char* buf, size_t length) { fprintf(stderr,"Sending Message\n"); + //write buffer to channel [(__bridge IOBluetoothRFCOMMChannel*)rfcommchannel writeSync:(void*)buf length:length]; - return 1; + return 1; // what to return here? } -// doesn't generate error anymore, but doesn't close connection yet, because the channel is not stored globaly + void MacOSBluetoothConnector::connectToMac(MacOSBluetoothConnector* MacOSBluetoothConnector) { MacOSBluetoothConnector->running = 1; @@ -83,6 +84,7 @@ -(void)rfcommChannelData:(IOBluetoothRFCOMMChannel *)rfcommChannel data:(void *) [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:1]]; } } + void MacOSBluetoothConnector::connect(const std::string& addrStr){ // convert mac adress to nsstring NSString *addressNSString = [NSString stringWithCString:addrStr.c_str() encoding:[NSString defaultCStringEncoding]]; @@ -99,13 +101,14 @@ -(void)rfcommChannelData:(IOBluetoothRFCOMMChannel *)rfcommChannel data:(void *) void MacOSBluetoothConnector::dataRec(const char *dataReceived) { - printf("%s\n",dataReceived); // do something more sensible than just printing it! For example establishing a callback here. + // print received data + printf("%s\n",dataReceived); } int MacOSBluetoothConnector::recv(char* buf, size_t length) { - return 1; - // printf("%s\n",dataReceived); // do something more sensible than just printing it! For example establishing a callback here. + // this becomes the receive function, currently just returning 1 + return 1; } @@ -148,7 +151,7 @@ -(void)rfcommChannelData:(IOBluetoothRFCOMMChannel *)rfcommChannel data:(void *) IOBluetoothDevice *device =(__bridge IOBluetoothDevice*) rfcommDevice; // disconnect from the device [device closeConnection]; - + fprintf(stderr,"closing"); } From 197016cfa5a53537f5aef7009642a9dae754cf51 Mon Sep 17 00:00:00 2001 From: semvis123 Date: Fri, 13 Nov 2020 20:36:32 +0100 Subject: [PATCH 08/55] Removed the macosgui and used the crossplatformgui instead. Setup of window happens in the main.mm file. --- Client/macos/MacOSGUI.cpp | 247 -------------------------------------- Client/macos/MacOSGUI.h | 43 ------- Client/macos/main.mm | 8 +- Client/macos/makefile | 7 +- 4 files changed, 9 insertions(+), 296 deletions(-) delete mode 100644 Client/macos/MacOSGUI.cpp delete mode 100644 Client/macos/MacOSGUI.h diff --git a/Client/macos/MacOSGUI.cpp b/Client/macos/MacOSGUI.cpp deleted file mode 100644 index 191cf17..0000000 --- a/Client/macos/MacOSGUI.cpp +++ /dev/null @@ -1,247 +0,0 @@ -#include "MacOSGUI.h" - -bool MacOSGUI::performGUIPass() -{ - ImGui::NewFrame(); - - static bool isConnected = false; - - bool open = true; - - ImGui::SetNextWindowPos({ 0,0 }); - - { - //TODO: Figure out how to get rid of the Windows window, make everything transparent, and just use ImGui for everything. - //TODO: ImGuiWindowFlags_AlwaysAutoResize causes some flickering. Figure out how to stop it - ImGui::Begin("Sony Headphones", &open, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar); - - //Legal disclaimer - ImGui::Text("! This product is not affiliated with Sony. Use at your own risk. !"); - ImGui::Text("Source: https://github.com/Plutoberth/SonyHeadphonesClient"); - ImGui::Spacing(); - - this->_drawErrors(); - this->_drawDeviceDiscovery(); - - if (this->_bt.isConnected()) - { - ImGui::Spacing(); - this->_drawASMControls(); - } - } - - ImGui::End(); - - return open; -} - -void MacOSGUI::_drawErrors() -{ - //There's a slight race condition here but I don't care, it'd only be for one frame. - if (this->_mq.begin() != this->_mq.end()) - { - ImGui::Text("Errors"); - ImGui::Text("----------------------------"); - for (auto&& message : this->_mq) - { - ImGui::Text(message.message.c_str()); - } - //TODO: add a better ending separator - ImGui::Text("----------------------------"); - } -} - - -void MacOSGUI::_drawDeviceDiscovery() -{ - if (ImGui::CollapsingHeader("Device Discovery ", ImGuiTreeNodeFlags_DefaultOpen)) - { - static std::vector connectedDevices; - static int selectedDevice = -1; - - if (this->_bt.isConnected()) - { - ImGui::Text("Connected to %s", this->_connectedDevice.name.c_str()); - if (ImGui::Button("Disconnect")) - { - selectedDevice = -1; - this->_bt.disconnect(); - } - } - else - { - ImGui::Text("Select from one of the available devices: "); - - int temp = 0; - for (auto device : connectedDevices) - { - ImGui::RadioButton(device.name.c_str(), &selectedDevice, temp++); - } - - ImGui::Spacing(); - - if (this->_connectFuture.valid()) - { - if (this->_connectFuture.ready()) - { - try - { - this->_connectFuture.get(); - } - catch (const RecoverableException& exc) - { - if (exc.shouldDisconnect) - { - this->_bt.disconnect(); - } - this->_mq.addMessage(exc.what()); - } - } - else - { - ImGui::Text("Connecting %c", "|/-\\"[(int)(ImGui::GetTime() / 0.05f) & 3]); - } - } - else - { - if (ImGui::Button("Connect")) - { - if (selectedDevice != -1) - { - this->_connectedDevice = connectedDevices[selectedDevice]; - this->_connectFuture.setFromAsync([this]() { this->_bt.connect(this->_connectedDevice.mac); }); - } - } - } - - ImGui::SameLine(); - - if (this->_connectedDevicesFuture.valid()) - { - if (this->_connectedDevicesFuture.ready()) - { - try - { - connectedDevices = this->_connectedDevicesFuture.get(); - } - catch (const RecoverableException& exc) - { - if (exc.shouldDisconnect) - { - this->_bt.disconnect(); - } - this->_mq.addMessage(exc.what()); - } - } - else - { - ImGui::Text("Discovering Devices %c", "|/-\\"[(int)(ImGui::GetTime() / 0.05f) & 3]); - } - } - else - { - if (ImGui::Button("Refresh devices")) - { - selectedDevice = -1; - this->_connectedDevicesFuture.setFromAsync([this]() { return this->_bt.getConnectedDevices(); }); - } - } - } - } -} - - -void MacOSGUI::_drawASMControls() -{ - static bool focusOnVoice = false; - static bool sentFocusOnVoice = focusOnVoice; - static int asmLevel = 0; - static int sentAsmLevel = asmLevel; - //Don't show if the command only takes a few frames to send - static int commandLinger = 0; - - if (ImGui::CollapsingHeader("Ambient Sound Mode ", ImGuiTreeNodeFlags_DefaultOpen)) - { - ImGui::Text("Control ambient sound for your %ss", this->_connectedDevice.name.c_str()); - - ImGui::SliderInt("Ambient Sound Level", &asmLevel, 0, 19); - - bool sliderActive = ImGui::IsItemActive(); - - if (asmLevel >= MINIMUM_VOICE_FOCUS_STEP) - { - ImGui::Checkbox("Focus on Voice", &focusOnVoice); - } - else - { - ImGui::Text("Focus on Voice isn't enabled on this level."); - } - - if (this->_sendCommandFuture.ready()) - { - commandLinger = 0; - try - { - this->_sendCommandFuture.get(); - } - catch (const RecoverableException& exc) - { - std::string excString; - //We kinda have to do it here and not in the wrapper, due to async causing timing issues. To fix it, the messagequeue can be made - //static, but I'm not sure if I wanna do that. - if (exc.shouldDisconnect) - { - this->_bt.disconnect(); - excString = "Disconnected due to: "; - } - this->_mq.addMessage(excString + exc.what()); - } - } - //This means that we're waiting - else if (this->_sendCommandFuture.valid()) - { - if (commandLinger++ > FPS / 10) - { - ImGui::Text("Sending command %c", "|/-\\"[(int)(ImGui::GetTime() / 0.05f) & 3]); - } - } - //We're not waiting, and there's no command in the air, so we can evaluate sending a new command - else if (sentAsmLevel != asmLevel || sentFocusOnVoice != focusOnVoice) - { - auto ncAsmEffect = sliderActive ? NC_ASM_EFFECT::ADJUSTMENT_IN_PROGRESS : NC_ASM_EFFECT::ADJUSTMENT_COMPLETION; - auto asmId = focusOnVoice ? ASM_ID::VOICE : ASM_ID::NORMAL; - - this->_sendCommandFuture.setFromAsync([=]() { - return this->_bt.sendCommand(CommandSerializer::serializeNcAndAsmSetting( - ncAsmEffect, - NC_ASM_SETTING_TYPE::LEVEL_ADJUSTMENT, - ASM_SETTING_TYPE::LEVEL_ADJUSTMENT, - asmId, - asmLevel - )); - }); - sentAsmLevel = asmLevel; - sentFocusOnVoice = focusOnVoice; - } - } -} - -MacOSGUI::MacOSGUI(BluetoothWrapper bt) : _bt(std::move(bt)) -{ - // bt.getConnectedDevices(); - // Setup Dear ImGui style - ImGui::StyleColorsDark(); - ImGuiIO& io = ImGui::GetIO(); (void)io; - - this->_mq = TimedMessageQueue(GUI_MAX_MESSAGES); - this->_connectedDevicesFuture.setFromAsync([this]() { return this->_bt.getConnectedDevices(); }); - - io.IniFilename = nullptr; - io.WantSaveIniSettings = false; - - //AddFontFromMemory will own the pointer, so there's no leak - char* fileData = new char[sizeof(CascadiaCodeTTF)]; - memcpy(fileData, CascadiaCodeTTF, sizeof(CascadiaCodeTTF)); - ImFont* font = io.Fonts->AddFontFromMemoryTTF(reinterpret_cast(fileData), sizeof(CascadiaCodeTTF), 15.0f); - IM_ASSERT(font != NULL); -} diff --git a/Client/macos/MacOSGUI.h b/Client/macos/MacOSGUI.h deleted file mode 100644 index 263b402..0000000 --- a/Client/macos/MacOSGUI.h +++ /dev/null @@ -1,43 +0,0 @@ -#pragma once - -#include "imgui/imgui.h" -#include "Constants.h" -#include "IBluetoothConnector.h" -#include "BluetoothWrapper.h" -#include "CommandSerializer.h" -#include "Exceptions.h" -#include "TimedMessageQueue.h" -#include "SingleInstanceFuture.h" -#include "CascadiaCodeFont.h" -#include "MacOSBluetoothConnector.h" - -#include - -constexpr auto GUI_MAX_MESSAGES = 10; -constexpr auto FPS = 60; -constexpr auto GUI_HEIGHT = 350; -constexpr auto GUI_WIDTH = 540; - -//This class should be constructed after AFTER the Dear ImGUI context is initialized. -class MacOSGUI -{ -public: - MacOSGUI(BluetoothWrapper bt); - - //Run the GUI code once. This function should be called from a loop from one of the GUI impls (Windows, OSX, Linux...) - //O: true if the user wants to close the window - bool performGUIPass(); -private: - void _drawErrors(); - void _drawDeviceDiscovery(); - void _drawASMControls(); - - BluetoothDevice _connectedDevice; - BluetoothWrapper _bt; - SingleInstanceFuture> _connectedDevicesFuture; - SingleInstanceFuture _sendCommandFuture; - SingleInstanceFuture _connectFuture; - TimedMessageQueue _mq; -}; - - diff --git a/Client/macos/main.mm b/Client/macos/main.mm index 40af0dc..4f146b3 100644 --- a/Client/macos/main.mm +++ b/Client/macos/main.mm @@ -15,7 +15,7 @@ #include "TimedMessageQueue.h" #include "BluetoothWrapper.h" #include "MacOSBluetoothConnector.h" -#include "MacOSGUI.h" +#include "CrossPlatformGUI.h" static void glfw_error_callback(int error, const char* description) { @@ -28,10 +28,10 @@ int main(int, char**) IMGUI_CHECKVERSION(); ImGui::CreateContext(); - // init MacOSGUI + // init GUI std::unique_ptr connector = std::make_unique(); BluetoothWrapper wrap(std::move(connector)); - MacOSGUI macOSGUI = MacOSGUI(std::move(wrap)); + CrossPlatformGUI GUI = CrossPlatformGUI(std::move(wrap)); // Setup window glfwSetErrorCallback(glfw_error_callback); @@ -83,7 +83,7 @@ int main(int, char**) // Start the Dear ImGui frame ImGui_ImplMetal_NewFrame(renderPassDescriptor); ImGui_ImplGlfw_NewFrame(); - macOSGUI.performGUIPass(); + GUI.performGUIPass(); // Rendering ImGui::Render(); diff --git a/Client/macos/makefile b/Client/macos/makefile index 8b2bdf1..4952dc1 100644 --- a/Client/macos/makefile +++ b/Client/macos/makefile @@ -8,7 +8,7 @@ EXE = sonyheadphonesclient SOURCES = main.mm -SOURCES += MacOSGUI.cpp MacOSBluetoothConnector.cpp BluetoothWrapper.cpp +SOURCES += ../GUI_Impls/CrossPlatformGUI.cpp MacOSBluetoothConnector.cpp BluetoothWrapper.cpp SOURCES += TimedMessageQueue.cpp CascadiaCodeFont.cpp CommandSerializer.cpp SOURCES += ByteMagic.cpp SOURCES += ../imgui/examples/imgui_impl_glfw.cpp ../imgui/examples/imgui_impl_metal.mm @@ -18,7 +18,7 @@ OBJS = $(addsuffix .o, $(basename $(notdir $(SOURCES)))) LIBS = -framework IOBluetooth -framework Metal -framework MetalKit -framework Cocoa -framework IOKit -framework CoreVideo -framework QuartzCore LIBS += -L/usr/local/lib -lglfw -CXXFLAGS = -I../imgui/ -I../imgui/examples/ -I../ -I/usr/local/include +CXXFLAGS = -I../imgui/ -I../GUI_Impls/ -I../imgui/examples/ -I../ -I/usr/local/include CXXFLAGS += -Wall -Wformat -std=c++17 -stdlib=libc++ CFLAGS = $(CXXFLAGS) @@ -32,6 +32,9 @@ CFLAGS = $(CXXFLAGS) %.o:../imgui/%.cpp $(CXX) $(CXXFLAGS) -c -o $@ $< +%.o:../GUI_Impls/%.cpp + $(CXX) $(CXXFLAGS) -c -o $@ $< + %.o:../imgui/examples/%.mm $(CXX) $(CXXFLAGS) -ObjC++ -fobjc-weak -fobjc-arc -c -o $@ $< From 8a4b7e888f4f769728c1edfb8ef17af5abd43dfb Mon Sep 17 00:00:00 2001 From: semvis123 Date: Fri, 13 Nov 2020 20:51:40 +0100 Subject: [PATCH 09/55] Returns expected sent amount of bytes instead of 1 --- Client/macos/MacOSBluetoothConnector.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Client/macos/MacOSBluetoothConnector.mm b/Client/macos/MacOSBluetoothConnector.mm index afd911a..4767177 100644 --- a/Client/macos/MacOSBluetoothConnector.mm +++ b/Client/macos/MacOSBluetoothConnector.mm @@ -50,7 +50,7 @@ -(void)rfcommChannelData:(IOBluetoothRFCOMMChannel *)rfcommChannel data:(void *) fprintf(stderr,"Sending Message\n"); //write buffer to channel [(__bridge IOBluetoothRFCOMMChannel*)rfcommchannel writeSync:(void*)buf length:length]; - return 1; // what to return here? + return length; } From 27eb3314edcfeab1bb8b4aba4a3b926ef160d6c7 Mon Sep 17 00:00:00 2001 From: semvis123 Date: Sat, 14 Nov 2020 20:35:04 +0100 Subject: [PATCH 10/55] Moved gui stuff to seperate file --- Client/GUI_Impls/MacOSGUI.h | 20 ++++++++ Client/GUI_Impls/MacOSGUI.mm | 90 +++++++++++++++++++++++++++++++++++ Client/macos/main.mm | 92 +++--------------------------------- Client/macos/makefile | 6 ++- 4 files changed, 121 insertions(+), 87 deletions(-) create mode 100644 Client/GUI_Impls/MacOSGUI.h create mode 100644 Client/GUI_Impls/MacOSGUI.mm diff --git a/Client/GUI_Impls/MacOSGUI.h b/Client/GUI_Impls/MacOSGUI.h new file mode 100644 index 0000000..19c7ed9 --- /dev/null +++ b/Client/GUI_Impls/MacOSGUI.h @@ -0,0 +1,20 @@ +#include "imgui.h" +#include "imgui_impl_glfw.h" +#include "imgui_impl_metal.h" +#include + +#define GLFW_INCLUDE_NONE +#define GLFW_EXPOSE_NATIVE_COCOA +#include +#include + +#include +#include + +#include "Constants.h" +#include "TimedMessageQueue.h" +#include "BluetoothWrapper.h" +#include "CrossPlatformGUI.h" + +static void glfw_error_callback(int error, const char* description); +void EnterGUIMainLoop(BluetoothWrapper bt); \ No newline at end of file diff --git a/Client/GUI_Impls/MacOSGUI.mm b/Client/GUI_Impls/MacOSGUI.mm new file mode 100644 index 0000000..f02f646 --- /dev/null +++ b/Client/GUI_Impls/MacOSGUI.mm @@ -0,0 +1,90 @@ +#include "MacOSGUI.h" + +static void glfw_error_callback(int error, const char* description) +{ + fprintf(stderr, "Glfw Error %d: %s\n", error, description); +} + +void EnterGUIMainLoop(BluetoothWrapper bt) +{ + // Setup Dear ImGui binding + IMGUI_CHECKVERSION(); + ImGui::CreateContext(); + + // init GUI + CrossPlatformGUI GUI = CrossPlatformGUI(std::move(bt)); + + // Setup window + glfwSetErrorCallback(glfw_error_callback); + if (!glfwInit()) + return; + + // Create window with graphics context + glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); + GLFWwindow* window = glfwCreateWindow(GUI_WIDTH, GUI_HEIGHT, "Sony Headphones App", NULL, NULL); + if (window == NULL) + return; + + id device = MTLCreateSystemDefaultDevice();; + id commandQueue = [device newCommandQueue]; + + ImGui_ImplGlfw_InitForOpenGL(window, true); + ImGui_ImplMetal_Init(device); + + NSWindow *nswin = glfwGetCocoaWindow(window); + CAMetalLayer *layer = [CAMetalLayer layer]; + layer.device = device; + layer.pixelFormat = MTLPixelFormatBGRA8Unorm; + nswin.contentView.layer = layer; + nswin.contentView.wantsLayer = YES; + + MTLRenderPassDescriptor *renderPassDescriptor = [MTLRenderPassDescriptor new]; + + float clear_color[4] = {0.45f, 0.55f, 0.60f, 1.00f}; + // Main loop + while (!glfwWindowShouldClose(window)) + { + @autoreleasepool + { + // Poll and handle events (inputs, window resize, etc.) + glfwPollEvents(); + + int width, height; + glfwGetFramebufferSize(window, &width, &height); + layer.drawableSize = CGSizeMake(width, height); + id drawable = [layer nextDrawable]; + + id commandBuffer = [commandQueue commandBuffer]; + renderPassDescriptor.colorAttachments[0].clearColor = MTLClearColorMake(clear_color[0], clear_color[1], clear_color[2], clear_color[3]); + renderPassDescriptor.colorAttachments[0].texture = drawable.texture; + renderPassDescriptor.colorAttachments[0].loadAction = MTLLoadActionClear; + renderPassDescriptor.colorAttachments[0].storeAction = MTLStoreActionStore; + id renderEncoder = [commandBuffer renderCommandEncoderWithDescriptor:renderPassDescriptor]; + + // Start the Dear ImGui frame + ImGui_ImplMetal_NewFrame(renderPassDescriptor); + ImGui_ImplGlfw_NewFrame(); + + // perform gui pass + GUI.performGUIPass(); + + // Rendering + ImGui::Render(); + ImGui_ImplMetal_RenderDrawData(ImGui::GetDrawData(), commandBuffer, renderEncoder); + + [renderEncoder popDebugGroup]; + [renderEncoder endEncoding]; + + [commandBuffer presentDrawable:drawable]; + [commandBuffer commit]; + } + } + + // Cleanup + ImGui_ImplMetal_Shutdown(); + ImGui_ImplGlfw_Shutdown(); + ImGui::DestroyContext(); + + glfwDestroyWindow(window); + glfwTerminate(); +}; diff --git a/Client/macos/main.mm b/Client/macos/main.mm index 4f146b3..b20297d 100644 --- a/Client/macos/main.mm +++ b/Client/macos/main.mm @@ -13,97 +13,17 @@ #include "Constants.h" #include "TimedMessageQueue.h" -#include "BluetoothWrapper.h" +#include "MacOSGUI.h" #include "MacOSBluetoothConnector.h" -#include "CrossPlatformGUI.h" - -static void glfw_error_callback(int error, const char* description) -{ - fprintf(stderr, "Glfw Error %d: %s\n", error, description); -} +#include "BluetoothWrapper.h" int main(int, char**) { - // Setup Dear ImGui binding - IMGUI_CHECKVERSION(); - ImGui::CreateContext(); - - // init GUI + // Get bluetooth connector std::unique_ptr connector = std::make_unique(); + // Wrap the connector using the bluetoothwrapper BluetoothWrapper wrap(std::move(connector)); - CrossPlatformGUI GUI = CrossPlatformGUI(std::move(wrap)); - - // Setup window - glfwSetErrorCallback(glfw_error_callback); - if (!glfwInit()) - return 1; - - // Create window with graphics context - glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); - GLFWwindow* window = glfwCreateWindow(GUI_WIDTH, GUI_HEIGHT, "Sony Headphones App", NULL, NULL); - if (window == NULL) - return 1; - - id device = MTLCreateSystemDefaultDevice();; - id commandQueue = [device newCommandQueue]; - - ImGui_ImplGlfw_InitForOpenGL(window, true); - ImGui_ImplMetal_Init(device); - - NSWindow *nswin = glfwGetCocoaWindow(window); - CAMetalLayer *layer = [CAMetalLayer layer]; - layer.device = device; - layer.pixelFormat = MTLPixelFormatBGRA8Unorm; - nswin.contentView.layer = layer; - nswin.contentView.wantsLayer = YES; - - MTLRenderPassDescriptor *renderPassDescriptor = [MTLRenderPassDescriptor new]; - - float clear_color[4] = {0.45f, 0.55f, 0.60f, 1.00f}; - // Main loop - while (!glfwWindowShouldClose(window)) - { - @autoreleasepool - { - // Poll and handle events (inputs, window resize, etc.) - glfwPollEvents(); - - int width, height; - glfwGetFramebufferSize(window, &width, &height); - layer.drawableSize = CGSizeMake(width, height); - id drawable = [layer nextDrawable]; - - id commandBuffer = [commandQueue commandBuffer]; - renderPassDescriptor.colorAttachments[0].clearColor = MTLClearColorMake(clear_color[0], clear_color[1], clear_color[2], clear_color[3]); - renderPassDescriptor.colorAttachments[0].texture = drawable.texture; - renderPassDescriptor.colorAttachments[0].loadAction = MTLLoadActionClear; - renderPassDescriptor.colorAttachments[0].storeAction = MTLStoreActionStore; - id renderEncoder = [commandBuffer renderCommandEncoderWithDescriptor:renderPassDescriptor]; - - // Start the Dear ImGui frame - ImGui_ImplMetal_NewFrame(renderPassDescriptor); - ImGui_ImplGlfw_NewFrame(); - GUI.performGUIPass(); - - // Rendering - ImGui::Render(); - ImGui_ImplMetal_RenderDrawData(ImGui::GetDrawData(), commandBuffer, renderEncoder); - - [renderEncoder popDebugGroup]; - [renderEncoder endEncoding]; - - [commandBuffer presentDrawable:drawable]; - [commandBuffer commit]; - } - } - - // Cleanup - ImGui_ImplMetal_Shutdown(); - ImGui_ImplGlfw_Shutdown(); - ImGui::DestroyContext(); - - glfwDestroyWindow(window); - glfwTerminate(); - + // Start the gui + EnterGUIMainLoop(std::move(wrap)); return 0; } \ No newline at end of file diff --git a/Client/macos/makefile b/Client/macos/makefile index 4952dc1..3bd7d67 100644 --- a/Client/macos/makefile +++ b/Client/macos/makefile @@ -8,7 +8,8 @@ EXE = sonyheadphonesclient SOURCES = main.mm -SOURCES += ../GUI_Impls/CrossPlatformGUI.cpp MacOSBluetoothConnector.cpp BluetoothWrapper.cpp +SOURCES += ../GUI_Impls/MacOSGUI.cpp ../GUI_Impls/CrossPlatformGUI.cpp +SOURCES += MacOSBluetoothConnector.cpp BluetoothWrapper.cpp SOURCES += TimedMessageQueue.cpp CascadiaCodeFont.cpp CommandSerializer.cpp SOURCES += ByteMagic.cpp SOURCES += ../imgui/examples/imgui_impl_glfw.cpp ../imgui/examples/imgui_impl_metal.mm @@ -35,6 +36,9 @@ CFLAGS = $(CXXFLAGS) %.o:../GUI_Impls/%.cpp $(CXX) $(CXXFLAGS) -c -o $@ $< +%.o:../GUI_Impls/%.mm + $(CXX) $(CXXFLAGS) -ObjC++ -fobjc-weak -fobjc-arc -c -o $@ $< + %.o:../imgui/examples/%.mm $(CXX) $(CXXFLAGS) -ObjC++ -fobjc-weak -fobjc-arc -c -o $@ $< From ced304b2d71054554820e069d9cd593802499d48 Mon Sep 17 00:00:00 2001 From: semvis123 Date: Sat, 14 Nov 2020 21:57:35 +0100 Subject: [PATCH 11/55] Cleaned headers --- Client/macos/main.mm | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/Client/macos/main.mm b/Client/macos/main.mm index b20297d..92f22d0 100644 --- a/Client/macos/main.mm +++ b/Client/macos/main.mm @@ -1,18 +1,5 @@ -#include "imgui.h" -#include "imgui_impl_glfw.h" -#include "imgui_impl_metal.h" #include -#define GLFW_INCLUDE_NONE -#define GLFW_EXPOSE_NATIVE_COCOA -#include -#include - -#import -#import - -#include "Constants.h" -#include "TimedMessageQueue.h" #include "MacOSGUI.h" #include "MacOSBluetoothConnector.h" #include "BluetoothWrapper.h" From 7a5ec48a578739983b7b047d121e2b4bd9ae9c0d Mon Sep 17 00:00:00 2001 From: Sem Vissscher Date: Sun, 20 Dec 2020 17:10:16 +0100 Subject: [PATCH 12/55] Changed receive function and started native ui version --- Client/macos/AppDelegate.h | 14 + Client/macos/AppDelegate.m | 27 ++ Client/macos/MacOSBluetoothConnector.h | 14 +- Client/macos/MacOSBluetoothConnector.mm | 134 ++++--- Client/macos/Main.storyboard | 307 +++++++++++++++ .../project.pbxproj | 357 ++++++++++++++++++ .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../UserInterfaceState.xcuserstate | Bin 0 -> 53090 bytes .../xcschemes/xcschememanagement.plist | 14 + Client/macos/TMacOSBluetoothConnector.h | 34 ++ Client/macos/TMacOSBluetoothConnector.mm | 162 ++++++++ Client/macos/ViewController.h | 14 + Client/macos/ViewController.m | 26 ++ Client/macos/info.plist | 30 +- Client/macos/main.mm | 9 +- 15 files changed, 1082 insertions(+), 68 deletions(-) create mode 100644 Client/macos/AppDelegate.h create mode 100644 Client/macos/AppDelegate.m create mode 100644 Client/macos/Main.storyboard create mode 100644 Client/macos/SonyHeadphonesClient.xcodeproj/project.pbxproj create mode 100644 Client/macos/SonyHeadphonesClient.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 Client/macos/SonyHeadphonesClient.xcodeproj/project.xcworkspace/xcuserdata/semvi.xcuserdatad/UserInterfaceState.xcuserstate create mode 100644 Client/macos/SonyHeadphonesClient.xcodeproj/xcuserdata/semvi.xcuserdatad/xcschemes/xcschememanagement.plist create mode 100644 Client/macos/TMacOSBluetoothConnector.h create mode 100644 Client/macos/TMacOSBluetoothConnector.mm create mode 100644 Client/macos/ViewController.h create mode 100644 Client/macos/ViewController.m diff --git a/Client/macos/AppDelegate.h b/Client/macos/AppDelegate.h new file mode 100644 index 0000000..794dc5f --- /dev/null +++ b/Client/macos/AppDelegate.h @@ -0,0 +1,14 @@ +// +// AppDelegate.h +// test +// +// Created by Sem Vissscher on 01/12/2020. +// + +#import + +@interface AppDelegate : NSObject + + +@end + diff --git a/Client/macos/AppDelegate.m b/Client/macos/AppDelegate.m new file mode 100644 index 0000000..c8273d5 --- /dev/null +++ b/Client/macos/AppDelegate.m @@ -0,0 +1,27 @@ +// +// AppDelegate.m +// test +// +// Created by Sem Vissscher on 01/12/2020. +// + +#import "AppDelegate.h" + +@interface AppDelegate () + + +@end + +@implementation AppDelegate + +- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { + // Insert code here to initialize your application +} + + +- (void)applicationWillTerminate:(NSNotification *)aNotification { + // Insert code here to tear down your application +} + + +@end diff --git a/Client/macos/MacOSBluetoothConnector.h b/Client/macos/MacOSBluetoothConnector.h index 72808f2..ebb2f89 100644 --- a/Client/macos/MacOSBluetoothConnector.h +++ b/Client/macos/MacOSBluetoothConnector.h @@ -7,28 +7,32 @@ #include #include "ByteMagic.h" #include - +#include #include +#include +#include + class MacOSBluetoothConnector final : public IBluetoothConnector { public: MacOSBluetoothConnector(); ~MacOSBluetoothConnector(); static void connectToMac(MacOSBluetoothConnector* MacOSBluetoothConnector) noexcept(false); - virtual void dataRec(const char *dataReceived) noexcept(false); virtual void connect(const std::string& addrStr) noexcept(false); virtual int send(char* buf, size_t length) noexcept(false); virtual int recv(char* buf, size_t length) noexcept(false); virtual void disconnect() noexcept; virtual bool isConnected() noexcept; virtual void closeConnection(); - - virtual std::vector getConnectedDevices() noexcept(false); + virtual std::vector getConnectedDevices() noexcept(false); + char* receivedBytes; + int* receivedLength; + bool wantNewData = false; private: void *rfcommDevice; void *rfcommchannel; std::thread* uthread = NULL; int running = 0; - + NSRunLoop * runLoop; }; \ No newline at end of file diff --git a/Client/macos/MacOSBluetoothConnector.mm b/Client/macos/MacOSBluetoothConnector.mm index 4767177..e2735a6 100644 --- a/Client/macos/MacOSBluetoothConnector.mm +++ b/Client/macos/MacOSBluetoothConnector.mm @@ -1,10 +1,8 @@ -// #import #include "MacOSBluetoothConnector.h" -#include MacOSBluetoothConnector::MacOSBluetoothConnector() { - + } MacOSBluetoothConnector::~MacOSBluetoothConnector() { @@ -15,8 +13,8 @@ } @interface AsyncCommDelegate : NSObject { - @public - MacOSBluetoothConnector* delegateCPP; + @public + MacOSBluetoothConnector* delegateCPP; } @end @@ -25,21 +23,34 @@ @implementation AsyncCommDelegate { // this function fires when the channel is opened -(void)rfcommChannelOpenComplete:(IOBluetoothRFCOMMChannel *)rfcommChannel status:(IOReturn)error { - - if ( error != kIOReturnSuccess ) { - fprintf(stderr,"Error - could not open the RFCOMM channel. Error code = %08x.\n",error); - return; - } - else{ - fprintf(stderr,"Connected. Yeah!\n"); - } - + + if ( error != kIOReturnSuccess ) { + fprintf(stderr,"Error - could not open the RFCOMM channel. Error code = %08x.\n",error); + return; + } + else{ + fprintf(stderr,"Connected. Yeah!\n"); + } + } // this function fires when the channel receives data -(void)rfcommChannelData:(IOBluetoothRFCOMMChannel *)rfcommChannel data:(void *)dataPointer length:(size_t)dataLength { - NSString *message = [[NSString alloc] initWithBytes:dataPointer length:dataLength encoding:NSUTF8StringEncoding]; - delegateCPP->dataRec([message UTF8String]); + // int array[(int)dataLength] = (int *)dataPointer; + char* convertedData = (char *)dataPointer; + // print the data + printf("length: %d\n", dataLength); + printf("array length: %d\n", sizeof(convertedData)); + for (int n=0; nreceivedBytes = convertedData; + delegateCPP->receivedLength = (int *)dataLength; + printf("newdata? %d\n",delegateCPP->wantNewData); + if(delegateCPP->wantNewData){ + delegateCPP->wantNewData = false; + } } @@ -47,40 +58,46 @@ -(void)rfcommChannelData:(IOBluetoothRFCOMMChannel *)rfcommChannel data:(void *) int MacOSBluetoothConnector::send(char* buf, size_t length) { - fprintf(stderr,"Sending Message\n"); - //write buffer to channel - [(__bridge IOBluetoothRFCOMMChannel*)rfcommchannel writeSync:(void*)buf length:length]; + fprintf(stderr,"Sending Message\n"); + // write buffer to channel + if ( [(__bridge IOBluetoothRFCOMMChannel*)rfcommchannel writeSync:(void*)buf length:length] != kIOReturnSuccess ){ + fprintf(stderr,"Error - couldn't send command\n"); + } + else { + fprintf(stderr,"Send command succesful\n"); + } return length; } -void MacOSBluetoothConnector::connectToMac(MacOSBluetoothConnector* MacOSBluetoothConnector) +void MacOSBluetoothConnector::connectToMac(MacOSBluetoothConnector* macOSBluetoothConnector) { - MacOSBluetoothConnector->running = 1; + macOSBluetoothConnector->running = 1; //get device - IOBluetoothDevice *device = (__bridge IOBluetoothDevice *)MacOSBluetoothConnector->rfcommDevice; + IOBluetoothDevice *device = (__bridge IOBluetoothDevice *)macOSBluetoothConnector->rfcommDevice; // create new channel IOBluetoothRFCOMMChannel *channel = [[IOBluetoothRFCOMMChannel alloc] init]; // create sppServiceid IOBluetoothSDPUUID *sppServiceUUID = [IOBluetoothSDPUUID uuid16: kBluetoothSDPUUID16RFCOMM]; // get sppServiceRecord - IOBluetoothSDPServiceRecord *sppServiceRecord = [device getServiceRecordForUUID:sppServiceUUID]; - // get rfcommChannelID from sppServiceRecord + IOBluetoothSDPServiceRecord *sppServiceRecord = [device getServiceRecordForUUID:sppServiceUUID]; + // get rfcommChannelID from sppServiceRecord UInt8 rfcommChannelID; - [sppServiceRecord getRFCOMMChannelID:&rfcommChannelID]; + [sppServiceRecord getRFCOMMChannelID:&rfcommChannelID]; // setup delegate AsyncCommDelegate* asyncCommDelegate = [[AsyncCommDelegate alloc] init]; - asyncCommDelegate->delegateCPP = MacOSBluetoothConnector; + asyncCommDelegate->delegateCPP = macOSBluetoothConnector; // try to open channel if ( [device openRFCOMMChannelAsync:&channel withChannelID:rfcommChannelID delegate:asyncCommDelegate] != kIOReturnSuccess ) { throw "Error - could not open the rfcomm.\n"; } // store the channel - MacOSBluetoothConnector->rfcommchannel = (__bridge void*) channel; - + macOSBluetoothConnector->rfcommchannel = (__bridge void*) channel; + printf("Successfully connected"); + // keep thread running - while (MacOSBluetoothConnector->running) { + while (macOSBluetoothConnector->running) { [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:1]]; } } @@ -99,20 +116,45 @@ -(void)rfcommChannelData:(IOBluetoothRFCOMMChannel *)rfcommChannel data:(void *) uthread = new std::thread(MacOSBluetoothConnector::connectToMac, this); } -void MacOSBluetoothConnector::dataRec(const char *dataReceived) -{ - // print received data - printf("%s\n",dataReceived); -} - int MacOSBluetoothConnector::recv(char* buf, size_t length) { - // this becomes the receive function, currently just returning 1 - return 1; + printf("waiting for newly received data...\n"); + + // wait for newly received data + wantNewData = true; + + int i = 0; + + // run until it has received enough data + while (length >= i) { + // run the runLoop so it can actually receive data + [runLoop runUntilDate:[NSDate dateWithTimeIntervalSinceNow:1]]; + if(!wantNewData) { + // received some data + printf("New data recveived. %d\n",sizeof(receivedBytes) / sizeof(receivedBytes[0])); + // fill the buf with the new data + for (int j=0;j stop waiting + break; + } + + wantNewData = true; + } + } + // buf = receivedBytes; + return *receivedLength; } -// currently working std::vector MacOSBluetoothConnector::getConnectedDevices() { // create the output vector @@ -135,28 +177,28 @@ -(void)rfcommChannelData:(IOBluetoothRFCOMMChannel *)rfcommChannel data:(void *) void MacOSBluetoothConnector::disconnect() noexcept { - running = 0; + running = 0; // wait for the thread to finish - uthread->join(); + uthread->join(); // close connection - closeConnection(); + closeConnection(); } void MacOSBluetoothConnector::closeConnection() { // get the channel - IOBluetoothRFCOMMChannel *chan = (__bridge IOBluetoothRFCOMMChannel*) rfcommchannel; + IOBluetoothRFCOMMChannel *chan = (__bridge IOBluetoothRFCOMMChannel*) rfcommchannel; // close the channel - [chan closeChannel]; + [chan closeChannel]; // get the device IOBluetoothDevice *device =(__bridge IOBluetoothDevice*) rfcommDevice; // disconnect from the device - [device closeConnection]; + // [device closeConnection]; - fprintf(stderr,"closing"); + fprintf(stderr,"closing"); } bool MacOSBluetoothConnector::isConnected() noexcept { return running; -} \ No newline at end of file +} diff --git a/Client/macos/Main.storyboard b/Client/macos/Main.storyboard new file mode 100644 index 0000000..b996f1c --- /dev/null +++ b/Client/macos/Main.storyboard @@ -0,0 +1,307 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ! This product is not affiliated with Sony. Use at your own risk. ! +Source: https://github.com/Plutoberth/SonyHeadphonesClient + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ! This product is not affiliated with Sony. Use at your own risk. ! +Source: https://github.com/Plutoberth/SonyHeadphonesClient + + + + + + + + + + + + + + + + + + + + + + diff --git a/Client/macos/SonyHeadphonesClient.xcodeproj/project.pbxproj b/Client/macos/SonyHeadphonesClient.xcodeproj/project.pbxproj new file mode 100644 index 0000000..4fd1ac2 --- /dev/null +++ b/Client/macos/SonyHeadphonesClient.xcodeproj/project.pbxproj @@ -0,0 +1,357 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 50; + objects = { + +/* Begin PBXBuildFile section */ + A8DC78E42576922700447738 /* info.plist in Resources */ = {isa = PBXBuildFile; fileRef = A8DC78E32576922700447738 /* info.plist */; }; + A8DC78EB2576923D00447738 /* main.mm in Sources */ = {isa = PBXBuildFile; fileRef = A8DC78EA2576923D00447738 /* main.mm */; }; + A8DC78EC2576923D00447738 /* MacOSBluetoothConnector.mm in Sources */ = {isa = PBXBuildFile; fileRef = A8DC78E82576923D00447738 /* MacOSBluetoothConnector.mm */; }; + A8DC78F12576952E00447738 /* BluetoothWrapper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A8DC78EF2576952E00447738 /* BluetoothWrapper.cpp */; }; + A8DC78F52576953600447738 /* CommandSerializer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A8DC78F32576953600447738 /* CommandSerializer.cpp */; }; + A8DC78FA2576954100447738 /* TimedMessageQueue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A8DC78F92576954100447738 /* TimedMessageQueue.cpp */; }; + A8DC78FF2576967D00447738 /* ByteMagic.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A8DC78FD2576967D00447738 /* ByteMagic.cpp */; }; + A8DC790525769A6600447738 /* IOBluetooth.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A8DC790425769A6600447738 /* IOBluetooth.framework */; }; + A8DC792C25769C9900447738 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = A8DC792825769C9900447738 /* AppDelegate.m */; }; + A8DC792D25769C9900447738 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = A8DC792A25769C9900447738 /* ViewController.m */; }; + A8DC793225769EA500447738 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = A8DC78E92576923D00447738 /* Main.storyboard */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + A8DC78E32576922700447738 /* info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = info.plist; sourceTree = ""; }; + A8DC78E62576922D00447738 /* SonyHeadphonesClient.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SonyHeadphonesClient.app; sourceTree = BUILT_PRODUCTS_DIR; }; + A8DC78E72576923D00447738 /* MacOSBluetoothConnector.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = MacOSBluetoothConnector.h; path = /Users/semvi/projects/SonyHeadphonesClient/Client/macos/MacOSBluetoothConnector.h; sourceTree = ""; }; + A8DC78E82576923D00447738 /* MacOSBluetoothConnector.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = MacOSBluetoothConnector.mm; path = /Users/semvi/projects/SonyHeadphonesClient/Client/macos/MacOSBluetoothConnector.mm; sourceTree = ""; }; + A8DC78E92576923D00447738 /* Main.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Main.storyboard; path = /Users/semvi/projects/SonyHeadphonesClient/Client/macos/Main.storyboard; sourceTree = ""; }; + A8DC78EA2576923D00447738 /* main.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = main.mm; path = /Users/semvi/projects/SonyHeadphonesClient/Client/macos/main.mm; sourceTree = ""; }; + A8DC78EE2576950500447738 /* IBluetoothConnector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IBluetoothConnector.h; path = ../IBluetoothConnector.h; sourceTree = ""; }; + A8DC78EF2576952E00447738 /* BluetoothWrapper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = BluetoothWrapper.cpp; path = ../BluetoothWrapper.cpp; sourceTree = ""; }; + A8DC78F02576952E00447738 /* BluetoothWrapper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BluetoothWrapper.h; path = ../BluetoothWrapper.h; sourceTree = ""; }; + A8DC78F32576953600447738 /* CommandSerializer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CommandSerializer.cpp; path = ../CommandSerializer.cpp; sourceTree = ""; }; + A8DC78F42576953600447738 /* CommandSerializer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CommandSerializer.h; path = ../CommandSerializer.h; sourceTree = ""; }; + A8DC78F72576954100447738 /* TimedMessageQueue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TimedMessageQueue.h; path = ../TimedMessageQueue.h; sourceTree = ""; }; + A8DC78F82576954100447738 /* SingleInstanceFuture.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SingleInstanceFuture.h; path = ../SingleInstanceFuture.h; sourceTree = ""; }; + A8DC78F92576954100447738 /* TimedMessageQueue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TimedMessageQueue.cpp; path = ../TimedMessageQueue.cpp; sourceTree = ""; }; + A8DC78FD2576967D00447738 /* ByteMagic.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ByteMagic.cpp; path = ../ByteMagic.cpp; sourceTree = ""; }; + A8DC78FE2576967D00447738 /* ByteMagic.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ByteMagic.h; path = ../ByteMagic.h; sourceTree = ""; }; + A8DC790425769A6600447738 /* IOBluetooth.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOBluetooth.framework; path = System/Library/Frameworks/IOBluetooth.framework; sourceTree = SDKROOT; }; + A8DC792825769C9900447738 /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + A8DC792925769C9900447738 /* ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; + A8DC792A25769C9900447738 /* ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; + A8DC792B25769C9900447738 /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + A8DC78C125757BF300447738 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + A8DC790525769A6600447738 /* IOBluetooth.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + A8DC78BB25757BF300447738 = { + isa = PBXGroup; + children = ( + A8DC78E72576923D00447738 /* MacOSBluetoothConnector.h */, + A8DC78E82576923D00447738 /* MacOSBluetoothConnector.mm */, + A8DC78EA2576923D00447738 /* main.mm */, + A8DC78E92576923D00447738 /* Main.storyboard */, + A8DC78E32576922700447738 /* info.plist */, + A8DC78E62576922D00447738 /* SonyHeadphonesClient.app */, + A8DC78EE2576950500447738 /* IBluetoothConnector.h */, + A8DC78EF2576952E00447738 /* BluetoothWrapper.cpp */, + A8DC78F02576952E00447738 /* BluetoothWrapper.h */, + A8DC78F32576953600447738 /* CommandSerializer.cpp */, + A8DC78F42576953600447738 /* CommandSerializer.h */, + A8DC78F82576954100447738 /* SingleInstanceFuture.h */, + A8DC78F92576954100447738 /* TimedMessageQueue.cpp */, + A8DC78F72576954100447738 /* TimedMessageQueue.h */, + A8DC78FD2576967D00447738 /* ByteMagic.cpp */, + A8DC78FE2576967D00447738 /* ByteMagic.h */, + A8DC792B25769C9900447738 /* AppDelegate.h */, + A8DC792825769C9900447738 /* AppDelegate.m */, + A8DC792925769C9900447738 /* ViewController.h */, + A8DC792A25769C9900447738 /* ViewController.m */, + A8DC790325769A6600447738 /* Frameworks */, + ); + sourceTree = ""; + }; + A8DC790325769A6600447738 /* Frameworks */ = { + isa = PBXGroup; + children = ( + A8DC790425769A6600447738 /* IOBluetooth.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + A8DC78C325757BF300447738 /* SonyHeadphonesClient */ = { + isa = PBXNativeTarget; + buildConfigurationList = A8DC78D825757BF500447738 /* Build configuration list for PBXNativeTarget "SonyHeadphonesClient" */; + buildPhases = ( + A8DC78C025757BF300447738 /* Sources */, + A8DC78C125757BF300447738 /* Frameworks */, + A8DC78C225757BF300447738 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = SonyHeadphonesClient; + productName = SonyHeadphonesClient; + productReference = A8DC78E62576922D00447738 /* SonyHeadphonesClient.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + A8DC78BC25757BF300447738 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 1220; + TargetAttributes = { + A8DC78C325757BF300447738 = { + CreatedOnToolsVersion = 12.2; + }; + }; + }; + buildConfigurationList = A8DC78BF25757BF300447738 /* Build configuration list for PBXProject "SonyHeadphonesClient" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = A8DC78BB25757BF300447738; + productRefGroup = A8DC78BB25757BF300447738; + projectDirPath = ""; + projectRoot = ""; + targets = ( + A8DC78C325757BF300447738 /* SonyHeadphonesClient */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + A8DC78C225757BF300447738 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + A8DC793225769EA500447738 /* Main.storyboard in Resources */, + A8DC78E42576922700447738 /* info.plist in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + A8DC78C025757BF300447738 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + A8DC78EB2576923D00447738 /* main.mm in Sources */, + A8DC78EC2576923D00447738 /* MacOSBluetoothConnector.mm in Sources */, + A8DC792D25769C9900447738 /* ViewController.m in Sources */, + A8DC78F12576952E00447738 /* BluetoothWrapper.cpp in Sources */, + A8DC78FA2576954100447738 /* TimedMessageQueue.cpp in Sources */, + A8DC78F52576953600447738 /* CommandSerializer.cpp in Sources */, + A8DC78FF2576967D00447738 /* ByteMagic.cpp in Sources */, + A8DC792C25769C9900447738 /* AppDelegate.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + A8DC78D625757BF500447738 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 11.0; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + }; + name = Debug; + }; + A8DC78D725757BF500447738 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 11.0; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = macosx; + }; + name = Release; + }; + A8DC78D925757BF500447738 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CLANG_CXX_LANGUAGE_STANDARD = "c++17"; + CODE_SIGN_ENTITLEMENTS = SonyHeadphonesClient/SonyHeadphonesClient.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = "$(SRCROOT)/info.plist"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + OTHER_CPLUSPLUSFLAGS = ( + "-std=c++17", + "-stdlib=libc++", + "$(OTHER_CFLAGS)", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.semvis123.SonyHeadphonesClient; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + A8DC78DA25757BF500447738 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CLANG_CXX_LANGUAGE_STANDARD = "c++17"; + CODE_SIGN_ENTITLEMENTS = SonyHeadphonesClient/SonyHeadphonesClient.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = "$(SRCROOT)/info.plist"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + OTHER_CPLUSPLUSFLAGS = ( + "-std=c++17", + "-stdlib=libc++", + "$(OTHER_CFLAGS)", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.semvis123.SonyHeadphonesClient; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + A8DC78BF25757BF300447738 /* Build configuration list for PBXProject "SonyHeadphonesClient" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + A8DC78D625757BF500447738 /* Debug */, + A8DC78D725757BF500447738 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + A8DC78D825757BF500447738 /* Build configuration list for PBXNativeTarget "SonyHeadphonesClient" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + A8DC78D925757BF500447738 /* Debug */, + A8DC78DA25757BF500447738 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = A8DC78BC25757BF300447738 /* Project object */; +} diff --git a/Client/macos/SonyHeadphonesClient.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Client/macos/SonyHeadphonesClient.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/Client/macos/SonyHeadphonesClient.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/Client/macos/SonyHeadphonesClient.xcodeproj/project.xcworkspace/xcuserdata/semvi.xcuserdatad/UserInterfaceState.xcuserstate b/Client/macos/SonyHeadphonesClient.xcodeproj/project.xcworkspace/xcuserdata/semvi.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000000000000000000000000000000000000..2fbd41db695464e96e25e80c6284773e36616165 GIT binary patch literal 53090 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 mOx}Xr60{{`i*$=-i*`%vmbQOfbz9qi?!myw + + + + SchemeUserState + + SonyHeadphonesClient.xcscheme_^#shared#^_ + + orderHint + 0 + + + + diff --git a/Client/macos/TMacOSBluetoothConnector.h b/Client/macos/TMacOSBluetoothConnector.h new file mode 100644 index 0000000..72808f2 --- /dev/null +++ b/Client/macos/TMacOSBluetoothConnector.h @@ -0,0 +1,34 @@ +#pragma once +#include +#include +#include +#include "../IBluetoothConnector.h" +#include "IOBluetooth/IOBluetooth.h" +#include +#include "ByteMagic.h" +#include + +#include +class MacOSBluetoothConnector final : public IBluetoothConnector +{ +public: + MacOSBluetoothConnector(); + ~MacOSBluetoothConnector(); + static void connectToMac(MacOSBluetoothConnector* MacOSBluetoothConnector) noexcept(false); + virtual void dataRec(const char *dataReceived) noexcept(false); + virtual void connect(const std::string& addrStr) noexcept(false); + virtual int send(char* buf, size_t length) noexcept(false); + virtual int recv(char* buf, size_t length) noexcept(false); + virtual void disconnect() noexcept; + virtual bool isConnected() noexcept; + virtual void closeConnection(); + + virtual std::vector getConnectedDevices() noexcept(false); + +private: + void *rfcommDevice; + void *rfcommchannel; + std::thread* uthread = NULL; + int running = 0; + +}; \ No newline at end of file diff --git a/Client/macos/TMacOSBluetoothConnector.mm b/Client/macos/TMacOSBluetoothConnector.mm new file mode 100644 index 0000000..4767177 --- /dev/null +++ b/Client/macos/TMacOSBluetoothConnector.mm @@ -0,0 +1,162 @@ +// #import +#include "MacOSBluetoothConnector.h" +#include + +MacOSBluetoothConnector::MacOSBluetoothConnector() +{ + +} +MacOSBluetoothConnector::~MacOSBluetoothConnector() +{ + //onclose event + if (isConnected()){ + disconnect(); + } +} + +@interface AsyncCommDelegate : NSObject { + @public + MacOSBluetoothConnector* delegateCPP; +} +@end + +@implementation AsyncCommDelegate { +} +// this function fires when the channel is opened +-(void)rfcommChannelOpenComplete:(IOBluetoothRFCOMMChannel *)rfcommChannel status:(IOReturn)error +{ + + if ( error != kIOReturnSuccess ) { + fprintf(stderr,"Error - could not open the RFCOMM channel. Error code = %08x.\n",error); + return; + } + else{ + fprintf(stderr,"Connected. Yeah!\n"); + } + +} +// this function fires when the channel receives data +-(void)rfcommChannelData:(IOBluetoothRFCOMMChannel *)rfcommChannel data:(void *)dataPointer length:(size_t)dataLength +{ + NSString *message = [[NSString alloc] initWithBytes:dataPointer length:dataLength encoding:NSUTF8StringEncoding]; + delegateCPP->dataRec([message UTF8String]); +} + + +@end + +int MacOSBluetoothConnector::send(char* buf, size_t length) +{ + fprintf(stderr,"Sending Message\n"); + //write buffer to channel + [(__bridge IOBluetoothRFCOMMChannel*)rfcommchannel writeSync:(void*)buf length:length]; + return length; +} + + +void MacOSBluetoothConnector::connectToMac(MacOSBluetoothConnector* MacOSBluetoothConnector) +{ + MacOSBluetoothConnector->running = 1; + //get device + IOBluetoothDevice *device = (__bridge IOBluetoothDevice *)MacOSBluetoothConnector->rfcommDevice; + // create new channel + IOBluetoothRFCOMMChannel *channel = [[IOBluetoothRFCOMMChannel alloc] init]; + // create sppServiceid + IOBluetoothSDPUUID *sppServiceUUID = [IOBluetoothSDPUUID uuid16: kBluetoothSDPUUID16RFCOMM]; + // get sppServiceRecord + IOBluetoothSDPServiceRecord *sppServiceRecord = [device getServiceRecordForUUID:sppServiceUUID]; + // get rfcommChannelID from sppServiceRecord + UInt8 rfcommChannelID; + [sppServiceRecord getRFCOMMChannelID:&rfcommChannelID]; + // setup delegate + AsyncCommDelegate* asyncCommDelegate = [[AsyncCommDelegate alloc] init]; + asyncCommDelegate->delegateCPP = MacOSBluetoothConnector; + // try to open channel + if ( [device openRFCOMMChannelAsync:&channel withChannelID:rfcommChannelID delegate:asyncCommDelegate] != kIOReturnSuccess ) { + throw "Error - could not open the rfcomm.\n"; + } + // store the channel + MacOSBluetoothConnector->rfcommchannel = (__bridge void*) channel; + + printf("Successfully connected"); + // keep thread running + while (MacOSBluetoothConnector->running) { + [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:1]]; + } +} + +void MacOSBluetoothConnector::connect(const std::string& addrStr){ + // convert mac adress to nsstring + NSString *addressNSString = [NSString stringWithCString:addrStr.c_str() encoding:[NSString defaultCStringEncoding]]; + // get device based on mac adress + IOBluetoothDevice *device = [IOBluetoothDevice deviceWithAddressString:addressNSString]; + // if device is not connected + if (![device isConnected]) { + [device openConnection]; + } + // store the device in an variable + rfcommDevice = (__bridge void*) device; + uthread = new std::thread(MacOSBluetoothConnector::connectToMac, this); +} + +void MacOSBluetoothConnector::dataRec(const char *dataReceived) +{ + // print received data + printf("%s\n",dataReceived); +} + +int MacOSBluetoothConnector::recv(char* buf, size_t length) +{ + // this becomes the receive function, currently just returning 1 + return 1; + +} + +// currently working +std::vector MacOSBluetoothConnector::getConnectedDevices() +{ + // create the output vector + std::vector res; + // loop through the paired devices (also includes non paired devices for some reason) + for (IOBluetoothDevice* device in [IOBluetoothDevice pairedDevices]) { + // check if device is connected + if ([device isConnected]) { + BluetoothDevice dev; + // save the mac address and name + dev.mac = [[device addressString]UTF8String]; + dev.name = [[device name] UTF8String]; + // add device to the connected devices vector + res.push_back(dev); + } + } + + return res; +} + +void MacOSBluetoothConnector::disconnect() noexcept +{ + running = 0; + // wait for the thread to finish + uthread->join(); + // close connection + closeConnection(); +} +void MacOSBluetoothConnector::closeConnection() { + // get the channel + IOBluetoothRFCOMMChannel *chan = (__bridge IOBluetoothRFCOMMChannel*) rfcommchannel; + // close the channel + [chan closeChannel]; + + // get the device + IOBluetoothDevice *device =(__bridge IOBluetoothDevice*) rfcommDevice; + // disconnect from the device + [device closeConnection]; + + fprintf(stderr,"closing"); +} + + +bool MacOSBluetoothConnector::isConnected() noexcept +{ + return running; +} \ No newline at end of file diff --git a/Client/macos/ViewController.h b/Client/macos/ViewController.h new file mode 100644 index 0000000..75bed1c --- /dev/null +++ b/Client/macos/ViewController.h @@ -0,0 +1,14 @@ +// +// ViewController.h +// test +// +// Created by Sem Vissscher on 01/12/2020. +// + +#import + +@interface ViewController : NSViewController + + +@end + diff --git a/Client/macos/ViewController.m b/Client/macos/ViewController.m new file mode 100644 index 0000000..c41069c --- /dev/null +++ b/Client/macos/ViewController.m @@ -0,0 +1,26 @@ +// +// ViewController.m +// test +// +// Created by Sem Vissscher on 01/12/2020. +// + +#import "ViewController.h" + +@implementation ViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + + // Do any additional setup after loading the view. +} + + +- (void)setRepresentedObject:(id)representedObject { + [super setRepresentedObject:representedObject]; + + // Update the view, if already loaded. +} + + +@end diff --git a/Client/macos/info.plist b/Client/macos/info.plist index 73eaaf4..ef9892b 100644 --- a/Client/macos/info.plist +++ b/Client/macos/info.plist @@ -2,17 +2,21 @@ - CFBundleExecutable - SonyHeadphonesClient - CFBundleIdentifier - com.semvis123.SonyHeadphonesClient - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - SonyHeadphonesClient - CFBundlePackageType - APPL - NSHighResolutionCapable - True + CFBundleExecutable + SonyHeadphonesClient + CFBundleIdentifier + com.semvis123.SonyHeadphonesClient + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + SonyHeadphonesClient + CFBundlePackageType + APPL + LSApplicationCategoryType + public.app-category.utilities + NSHighResolutionCapable + True + NSMainStoryboardFile + Main - \ No newline at end of file + diff --git a/Client/macos/main.mm b/Client/macos/main.mm index 92f22d0..574b792 100644 --- a/Client/macos/main.mm +++ b/Client/macos/main.mm @@ -1,10 +1,10 @@ #include - +//#import #include "MacOSGUI.h" #include "MacOSBluetoothConnector.h" #include "BluetoothWrapper.h" -int main(int, char**) +int main(int argc, const char * argv[]) { // Get bluetooth connector std::unique_ptr connector = std::make_unique(); @@ -12,5 +12,6 @@ int main(int, char**) BluetoothWrapper wrap(std::move(connector)); // Start the gui EnterGUIMainLoop(std::move(wrap)); - return 0; -} \ No newline at end of file + return 1; +// return NSApplicationMain(argc, argv); +} From f3d5e122601bcf38ee2affd233e2246e6775563a Mon Sep 17 00:00:00 2001 From: semvis123 Date: Tue, 22 Dec 2020 19:55:26 +0100 Subject: [PATCH 13/55] Delete TMacOSBluetoothConnector.mm --- Client/macos/TMacOSBluetoothConnector.mm | 162 ----------------------- 1 file changed, 162 deletions(-) delete mode 100644 Client/macos/TMacOSBluetoothConnector.mm diff --git a/Client/macos/TMacOSBluetoothConnector.mm b/Client/macos/TMacOSBluetoothConnector.mm deleted file mode 100644 index 4767177..0000000 --- a/Client/macos/TMacOSBluetoothConnector.mm +++ /dev/null @@ -1,162 +0,0 @@ -// #import -#include "MacOSBluetoothConnector.h" -#include - -MacOSBluetoothConnector::MacOSBluetoothConnector() -{ - -} -MacOSBluetoothConnector::~MacOSBluetoothConnector() -{ - //onclose event - if (isConnected()){ - disconnect(); - } -} - -@interface AsyncCommDelegate : NSObject { - @public - MacOSBluetoothConnector* delegateCPP; -} -@end - -@implementation AsyncCommDelegate { -} -// this function fires when the channel is opened --(void)rfcommChannelOpenComplete:(IOBluetoothRFCOMMChannel *)rfcommChannel status:(IOReturn)error -{ - - if ( error != kIOReturnSuccess ) { - fprintf(stderr,"Error - could not open the RFCOMM channel. Error code = %08x.\n",error); - return; - } - else{ - fprintf(stderr,"Connected. Yeah!\n"); - } - -} -// this function fires when the channel receives data --(void)rfcommChannelData:(IOBluetoothRFCOMMChannel *)rfcommChannel data:(void *)dataPointer length:(size_t)dataLength -{ - NSString *message = [[NSString alloc] initWithBytes:dataPointer length:dataLength encoding:NSUTF8StringEncoding]; - delegateCPP->dataRec([message UTF8String]); -} - - -@end - -int MacOSBluetoothConnector::send(char* buf, size_t length) -{ - fprintf(stderr,"Sending Message\n"); - //write buffer to channel - [(__bridge IOBluetoothRFCOMMChannel*)rfcommchannel writeSync:(void*)buf length:length]; - return length; -} - - -void MacOSBluetoothConnector::connectToMac(MacOSBluetoothConnector* MacOSBluetoothConnector) -{ - MacOSBluetoothConnector->running = 1; - //get device - IOBluetoothDevice *device = (__bridge IOBluetoothDevice *)MacOSBluetoothConnector->rfcommDevice; - // create new channel - IOBluetoothRFCOMMChannel *channel = [[IOBluetoothRFCOMMChannel alloc] init]; - // create sppServiceid - IOBluetoothSDPUUID *sppServiceUUID = [IOBluetoothSDPUUID uuid16: kBluetoothSDPUUID16RFCOMM]; - // get sppServiceRecord - IOBluetoothSDPServiceRecord *sppServiceRecord = [device getServiceRecordForUUID:sppServiceUUID]; - // get rfcommChannelID from sppServiceRecord - UInt8 rfcommChannelID; - [sppServiceRecord getRFCOMMChannelID:&rfcommChannelID]; - // setup delegate - AsyncCommDelegate* asyncCommDelegate = [[AsyncCommDelegate alloc] init]; - asyncCommDelegate->delegateCPP = MacOSBluetoothConnector; - // try to open channel - if ( [device openRFCOMMChannelAsync:&channel withChannelID:rfcommChannelID delegate:asyncCommDelegate] != kIOReturnSuccess ) { - throw "Error - could not open the rfcomm.\n"; - } - // store the channel - MacOSBluetoothConnector->rfcommchannel = (__bridge void*) channel; - - printf("Successfully connected"); - // keep thread running - while (MacOSBluetoothConnector->running) { - [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:1]]; - } -} - -void MacOSBluetoothConnector::connect(const std::string& addrStr){ - // convert mac adress to nsstring - NSString *addressNSString = [NSString stringWithCString:addrStr.c_str() encoding:[NSString defaultCStringEncoding]]; - // get device based on mac adress - IOBluetoothDevice *device = [IOBluetoothDevice deviceWithAddressString:addressNSString]; - // if device is not connected - if (![device isConnected]) { - [device openConnection]; - } - // store the device in an variable - rfcommDevice = (__bridge void*) device; - uthread = new std::thread(MacOSBluetoothConnector::connectToMac, this); -} - -void MacOSBluetoothConnector::dataRec(const char *dataReceived) -{ - // print received data - printf("%s\n",dataReceived); -} - -int MacOSBluetoothConnector::recv(char* buf, size_t length) -{ - // this becomes the receive function, currently just returning 1 - return 1; - -} - -// currently working -std::vector MacOSBluetoothConnector::getConnectedDevices() -{ - // create the output vector - std::vector res; - // loop through the paired devices (also includes non paired devices for some reason) - for (IOBluetoothDevice* device in [IOBluetoothDevice pairedDevices]) { - // check if device is connected - if ([device isConnected]) { - BluetoothDevice dev; - // save the mac address and name - dev.mac = [[device addressString]UTF8String]; - dev.name = [[device name] UTF8String]; - // add device to the connected devices vector - res.push_back(dev); - } - } - - return res; -} - -void MacOSBluetoothConnector::disconnect() noexcept -{ - running = 0; - // wait for the thread to finish - uthread->join(); - // close connection - closeConnection(); -} -void MacOSBluetoothConnector::closeConnection() { - // get the channel - IOBluetoothRFCOMMChannel *chan = (__bridge IOBluetoothRFCOMMChannel*) rfcommchannel; - // close the channel - [chan closeChannel]; - - // get the device - IOBluetoothDevice *device =(__bridge IOBluetoothDevice*) rfcommDevice; - // disconnect from the device - [device closeConnection]; - - fprintf(stderr,"closing"); -} - - -bool MacOSBluetoothConnector::isConnected() noexcept -{ - return running; -} \ No newline at end of file From 73db6e5450fc788e7585ed41a9c31451bac61103 Mon Sep 17 00:00:00 2001 From: semvis123 Date: Tue, 22 Dec 2020 19:55:35 +0100 Subject: [PATCH 14/55] Delete TMacOSBluetoothConnector.h --- Client/macos/TMacOSBluetoothConnector.h | 34 ------------------------- 1 file changed, 34 deletions(-) delete mode 100644 Client/macos/TMacOSBluetoothConnector.h diff --git a/Client/macos/TMacOSBluetoothConnector.h b/Client/macos/TMacOSBluetoothConnector.h deleted file mode 100644 index 72808f2..0000000 --- a/Client/macos/TMacOSBluetoothConnector.h +++ /dev/null @@ -1,34 +0,0 @@ -#pragma once -#include -#include -#include -#include "../IBluetoothConnector.h" -#include "IOBluetooth/IOBluetooth.h" -#include -#include "ByteMagic.h" -#include - -#include -class MacOSBluetoothConnector final : public IBluetoothConnector -{ -public: - MacOSBluetoothConnector(); - ~MacOSBluetoothConnector(); - static void connectToMac(MacOSBluetoothConnector* MacOSBluetoothConnector) noexcept(false); - virtual void dataRec(const char *dataReceived) noexcept(false); - virtual void connect(const std::string& addrStr) noexcept(false); - virtual int send(char* buf, size_t length) noexcept(false); - virtual int recv(char* buf, size_t length) noexcept(false); - virtual void disconnect() noexcept; - virtual bool isConnected() noexcept; - virtual void closeConnection(); - - virtual std::vector getConnectedDevices() noexcept(false); - -private: - void *rfcommDevice; - void *rfcommchannel; - std::thread* uthread = NULL; - int running = 0; - -}; \ No newline at end of file From c04bd5c085e4900ca69d061adf490906446821de Mon Sep 17 00:00:00 2001 From: semvis123 Date: Tue, 22 Dec 2020 20:53:17 +0100 Subject: [PATCH 15/55] Simplified bluetooth connector --- Client/macos/MacOSBluetoothConnector.h | 2 +- Client/macos/MacOSBluetoothConnector.mm | 52 +++++++++---------------- 2 files changed, 19 insertions(+), 35 deletions(-) diff --git a/Client/macos/MacOSBluetoothConnector.h b/Client/macos/MacOSBluetoothConnector.h index ebb2f89..fe52718 100644 --- a/Client/macos/MacOSBluetoothConnector.h +++ b/Client/macos/MacOSBluetoothConnector.h @@ -27,7 +27,7 @@ class MacOSBluetoothConnector final : public IBluetoothConnector virtual std::vector getConnectedDevices() noexcept(false); char* receivedBytes; - int* receivedLength; + int receivedLength; bool wantNewData = false; private: void *rfcommDevice; diff --git a/Client/macos/MacOSBluetoothConnector.mm b/Client/macos/MacOSBluetoothConnector.mm index e2735a6..21a49a9 100644 --- a/Client/macos/MacOSBluetoothConnector.mm +++ b/Client/macos/MacOSBluetoothConnector.mm @@ -36,21 +36,18 @@ -(void)rfcommChannelOpenComplete:(IOBluetoothRFCOMMChannel *)rfcommChannel statu // this function fires when the channel receives data -(void)rfcommChannelData:(IOBluetoothRFCOMMChannel *)rfcommChannel data:(void *)dataPointer length:(size_t)dataLength { - // int array[(int)dataLength] = (int *)dataPointer; char* convertedData = (char *)dataPointer; // print the data printf("length: %d\n", dataLength); printf("array length: %d\n", sizeof(convertedData)); - for (int n=0; nreceivedBytes = convertedData; - delegateCPP->receivedLength = (int *)dataLength; + delegateCPP->receivedLength = dataLength; printf("newdata? %d\n",delegateCPP->wantNewData); - if(delegateCPP->wantNewData){ - delegateCPP->wantNewData = false; - } + delegateCPP->wantNewData = false; } @@ -58,7 +55,11 @@ -(void)rfcommChannelData:(IOBluetoothRFCOMMChannel *)rfcommChannel data:(void *) int MacOSBluetoothConnector::send(char* buf, size_t length) { - fprintf(stderr,"Sending Message\n"); + printf(stderr,"Sending Message\n"); + for (int n=0; n= i) { + // run until it has received data + while (wantNewData) { // run the runLoop so it can actually receive data - [runLoop runUntilDate:[NSDate dateWithTimeIntervalSinceNow:1]]; - if(!wantNewData) { - // received some data - printf("New data recveived. %d\n",sizeof(receivedBytes) / sizeof(receivedBytes[0])); - // fill the buf with the new data - for (int j=0;j stop waiting - break; - } - - wantNewData = true; - } + [runLoop runUntilDate:[NSDate dateWithTimeIntervalSinceNow:10]]; + } + printf("New data received. \n"); + + // fill the buf with the new data + for (int n=0;n MacOSBluetoothConnector::getConnectedDevices() From 84fadc1cee28dddbbbadd5e88e6b12117a09dcfb Mon Sep 17 00:00:00 2001 From: semvis123 Date: Tue, 22 Dec 2020 21:02:50 +0100 Subject: [PATCH 16/55] fixed typo --- Client/macos/MacOSBluetoothConnector.mm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Client/macos/MacOSBluetoothConnector.mm b/Client/macos/MacOSBluetoothConnector.mm index 21a49a9..2425f7d 100644 --- a/Client/macos/MacOSBluetoothConnector.mm +++ b/Client/macos/MacOSBluetoothConnector.mm @@ -55,11 +55,11 @@ -(void)rfcommChannelData:(IOBluetoothRFCOMMChannel *)rfcommChannel data:(void *) int MacOSBluetoothConnector::send(char* buf, size_t length) { - printf(stderr,"Sending Message\n"); + printf("Sending Message\n"); for (int n=0; n Date: Thu, 31 Dec 2020 22:03:11 +0100 Subject: [PATCH 17/55] Got the bluetooth connector working -- macOS --- Client/Constants.h | 4 +++ Client/macos/MacOSBluetoothConnector.h | 13 +++---- Client/macos/MacOSBluetoothConnector.mm | 46 +++++-------------------- Client/macos/main.mm | 19 ++++++---- 4 files changed, 29 insertions(+), 53 deletions(-) diff --git a/Client/Constants.h b/Client/Constants.h index fafd6eb..7c18370 100644 --- a/Client/Constants.h +++ b/Client/Constants.h @@ -9,6 +9,10 @@ inline constexpr char END_MARKER{ 60 }; inline constexpr auto MAC_ADDR_STR_SIZE = 17; inline constexpr auto SERVICE_UUID = "96CC203E-5068-46ad-B32D-E316F5E069BA"; +inline unsigned char SERVICE_UUID_IN_BYTES[] = { // this is the SERVICE_UUID but in bytes + 0x96, 0xcc, 0x20, 0x3e, 0x50, 0x68, 0x46, 0xad, + 0xb3, 0x2d, 0xe3, 0x16, 0xf5, 0xe0, 0x69, 0xba +}; inline constexpr auto APP_NAME_W = L"Sony Headphones App"; diff --git a/Client/macos/MacOSBluetoothConnector.h b/Client/macos/MacOSBluetoothConnector.h index fe52718..bb779be 100644 --- a/Client/macos/MacOSBluetoothConnector.h +++ b/Client/macos/MacOSBluetoothConnector.h @@ -1,16 +1,9 @@ #pragma once #include -#include -#include #include "../IBluetoothConnector.h" #include "IOBluetooth/IOBluetooth.h" -#include -#include "ByteMagic.h" -#include -#include +#include "Constants.h" #include -#include -#include class MacOSBluetoothConnector final : public IBluetoothConnector { @@ -29,10 +22,12 @@ class MacOSBluetoothConnector final : public IBluetoothConnector char* receivedBytes; int receivedLength; bool wantNewData = false; + NSRunLoop * runLoop; + private: void *rfcommDevice; void *rfcommchannel; std::thread* uthread = NULL; int running = 0; - NSRunLoop * runLoop; + }; \ No newline at end of file diff --git a/Client/macos/MacOSBluetoothConnector.mm b/Client/macos/MacOSBluetoothConnector.mm index 2425f7d..9b8b647 100644 --- a/Client/macos/MacOSBluetoothConnector.mm +++ b/Client/macos/MacOSBluetoothConnector.mm @@ -20,10 +20,9 @@ @interface AsyncCommDelegate : NSObject { @implementation AsyncCommDelegate { } -// this function fires when the channel is opened + -(void)rfcommChannelOpenComplete:(IOBluetoothRFCOMMChannel *)rfcommChannel status:(IOReturn)error { - if ( error != kIOReturnSuccess ) { fprintf(stderr,"Error - could not open the RFCOMM channel. Error code = %08x.\n",error); return; @@ -31,22 +30,12 @@ -(void)rfcommChannelOpenComplete:(IOBluetoothRFCOMMChannel *)rfcommChannel statu else{ fprintf(stderr,"Connected. Yeah!\n"); } - } -// this function fires when the channel receives data + -(void)rfcommChannelData:(IOBluetoothRFCOMMChannel *)rfcommChannel data:(void *)dataPointer length:(size_t)dataLength { - char* convertedData = (char *)dataPointer; - // print the data - printf("length: %d\n", dataLength); - printf("array length: %d\n", sizeof(convertedData)); - for (int n=0; nreceivedBytes = convertedData; + delegateCPP->receivedBytes = (char*)dataPointer; delegateCPP->receivedLength = dataLength; - printf("newdata? %d\n",delegateCPP->wantNewData); delegateCPP->wantNewData = false; } @@ -55,17 +44,9 @@ -(void)rfcommChannelData:(IOBluetoothRFCOMMChannel *)rfcommChannel data:(void *) int MacOSBluetoothConnector::send(char* buf, size_t length) { - printf("Sending Message\n"); - for (int n=0; n connector = std::make_unique(); - // Wrap the connector using the bluetoothwrapper - BluetoothWrapper wrap(std::move(connector)); - // Start the gui - EnterGUIMainLoop(std::move(wrap)); - return 1; + try { + // Get bluetooth connector + std::unique_ptr connector = std::make_unique(); + // Wrap the connector using the bluetoothwrapper + BluetoothWrapper wrap(std::move(connector)); + // Start the gui + EnterGUIMainLoop(std::move(wrap)); + return 1; + } catch (const std::exception& e) + { + printf("%s",e.what()); + } // return NSApplicationMain(argc, argv); } From 57e1454d333e249437d3a40f4b21349b404bc2d5 Mon Sep 17 00:00:00 2001 From: semvis123 Date: Thu, 31 Dec 2020 22:12:11 +0100 Subject: [PATCH 18/55] Update readme, and added name to license --- LICENSE | 2 +- README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/LICENSE b/LICENSE index a7e1895..d22d30e 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2020 Nir Harel, Mor Gal, and other contributors +Copyright (c) 2020 Nir Harel, Mor Gal, Sem Visscher, and other contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 284dd96..8ba1e1f 100644 --- a/README.md +++ b/README.md @@ -63,7 +63,7 @@ It shouldn't be too much work to add support for a new platform. Open a PR if yo - [x] Windows - [ ] [Linux](https://github.com/Plutoberth/SonyHeadphonesClient/issues/7) -- [ ] [macOS](https://github.com/Plutoberth/SonyHeadphonesClient/issues/6) +- [x] macOS ## For Developers From 43ec2498bbe2715dc9301ba54c925cc833d0b6f5 Mon Sep 17 00:00:00 2001 From: semvis123 Date: Fri, 1 Jan 2021 13:02:01 +0100 Subject: [PATCH 19/55] removed native gui stuff --- Client/macos/AppDelegate.h | 14 - Client/macos/AppDelegate.m | 27 -- Client/macos/Main.storyboard | 307 --------------- .../project.pbxproj | 357 ------------------ .../xcshareddata/IDEWorkspaceChecks.plist | 8 - .../UserInterfaceState.xcuserstate | Bin 53090 -> 0 bytes .../xcschemes/xcschememanagement.plist | 14 - Client/macos/ViewController.h | 14 - Client/macos/ViewController.m | 26 -- Client/macos/main.mm | 7 +- 10 files changed, 2 insertions(+), 772 deletions(-) delete mode 100644 Client/macos/AppDelegate.h delete mode 100644 Client/macos/AppDelegate.m delete mode 100644 Client/macos/Main.storyboard delete mode 100644 Client/macos/SonyHeadphonesClient.xcodeproj/project.pbxproj delete mode 100644 Client/macos/SonyHeadphonesClient.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist delete mode 100644 Client/macos/SonyHeadphonesClient.xcodeproj/project.xcworkspace/xcuserdata/semvi.xcuserdatad/UserInterfaceState.xcuserstate delete mode 100644 Client/macos/SonyHeadphonesClient.xcodeproj/xcuserdata/semvi.xcuserdatad/xcschemes/xcschememanagement.plist delete mode 100644 Client/macos/ViewController.h delete mode 100644 Client/macos/ViewController.m diff --git a/Client/macos/AppDelegate.h b/Client/macos/AppDelegate.h deleted file mode 100644 index 794dc5f..0000000 --- a/Client/macos/AppDelegate.h +++ /dev/null @@ -1,14 +0,0 @@ -// -// AppDelegate.h -// test -// -// Created by Sem Vissscher on 01/12/2020. -// - -#import - -@interface AppDelegate : NSObject - - -@end - diff --git a/Client/macos/AppDelegate.m b/Client/macos/AppDelegate.m deleted file mode 100644 index c8273d5..0000000 --- a/Client/macos/AppDelegate.m +++ /dev/null @@ -1,27 +0,0 @@ -// -// AppDelegate.m -// test -// -// Created by Sem Vissscher on 01/12/2020. -// - -#import "AppDelegate.h" - -@interface AppDelegate () - - -@end - -@implementation AppDelegate - -- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { - // Insert code here to initialize your application -} - - -- (void)applicationWillTerminate:(NSNotification *)aNotification { - // Insert code here to tear down your application -} - - -@end diff --git a/Client/macos/Main.storyboard b/Client/macos/Main.storyboard deleted file mode 100644 index b996f1c..0000000 --- a/Client/macos/Main.storyboard +++ /dev/null @@ -1,307 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ! This product is not affiliated with Sony. Use at your own risk. ! -Source: https://github.com/Plutoberth/SonyHeadphonesClient - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ! This product is not affiliated with Sony. Use at your own risk. ! -Source: https://github.com/Plutoberth/SonyHeadphonesClient - - - - - - - - - - - - - - - - - - - - - - diff --git a/Client/macos/SonyHeadphonesClient.xcodeproj/project.pbxproj b/Client/macos/SonyHeadphonesClient.xcodeproj/project.pbxproj deleted file mode 100644 index 4fd1ac2..0000000 --- a/Client/macos/SonyHeadphonesClient.xcodeproj/project.pbxproj +++ /dev/null @@ -1,357 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 50; - objects = { - -/* Begin PBXBuildFile section */ - A8DC78E42576922700447738 /* info.plist in Resources */ = {isa = PBXBuildFile; fileRef = A8DC78E32576922700447738 /* info.plist */; }; - A8DC78EB2576923D00447738 /* main.mm in Sources */ = {isa = PBXBuildFile; fileRef = A8DC78EA2576923D00447738 /* main.mm */; }; - A8DC78EC2576923D00447738 /* MacOSBluetoothConnector.mm in Sources */ = {isa = PBXBuildFile; fileRef = A8DC78E82576923D00447738 /* MacOSBluetoothConnector.mm */; }; - A8DC78F12576952E00447738 /* BluetoothWrapper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A8DC78EF2576952E00447738 /* BluetoothWrapper.cpp */; }; - A8DC78F52576953600447738 /* CommandSerializer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A8DC78F32576953600447738 /* CommandSerializer.cpp */; }; - A8DC78FA2576954100447738 /* TimedMessageQueue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A8DC78F92576954100447738 /* TimedMessageQueue.cpp */; }; - A8DC78FF2576967D00447738 /* ByteMagic.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A8DC78FD2576967D00447738 /* ByteMagic.cpp */; }; - A8DC790525769A6600447738 /* IOBluetooth.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A8DC790425769A6600447738 /* IOBluetooth.framework */; }; - A8DC792C25769C9900447738 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = A8DC792825769C9900447738 /* AppDelegate.m */; }; - A8DC792D25769C9900447738 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = A8DC792A25769C9900447738 /* ViewController.m */; }; - A8DC793225769EA500447738 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = A8DC78E92576923D00447738 /* Main.storyboard */; }; -/* End PBXBuildFile section */ - -/* Begin PBXFileReference section */ - A8DC78E32576922700447738 /* info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = info.plist; sourceTree = ""; }; - A8DC78E62576922D00447738 /* SonyHeadphonesClient.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SonyHeadphonesClient.app; sourceTree = BUILT_PRODUCTS_DIR; }; - A8DC78E72576923D00447738 /* MacOSBluetoothConnector.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = MacOSBluetoothConnector.h; path = /Users/semvi/projects/SonyHeadphonesClient/Client/macos/MacOSBluetoothConnector.h; sourceTree = ""; }; - A8DC78E82576923D00447738 /* MacOSBluetoothConnector.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = MacOSBluetoothConnector.mm; path = /Users/semvi/projects/SonyHeadphonesClient/Client/macos/MacOSBluetoothConnector.mm; sourceTree = ""; }; - A8DC78E92576923D00447738 /* Main.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Main.storyboard; path = /Users/semvi/projects/SonyHeadphonesClient/Client/macos/Main.storyboard; sourceTree = ""; }; - A8DC78EA2576923D00447738 /* main.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = main.mm; path = /Users/semvi/projects/SonyHeadphonesClient/Client/macos/main.mm; sourceTree = ""; }; - A8DC78EE2576950500447738 /* IBluetoothConnector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IBluetoothConnector.h; path = ../IBluetoothConnector.h; sourceTree = ""; }; - A8DC78EF2576952E00447738 /* BluetoothWrapper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = BluetoothWrapper.cpp; path = ../BluetoothWrapper.cpp; sourceTree = ""; }; - A8DC78F02576952E00447738 /* BluetoothWrapper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BluetoothWrapper.h; path = ../BluetoothWrapper.h; sourceTree = ""; }; - A8DC78F32576953600447738 /* CommandSerializer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CommandSerializer.cpp; path = ../CommandSerializer.cpp; sourceTree = ""; }; - A8DC78F42576953600447738 /* CommandSerializer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CommandSerializer.h; path = ../CommandSerializer.h; sourceTree = ""; }; - A8DC78F72576954100447738 /* TimedMessageQueue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TimedMessageQueue.h; path = ../TimedMessageQueue.h; sourceTree = ""; }; - A8DC78F82576954100447738 /* SingleInstanceFuture.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SingleInstanceFuture.h; path = ../SingleInstanceFuture.h; sourceTree = ""; }; - A8DC78F92576954100447738 /* TimedMessageQueue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TimedMessageQueue.cpp; path = ../TimedMessageQueue.cpp; sourceTree = ""; }; - A8DC78FD2576967D00447738 /* ByteMagic.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ByteMagic.cpp; path = ../ByteMagic.cpp; sourceTree = ""; }; - A8DC78FE2576967D00447738 /* ByteMagic.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ByteMagic.h; path = ../ByteMagic.h; sourceTree = ""; }; - A8DC790425769A6600447738 /* IOBluetooth.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOBluetooth.framework; path = System/Library/Frameworks/IOBluetooth.framework; sourceTree = SDKROOT; }; - A8DC792825769C9900447738 /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; - A8DC792925769C9900447738 /* ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; - A8DC792A25769C9900447738 /* ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; - A8DC792B25769C9900447738 /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - A8DC78C125757BF300447738 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - A8DC790525769A6600447738 /* IOBluetooth.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - A8DC78BB25757BF300447738 = { - isa = PBXGroup; - children = ( - A8DC78E72576923D00447738 /* MacOSBluetoothConnector.h */, - A8DC78E82576923D00447738 /* MacOSBluetoothConnector.mm */, - A8DC78EA2576923D00447738 /* main.mm */, - A8DC78E92576923D00447738 /* Main.storyboard */, - A8DC78E32576922700447738 /* info.plist */, - A8DC78E62576922D00447738 /* SonyHeadphonesClient.app */, - A8DC78EE2576950500447738 /* IBluetoothConnector.h */, - A8DC78EF2576952E00447738 /* BluetoothWrapper.cpp */, - A8DC78F02576952E00447738 /* BluetoothWrapper.h */, - A8DC78F32576953600447738 /* CommandSerializer.cpp */, - A8DC78F42576953600447738 /* CommandSerializer.h */, - A8DC78F82576954100447738 /* SingleInstanceFuture.h */, - A8DC78F92576954100447738 /* TimedMessageQueue.cpp */, - A8DC78F72576954100447738 /* TimedMessageQueue.h */, - A8DC78FD2576967D00447738 /* ByteMagic.cpp */, - A8DC78FE2576967D00447738 /* ByteMagic.h */, - A8DC792B25769C9900447738 /* AppDelegate.h */, - A8DC792825769C9900447738 /* AppDelegate.m */, - A8DC792925769C9900447738 /* ViewController.h */, - A8DC792A25769C9900447738 /* ViewController.m */, - A8DC790325769A6600447738 /* Frameworks */, - ); - sourceTree = ""; - }; - A8DC790325769A6600447738 /* Frameworks */ = { - isa = PBXGroup; - children = ( - A8DC790425769A6600447738 /* IOBluetooth.framework */, - ); - name = Frameworks; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - A8DC78C325757BF300447738 /* SonyHeadphonesClient */ = { - isa = PBXNativeTarget; - buildConfigurationList = A8DC78D825757BF500447738 /* Build configuration list for PBXNativeTarget "SonyHeadphonesClient" */; - buildPhases = ( - A8DC78C025757BF300447738 /* Sources */, - A8DC78C125757BF300447738 /* Frameworks */, - A8DC78C225757BF300447738 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = SonyHeadphonesClient; - productName = SonyHeadphonesClient; - productReference = A8DC78E62576922D00447738 /* SonyHeadphonesClient.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - A8DC78BC25757BF300447738 /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 1220; - TargetAttributes = { - A8DC78C325757BF300447738 = { - CreatedOnToolsVersion = 12.2; - }; - }; - }; - buildConfigurationList = A8DC78BF25757BF300447738 /* Build configuration list for PBXProject "SonyHeadphonesClient" */; - compatibilityVersion = "Xcode 9.3"; - developmentRegion = en; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = A8DC78BB25757BF300447738; - productRefGroup = A8DC78BB25757BF300447738; - projectDirPath = ""; - projectRoot = ""; - targets = ( - A8DC78C325757BF300447738 /* SonyHeadphonesClient */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - A8DC78C225757BF300447738 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - A8DC793225769EA500447738 /* Main.storyboard in Resources */, - A8DC78E42576922700447738 /* info.plist in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - A8DC78C025757BF300447738 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - A8DC78EB2576923D00447738 /* main.mm in Sources */, - A8DC78EC2576923D00447738 /* MacOSBluetoothConnector.mm in Sources */, - A8DC792D25769C9900447738 /* ViewController.m in Sources */, - A8DC78F12576952E00447738 /* BluetoothWrapper.cpp in Sources */, - A8DC78FA2576954100447738 /* TimedMessageQueue.cpp in Sources */, - A8DC78F52576953600447738 /* CommandSerializer.cpp in Sources */, - A8DC78FF2576967D00447738 /* ByteMagic.cpp in Sources */, - A8DC792C25769C9900447738 /* AppDelegate.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin XCBuildConfiguration section */ - A8DC78D625757BF500447738 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 11.0; - MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; - MTL_FAST_MATH = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = macosx; - }; - name = Debug; - }; - A8DC78D725757BF500447738 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 11.0; - MTL_ENABLE_DEBUG_INFO = NO; - MTL_FAST_MATH = YES; - SDKROOT = macosx; - }; - name = Release; - }; - A8DC78D925757BF500447738 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; - CLANG_CXX_LANGUAGE_STANDARD = "c++17"; - CODE_SIGN_ENTITLEMENTS = SonyHeadphonesClient/SonyHeadphonesClient.entitlements; - CODE_SIGN_STYLE = Automatic; - COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = "$(SRCROOT)/info.plist"; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/../Frameworks", - ); - OTHER_CPLUSPLUSFLAGS = ( - "-std=c++17", - "-stdlib=libc++", - "$(OTHER_CFLAGS)", - ); - PRODUCT_BUNDLE_IDENTIFIER = com.semvis123.SonyHeadphonesClient; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - A8DC78DA25757BF500447738 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; - CLANG_CXX_LANGUAGE_STANDARD = "c++17"; - CODE_SIGN_ENTITLEMENTS = SonyHeadphonesClient/SonyHeadphonesClient.entitlements; - CODE_SIGN_STYLE = Automatic; - COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = "$(SRCROOT)/info.plist"; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/../Frameworks", - ); - OTHER_CPLUSPLUSFLAGS = ( - "-std=c++17", - "-stdlib=libc++", - "$(OTHER_CFLAGS)", - ); - PRODUCT_BUNDLE_IDENTIFIER = com.semvis123.SonyHeadphonesClient; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - A8DC78BF25757BF300447738 /* Build configuration list for PBXProject "SonyHeadphonesClient" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - A8DC78D625757BF500447738 /* Debug */, - A8DC78D725757BF500447738 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - A8DC78D825757BF500447738 /* Build configuration list for PBXNativeTarget "SonyHeadphonesClient" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - A8DC78D925757BF500447738 /* Debug */, - A8DC78DA25757BF500447738 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = A8DC78BC25757BF300447738 /* Project object */; -} diff --git a/Client/macos/SonyHeadphonesClient.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Client/macos/SonyHeadphonesClient.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist deleted file mode 100644 index 18d9810..0000000 --- a/Client/macos/SonyHeadphonesClient.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEDidComputeMac32BitWarning - - - diff --git a/Client/macos/SonyHeadphonesClient.xcodeproj/project.xcworkspace/xcuserdata/semvi.xcuserdatad/UserInterfaceState.xcuserstate b/Client/macos/SonyHeadphonesClient.xcodeproj/project.xcworkspace/xcuserdata/semvi.xcuserdatad/UserInterfaceState.xcuserstate deleted file mode 100644 index 2fbd41db695464e96e25e80c6284773e36616165..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 53090 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 mOx}Xr60{{`i*$=-i*`%vmbQOfbz9qi?!myw - - - - SchemeUserState - - SonyHeadphonesClient.xcscheme_^#shared#^_ - - orderHint - 0 - - - - diff --git a/Client/macos/ViewController.h b/Client/macos/ViewController.h deleted file mode 100644 index 75bed1c..0000000 --- a/Client/macos/ViewController.h +++ /dev/null @@ -1,14 +0,0 @@ -// -// ViewController.h -// test -// -// Created by Sem Vissscher on 01/12/2020. -// - -#import - -@interface ViewController : NSViewController - - -@end - diff --git a/Client/macos/ViewController.m b/Client/macos/ViewController.m deleted file mode 100644 index c41069c..0000000 --- a/Client/macos/ViewController.m +++ /dev/null @@ -1,26 +0,0 @@ -// -// ViewController.m -// test -// -// Created by Sem Vissscher on 01/12/2020. -// - -#import "ViewController.h" - -@implementation ViewController - -- (void)viewDidLoad { - [super viewDidLoad]; - - // Do any additional setup after loading the view. -} - - -- (void)setRepresentedObject:(id)representedObject { - [super setRepresentedObject:representedObject]; - - // Update the view, if already loaded. -} - - -@end diff --git a/Client/macos/main.mm b/Client/macos/main.mm index 11c001e..58dee44 100644 --- a/Client/macos/main.mm +++ b/Client/macos/main.mm @@ -1,5 +1,4 @@ #include -//#import #include "MacOSGUI.h" #include "MacOSBluetoothConnector.h" #include "BluetoothWrapper.h" @@ -13,10 +12,8 @@ int main(int argc, const char * argv[]) BluetoothWrapper wrap(std::move(connector)); // Start the gui EnterGUIMainLoop(std::move(wrap)); - return 1; - } catch (const std::exception& e) - { + } catch (const std::exception& e){ printf("%s",e.what()); } -// return NSApplicationMain(argc, argv); + return 1; } From c55a70a43ad21c4c336c51a0b7106951645d5b25 Mon Sep 17 00:00:00 2001 From: semvis123 Date: Fri, 1 Jan 2021 13:08:03 +0100 Subject: [PATCH 20/55] initial changes --- Client/Constants.h | 4 + Client/GUI_Impls/MacOSGUI.h | 20 + Client/GUI_Impls/MacOSGUI.mm | 90 +++++ Client/macos/AppDelegate.h | 14 + Client/macos/AppDelegate.m | 27 ++ Client/macos/MacOSBluetoothConnector.h | 33 ++ Client/macos/MacOSBluetoothConnector.mm | 160 ++++++++ Client/macos/Main.storyboard | 307 +++++++++++++++ .../project.pbxproj | 357 ++++++++++++++++++ .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../UserInterfaceState.xcuserstate | Bin 0 -> 53090 bytes .../xcschemes/xcschememanagement.plist | 14 + Client/macos/ViewController.h | 14 + Client/macos/ViewController.m | 26 ++ Client/macos/info.plist | 22 ++ Client/macos/main.mm | 22 ++ Client/macos/makefile | 70 ++++ LICENSE | 2 +- README.md | 3 +- 19 files changed, 1191 insertions(+), 2 deletions(-) create mode 100644 Client/GUI_Impls/MacOSGUI.h create mode 100644 Client/GUI_Impls/MacOSGUI.mm create mode 100644 Client/macos/AppDelegate.h create mode 100644 Client/macos/AppDelegate.m create mode 100644 Client/macos/MacOSBluetoothConnector.h create mode 100644 Client/macos/MacOSBluetoothConnector.mm create mode 100644 Client/macos/Main.storyboard create mode 100644 Client/macos/SonyHeadphonesClient.xcodeproj/project.pbxproj create mode 100644 Client/macos/SonyHeadphonesClient.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 Client/macos/SonyHeadphonesClient.xcodeproj/project.xcworkspace/xcuserdata/semvi.xcuserdatad/UserInterfaceState.xcuserstate create mode 100644 Client/macos/SonyHeadphonesClient.xcodeproj/xcuserdata/semvi.xcuserdatad/xcschemes/xcschememanagement.plist create mode 100644 Client/macos/ViewController.h create mode 100644 Client/macos/ViewController.m create mode 100644 Client/macos/info.plist create mode 100644 Client/macos/main.mm create mode 100644 Client/macos/makefile diff --git a/Client/Constants.h b/Client/Constants.h index fafd6eb..7c18370 100644 --- a/Client/Constants.h +++ b/Client/Constants.h @@ -9,6 +9,10 @@ inline constexpr char END_MARKER{ 60 }; inline constexpr auto MAC_ADDR_STR_SIZE = 17; inline constexpr auto SERVICE_UUID = "96CC203E-5068-46ad-B32D-E316F5E069BA"; +inline unsigned char SERVICE_UUID_IN_BYTES[] = { // this is the SERVICE_UUID but in bytes + 0x96, 0xcc, 0x20, 0x3e, 0x50, 0x68, 0x46, 0xad, + 0xb3, 0x2d, 0xe3, 0x16, 0xf5, 0xe0, 0x69, 0xba +}; inline constexpr auto APP_NAME_W = L"Sony Headphones App"; diff --git a/Client/GUI_Impls/MacOSGUI.h b/Client/GUI_Impls/MacOSGUI.h new file mode 100644 index 0000000..19c7ed9 --- /dev/null +++ b/Client/GUI_Impls/MacOSGUI.h @@ -0,0 +1,20 @@ +#include "imgui.h" +#include "imgui_impl_glfw.h" +#include "imgui_impl_metal.h" +#include + +#define GLFW_INCLUDE_NONE +#define GLFW_EXPOSE_NATIVE_COCOA +#include +#include + +#include +#include + +#include "Constants.h" +#include "TimedMessageQueue.h" +#include "BluetoothWrapper.h" +#include "CrossPlatformGUI.h" + +static void glfw_error_callback(int error, const char* description); +void EnterGUIMainLoop(BluetoothWrapper bt); \ No newline at end of file diff --git a/Client/GUI_Impls/MacOSGUI.mm b/Client/GUI_Impls/MacOSGUI.mm new file mode 100644 index 0000000..f02f646 --- /dev/null +++ b/Client/GUI_Impls/MacOSGUI.mm @@ -0,0 +1,90 @@ +#include "MacOSGUI.h" + +static void glfw_error_callback(int error, const char* description) +{ + fprintf(stderr, "Glfw Error %d: %s\n", error, description); +} + +void EnterGUIMainLoop(BluetoothWrapper bt) +{ + // Setup Dear ImGui binding + IMGUI_CHECKVERSION(); + ImGui::CreateContext(); + + // init GUI + CrossPlatformGUI GUI = CrossPlatformGUI(std::move(bt)); + + // Setup window + glfwSetErrorCallback(glfw_error_callback); + if (!glfwInit()) + return; + + // Create window with graphics context + glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); + GLFWwindow* window = glfwCreateWindow(GUI_WIDTH, GUI_HEIGHT, "Sony Headphones App", NULL, NULL); + if (window == NULL) + return; + + id device = MTLCreateSystemDefaultDevice();; + id commandQueue = [device newCommandQueue]; + + ImGui_ImplGlfw_InitForOpenGL(window, true); + ImGui_ImplMetal_Init(device); + + NSWindow *nswin = glfwGetCocoaWindow(window); + CAMetalLayer *layer = [CAMetalLayer layer]; + layer.device = device; + layer.pixelFormat = MTLPixelFormatBGRA8Unorm; + nswin.contentView.layer = layer; + nswin.contentView.wantsLayer = YES; + + MTLRenderPassDescriptor *renderPassDescriptor = [MTLRenderPassDescriptor new]; + + float clear_color[4] = {0.45f, 0.55f, 0.60f, 1.00f}; + // Main loop + while (!glfwWindowShouldClose(window)) + { + @autoreleasepool + { + // Poll and handle events (inputs, window resize, etc.) + glfwPollEvents(); + + int width, height; + glfwGetFramebufferSize(window, &width, &height); + layer.drawableSize = CGSizeMake(width, height); + id drawable = [layer nextDrawable]; + + id commandBuffer = [commandQueue commandBuffer]; + renderPassDescriptor.colorAttachments[0].clearColor = MTLClearColorMake(clear_color[0], clear_color[1], clear_color[2], clear_color[3]); + renderPassDescriptor.colorAttachments[0].texture = drawable.texture; + renderPassDescriptor.colorAttachments[0].loadAction = MTLLoadActionClear; + renderPassDescriptor.colorAttachments[0].storeAction = MTLStoreActionStore; + id renderEncoder = [commandBuffer renderCommandEncoderWithDescriptor:renderPassDescriptor]; + + // Start the Dear ImGui frame + ImGui_ImplMetal_NewFrame(renderPassDescriptor); + ImGui_ImplGlfw_NewFrame(); + + // perform gui pass + GUI.performGUIPass(); + + // Rendering + ImGui::Render(); + ImGui_ImplMetal_RenderDrawData(ImGui::GetDrawData(), commandBuffer, renderEncoder); + + [renderEncoder popDebugGroup]; + [renderEncoder endEncoding]; + + [commandBuffer presentDrawable:drawable]; + [commandBuffer commit]; + } + } + + // Cleanup + ImGui_ImplMetal_Shutdown(); + ImGui_ImplGlfw_Shutdown(); + ImGui::DestroyContext(); + + glfwDestroyWindow(window); + glfwTerminate(); +}; diff --git a/Client/macos/AppDelegate.h b/Client/macos/AppDelegate.h new file mode 100644 index 0000000..794dc5f --- /dev/null +++ b/Client/macos/AppDelegate.h @@ -0,0 +1,14 @@ +// +// AppDelegate.h +// test +// +// Created by Sem Vissscher on 01/12/2020. +// + +#import + +@interface AppDelegate : NSObject + + +@end + diff --git a/Client/macos/AppDelegate.m b/Client/macos/AppDelegate.m new file mode 100644 index 0000000..c8273d5 --- /dev/null +++ b/Client/macos/AppDelegate.m @@ -0,0 +1,27 @@ +// +// AppDelegate.m +// test +// +// Created by Sem Vissscher on 01/12/2020. +// + +#import "AppDelegate.h" + +@interface AppDelegate () + + +@end + +@implementation AppDelegate + +- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { + // Insert code here to initialize your application +} + + +- (void)applicationWillTerminate:(NSNotification *)aNotification { + // Insert code here to tear down your application +} + + +@end diff --git a/Client/macos/MacOSBluetoothConnector.h b/Client/macos/MacOSBluetoothConnector.h new file mode 100644 index 0000000..bb779be --- /dev/null +++ b/Client/macos/MacOSBluetoothConnector.h @@ -0,0 +1,33 @@ +#pragma once +#include +#include "../IBluetoothConnector.h" +#include "IOBluetooth/IOBluetooth.h" +#include "Constants.h" +#include + +class MacOSBluetoothConnector final : public IBluetoothConnector +{ +public: + MacOSBluetoothConnector(); + ~MacOSBluetoothConnector(); + static void connectToMac(MacOSBluetoothConnector* MacOSBluetoothConnector) noexcept(false); + virtual void connect(const std::string& addrStr) noexcept(false); + virtual int send(char* buf, size_t length) noexcept(false); + virtual int recv(char* buf, size_t length) noexcept(false); + virtual void disconnect() noexcept; + virtual bool isConnected() noexcept; + virtual void closeConnection(); + + virtual std::vector getConnectedDevices() noexcept(false); + char* receivedBytes; + int receivedLength; + bool wantNewData = false; + NSRunLoop * runLoop; + +private: + void *rfcommDevice; + void *rfcommchannel; + std::thread* uthread = NULL; + int running = 0; + +}; \ No newline at end of file diff --git a/Client/macos/MacOSBluetoothConnector.mm b/Client/macos/MacOSBluetoothConnector.mm new file mode 100644 index 0000000..9b8b647 --- /dev/null +++ b/Client/macos/MacOSBluetoothConnector.mm @@ -0,0 +1,160 @@ +#include "MacOSBluetoothConnector.h" + +MacOSBluetoothConnector::MacOSBluetoothConnector() +{ + +} +MacOSBluetoothConnector::~MacOSBluetoothConnector() +{ + //onclose event + if (isConnected()){ + disconnect(); + } +} + +@interface AsyncCommDelegate : NSObject { + @public + MacOSBluetoothConnector* delegateCPP; +} +@end + +@implementation AsyncCommDelegate { +} + +-(void)rfcommChannelOpenComplete:(IOBluetoothRFCOMMChannel *)rfcommChannel status:(IOReturn)error +{ + if ( error != kIOReturnSuccess ) { + fprintf(stderr,"Error - could not open the RFCOMM channel. Error code = %08x.\n",error); + return; + } + else{ + fprintf(stderr,"Connected. Yeah!\n"); + } +} + +-(void)rfcommChannelData:(IOBluetoothRFCOMMChannel *)rfcommChannel data:(void *)dataPointer length:(size_t)dataLength +{ + delegateCPP->receivedBytes = (char*)dataPointer; + delegateCPP->receivedLength = dataLength; + delegateCPP->wantNewData = false; +} + + +@end + +int MacOSBluetoothConnector::send(char* buf, size_t length) +{ + int error = [(__bridge IOBluetoothRFCOMMChannel*)rfcommchannel writeSync:(void*)buf length:length]; + if ( error != kIOReturnSuccess ) { + fprintf(stderr,"Error - could send bluetooth command. Error code = %08x.\n",error); + } + return length; +} + + +void MacOSBluetoothConnector::connectToMac(MacOSBluetoothConnector* macOSBluetoothConnector) +{ + macOSBluetoothConnector->running = 1; + //get device + IOBluetoothDevice *device = (__bridge IOBluetoothDevice *)macOSBluetoothConnector->rfcommDevice; + // create new channel + IOBluetoothRFCOMMChannel *channel = [[IOBluetoothRFCOMMChannel alloc] init]; + // create sppServiceid + IOBluetoothSDPUUID *sppServiceUUID = [IOBluetoothSDPUUID uuidWithBytes:(void*)SERVICE_UUID_IN_BYTES length: 16]; + // get sppServiceRecord + IOBluetoothSDPServiceRecord *sppServiceRecord = [device getServiceRecordForUUID:sppServiceUUID]; + // get rfcommChannelID from sppServiceRecord + UInt8 rfcommChannelID; + [sppServiceRecord getRFCOMMChannelID:&rfcommChannelID]; + // setup delegate + AsyncCommDelegate* asyncCommDelegate = [[AsyncCommDelegate alloc] init]; + asyncCommDelegate->delegateCPP = macOSBluetoothConnector; + // try to open channel + if ( [device openRFCOMMChannelAsync:&channel withChannelID:rfcommChannelID delegate:asyncCommDelegate] != kIOReturnSuccess ) { + throw "Error - could not open the rfcomm.\n"; + } + // store the channel + macOSBluetoothConnector->rfcommchannel = (__bridge void*) channel; + + printf("Successfully connected"); + + // keep thread running + while (macOSBluetoothConnector->running) { + [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:1]]; + } +} +void MacOSBluetoothConnector::connect(const std::string& addrStr){ + // convert mac adress to nsstring + NSString *addressNSString = [NSString stringWithCString:addrStr.c_str() encoding:[NSString defaultCStringEncoding]]; + // get device based on mac adress + IOBluetoothDevice *device = [IOBluetoothDevice deviceWithAddressString:addressNSString]; + // if device is not connected + if (![device isConnected]) { + [device openConnection]; + } + // store the device in an variable + rfcommDevice = (__bridge void*) device; + uthread = new std::thread(MacOSBluetoothConnector::connectToMac, this); +} + +int MacOSBluetoothConnector::recv(char* buf, size_t length) +{ + // wait for newly received data + wantNewData = true; + + // wait until it has received data + while (wantNewData) { + // run the runLoop so it can actually receive data + [runLoop runUntilDate:[NSDate dateWithTimeIntervalSinceNow:10]]; + } + + // fill the buf with the new data + for (int n=0;n MacOSBluetoothConnector::getConnectedDevices() +{ + // create the output vector + std::vector res; + // loop through the paired devices (also includes non paired devices for some reason) + for (IOBluetoothDevice* device in [IOBluetoothDevice pairedDevices]) { + // check if device is connected + if ([device isConnected]) { + BluetoothDevice dev; + // save the mac address and name + dev.mac = [[device addressString]UTF8String]; + dev.name = [[device name] UTF8String]; + // add device to the connected devices vector + res.push_back(dev); + } + } + + return res; +} + +void MacOSBluetoothConnector::disconnect() noexcept +{ + running = 0; + // wait for the thread to finish + uthread->join(); + // close connection + closeConnection(); +} +void MacOSBluetoothConnector::closeConnection() { + // get the channel + IOBluetoothRFCOMMChannel *chan = (__bridge IOBluetoothRFCOMMChannel*) rfcommchannel; + // close the channel + [chan closeChannel]; + + printf("closing"); +} + + +bool MacOSBluetoothConnector::isConnected() noexcept +{ + return running; +} diff --git a/Client/macos/Main.storyboard b/Client/macos/Main.storyboard new file mode 100644 index 0000000..b996f1c --- /dev/null +++ b/Client/macos/Main.storyboard @@ -0,0 +1,307 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ! This product is not affiliated with Sony. Use at your own risk. ! +Source: https://github.com/Plutoberth/SonyHeadphonesClient + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ! This product is not affiliated with Sony. Use at your own risk. ! +Source: https://github.com/Plutoberth/SonyHeadphonesClient + + + + + + + + + + + + + + + + + + + + + + diff --git a/Client/macos/SonyHeadphonesClient.xcodeproj/project.pbxproj b/Client/macos/SonyHeadphonesClient.xcodeproj/project.pbxproj new file mode 100644 index 0000000..4fd1ac2 --- /dev/null +++ b/Client/macos/SonyHeadphonesClient.xcodeproj/project.pbxproj @@ -0,0 +1,357 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 50; + objects = { + +/* Begin PBXBuildFile section */ + A8DC78E42576922700447738 /* info.plist in Resources */ = {isa = PBXBuildFile; fileRef = A8DC78E32576922700447738 /* info.plist */; }; + A8DC78EB2576923D00447738 /* main.mm in Sources */ = {isa = PBXBuildFile; fileRef = A8DC78EA2576923D00447738 /* main.mm */; }; + A8DC78EC2576923D00447738 /* MacOSBluetoothConnector.mm in Sources */ = {isa = PBXBuildFile; fileRef = A8DC78E82576923D00447738 /* MacOSBluetoothConnector.mm */; }; + A8DC78F12576952E00447738 /* BluetoothWrapper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A8DC78EF2576952E00447738 /* BluetoothWrapper.cpp */; }; + A8DC78F52576953600447738 /* CommandSerializer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A8DC78F32576953600447738 /* CommandSerializer.cpp */; }; + A8DC78FA2576954100447738 /* TimedMessageQueue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A8DC78F92576954100447738 /* TimedMessageQueue.cpp */; }; + A8DC78FF2576967D00447738 /* ByteMagic.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A8DC78FD2576967D00447738 /* ByteMagic.cpp */; }; + A8DC790525769A6600447738 /* IOBluetooth.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A8DC790425769A6600447738 /* IOBluetooth.framework */; }; + A8DC792C25769C9900447738 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = A8DC792825769C9900447738 /* AppDelegate.m */; }; + A8DC792D25769C9900447738 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = A8DC792A25769C9900447738 /* ViewController.m */; }; + A8DC793225769EA500447738 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = A8DC78E92576923D00447738 /* Main.storyboard */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + A8DC78E32576922700447738 /* info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = info.plist; sourceTree = ""; }; + A8DC78E62576922D00447738 /* SonyHeadphonesClient.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SonyHeadphonesClient.app; sourceTree = BUILT_PRODUCTS_DIR; }; + A8DC78E72576923D00447738 /* MacOSBluetoothConnector.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = MacOSBluetoothConnector.h; path = /Users/semvi/projects/SonyHeadphonesClient/Client/macos/MacOSBluetoothConnector.h; sourceTree = ""; }; + A8DC78E82576923D00447738 /* MacOSBluetoothConnector.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = MacOSBluetoothConnector.mm; path = /Users/semvi/projects/SonyHeadphonesClient/Client/macos/MacOSBluetoothConnector.mm; sourceTree = ""; }; + A8DC78E92576923D00447738 /* Main.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Main.storyboard; path = /Users/semvi/projects/SonyHeadphonesClient/Client/macos/Main.storyboard; sourceTree = ""; }; + A8DC78EA2576923D00447738 /* main.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = main.mm; path = /Users/semvi/projects/SonyHeadphonesClient/Client/macos/main.mm; sourceTree = ""; }; + A8DC78EE2576950500447738 /* IBluetoothConnector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IBluetoothConnector.h; path = ../IBluetoothConnector.h; sourceTree = ""; }; + A8DC78EF2576952E00447738 /* BluetoothWrapper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = BluetoothWrapper.cpp; path = ../BluetoothWrapper.cpp; sourceTree = ""; }; + A8DC78F02576952E00447738 /* BluetoothWrapper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BluetoothWrapper.h; path = ../BluetoothWrapper.h; sourceTree = ""; }; + A8DC78F32576953600447738 /* CommandSerializer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CommandSerializer.cpp; path = ../CommandSerializer.cpp; sourceTree = ""; }; + A8DC78F42576953600447738 /* CommandSerializer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CommandSerializer.h; path = ../CommandSerializer.h; sourceTree = ""; }; + A8DC78F72576954100447738 /* TimedMessageQueue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TimedMessageQueue.h; path = ../TimedMessageQueue.h; sourceTree = ""; }; + A8DC78F82576954100447738 /* SingleInstanceFuture.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SingleInstanceFuture.h; path = ../SingleInstanceFuture.h; sourceTree = ""; }; + A8DC78F92576954100447738 /* TimedMessageQueue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TimedMessageQueue.cpp; path = ../TimedMessageQueue.cpp; sourceTree = ""; }; + A8DC78FD2576967D00447738 /* ByteMagic.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ByteMagic.cpp; path = ../ByteMagic.cpp; sourceTree = ""; }; + A8DC78FE2576967D00447738 /* ByteMagic.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ByteMagic.h; path = ../ByteMagic.h; sourceTree = ""; }; + A8DC790425769A6600447738 /* IOBluetooth.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOBluetooth.framework; path = System/Library/Frameworks/IOBluetooth.framework; sourceTree = SDKROOT; }; + A8DC792825769C9900447738 /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + A8DC792925769C9900447738 /* ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; + A8DC792A25769C9900447738 /* ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; + A8DC792B25769C9900447738 /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + A8DC78C125757BF300447738 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + A8DC790525769A6600447738 /* IOBluetooth.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + A8DC78BB25757BF300447738 = { + isa = PBXGroup; + children = ( + A8DC78E72576923D00447738 /* MacOSBluetoothConnector.h */, + A8DC78E82576923D00447738 /* MacOSBluetoothConnector.mm */, + A8DC78EA2576923D00447738 /* main.mm */, + A8DC78E92576923D00447738 /* Main.storyboard */, + A8DC78E32576922700447738 /* info.plist */, + A8DC78E62576922D00447738 /* SonyHeadphonesClient.app */, + A8DC78EE2576950500447738 /* IBluetoothConnector.h */, + A8DC78EF2576952E00447738 /* BluetoothWrapper.cpp */, + A8DC78F02576952E00447738 /* BluetoothWrapper.h */, + A8DC78F32576953600447738 /* CommandSerializer.cpp */, + A8DC78F42576953600447738 /* CommandSerializer.h */, + A8DC78F82576954100447738 /* SingleInstanceFuture.h */, + A8DC78F92576954100447738 /* TimedMessageQueue.cpp */, + A8DC78F72576954100447738 /* TimedMessageQueue.h */, + A8DC78FD2576967D00447738 /* ByteMagic.cpp */, + A8DC78FE2576967D00447738 /* ByteMagic.h */, + A8DC792B25769C9900447738 /* AppDelegate.h */, + A8DC792825769C9900447738 /* AppDelegate.m */, + A8DC792925769C9900447738 /* ViewController.h */, + A8DC792A25769C9900447738 /* ViewController.m */, + A8DC790325769A6600447738 /* Frameworks */, + ); + sourceTree = ""; + }; + A8DC790325769A6600447738 /* Frameworks */ = { + isa = PBXGroup; + children = ( + A8DC790425769A6600447738 /* IOBluetooth.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + A8DC78C325757BF300447738 /* SonyHeadphonesClient */ = { + isa = PBXNativeTarget; + buildConfigurationList = A8DC78D825757BF500447738 /* Build configuration list for PBXNativeTarget "SonyHeadphonesClient" */; + buildPhases = ( + A8DC78C025757BF300447738 /* Sources */, + A8DC78C125757BF300447738 /* Frameworks */, + A8DC78C225757BF300447738 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = SonyHeadphonesClient; + productName = SonyHeadphonesClient; + productReference = A8DC78E62576922D00447738 /* SonyHeadphonesClient.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + A8DC78BC25757BF300447738 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 1220; + TargetAttributes = { + A8DC78C325757BF300447738 = { + CreatedOnToolsVersion = 12.2; + }; + }; + }; + buildConfigurationList = A8DC78BF25757BF300447738 /* Build configuration list for PBXProject "SonyHeadphonesClient" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = A8DC78BB25757BF300447738; + productRefGroup = A8DC78BB25757BF300447738; + projectDirPath = ""; + projectRoot = ""; + targets = ( + A8DC78C325757BF300447738 /* SonyHeadphonesClient */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + A8DC78C225757BF300447738 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + A8DC793225769EA500447738 /* Main.storyboard in Resources */, + A8DC78E42576922700447738 /* info.plist in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + A8DC78C025757BF300447738 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + A8DC78EB2576923D00447738 /* main.mm in Sources */, + A8DC78EC2576923D00447738 /* MacOSBluetoothConnector.mm in Sources */, + A8DC792D25769C9900447738 /* ViewController.m in Sources */, + A8DC78F12576952E00447738 /* BluetoothWrapper.cpp in Sources */, + A8DC78FA2576954100447738 /* TimedMessageQueue.cpp in Sources */, + A8DC78F52576953600447738 /* CommandSerializer.cpp in Sources */, + A8DC78FF2576967D00447738 /* ByteMagic.cpp in Sources */, + A8DC792C25769C9900447738 /* AppDelegate.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + A8DC78D625757BF500447738 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 11.0; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + }; + name = Debug; + }; + A8DC78D725757BF500447738 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 11.0; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = macosx; + }; + name = Release; + }; + A8DC78D925757BF500447738 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CLANG_CXX_LANGUAGE_STANDARD = "c++17"; + CODE_SIGN_ENTITLEMENTS = SonyHeadphonesClient/SonyHeadphonesClient.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = "$(SRCROOT)/info.plist"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + OTHER_CPLUSPLUSFLAGS = ( + "-std=c++17", + "-stdlib=libc++", + "$(OTHER_CFLAGS)", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.semvis123.SonyHeadphonesClient; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + A8DC78DA25757BF500447738 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CLANG_CXX_LANGUAGE_STANDARD = "c++17"; + CODE_SIGN_ENTITLEMENTS = SonyHeadphonesClient/SonyHeadphonesClient.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = "$(SRCROOT)/info.plist"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + OTHER_CPLUSPLUSFLAGS = ( + "-std=c++17", + "-stdlib=libc++", + "$(OTHER_CFLAGS)", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.semvis123.SonyHeadphonesClient; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + A8DC78BF25757BF300447738 /* Build configuration list for PBXProject "SonyHeadphonesClient" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + A8DC78D625757BF500447738 /* Debug */, + A8DC78D725757BF500447738 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + A8DC78D825757BF500447738 /* Build configuration list for PBXNativeTarget "SonyHeadphonesClient" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + A8DC78D925757BF500447738 /* Debug */, + A8DC78DA25757BF500447738 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = A8DC78BC25757BF300447738 /* Project object */; +} diff --git a/Client/macos/SonyHeadphonesClient.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Client/macos/SonyHeadphonesClient.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/Client/macos/SonyHeadphonesClient.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/Client/macos/SonyHeadphonesClient.xcodeproj/project.xcworkspace/xcuserdata/semvi.xcuserdatad/UserInterfaceState.xcuserstate b/Client/macos/SonyHeadphonesClient.xcodeproj/project.xcworkspace/xcuserdata/semvi.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000000000000000000000000000000000000..2fbd41db695464e96e25e80c6284773e36616165 GIT binary patch literal 53090 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 mOx}Xr60{{`i*$=-i*`%vmbQOfbz9qi?!myw + + + + SchemeUserState + + SonyHeadphonesClient.xcscheme_^#shared#^_ + + orderHint + 0 + + + + diff --git a/Client/macos/ViewController.h b/Client/macos/ViewController.h new file mode 100644 index 0000000..75bed1c --- /dev/null +++ b/Client/macos/ViewController.h @@ -0,0 +1,14 @@ +// +// ViewController.h +// test +// +// Created by Sem Vissscher on 01/12/2020. +// + +#import + +@interface ViewController : NSViewController + + +@end + diff --git a/Client/macos/ViewController.m b/Client/macos/ViewController.m new file mode 100644 index 0000000..c41069c --- /dev/null +++ b/Client/macos/ViewController.m @@ -0,0 +1,26 @@ +// +// ViewController.m +// test +// +// Created by Sem Vissscher on 01/12/2020. +// + +#import "ViewController.h" + +@implementation ViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + + // Do any additional setup after loading the view. +} + + +- (void)setRepresentedObject:(id)representedObject { + [super setRepresentedObject:representedObject]; + + // Update the view, if already loaded. +} + + +@end diff --git a/Client/macos/info.plist b/Client/macos/info.plist new file mode 100644 index 0000000..ef9892b --- /dev/null +++ b/Client/macos/info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleExecutable + SonyHeadphonesClient + CFBundleIdentifier + com.semvis123.SonyHeadphonesClient + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + SonyHeadphonesClient + CFBundlePackageType + APPL + LSApplicationCategoryType + public.app-category.utilities + NSHighResolutionCapable + True + NSMainStoryboardFile + Main + + diff --git a/Client/macos/main.mm b/Client/macos/main.mm new file mode 100644 index 0000000..11c001e --- /dev/null +++ b/Client/macos/main.mm @@ -0,0 +1,22 @@ +#include +//#import +#include "MacOSGUI.h" +#include "MacOSBluetoothConnector.h" +#include "BluetoothWrapper.h" + +int main(int argc, const char * argv[]) +{ + try { + // Get bluetooth connector + std::unique_ptr connector = std::make_unique(); + // Wrap the connector using the bluetoothwrapper + BluetoothWrapper wrap(std::move(connector)); + // Start the gui + EnterGUIMainLoop(std::move(wrap)); + return 1; + } catch (const std::exception& e) + { + printf("%s",e.what()); + } +// return NSApplicationMain(argc, argv); +} diff --git a/Client/macos/makefile b/Client/macos/makefile new file mode 100644 index 0000000..3bd7d67 --- /dev/null +++ b/Client/macos/makefile @@ -0,0 +1,70 @@ +# +# You will need GLFW (http://www.glfw.org): +# brew install glfw +# + +#CXX = g++ +#CXX = clang++ + +EXE = sonyheadphonesclient +SOURCES = main.mm +SOURCES += ../GUI_Impls/MacOSGUI.cpp ../GUI_Impls/CrossPlatformGUI.cpp +SOURCES += MacOSBluetoothConnector.cpp BluetoothWrapper.cpp +SOURCES += TimedMessageQueue.cpp CascadiaCodeFont.cpp CommandSerializer.cpp +SOURCES += ByteMagic.cpp +SOURCES += ../imgui/examples/imgui_impl_glfw.cpp ../imgui/examples/imgui_impl_metal.mm +SOURCES += ../imgui/imgui.cpp ../imgui/imgui_widgets.cpp ../imgui/imgui_demo.cpp ../imgui/imgui_draw.cpp +OBJS = $(addsuffix .o, $(basename $(notdir $(SOURCES)))) + +LIBS = -framework IOBluetooth -framework Metal -framework MetalKit -framework Cocoa -framework IOKit -framework CoreVideo -framework QuartzCore +LIBS += -L/usr/local/lib -lglfw + +CXXFLAGS = -I../imgui/ -I../GUI_Impls/ -I../imgui/examples/ -I../ -I/usr/local/include +CXXFLAGS += -Wall -Wformat -std=c++17 -stdlib=libc++ +CFLAGS = $(CXXFLAGS) + +%.o:%.cpp + $(CXX) $(CXXFLAGS) -c -o $@ $< +%.o:../%.cpp + $(CXX) $(CXXFLAGS) -c -o $@ $< +%.o:../imgui/examples/%.cpp + $(CXX) $(CXXFLAGS) -c -o $@ $< + +%.o:../imgui/%.cpp + $(CXX) $(CXXFLAGS) -c -o $@ $< + +%.o:../GUI_Impls/%.cpp + $(CXX) $(CXXFLAGS) -c -o $@ $< + +%.o:../GUI_Impls/%.mm + $(CXX) $(CXXFLAGS) -ObjC++ -fobjc-weak -fobjc-arc -c -o $@ $< + +%.o:../imgui/examples/%.mm + $(CXX) $(CXXFLAGS) -ObjC++ -fobjc-weak -fobjc-arc -c -o $@ $< + +%.o:%.mm + $(CXX) $(CXXFLAGS) -ObjC++ -fobjc-weak -fobjc-arc -c -o $@ $< + +%.o:../%.mm + $(CXX) $(CXXFLAGS) -ObjC++ -fobjc-weak -fobjc-arc -c -o $@ $< + +all: $(EXE) + $(MAKE) clean_app + $(MAKE) package_app + $(MAKE) clean + @echo Build complete + +$(EXE): $(OBJS) + $(CXX) -o $@ $^ $(CXXFLAGS) $(LIBS) + +clean: + rm -f $(EXE) $(OBJS) + +clean_app: + rm -rf "./$(EXE).app/" + +package_app: + mkdir -p "./$(EXE).app"/Contents/{MacOS,Resources} + cp ./Info.plist "./$(EXE).app/Contents/" + sed -e "s/APP_NAME/$(EXE)/g" -i "" "./$(EXE).app/Contents/Info.plist" + cp ./$(EXE) "./$(EXE).app/Contents/MacOS/$(EXE)" \ No newline at end of file diff --git a/LICENSE b/LICENSE index a7e1895..d22d30e 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2020 Nir Harel, Mor Gal, and other contributors +Copyright (c) 2020 Nir Harel, Mor Gal, Sem Visscher, and other contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 33f7877..0e05b29 100644 --- a/README.md +++ b/README.md @@ -61,7 +61,8 @@ It shouldn't be too much work to add support for a new platform. Open a PR if yo - [x] Windows - [ ] [Linux](https://github.com/Plutoberth/SonyHeadphonesClient/issues/7) -- [ ] [macOS](https://github.com/Plutoberth/SonyHeadphonesClient/issues/6) - In Progress by semvis123 +- [x] macOS + ## For Developers From 7cf4fdf5fc04850a7a79da256f38476bffe617c0 Mon Sep 17 00:00:00 2001 From: semvis123 Date: Fri, 1 Jan 2021 23:51:20 +0100 Subject: [PATCH 21/55] Updated native gui ( not fully working ) --- Client/macos/AppDelegate.h | 10 +- .../macos/{AppDelegate.m => AppDelegate.mm} | 8 +- Client/macos/Main.storyboard | 108 +++--------------- .../project.pbxproj | 50 +++++--- Client/macos/ViewController.h | 12 +- Client/macos/ViewController.m | 26 ----- Client/macos/ViewController.mm | 59 ++++++++++ Client/macos/main.mm | 30 ++--- 8 files changed, 144 insertions(+), 159 deletions(-) rename Client/macos/{AppDelegate.m => AppDelegate.mm} (74%) delete mode 100644 Client/macos/ViewController.m create mode 100644 Client/macos/ViewController.mm diff --git a/Client/macos/AppDelegate.h b/Client/macos/AppDelegate.h index 794dc5f..de40df4 100644 --- a/Client/macos/AppDelegate.h +++ b/Client/macos/AppDelegate.h @@ -1,14 +1,16 @@ // // AppDelegate.h -// test +// SonyHeadphonesClient // -// Created by Sem Vissscher on 01/12/2020. +// Created by Sem Visscher on 01/12/2020. // #import +#import +#import +#import "BluetoothWrapper.h" +#import "MacOSBluetoothConnector.h" @interface AppDelegate : NSObject - @end - diff --git a/Client/macos/AppDelegate.m b/Client/macos/AppDelegate.mm similarity index 74% rename from Client/macos/AppDelegate.m rename to Client/macos/AppDelegate.mm index c8273d5..2bab817 100644 --- a/Client/macos/AppDelegate.m +++ b/Client/macos/AppDelegate.mm @@ -1,8 +1,8 @@ // // AppDelegate.m -// test +// SonyHeadphonesClient // -// Created by Sem Vissscher on 01/12/2020. +// Created by Sem Visscher on 01/12/2020. // #import "AppDelegate.h" @@ -13,9 +13,8 @@ @interface AppDelegate () @end @implementation AppDelegate - - (void)applicationDidFinishLaunching:(NSNotification *)aNotification { - // Insert code here to initialize your application + } @@ -23,5 +22,4 @@ - (void)applicationWillTerminate:(NSNotification *)aNotification { // Insert code here to tear down your application } - @end diff --git a/Client/macos/Main.storyboard b/Client/macos/Main.storyboard index b996f1c..6b63668 100644 --- a/Client/macos/Main.storyboard +++ b/Client/macos/Main.storyboard @@ -1,7 +1,7 @@ - + - + @@ -133,12 +133,9 @@ - - - - + @@ -167,7 +164,7 @@ - + @@ -187,7 +184,10 @@ - + + + + @@ -209,7 +212,7 @@ Source: https://github.com/Plutoberth/SonyHeadphonesClient - + @@ -219,89 +222,16 @@ Source: https://github.com/Plutoberth/SonyHeadphonesClient + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ! This product is not affiliated with Sony. Use at your own risk. ! -Source: https://github.com/Plutoberth/SonyHeadphonesClient - - - - - - - - - - - - - - - - - - - + diff --git a/Client/macos/SonyHeadphonesClient.xcodeproj/project.pbxproj b/Client/macos/SonyHeadphonesClient.xcodeproj/project.pbxproj index 4fd1ac2..3309027 100644 --- a/Client/macos/SonyHeadphonesClient.xcodeproj/project.pbxproj +++ b/Client/macos/SonyHeadphonesClient.xcodeproj/project.pbxproj @@ -7,7 +7,9 @@ objects = { /* Begin PBXBuildFile section */ - A8DC78E42576922700447738 /* info.plist in Resources */ = {isa = PBXBuildFile; fileRef = A8DC78E32576922700447738 /* info.plist */; }; + A87B3287259FAA3300EA6551 /* AppKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A87B3283259FAA1400EA6551 /* AppKit.framework */; }; + A87B328B259FAA8B00EA6551 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A87B328A259FAA8B00EA6551 /* Cocoa.framework */; }; + A87B328E259FAB0E00EA6551 /* IOBluetoothUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A87B328D259FAB0E00EA6551 /* IOBluetoothUI.framework */; }; A8DC78EB2576923D00447738 /* main.mm in Sources */ = {isa = PBXBuildFile; fileRef = A8DC78EA2576923D00447738 /* main.mm */; }; A8DC78EC2576923D00447738 /* MacOSBluetoothConnector.mm in Sources */ = {isa = PBXBuildFile; fileRef = A8DC78E82576923D00447738 /* MacOSBluetoothConnector.mm */; }; A8DC78F12576952E00447738 /* BluetoothWrapper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A8DC78EF2576952E00447738 /* BluetoothWrapper.cpp */; }; @@ -15,18 +17,23 @@ A8DC78FA2576954100447738 /* TimedMessageQueue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A8DC78F92576954100447738 /* TimedMessageQueue.cpp */; }; A8DC78FF2576967D00447738 /* ByteMagic.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A8DC78FD2576967D00447738 /* ByteMagic.cpp */; }; A8DC790525769A6600447738 /* IOBluetooth.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A8DC790425769A6600447738 /* IOBluetooth.framework */; }; - A8DC792C25769C9900447738 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = A8DC792825769C9900447738 /* AppDelegate.m */; }; - A8DC792D25769C9900447738 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = A8DC792A25769C9900447738 /* ViewController.m */; }; + A8DC792C25769C9900447738 /* AppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = A8DC792825769C9900447738 /* AppDelegate.mm */; }; + A8DC792D25769C9900447738 /* ViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = A8DC792A25769C9900447738 /* ViewController.mm */; }; A8DC793225769EA500447738 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = A8DC78E92576923D00447738 /* Main.storyboard */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ + A87B327A259F69BA00EA6551 /* Constants.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Constants.h; path = ../Constants.h; sourceTree = ""; }; + A87B3283259FAA1400EA6551 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; }; + A87B328A259FAA8B00EA6551 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; + A87B328D259FAB0E00EA6551 /* IOBluetoothUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOBluetoothUI.framework; path = System/Library/Frameworks/IOBluetoothUI.framework; sourceTree = SDKROOT; }; + A8952E6C259F698D00B30ED6 /* Constants.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Constants.h; path = ../Constants.h; sourceTree = ""; }; A8DC78E32576922700447738 /* info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = info.plist; sourceTree = ""; }; A8DC78E62576922D00447738 /* SonyHeadphonesClient.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SonyHeadphonesClient.app; sourceTree = BUILT_PRODUCTS_DIR; }; - A8DC78E72576923D00447738 /* MacOSBluetoothConnector.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = MacOSBluetoothConnector.h; path = /Users/semvi/projects/SonyHeadphonesClient/Client/macos/MacOSBluetoothConnector.h; sourceTree = ""; }; - A8DC78E82576923D00447738 /* MacOSBluetoothConnector.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = MacOSBluetoothConnector.mm; path = /Users/semvi/projects/SonyHeadphonesClient/Client/macos/MacOSBluetoothConnector.mm; sourceTree = ""; }; - A8DC78E92576923D00447738 /* Main.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Main.storyboard; path = /Users/semvi/projects/SonyHeadphonesClient/Client/macos/Main.storyboard; sourceTree = ""; }; - A8DC78EA2576923D00447738 /* main.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = main.mm; path = /Users/semvi/projects/SonyHeadphonesClient/Client/macos/main.mm; sourceTree = ""; }; + A8DC78E72576923D00447738 /* MacOSBluetoothConnector.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MacOSBluetoothConnector.h; sourceTree = ""; }; + A8DC78E82576923D00447738 /* MacOSBluetoothConnector.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = MacOSBluetoothConnector.mm; sourceTree = ""; }; + A8DC78E92576923D00447738 /* Main.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = Main.storyboard; sourceTree = ""; }; + A8DC78EA2576923D00447738 /* main.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = main.mm; sourceTree = ""; }; A8DC78EE2576950500447738 /* IBluetoothConnector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IBluetoothConnector.h; path = ../IBluetoothConnector.h; sourceTree = ""; }; A8DC78EF2576952E00447738 /* BluetoothWrapper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = BluetoothWrapper.cpp; path = ../BluetoothWrapper.cpp; sourceTree = ""; }; A8DC78F02576952E00447738 /* BluetoothWrapper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BluetoothWrapper.h; path = ../BluetoothWrapper.h; sourceTree = ""; }; @@ -38,9 +45,9 @@ A8DC78FD2576967D00447738 /* ByteMagic.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ByteMagic.cpp; path = ../ByteMagic.cpp; sourceTree = ""; }; A8DC78FE2576967D00447738 /* ByteMagic.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ByteMagic.h; path = ../ByteMagic.h; sourceTree = ""; }; A8DC790425769A6600447738 /* IOBluetooth.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOBluetooth.framework; path = System/Library/Frameworks/IOBluetooth.framework; sourceTree = SDKROOT; }; - A8DC792825769C9900447738 /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + A8DC792825769C9900447738 /* AppDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = AppDelegate.mm; sourceTree = ""; }; A8DC792925769C9900447738 /* ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; - A8DC792A25769C9900447738 /* ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; + A8DC792A25769C9900447738 /* ViewController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ViewController.mm; sourceTree = ""; }; A8DC792B25769C9900447738 /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; /* End PBXFileReference section */ @@ -49,6 +56,9 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + A87B328E259FAB0E00EA6551 /* IOBluetoothUI.framework in Frameworks */, + A87B328B259FAA8B00EA6551 /* Cocoa.framework in Frameworks */, + A87B3287259FAA3300EA6551 /* AppKit.framework in Frameworks */, A8DC790525769A6600447738 /* IOBluetooth.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -59,6 +69,7 @@ A8DC78BB25757BF300447738 = { isa = PBXGroup; children = ( + A87B327A259F69BA00EA6551 /* Constants.h */, A8DC78E72576923D00447738 /* MacOSBluetoothConnector.h */, A8DC78E82576923D00447738 /* MacOSBluetoothConnector.mm */, A8DC78EA2576923D00447738 /* main.mm */, @@ -76,9 +87,9 @@ A8DC78FD2576967D00447738 /* ByteMagic.cpp */, A8DC78FE2576967D00447738 /* ByteMagic.h */, A8DC792B25769C9900447738 /* AppDelegate.h */, - A8DC792825769C9900447738 /* AppDelegate.m */, + A8DC792825769C9900447738 /* AppDelegate.mm */, A8DC792925769C9900447738 /* ViewController.h */, - A8DC792A25769C9900447738 /* ViewController.m */, + A8DC792A25769C9900447738 /* ViewController.mm */, A8DC790325769A6600447738 /* Frameworks */, ); sourceTree = ""; @@ -86,6 +97,10 @@ A8DC790325769A6600447738 /* Frameworks */ = { isa = PBXGroup; children = ( + A87B328D259FAB0E00EA6551 /* IOBluetoothUI.framework */, + A87B328A259FAA8B00EA6551 /* Cocoa.framework */, + A87B3283259FAA1400EA6551 /* AppKit.framework */, + A8952E6C259F698D00B30ED6 /* Constants.h */, A8DC790425769A6600447738 /* IOBluetooth.framework */, ); name = Frameworks; @@ -117,7 +132,7 @@ A8DC78BC25757BF300447738 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 1220; + LastUpgradeCheck = 1230; TargetAttributes = { A8DC78C325757BF300447738 = { CreatedOnToolsVersion = 12.2; @@ -148,7 +163,6 @@ buildActionMask = 2147483647; files = ( A8DC793225769EA500447738 /* Main.storyboard in Resources */, - A8DC78E42576922700447738 /* info.plist in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -161,12 +175,12 @@ files = ( A8DC78EB2576923D00447738 /* main.mm in Sources */, A8DC78EC2576923D00447738 /* MacOSBluetoothConnector.mm in Sources */, - A8DC792D25769C9900447738 /* ViewController.m in Sources */, + A8DC792D25769C9900447738 /* ViewController.mm in Sources */, A8DC78F12576952E00447738 /* BluetoothWrapper.cpp in Sources */, A8DC78FA2576954100447738 /* TimedMessageQueue.cpp in Sources */, A8DC78F52576953600447738 /* CommandSerializer.cpp in Sources */, A8DC78FF2576967D00447738 /* ByteMagic.cpp in Sources */, - A8DC792C25769C9900447738 /* AppDelegate.m in Sources */, + A8DC792C25769C9900447738 /* AppDelegate.mm in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -289,7 +303,8 @@ buildSettings = { ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CLANG_CXX_LANGUAGE_STANDARD = "c++17"; - CODE_SIGN_ENTITLEMENTS = SonyHeadphonesClient/SonyHeadphonesClient.entitlements; + CODE_SIGN_ENTITLEMENTS = SonyHeadphonesClient.entitlements; + CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = "$(SRCROOT)/info.plist"; @@ -312,7 +327,8 @@ buildSettings = { ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CLANG_CXX_LANGUAGE_STANDARD = "c++17"; - CODE_SIGN_ENTITLEMENTS = SonyHeadphonesClient/SonyHeadphonesClient.entitlements; + CODE_SIGN_ENTITLEMENTS = SonyHeadphonesClient.entitlements; + CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = "$(SRCROOT)/info.plist"; diff --git a/Client/macos/ViewController.h b/Client/macos/ViewController.h index 75bed1c..dfce35c 100644 --- a/Client/macos/ViewController.h +++ b/Client/macos/ViewController.h @@ -1,14 +1,20 @@ // // ViewController.h -// test +// SonyHeadphonesClient // -// Created by Sem Vissscher on 01/12/2020. +// Created by Sem Visscher on 01/12/2020. // #import +#import "AppDelegate.h" -@interface ViewController : NSViewController +BluetoothWrapper bt = (BluetoothWrapper)nil; +@interface ViewController : NSViewController +@property (weak, nonatomic) IBOutlet NSTextField *connectedLabel; +@property (weak, nonatomic) IBOutlet NSTextField *ANCValueLabel; +@property (weak, nonatomic) IBOutlet NSButton *connectButton; +@property (weak, nonatomic) IBOutlet NSSlider *ANCSlider; @end diff --git a/Client/macos/ViewController.m b/Client/macos/ViewController.m deleted file mode 100644 index c41069c..0000000 --- a/Client/macos/ViewController.m +++ /dev/null @@ -1,26 +0,0 @@ -// -// ViewController.m -// test -// -// Created by Sem Vissscher on 01/12/2020. -// - -#import "ViewController.h" - -@implementation ViewController - -- (void)viewDidLoad { - [super viewDidLoad]; - - // Do any additional setup after loading the view. -} - - -- (void)setRepresentedObject:(id)representedObject { - [super setRepresentedObject:representedObject]; - - // Update the view, if already loaded. -} - - -@end diff --git a/Client/macos/ViewController.mm b/Client/macos/ViewController.mm new file mode 100644 index 0000000..c3cc964 --- /dev/null +++ b/Client/macos/ViewController.mm @@ -0,0 +1,59 @@ +// +// ViewController.m +// SonyHeadphonesClient +// +// Created by Sem Visscher on 01/12/2020. +// + +#import "ViewController.h" + +@implementation ViewController +@synthesize connectedLabel, connectButton, ANCSlider, ANCValueLabel; + +- (void)viewDidLoad { + [super viewDidLoad]; + std::unique_ptr connector = std::make_unique(); + // Wrap the connector using the bluetoothwrapper + bt = BluetoothWrapper(std::move(connector)); +} + + +- (void)setRepresentedObject:(id)representedObject { + [super setRepresentedObject:representedObject]; + + // Update the view, if already loaded. +} + +- (IBAction)connectToDevice:(id)sender { + if (bt.isConnected()){ + bt.disconnect(); + [ANCSlider setEnabled:FALSE]; + [connectButton setTitle:@"Connect to Bluetooth device"]; + [connectedLabel setStringValue:@"Not connected"]; + } + else { + IOBluetoothDeviceSelectorController *dSelector = [IOBluetoothDeviceSelectorController deviceSelector]; + int result = [dSelector runModal]; + if (result == kIOBluetoothUISuccess) { + IOBluetoothDevice *device = [[dSelector getResults] lastObject]; + NSLog(@"%@", [device addressString]); + bt.connect([[device addressString] UTF8String]); + } + int timeout = 20; + while(!bt.isConnected() and timeout >= 0){ + [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; + } + if (bt.isConnected()){ + IOBluetoothDevice *device = [[dSelector getResults] lastObject]; + [connectedLabel setStringValue:[@"Connected: " stringByAppendingString:[device nameOrAddress]]]; + [connectButton setTitle:@"Disconnect"]; + [ANCSlider setEnabled:TRUE]; + } + } +} +- (IBAction)sliderChanged:(id)sender { + NSLog(@"%@", ANCSlider.stringValue); + [ANCValueLabel setStringValue:ANCSlider.stringValue]; +} + +@end diff --git a/Client/macos/main.mm b/Client/macos/main.mm index 11c001e..1f3f0ce 100644 --- a/Client/macos/main.mm +++ b/Client/macos/main.mm @@ -1,22 +1,22 @@ #include -//#import -#include "MacOSGUI.h" +#import +//#include "MacOSGUI.h" #include "MacOSBluetoothConnector.h" #include "BluetoothWrapper.h" int main(int argc, const char * argv[]) { - try { - // Get bluetooth connector - std::unique_ptr connector = std::make_unique(); - // Wrap the connector using the bluetoothwrapper - BluetoothWrapper wrap(std::move(connector)); - // Start the gui - EnterGUIMainLoop(std::move(wrap)); - return 1; - } catch (const std::exception& e) - { - printf("%s",e.what()); - } -// return NSApplicationMain(argc, argv); +// try { +// // Get bluetooth connector +// std::unique_ptr connector = std::make_unique(); +// // Wrap the connector using the bluetoothwrapper +// BluetoothWrapper wrap(std::move(connector)); +// // Start the gui +// EnterGUIMainLoop(std::move(wrap)); +// return 1; +// } catch (const std::exception& e) +// { +// printf("%s",e.what()); +// } + return NSApplicationMain(argc, argv); } From a4f077ad089031bc78ebf61a1c1ad7d55a5ae8e3 Mon Sep 17 00:00:00 2001 From: semvis123 Date: Sat, 2 Jan 2021 00:29:44 +0100 Subject: [PATCH 22/55] Working, except disconnect button --- Client/macos/Main.storyboard | 21 ++++++++++++------- Client/macos/ViewController.h | 2 ++ Client/macos/ViewController.mm | 38 ++++++++++++++++++++++++++++++---- 3 files changed, 49 insertions(+), 12 deletions(-) diff --git a/Client/macos/Main.storyboard b/Client/macos/Main.storyboard index 6b63668..0dda3a4 100644 --- a/Client/macos/Main.storyboard +++ b/Client/macos/Main.storyboard @@ -131,7 +131,7 @@ - + @@ -140,7 +140,7 @@ - + @@ -150,10 +150,6 @@ - - - - @@ -173,9 +169,9 @@ - + - + @@ -220,6 +216,13 @@ Source: https://github.com/Plutoberth/SonyHeadphonesClient + + + + + + + @@ -227,6 +230,8 @@ Source: https://github.com/Plutoberth/SonyHeadphonesClient + + diff --git a/Client/macos/ViewController.h b/Client/macos/ViewController.h index dfce35c..841adbd 100644 --- a/Client/macos/ViewController.h +++ b/Client/macos/ViewController.h @@ -13,6 +13,8 @@ BluetoothWrapper bt = (BluetoothWrapper)nil; @interface ViewController : NSViewController @property (weak, nonatomic) IBOutlet NSTextField *connectedLabel; @property (weak, nonatomic) IBOutlet NSTextField *ANCValueLabel; +@property (weak, nonatomic) IBOutlet NSTextField *focusOnVoiceLabel; +@property (weak, nonatomic) IBOutlet NSSwitch *focusOnVoice; @property (weak, nonatomic) IBOutlet NSButton *connectButton; @property (weak, nonatomic) IBOutlet NSSlider *ANCSlider; diff --git a/Client/macos/ViewController.mm b/Client/macos/ViewController.mm index c3cc964..0f49fef 100644 --- a/Client/macos/ViewController.mm +++ b/Client/macos/ViewController.mm @@ -8,7 +8,7 @@ #import "ViewController.h" @implementation ViewController -@synthesize connectedLabel, connectButton, ANCSlider, ANCValueLabel; +@synthesize connectedLabel, connectButton, ANCSlider, ANCValueLabel, focusOnVoice, focusOnVoiceLabel; - (void)viewDidLoad { [super viewDidLoad]; @@ -20,7 +20,7 @@ - (void)viewDidLoad { - (void)setRepresentedObject:(id)representedObject { [super setRepresentedObject:representedObject]; - + // Update the view, if already loaded. } @@ -28,6 +28,7 @@ - (IBAction)connectToDevice:(id)sender { if (bt.isConnected()){ bt.disconnect(); [ANCSlider setEnabled:FALSE]; + [focusOnVoice setEnabled:FALSE]; [connectButton setTitle:@"Connect to Bluetooth device"]; [connectedLabel setStringValue:@"Not connected"]; } @@ -48,12 +49,41 @@ - (IBAction)connectToDevice:(id)sender { [connectedLabel setStringValue:[@"Connected: " stringByAppendingString:[device nameOrAddress]]]; [connectButton setTitle:@"Disconnect"]; [ANCSlider setEnabled:TRUE]; + [focusOnVoice setEnabled:FALSE]; } } } - (IBAction)sliderChanged:(id)sender { - NSLog(@"%@", ANCSlider.stringValue); [ANCValueLabel setStringValue:ANCSlider.stringValue]; -} + if (ANCSlider.intValue >= MINIMUM_VOICE_FOCUS_STEP) + { + [focusOnVoiceLabel setStringValue:@"Focus on Voice"]; + [focusOnVoice setEnabled:TRUE]; + } + else + { + [focusOnVoiceLabel setStringValue:@"Focus on Voice isn't enabled on this level."]; + [focusOnVoice setEnabled:FALSE]; + } + auto ncAsmEffect = NC_ASM_EFFECT::ADJUSTMENT_COMPLETION; + auto asmId = focusOnVoice.state == NSControlStateValueOn ? ASM_ID::VOICE : ASM_ID::NORMAL; + bt.sendCommand(CommandSerializer::serializeNcAndAsmSetting( + ncAsmEffect, + NC_ASM_SETTING_TYPE::LEVEL_ADJUSTMENT, + ASM_SETTING_TYPE::LEVEL_ADJUSTMENT, + asmId, + ANCSlider.intValue + ));} +- (IBAction)voiceChanged:(id)sender { + [ANCValueLabel setStringValue:ANCSlider.stringValue]; + auto ncAsmEffect = NC_ASM_EFFECT::ADJUSTMENT_COMPLETION; + auto asmId = focusOnVoice.state == NSControlStateValueOn ? ASM_ID::VOICE : ASM_ID::NORMAL; + bt.sendCommand(CommandSerializer::serializeNcAndAsmSetting( + ncAsmEffect, + NC_ASM_SETTING_TYPE::LEVEL_ADJUSTMENT, + ASM_SETTING_TYPE::LEVEL_ADJUSTMENT, + asmId, + ANCSlider.intValue + ));} @end From 4c215b3f3993efd582777432102f085f30e0b329 Mon Sep 17 00:00:00 2001 From: semvis123 Date: Sat, 2 Jan 2021 16:41:04 +0100 Subject: [PATCH 23/55] Fixed the disconnect function --- Client/macos/MacOSBluetoothConnector.mm | 1 + 1 file changed, 1 insertion(+) diff --git a/Client/macos/MacOSBluetoothConnector.mm b/Client/macos/MacOSBluetoothConnector.mm index 9b8b647..cb509a2 100644 --- a/Client/macos/MacOSBluetoothConnector.mm +++ b/Client/macos/MacOSBluetoothConnector.mm @@ -147,6 +147,7 @@ -(void)rfcommChannelData:(IOBluetoothRFCOMMChannel *)rfcommChannel data:(void *) void MacOSBluetoothConnector::closeConnection() { // get the channel IOBluetoothRFCOMMChannel *chan = (__bridge IOBluetoothRFCOMMChannel*) rfcommchannel; + [chan setDelegate: nil]; // close the channel [chan closeChannel]; From fa6e467bf81d22193392f5e4c8407ed3b8d6e1d2 Mon Sep 17 00:00:00 2001 From: semvis123 Date: Sat, 2 Jan 2021 17:03:53 +0100 Subject: [PATCH 24/55] Fully working now, added comments --- Client/macos/MacOSBluetoothConnector.mm | 1 + .../UserInterfaceState.xcuserstate | Bin 53090 -> 57606 bytes Client/macos/ViewController.mm | 46 ++++++++++++------ 3 files changed, 31 insertions(+), 16 deletions(-) diff --git a/Client/macos/MacOSBluetoothConnector.mm b/Client/macos/MacOSBluetoothConnector.mm index 9b8b647..cb509a2 100644 --- a/Client/macos/MacOSBluetoothConnector.mm +++ b/Client/macos/MacOSBluetoothConnector.mm @@ -147,6 +147,7 @@ -(void)rfcommChannelData:(IOBluetoothRFCOMMChannel *)rfcommChannel data:(void *) void MacOSBluetoothConnector::closeConnection() { // get the channel IOBluetoothRFCOMMChannel *chan = (__bridge IOBluetoothRFCOMMChannel*) rfcommchannel; + [chan setDelegate: nil]; // close the channel [chan closeChannel]; diff --git a/Client/macos/SonyHeadphonesClient.xcodeproj/project.xcworkspace/xcuserdata/semvi.xcuserdatad/UserInterfaceState.xcuserstate b/Client/macos/SonyHeadphonesClient.xcodeproj/project.xcworkspace/xcuserdata/semvi.xcuserdatad/UserInterfaceState.xcuserstate index 2fbd41db695464e96e25e80c6284773e36616165..f5c8139776a48910cf8adb3892432507ba4c11a9 100644 GIT binary patch delta 28848 zcma&O2YeL8`#-)jySKM}FTIgQ+5t&ONF#;x-W#DOgb*N<1d`Cf+W|yGq#aFqLJhr$ z^eQSKO#uO=7eT6s2!i5o_AbW<)UW@)zV68F&d$#J{XFx`^UORmHx`o<50TT$4F?FG z5C{jtk#Hi~5=qcB32Vk#2R8Pv6 zuZSbWQQ{c!wShQJd`FxoE)W-q%fxNsN8%1~m-v}@Li|EJC4MD-Bc2m~60d;-WS|39 zz#7;9TVMxT09W7!+<^!12JJuy2nAsv97KQwkO-1MGDra#pa2wtB2WyvgC3w1l!2b0 z9P|bKzz8rBi~^&<7%&zX-U9~kK9~qT0F%HJFbB*B3&0Yv6f6fTz(%kMYzAAvXJ9AT z0}gEG5lT>oI%oy0p*?hi?$86a zhHaof41j^KEewH4Fd3%6RG0?S4KM>{!W@_jJHzgHlZ$JA768a17oLCvI$)GTT?HHVr{HBgPzYO0CaOl_gIQlCMUhA zM}0?~r!G(zsqd*Ds7ur}>JIggdPMz3J*Qr12o2CUXdE?88fT4*riI2;a#N%Ls|=densu73nw^?mnnRk;HHS6FH77JTHMcakH9u)SFYHhT(+7?<@t((?e>!HDsy4McT#MmD*L>)!I$k&DyWDN3=(^ z$FyH-k84k8PijwTPixO=f6!jn-q7CD-q$|R{;GY(@QlESjKs){j|?%UzG5yjSD35JHRd{V zgSpAvVs0}(GWVD#%rDFf=64pbkR@5371)*r){FIKeOO=CkJYoS*w$?l@Y5&I!Knf-`0va{GV>{@mmyPn;^ zZe%yHo7pYwR(3nPk3GzO!Jc4GvZvVd>;?7_`JX;9cRzEaqe6g7tTd+?YT%Uii_rAxDH$_m&j#sd0al%nd`!J<$7@y+(>Q| zH<}y6jpg3s44lFtZX7p}`6PT&PW5Cut)1)X3eSPM3StKcTM3m$@AXeWdSp+cAtE<_0Jg+w7qNET9rJRx5w z5DJCvLJy%_s1$|@!-V0&2!k+E7%M0O62=J=g(<>x!6+;hmJ2I{?ZOUWr?5-dE$k8Y z3j2ip!a3nP;k>dk|HZ|q9n?q zt=K|z72U)rF2p7m@KA_%oMZ4Y_U)*5=+ERVh^!Y>?8IS z`-v08_r;0g2jV30LvgbBkvK*CSez>+!~EoCp+TlSHCWk0!%+)i#UN6HCuqMRvb z$$4^-++FS^_mv08HS%D&UY;y}Bu|k)mZ!?okZg6=;WpYi$&_R{e^<_Hmkf6lSgrJDvfS|~Ph=9az7#uD0<`T#5>8X2SMQ2} z<#lz{<%23aoByn=>zG^Au`s(4->&SOTa?$Ue`Q7e+m%P-pkn ztE)|SUCVSu#)KZOR9#K=NMmrgms%{SSu8_{VMO3^qL!#5>WQI>yW*jEDlL~2!-=89 zNMe-YrL0-R{ZeuA9ZbElsd5n^K;XP>18^b+@hSJ_2s<=Rwh?f)K}G1m)DM5Moc4S5S86? zi~e`bQmK)cuL^e-F`Jk}%q8X#pD3-BHj2Lzpad#yR}u?|g~TFaF|mYLsst&)N;@S) ziBQ@r`mSATY6hj2SJc2f# zx>V775zYTuTCj^aKm@KJb`yJuy~I9ZzY?WHD=|t3C3XdI5RY z!(PyNNiuPQ_(oNjlf)_Fv=Xl*D2dB(W6uz0aWj*YTt#1+k(ggwIjpL3cu__9z{)b6 z?#+e5%8IJNm377;T|9%$&HkPk*FgNBBrD#QW?dn!6ZVb7RpOeGqNFwwH;9``nv$;M z7;klH=S=)WJWy}nBkn61N@gSRka(nIDcSgTXxEq^vp{AL&l*+Yz2Z)rFLA+EY z`MZ+;KS_E;5q|+1%K{Jp00>Ax0gY0q6e-0@N2NsRgk=F3ViDi~Z<0l4EQ>BmsVWQO z)2{O!fITs8IdA}uzzH}jU6pQ1ccllWe|5KzB;W~Jn(1$D0`LKCFzdh<_yIj=1zIaT zm2#z*Qla!-0sM*KAP}?#K}scNy~m~{{dqCm9LN9n8d!>of?5QkZ> zQu^a!y}A_mgH%i>NK*#9p%Y|+9LyKU0@=zyWl$r?1$j!fQqxQ)=miXK6fdeaREpU2)-k4EPp$vPQQBVa2 ztBm#s1HeEq2vma_WrQ+P8KsO?#wcS|Mr$#n^rm~aDbe+_)9vRhr zY61rjtg3t4f`MhGLX*pM8AenZXY@|DY6(_?HEN4ifz_Z%nWB8GOkIYhybi3#5}u|Q zvEY`b+ZqR_%f`lZPvhzg&r&nwtzcUN_*9v$%ryVr4t6Y6W|;IF>;k(>-*&}kqm8cSB199dd2%JbbyY~iIAZ)bb&3PYnQspfp~DlgGiV9szH@? z_2q*GckA8ktKczI*`#b#HYmr8r!u=Fc_kd$b#PMH_|eVWKu_p{xq&UA7xY#(D_fMU z%b+jxgL>stWt;MuqAyA5U4=)FlH&5(zLnVbX=!|%=VbgUHz6Aasf`L&w!g6-Fce1P zo(#iaIE;YpVI+)Fb|^cQUCM4{kFs|qjDa0sEdDt@}9A=qBtRu|7^1zN&Fdr7cLRbWgVMkb^98wM|UnpNHUnxhFqpHr! zunX)8yLG`%M_qkwRdrwG^Dmu+p6FD_j(gPYaPupVxJ8{sD9igH!Crd(eR zx4^CNQ@BmJq1;q%Dfe;Rvb6?y2A+MljpyMrB5GEsLgDFlq zP%7EK^-!{U7XhM7my7{K8r{l-w{K^dZ^OUwGr^?^H-phPl!0}h%+t>S=uS;rNW}I1W z|2CR|=6kv_UB|z-QFeNl<00mv)@8a>Rj_XVB8Fk+BDUrjFQ-{jXWqg(+FZi^f7}ap z?~taL3piqMW$)7YzWI*x--vfLTKBen8}4LtxfaHP;2v*ZpJu-9W*kyc@b>jt=Ib76 zlhnH2rpM%9BGB@0B6JNX!eiLL%8Y6}vR7ABrVgziT3Z?T4iJ;SiGX*RuCu8hjOp$C zcFiVF69M1}`8i6(l_#+U2 zKp+Bb5eRA`HxrBSOvNH{8?h9|;(vD{poW~1(hh+T?3W)<|AkVJlgO*Z)@ z0`1h$84o$+Q5*u9+yLwfm|OtW4X_w!@-+D^Vc$T0gFt8lc?N+n99~=>VS8L+Z&V9^YJ2l2L*5{7t3_{;w-AUzAo}g19sAS_>|JLp z7-C;aJ|KTn;XfoFk&nrr$tUD54Vg0>ub)M4$wLP6%{vqB@xApc1G=Dv4M` zr6AD7LPs|QdLmG+>O-$LgcPWR;HtV>2Q~0}&Y1M2&BzQfulUNZEbq<~Mn_W%6OqzAQ)+F_<-yNQw!Z$ED8Gt@rn zh|0)*>Hu|+Iz)X=9j3mZzNEfFU=#wQ5g3EOSOng~jtl|{0+^|BP1Mn5MoyUf42665 zcnc%%Tl&o8H!5;jCFBYM6D)*W|4$XUOWjk+_z8iD4b*)EJ}{Hfk$O!1VkYB>iHu3A zfPXcq$cO*J#`_j>f2aO1lkmz!!bk5sW@14DH3DWqLux3EMnh|~8b-rvI1P`$#|TVC zU>X9`5txC%OazPw%tByxlSVYNps_NupurB_919EcEG#Utu%Pk8ENEIHFt?cnjn99v zpz+rPViq*mQh(B*!IpY{GYgs!O*n?52_><2w*V8-sEMGkC%F(4@lO`u%w`re9W?PK z7Bq1t78YX`G!Z897UG&!`>9FQxE$<^c`uoQs?1R4=oh5%O5 z6$oG@U4_8vCQU&z3muzT=z{QMNAvKp*22Q3H!M`DEa0BD#==6?f3h%GgZp%Y26wY{ z4VpTHr%uenhi15DlnUp9W~50MHek)xj8QwrMqJ`am6NLmX(pHfk2e9{{7wlI-pQI- zD&CJYQ#2oIrfQ~XrfX(sW@@m2w<7Q<0^1Py3<2DAb|A15fn5mfZqm$d#`{S#-bD!P zvEbcj!Tb3eyiF?JH3;mr;9dWpct6#ArsBnK-ru0XZ$4ngTcp{o*=NSP*M#?=ispcd z_s~CuPH(jc{R_& z5x`F!LEtC?#}N1$f#V3AK;UGP=3+Akm(3PYa~*+G77nm2Xts#oy&>VDO2Q)qPFqNL z@}DHU(7aSh_#J_78#K7np0SYd7Y#8Snow2$tg8AnNeoBe9G+w7FB0e&Iu?^a zcR=8F1C9IakIf{|Npz}8Lb6K29TN#@DhYT0m4w+A5_0H#GYPmiV-oJEB&4Y%+_jKU zLibcj=tOs>yU<_aip%Zz&=G| zzq*k=jbTG86YMh>Hnjd%*bvWWo0c!>i}WQkY^>54wyg^Lj0ziCn_>5)Z_p1^*f;50 z^lkb_`VM`U{)xUv<9P&o1RW4`M9>LAX9QgkY=NLFf^JRp!)7L)(7(`6iAD4?1l=u6 zcp<1quoZS2Ve4itvb6wnp@j%~G;^WVU@o+@R;zvx#86tAzZGvQ@V&068Gu&O>M$W% z8A0y`trdbkW^mjY5l~yL9ialQ(GJ!Q(bj6~wDsDd z+F{z^2*x9rfM6nmNeCt*n1Wy`f@uh*H)%&U10HMEdM!dQ!vZ+VqV@T2@P4e~or++l z1uveX{J#T6?L6JIhqW;bXTAedvpyF}Y)#)~}>EZ|%f&2klQ9xicZsFSOssS>rc!T#F74NqQ;&nh%;HEwIpLj26uc&x0BUsj;y^3H@ zGu|TYP3@0nythqw%T+Yk$RpV6pMxE#So+69?ayWou&u^Q-uvyROkSS$H-=C-c&>e+ z{ayP~`%3$V_D}6=?OzD?L9j1^{Sd4|us?zW5FCi$AOx$M7+~gr(GUyN7>HpJtg&!V zhu0xZ9E@n@Ad9iX95C2i3~uItal#xh&WwxtL2w9ywdQYZ>$JM?=EgHE8Qen~7>u#L zf$>2Q2RUjORK&Dm)M%G!ty()gdW1JJ0eH-V!~bo}qiZeIg)pk8Ox|R|OkCiV{ozc2 z%HVKZFV+WlCWcAHTreG&SSF5%XA+o1CW%RAQV<-C;25J)Y3JX>q%~vDVzTK`7<(Rq z6D-&#A^0&Kuv870`UZVB6@7OE-?yMIQ_=Ti%GD2o6A}Et{EgAO=zJ{A?Z@<2(PQ#I zY+x|?lg;Q$nHt6v*j`|;8;mty4PcmhlhK~?PgT(E^osX*CkkXnF=Nd<;9w5x#I$#w zH+ewJc;;i3hzZR5%tYn`W)kxuGnx5_nS$U91ZN^>L~s^@vk{zw;9LafA^1rXGqstR znP$t!;Cu5e#4LJa`5K#fNn;vSUX~%az{1N)m6ug8R{bEjP#yp97iPuE!pR0^lgi0P z1Q$0jn-N@M(THt~DYCu5Y&UVTRF&;6RkjWPqy)aHZa;I#%)~(x6U*Ly%1p!&oKt~` zILaJjzGjXyCzzAWDdsfu4T38W#6$lo1Xm;2gy0$k*CMzM!SzkdnPwu+Hxuy#f*UME zY<@!oUVbyr5HNRCBJLu%(L%(1Oawg&6Y)r$A$YD5vB^Y)WFg`y^Gqe;R|K~-Fux(V z)l7sd^OE@!LtpC`j5pJS_ZY^@CaQRknDIImu-#O=g=`U9%ywi;*iLL` zwhPvg26nOFqLz^5t$+YtQ8!oZIIWMDsgP-OtC()|YZ5P}cP47jmh zvPV@0zET;$K?i2wnCjQ!;6u&xdGxW98+#gO$*E?Y{nmu{XKc<`9H3$!_K_KI*+urI z3ix~W2lf(snZ3eZWv{W^d(krlaW8s~;0pwQNAP76d#f4nUG^vT9S|O4_B#TH6kvt*=M2d)%5Q*~;bxm9wGia`@ zS;|}pBCVQ1lQzv#CLK+XLqT#JM$E+{(z+QjmxK}1qhXBt!J!*QtbVT8;@)-_|r1bbVs`dYA>Ba~2(I9|m% z0g*lytRMWBLUU8O=_=A`i1cgVW*}1EEZN!IJTua{CZw&@&UsAjoMv6McjXpy4Q9#W zNj8j14NKlB(SlpW;YIZ(ZZ+4$t>M;k>$vsY25uv_36TLt_t7{I<+e0K`>Yw-E<{>l z5VE}mnmGi)(7sfmeT7I%1i~HrPiWt8xW6@U-y$-yfjf)v+NkQ4`4nH^elSB*Efpf8 zaX;iPtNoC~5y;@|N{qmOSm(3jDK5Gd}NK05kTEdbPp2H;Y zxIM0Oa9IR72nJP@5{F`Nu9?lbC?A+R(bQ3$rIt*@{yPXK8O$I+wmcMC?Cd$ z^AUV|L>3{k7?B+jS%Sz;i0q8WE{N=k$Zk!1l$iuR);w_Wm?=xFLY7(vF0#U6w)tF@ zg*-%Bf)&2-zf^(m!go_S!0#$+;JYJI4OTD*1wHu+jD{~)?N>Rbp^@*c+OJ;!Hf}Xq zDCo}*GE*?nM1dNr@V!;yaDbyypy%uOp*U%VuSaB`27VYK`@NHuz?+wZ$-c(-Q(_$W z_jpAuY(QjH1CJ2dU(K;`!Z|WdzNR>ge_zFlbFXoRxHC4L_Qn zW^_n(b0l%HF}9a|5jpS-KZBo%3uf>}ewHyx?-#1WHgu3F(T<hPUCD@C|A^mm+d-1K)_q+IK;%GA$~T zL&|jB@w$4hacGfUSAGq@l?YtTujSYA>-i1*Mt&2&ncsrQIz(b}h9VM^gZUnT$dQN~ zwVMBw-^PE&Z|8ULJNaGwZbXho{3?fkje-4r3RF37!5rfMy5xq0&D+gsH*O}SA z$bXL^jyIYPSCX{yzU3 zVZVldz(3?4@sIhR`6v7@{8Ro{{uv@CBl06ePC?|yh@6T@Y7;UBIhD<9wI+M1ZTkokxLMXxm<&3E1f&AQ1AphRtPNxFTq>z5quGe@vcJTT7(ze z$*szaX3~UKLV#LlYoU$ckH`i@VxccvCIkv?g&;&ON8}1bu2hNiH4fh7W{jFQ-5^8? z9scc^SRqbr$7)12ncCqMZ;tec0*{V~L#qb%w!AY{$o#kGvxIB`55wyaxgL=laAJ78 z&RjuZln34)QG_$=(<{q+8@u_7#?#q!oKPfm`j>i$1wt30tAbmP$DqxMzJl=ZfrQ7m zLMb5&WkOGNt3dDa`tq%_KIvy~Ah(#5K-XL~g^pA@VasZeJ+`!Wdz&Fa+ly#$XPy<3a8~@%g- z;hi1{IE!*vRsBfg=uI}ps!i`1gi*M4qlGbQ>(tyzoJ@AQpU1s1nTXtJZsB`^!Q7b2 zM&Ui8vb4CSclk(<@_LWph^U}o-93|L3**6#2Etk)|0m%O1k)}7e62yiYKfa*F8T4B zlK8g)zkLQUXY%5_31Jp7ZVmj2C=%x41hk7d@$3;!F1rcw2r4Tr5P48}rrr<&ociZ^Mif;kU_JXEHu91$==P0J?B?Q&CeMFxZ@gAEjoy*4DMHs~j|} z%J{H5_s-slBJ-TEuu|AS1g;WR39E%BVU4g>SSMiZIE=_I5KiMVkw+1EY?ZK4 z*hDN6wg{`$zJc`dxwO!Pi!BV8Wzy5T}os?Xk<#efW+j) zgn;nmc0myl!6`wJ$q`11+h}kaJ-S^u&h^D;LHGAQUxvafJJIEDv7;h=Cx z_*^(Fd?9=(d?g$aaBEH=@+2ZpA@VfB*(D_QPOw!vi^y|$-;HowI3b)AP6?-lZ}6`( z3ifxuL*z?DzCtAS3;seBz}N6bS=?eTenpH$_pS=JaQdQfO}H-H5N;y!JW@xri-`Pw zxo{g_z9Za4F7N8}Cs2X2m!dmm2tOC$(;ymKSRc+}m+xXE2> zD^j8wI*1xX-fR%Hh`eRG=|+pZD2Sr*p}Q+K4A^$w&a(modYSUmgM!WiNKzV|m4ngC zBZ_RK1!F&tE@7wpIDL`!GDKDX0l%H_Y_zs*w6XDOwj@NOoxNB55c4mu_(_WCuLehB zfTz2mOlS4(UI3g;r?Vv(!V2$*3dCELvhcq4BBC?Vi|9>^#=F_a;XN+P@!pir@ILiD z#20v{`ZvV)#3j7X;}-D>$mX{|VEz~HsCwr=U}fr-qE58J#xZ5YU}Kt>H!WI=Hh3f% z;x$#@%(7@FVyoRK+Kbp`V*<h(%?V9?oJd)A?W#wJ`3s=8YlNu7-@dx}lYp1rgC* z^d|z>i5{Y-*i!Toy+t35gT!jFMjR{-5o^Udv0faCC=H@$ zL}`r&XS>9#6NkfCailm(94(F!$BOUaUy6vZ38Ad8pG~duJ=#Y2QFel8vszYxC^ zzY>p#M~xpl708GRMwBe5HqsjL~lrN(E5QWv=3J(U=)mWj5Ym)JvtcuDg9Ztq8 zCwhrLh?k5t&K{I_8F!=_XZK1=oma77&LgU|Dgb@yyItK<=9YL{E#r@<0P}0!EoQO^ zma_NE^|dwCXUz9^Fz9f`wUhX>_(c3ge2P*03LV8~;&0?Ym?OTxXE)@Czf%oFcd9|m zz$%ZEBx~z&!emm-z@dYxbB7MPnqiZ#_K)p&fwkCYj7I`hNXcw5t(`Yf+``{Lj0tEoUhr)zTsflNvYj-$`HjoO*WzCU-U0V+0i#ER2Wxs<0unTaxcE~NiG>j2(k9c??lGx~7s56>nB}<$xJ>0x_;pN|cfim4K+k|7rQV+SaUBQl?q2 zl1zG~IY*VUwwqR!FPyB*L35 zqf(Q!2I0I?N}ZW_(Z$V0+8}LK3;b`>sI*nVjF;p4SzUcPyxAxE|GD2$+9~bELy)u! zQI&6PcubNGNMGTAMLH-Ql0KIXOJ7J|BC0RK$*WWqqWU9h0HOxsZI2Spnv}klj;q@q z5j9Blo2wC3i)ZKbM!fUU_wPF&rSocUydYhazDE=m^I${`QA|5~Iq8~o-8{hH&E8Rl ze=6H;=||~~bQdezZFp0{reOr4#vkud?Y=#XxkV>4SQGHepP$t zGwC-(4M)_d|0&yT>7{rck6XC?qZX$Q=#UzQO74KwPL9U$1BF+JajM!GbtT7Ioe@(f zw^HRKS>4oy`uzj1y%yN zw~S5KY(&j@qXeSYzuIVdpjqB?|1R%$?6ZZ(p|U}h?l5_{JVG8RkCI2rW8|?iR@nK7 zT7am9h+2fG#fVyhsHKQ%KvZLstTan^f_Y(Ho`k4n7U`~dvoKFJsWE_aQO#C*WFSbB zaopV?V+6}BGM=YS{Qm3eyrp$ZWb8{e$oR!88)R&MR#~LHQf^YEyh@ewYE{Ziy(;A? z7AY6X8|5u#DdTluEaf#=%1pf~<$o^Sn+6wohrF{)XZQCprKrBVVnCz33%d$Q(ZRv; zUilDq3FLk9e))iW5K$WtwGmO95Vd)^{JDG>#>m(RZ9&v_JTpS=#1>{nbcaCsgp3!r zm&+&RQ}Su~8$@kI)TfBrhN#b$6FxYvV>ov4CF~G*sgAc%7xSKtd|AGVjh=i3Q9Bw; z`#bc;h8P!vd`tcjUpM>X@*PC&YM%3u?_qyjzAryO)NVxWedEN)kL9QT;#JH02p<`n zl?|#_y+_IMiXR>HwlgljlwbeLV-fOx!bb-%X!W^$>T{#6nVvJvLFqI?&pazC^W89* z*7_P3bck}78J6P(QId65);6|w_709t&Mqxn+}u4pTY7o>7+-d1&3DZ$!cKc)Ee^|! zrLmDAy0YA&PF2;tYldf+kE|J5Ux(*H{zlG!2J;ut@+z#XYI4;>cwS9O{LU?3I zKtyUpLO^J6`=o%xgv53Mk>N@0!Xi^r+a)F?n|03OAHB8Nzim)(yU=jspNz9rLx{pO zgyFMIbZ6Q}21iB57(2uVYfJ~880+H0sQ84$B;&exZ|lV5|DE!Yniia%k!idUALlM& z<&yE7{QoiQV~kH|VTe!2&BGhq-{!h8H~HK6go46%&eCWsNG=T;5z(i8L}>eVy(%KY zf=sgz&V)D73ZJ?cflu1&PmCZGe9FcWVii6cV>><}?>pir;u+w9JwEI%5CnmC%}3p} z2azBebO3R{kciK_O9kop(1f0#4?f0j8dwH)fUDp+cnxWM44ot1sNDh|MCXC`oVLP8 z&vk*_)Sbq7pRN(k!)M8@!)M3s!>7ibg!k}9O$l$(v?c?|G%}m)h7W|2ngB3xNu**9T`>2DZ zTImQrFX#&PTW;W!f_{`9OHZVy*r9kX{Vvp2b>q|qI1=`>pXS%1Q=aAU8pWx*IpN;i_xX&igZ=F z@wzp-!@3i?OS;RtA9W9Pk9ALUPj%0%2rJ&o-pb3$+senv&nn2OgH^g!rd768u2sHO zp;Zs7GOKc{3ad)1zE)LMGp!68tPWY-wFcIbwVkztwUf1rbxUh+YhP=ul>m z*2AnvT939KYdzU|n)M88qxC%N`PK`q7h5m4-eP^!`aA0%tS?(%wZ3KjqxD_ud)7Z& zzp?=~zBX-bLTx(OWZLA|8)Y=$qrr1oinQk-FW|qwyn|U@XY*ra;nrznE zthd={v)N{=%|4rBHrH%k+IreX+os#%ZMe4GZA)!?+V-;TZChhI%JzNR>9&h(7uzne zZLr;7yVG{J?Oxmcwg+uLw>@cl+V)%9v$o&aUaP3$g2BS8Hdmn`k%5ZnE7J zJEPrfySa9s*e$SIWB0Y)6}vljKifUEGd#0_Po7lZ*6aDZ*T8t?`H3BpJbnJ z-_gF4eHZ&u`=0i_?0ehyw;yUh+J341F8iK3G2Ai9F~u>>F~f0}<5!MH9lv%w;pFEO z>J;wO-YLpyqLa~SzSBad#ZF6|Ryj2}t#w-Ow9)Cb(-UV~XIEzr=a$ai&H>JW&Oy$R z&gss1&Yhhrod-JCI)CUq$9a+S66XfzWzL2*&g+~vIB#;^;=J2=pYs9dL(X42A9p_K zeB1dK=ii-QIsfVWmkaH}xNt6li{#SQCEumaWsHl#1-XoOnd0)X%QTnOF56u8xa@N| z;Bv_2sLR(bCtOaseB*M(<(kV4ms>45w8(6c-6FR|ev54_4z)Pk;>#9CT=lMDuCcE1 zu8FS62G>;AJl6u(BG-~1+aR|Zw;^tI zZbRKpx}A5s<#ylgq1$7(CvGp?Ub_9^_S&6r*SbsYA?|tZecWr@Yu)SJhq;e;pYA@> zeU|$i_j&H~-50tyxvzC!@4nG}v-?)}ZSLFMFS)<)Ft~f9cnt9P$m3&=IUaL8KJi%K zvD{;;$2O1c9y>jDd+hbt?{U!MbC2U5-+5f{4E5~bnde#JS?1Z#v%hDP=N8XTJ%4Wr zTT(64TNbn|YB{szf|iR~UT*ng%e!8!yxMscdUf#{={3!3q1O_x2CwB_E4@~Go$xy2 zb095!!r1+%y6#Mk>Df21!sqm@v zsrDJ{Q|nXjGt6g%&uX9ZzO-*!-wfYU-@d;6eFyqh`x<#ePfu8vU00t@K;%x5jUs-$uVJ ze%t(Z`0e)F=XcQWu-{jH$NWzCo%TE9_nqHGze|2s{ciZ(*0(;IPTL-odYW;renXPBF zp3{0>>mOS`ZT+nE^VYw&DQQ#Drm{`nHdX#D{oDEn`-k|4`A_hl;cxUe%=Vw>f7Sni z|0DmO{htP;1r!IA1auDQ7O*8?f55?j&jY>;9259q;75TU2Tl)s82B>qkHFV$LEG}S z)olm2t!+EB?U!xOv_04MeB1AX+61)^iVBJeiVK<>v^;2K(CVPILB9rrU@}+}%mkMP z4+tIe zAtCRDC?VrQ-VZq&ay{f`$nB83p>d(vp}C>?p+%t^LU)Jm4c#AlD9kp@Gb}VLA}lJb zLs)!RQdnwOMp$-OURbZN%CNp+Rbd0ds>23{)rQrF4G$X`HYaRb*u}6{;qKun;Z@;= zN#U!)H-&Ev|15k*_`&dF;m5;IhMx}qHvDY(_3&Hacf#+5KMa2yAw)PuxJ7tIct^B~ zXcG|_5fl*mxQrY>oIVVrRsj zi2V_VBF;rzi1k&62Zb#gSxEJxDJ!@#MZ=c=1y8X=dJKA4r|0>cs(ks$8 zvQ=c8$k50Rk#Ug;kx7v$k!g{|k)0yDM)rv88QCk+5IH4sM&zu>xseMamqa#3E|1(A zxhHaO5m~jXWQDDe`LMjmTS(Posz^n<)Dzr>GWD?olnHe4_MGZK49B5~7l$ zQlrwNGNTMRQTb6tQ5~Z?M|F)F9yKRwSJb6wBHA}PGrB5zQuK`IS*$lwr=uT6zl{D1FVJdYxEL`;7h@gc8RH!j5Ysj$CMF>! zIVLS8J0>rtFs3-BB4%*R_?U??AI40HnHDoMW_HZHm<5KI#W9;>K8^V-W=G7fn7uIv zVh+U|j`=F)Xv~itG#y%X$m&qjVRna|9WHcu9!tcMv2-jGYZdDp>l*7G+cMTW);Crk z8y4F>Haa#oHX$}CwrA|1*xJ~ku_I!~#u{SB#ZHJd#?Fad61y&TbL^+F+hg~{?u$Jb z`+4lQu~%b%iG3DpcoF+5_H`VHqvEu2T$~u^5$6@>6XzG#D$YMHFfJ&rU0hgPL|k!P zUEJKbopG1r$#}o`)cDHy>i8k?_3^{v4e^uWC&y2TpBg_serEiV_{R7Z@vGz4#;=b* z7JokeQvB8U8}WDI@5Miie;ofh0VGHXHVO6#P6=)ao(bLwzJ`Rbgv5l737r$VC6p$V zC-hF}o6tXDP{QDZ@d*2T6lNym~-B%Mw=lk{WK zPf7Qa9wt3b`X%Ytq~DTWB)v-dGub&gGPy^xA$eKy(d36ILQ0#I(3FUjsFawLl$6|* z{FK6!;*^q<&MB2C{Za;`RHqC{sY{ujvM8l7Wkt&Bl=UeaQ?{ghn)10J<;#>aDHl?H zNV$@7Gv#*5-IRMNzo*ivPN^+Y-BVkp`lRYp+oT4j2B(Imrln@4W~b(+=BE~=c1-P* z+9kDnYH8}|)cL9VQm>^^X|2<8(*~tYNt>NEFKt2EqO_H18`CzYZB5&jwmofU+LviZ z(~hT|O8YkLY}%8w*Xd+BozA8kq;y@nO}bsWce-DCXnJINOnO{;a(ZfdMtW9y*Yv*W zqteHwE9v9YC#HXxJ|%rx`pop%>8sP%rms)mn7%pv)Aa4>JJWZk?@K?BemVV*43CV& zj6NAtGB#zL%6OFVJmY1?pBaB;GMQGHHko#r4w+7wE}8nwHkpB$!I`0%;h9B-%$}K* znf)>cWDd@(%N&|HJab~^hnaIS7i2EZY{*=hxjJ)g=K9P%nMX4(WnRs^k$F4wZsz^W zN10DDf6aWJ#bt?Ea+Xz=O_qI@Q}}bHvcJkcmVF}o+w61M=d&+n z-_5?C{UZC%93qFzVRE<}F-OjE%W0Dno0E`}oRgN5nUj-~pHq}mlG7z;U`|cWkes@l zp*bURM(2#pG31QPnUK?vb0FtdE}h#tH$S&N*Ok$JIs33d1LdYyzlca=UvUao_90v$Gp3F z_wpX(Jeo7GxLX7UUQ7 zDCk*GQP8KLs$f9Dq=MN6^9vRgEG<}3u)1Jv!TN$d1^Ww*7kpE2w%~lhrGl#kHwtbQ zJS`*&Z3^uRoeEnNx)-)A^eNOAwkZrOOejn)Of5_=%q+|)%r7h|>{!^juxsJ)!a0Sz z3NIBAh9cjh%%ZBINkub?W);mX`lP6_Xl>DkqRmC07Hu!uS+u8UU(we^CyTx*I$LzU z=wi`t#bhy4%oj_=HpOXQ!t&07N!;0G%rxa%v=M?7`cP#Ey+_kuS@qpqH#UB+< zEuK+4t9Wkl{NhE$ON*BkuPokKyr+0y@qyw)#a|R3DK;D{K3;sP_?zNK9mS5p9g8{+ z@3^Sr!H(BD{#C-1@Fh}-uEeRNWr=r*Z;8I7b%}pTWJyd(TuEX{N=aHt?~)-U!%9Y$ zj444S<4Y!%Oe&dM@=3|clC>opN;a2#R{5YvR8Dnm8OkjysB_#l0t$ z;wXrsh@yVniX!fvaAa^vI5M~-92sOCIjs|SwI(4+4GGy~9hZsX9#v86s$xZ`h;`)ZKNHf3X+CY zNivd5Bn!z(Iz_rlx=H$-)JS?jY9Y0f+DQM9-jly3cPIBE_azS^4z_9*kD7<& z9m%WDJD+zkuOaVh-krRbyoY&@@*d|s$$OUfKJOFI3Fr!R1LA?vKn9Qn%m8Kq^MQrH zVqghC0sx>0C`J zKw(e{DQpUl!lwu+yD2)#FO(`uHN{D(p?E2N%5lmm%2mou%I}m$$^%LZrImuVQU0NR zMIA&PN*zHRNlm7Xp{7vNsOi)UYBn{8noC_qT|r$d=(Y~Uk z(pJ!lX%)1Cw8JzVO;4+)d1!uGEiFWg(&}i(Xvb-nX;*32X}4&1XpOXY^ltP7dQW;E z`at>+`fz$8eLQ_4eL6~CL|;l@L0?VZKqu4l=~Q|#T}IzU-%CG0KSbBiE9pkMiEg3W z=u!GndOiIF{S^Hy{Q~_W{WAS3{Wp4hL9c?z1?vmS3XBCO3!1^s;J088us7Hj90ra8 z$AT$f8aM%*2xfqD!1-V{m;){amxCNo0xCch#6WZ_xE-tjcY}KH7tjs*!CEi`)`7>s z6W}TEH?Rrp0N;S`z>nZ(Mi)jLBc74K=*dW8jAD#o{J=qdnLC)fn0uJ}nLjZPF%L5>OdHe5tYP|?0hD=#d5_u5 ze8_BLK4Z2sUou~@y0W^l`mqMHhOrV^$*j?=A6TiZ>8wR8GAo}&V}UFdtBA#A!7L%G zl(m($gH^%W&DzU4z&gY_%+j*-EF&w%y36`pm{gcu$SvGcSW|eZ@Mhufg^h)O6h10! zFML_}s_;$W+rszI*AV(G)C1}b^@9dL8PFVPA+#9Eg;qjqpmop&hy_7VDO3h2AQajR zZGpB!J0UG(g(6TLR1ckm&Oqm(i% zB6<;4R9$qjsGZ%5J%OFYp242Qp2N;zuV$}huSeM%*__as*iYFXIPsieoJ39%XB1~FCzUgvGm$fy zGnKQ1vy8KXvx>8Zv!1h&L*@V+Du>Qdaw<9XoMvt}ZW?zLm(ShJ{h6!f>baFc%^EUIg@^B0LiQ9v%fxf-~VPcm_NRo&)E@ zY#4@xa4B2{D_|8|4)1~Y!#Y?GJ75p&hil;o9D|R+$KfmRJ-8k2fZxFH;E(WUeiwcm zKc1h!Pvj@@lli0hWBIB4H2wtsME+#{6h69!FXSKO2l;meodu%>3k3`TPrw(H2ucM? z!4|=G!A`+$!Ct|Bfl*)*SOhkKQ{Wa{5Zn?p3hoP<1&;)e1y2Rf1)qeSggu0Pg#(0x zg(HOD3BMPP5>6J*6|NO-5R!%YLYfd1vV=uKt`HWgg`0(2gxiEWgu8@$P~kq|0pTIx zVPUQCy6|nu(306D%#v*-){-+N4JFq~Zj{_AX)1YK@}%Th$=@X}N;;5ENLQpA@(t1* z>4}U(rXjPCxyS+}2gya2BP$Uq@Xi92Vadf0m4vERhsRwo3L&4oD734oi+m91^$0Bk@ac2_ZQtIU_kQxhQFnT$MbR ze2{jMc9nLMCP;fodrSLDlcb}hlcZCn)1@<|^P~%;i=;WyjZ&smB9%#%(sC)fNxDV4 zU0NaCBi%2xNNrMw)FrKv`lPs&kcOmDX`S?r^j+DAvN>gpvh8K=vWsO;%3hWIQ}({> zqbyF=Q`TG7SJq!PP&QaLTK0o%oNR(@l5DbUm5d?-Wh_~dtXL+HmB>nEn`A%A_RD^j zX=QquNoJN=Wp-Ieb{dtPll>~YEW0ZEP1Yo9mi;MvBp)tMk*CSi|CG1OUn@E*zEvbEQWXmnWJRHZt>7v6 ziV{VsLao@O_))P<@ksGX8K;a_CMbI<`zZS>2Puat(GkiC%1O#hWtMV=a+Y$ga)EM@ zGDit2VWnDGsdOmolnu&z%2wqgai2pY3v+!0lSLb!J0KoG|M#WH4F_$ zBh;ugJ2ksC`!qjke%5F;dW}Ql)_632R8y-7YQmbRrb!#8P1lmOpq8UWv|=r)-J;#8 z)oLrX7OhR|(7Lo?ZA^Pqdt7@;dq&%!y{5gcy{WygZPGStpXfU2y6WO|@w#ty-F3Zm zeRTtLgLOl7!*waTak}xkiMqo&iw@TXbrD^iu3mRicSd(!cUyN?hyI~!(zWPXb#1!8 zbWe33DrZ)*D)(0UD=$|**2n4l>PPE;(2vtk&`;85>a+AS^t1GH^=tL(^&~x@r|Jvz zOg*G$>v?)uuh##hx9Ow$27ROcr6JDH&oI)EVn{Qj8!`-246_aM3=0j54Y`J82EJjF z;h>?`aKi8_YPf8;YPfE=WoRbI)qsyF5Y^H6iLd6apKIo-U-ywaR+rkO!A%UopUn0K3hHXk-? z%~fWvIbbHtVRO`6XTEE0Ge0x8n>);J&F{@0&Hq{kTBcdDEmTW^g=v8-97{235m*q5 z*ivRuSWpXQ(OC?ZUo2IYYKz_CvUn_h3vLNoB9@rtsO4Jq*VU=jQ>sbT^6FjHf$9_0 zcdFa1!>m78$5|&>Cs{MCQ?0qywN{c9uu`pbYq7P|DzVC}O6z9pR_k_ag>|>J(rUNH ztY@qZ)<$cKwbhC~wm!9XSl?LRT0dAn*?QRq+s50{Z8L3iY|CuRZ7Xc6Y=BK*+hp5s zv)GQ?PT9`dF4!*FuGqWS6YTx%gX}}?BkUvX-`mseGwgHi3+#*ROY9Uo&0b{RYOk<6 z?IC;AUT3ejH`p8P_wCL0hxT{&4~}?8f}@9{w__~oNO7!jupKJLeuu>oa$IseaQx|L zbv$-FalCT&bPjN)JF}fDoMldx)9&;;Yn>ry#Cg_v#rd1_rt^1aqw}G&&H2Rn-1)-U z;riM&!jYC-6>ssJiT;cE{*FKSCy;UWp_DU7hP@c?rt>E zJ=49)o$r>pmF{vk=Kj&W&ArpT+r7_S?Y6sJZjamV#@%)96YkUQbM6c7TkbpVd+sLp zGk3fDrTcYF_nIL!!)v~)NvcV$nOl=x1JtN%d^IO)F4nZvwAFm}jPxXX#&}XZX`XaX zh9}dLv?&_Z;_}^qldW z^St(U@%Hfc_V)7*^bYY3_m1_Zdegk=-VE;)Z%n) zd*6CLct82N`@Zwd^)2x&^R4u)_ECKdAIk^%cs{J=clr+d^gg5Sh_Bjb^ErKP z-!ysJ0)qp?0*Qg7KyqM0V0vI-V0BgQ~CHxA04Zn`x#DB-{;`i|Tcr*TIZRgsNwF_$tYj@Oo zYp>UK5PgYZL?V$yBok;FF@=~$%phhFbBKAw3Su>}j@U@#5&1+Jv4z-4>?ZaRhX@U! zBlLue2opz%aB(m;MU-dU`0?9tPC21CN$^?`h$2d7`z<38~h{qAlMRY4|NT7 z3w;yn9_kh98yXNA92yo%3{47UhNgz5g=U0ih31A9gt9|9q1+G@+7fbvE{58}1H&`I z zxJdsBzarg~+8y zL*#a(Ir1zT7wsDz7EO#MMMp))MkhuyqM6aD(P_~cQBqVCJskB#k4BG2Pesp0&qsfa z-j6hc`%6>s|5tzee*ir+JT3qL delta 28153 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

B29!EDb&5f|yGGhrE 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 0){ - [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; - } - if (bt.isConnected()){ - IOBluetoothDevice *device = [[dSelector getResults] lastObject]; - [connectedLabel setStringValue:[@"Connected: " stringByAppendingString:[device nameOrAddress]]]; - [connectButton setTitle:@"Disconnect"]; - [ANCSlider setEnabled:TRUE]; - [focusOnVoice setEnabled:FALSE]; + // give it some time to connect + int timeout = 50; + while(!bt.isConnected() and timeout >= 0){ + [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; + } + if (bt.isConnected()){ + IOBluetoothDevice *device = [[dSelector getResults] lastObject]; + [connectedLabel setStringValue:[@"Connected: " stringByAppendingString:[device nameOrAddress]]]; + [connectButton setTitle:@"Disconnect"]; + [ANCSlider setEnabled:TRUE]; + [focusOnVoice setEnabled:FALSE]; + } + else { + [connectedLabel setStringValue:@"Not connected, connection timed out."]; + } + } else { + [connectedLabel setStringValue:@"Not connected, device selector canceled."]; } } } + - (IBAction)sliderChanged:(id)sender { [ANCValueLabel setStringValue:ANCSlider.stringValue]; if (ANCSlider.intValue >= MINIMUM_VOICE_FOCUS_STEP) @@ -65,6 +74,7 @@ - (IBAction)sliderChanged:(id)sender { [focusOnVoiceLabel setStringValue:@"Focus on Voice isn't enabled on this level."]; [focusOnVoice setEnabled:FALSE]; } + // send current settings auto ncAsmEffect = NC_ASM_EFFECT::ADJUSTMENT_COMPLETION; auto asmId = focusOnVoice.state == NSControlStateValueOn ? ASM_ID::VOICE : ASM_ID::NORMAL; bt.sendCommand(CommandSerializer::serializeNcAndAsmSetting( @@ -73,8 +83,11 @@ - (IBAction)sliderChanged:(id)sender { ASM_SETTING_TYPE::LEVEL_ADJUSTMENT, asmId, ANCSlider.intValue - ));} + )); +} + - (IBAction)voiceChanged:(id)sender { + // send current settings [ANCValueLabel setStringValue:ANCSlider.stringValue]; auto ncAsmEffect = NC_ASM_EFFECT::ADJUSTMENT_COMPLETION; auto asmId = focusOnVoice.state == NSControlStateValueOn ? ASM_ID::VOICE : ASM_ID::NORMAL; @@ -84,6 +97,7 @@ - (IBAction)voiceChanged:(id)sender { ASM_SETTING_TYPE::LEVEL_ADJUSTMENT, asmId, ANCSlider.intValue - ));} + )); +} @end From 302a09f903d36cfa4a4cedec1dfada0cdd9b0c5d Mon Sep 17 00:00:00 2001 From: semvis123 Date: Sat, 2 Jan 2021 17:59:16 +0100 Subject: [PATCH 25/55] Makes the application quit immediatly instead of going to background --- Client/macos/AppDelegate.mm | 3 +++ Client/macos/Main.storyboard | 4 ++-- .../UserInterfaceState.xcuserstate | Bin 57606 -> 61069 bytes 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Client/macos/AppDelegate.mm b/Client/macos/AppDelegate.mm index 2bab817..5559526 100644 --- a/Client/macos/AppDelegate.mm +++ b/Client/macos/AppDelegate.mm @@ -17,6 +17,9 @@ - (void)applicationDidFinishLaunching:(NSNotification *)aNotification { } +- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)theApplication { + return YES; +} - (void)applicationWillTerminate:(NSNotification *)aNotification { // Insert code here to tear down your application diff --git a/Client/macos/Main.storyboard b/Client/macos/Main.storyboard index 0dda3a4..200f949 100644 --- a/Client/macos/Main.storyboard +++ b/Client/macos/Main.storyboard @@ -132,7 +132,7 @@ - + @@ -236,7 +236,7 @@ Source: https://github.com/Plutoberth/SonyHeadphonesClient - + diff --git a/Client/macos/SonyHeadphonesClient.xcodeproj/project.xcworkspace/xcuserdata/semvi.xcuserdatad/UserInterfaceState.xcuserstate b/Client/macos/SonyHeadphonesClient.xcodeproj/project.xcworkspace/xcuserdata/semvi.xcuserdatad/UserInterfaceState.xcuserstate index f5c8139776a48910cf8adb3892432507ba4c11a9..1c7c8fe7b63e7f4c6bde8f1e8d3a6c989198cd19 100644 GIT binary patch delta 27941 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 J(y3+ne*q3QbDjVI delta 25165 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 CzE Date: Sat, 2 Jan 2021 19:44:12 +0100 Subject: [PATCH 26/55] added bluetooth permission to info.plist --- .DS_Store | Bin 0 -> 10244 bytes .../UserInterfaceState.xcuserstate | Bin 61069 -> 62694 bytes Client/macos/info.plist | 2 ++ 3 files changed, 2 insertions(+) create mode 100644 .DS_Store diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..58b15a0fabade78dfc3154c20c4ca6fbb1b8e5d3 GIT binary patch literal 10244 zcmeHMU2GLa6h3Duuv-?`mICGS(+ia!<%%toLJfr5+ZI~>T6$aBQlRX;yR;kj?v~xX zEl@C3i9RU$X87^V7&YQg6ak+!CK}WS6Cfdwpb{T^!Nh2U7ZW_Qv$wPt@W}v)JIU;s zIWuQw=bP`$&ddS;CbC*3KokH(icBgpJ?;}&Ig9rMA<#@BiDVC8f!Ac(>6B@w?x`Ir zLIgqtLIgqtLIgqt9tQ;Io6UmAzTaU85eN|o5g3gCTOXnnnT!W=m`i`@pof11AXz|a zKTw*^0lrN%knuncbLpE>oBZ^Efhh(@4CLli9%a=@#sfLbB{v7;=72%Z7@Sbh@15+T zes#b&m*F!+AVlC^1lYHK0@Q&C2IzU`cjiiQip%c!fl_&OQ-f}QaMu4e)o&WES5a{V zg>ePrCrlK@!otGIg}ah{_F&Rey{wy1oo<$EQN6xYkZ!YWb0n>%wj26jk5W=+Tb^oI zy5k!gnod=Ab{Ljs4<_uarMZ4PNnRj|k|gygr9(s2RjXprRV$CgqC=Gx)itqb)r#sP zMHMtUF^Bz~G3Un^NuE4q zs!~)ut*E4E`t<2DW==1iHEVW{GA*U1_w_pLh3jn7b`oY*?=;f3l{60Not}QcV~HN6 zIImu-uI;|7YCG6ZbxQ6k{I)hYx^8v%I)>J~cdx5^ojuA_H|^M_*6s>LuT4D;5YEm0teU%BcU+S9*mriRj-y(=dg9w-({COL-RraMr_ zIXiAqZaS}Fz*&DXBW>;5JLIkh!Zdd99ckOlW-PZyDN3tmI%}$)UTd0cYDt$rDWj%6 zuc&i}YdaoIE;ZJpC|Or;)u}CGK(D73-4Ws_D1A6(=A8KppL(XMW^H2qrsm6xd~%6A zqhr8ujg+ak4;q@+*QL5?-O^}Ic95f3p0U@^9jORoQk$h_^vlIc(bUpekw|AYW$e!y z-a(~Y6nR_oB2h{COx&qa&s%JbS!#YsWM1S6QS4^=I!C7`SIdhdPfCg^wz)KF-b74Z zCMmAewvW7)n^wvzL`9R@eKK)XwY*wXHc1@=oP%6hBCipp&a|D$&`Y~qw=PmEDi_4v ztmDn9>oxc57WK`BP&Y3U>0L_h2>BWn_&+) zFa*coIJ^&M;4GYjZ{P>G0@vYJ_yhigTW}lx#_>1>6)eJHoQ-pE9+qJYS7J4;!aCfH zTd# z2bHbg(AXqzdVD?TDqpZmXt9nmM_RQeKEgOo&>Sa6bKR%+7^m>*?NcD1n&ert=ggJM z+KK=Afqak5d8#sz`J;H5)tp&nhw$v8#gv^u-odj=V`XKEKu*cC6_sVOGLBqM z@@*%@%H$xqx<;0j0&+cGvUV9d|ZrA z6M@%ZE!JZLt|t<2!z8x(MBYO*PNRkyw28_Nk@+w_hr{?hzJRabt9T6GAVQzSQ}`yn zjql*Q_#S?OXYeeZ!}It#eudu?v9IE_Jlbv^OI!RUpSA-@$1-iJm-OsoF_B!fi8ekB zu$4YJ4WoWrux-z2iletZ60}myT5{|yB$q)3w6PXgnrATqT<}1pXh1rz?$Lj%J8DyP zA?IF?YEw0HXsD*9G8SE3!!}hl%Pa1`r#epKq42;x729)-!6R=jeCzNLA`l`FA`l|* zun-u>JBqS9fQASE|9@Do6ZR7#5F+ph5Ws@^WPO4<&RwG9zXQ8#k5b%2kp)(7m`mS; w9{zPaN&h;YGVD6uKP!_icQ$5randt6%q68LJoKLdbb}S1|HJeD|M~p?53`-1x&QzG literal 0 HcmV?d00001 diff --git a/Client/macos/SonyHeadphonesClient.xcodeproj/project.xcworkspace/xcuserdata/semvi.xcuserdatad/UserInterfaceState.xcuserstate b/Client/macos/SonyHeadphonesClient.xcodeproj/project.xcworkspace/xcuserdata/semvi.xcuserdatad/UserInterfaceState.xcuserstate index 1c7c8fe7b63e7f4c6bde8f1e8d3a6c989198cd19..3b07a5b1c432caec25a6d0a7b4c14e59a9d32fa7 100644 GIT binary patch delta 30096 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.app-category.utilities NSHighResolutionCapable True + NSBluetoothAlwaysUsageDescription + This app uses Bluetooth in order to connect to your headphones. NSMainStoryboardFile Main From b6bd7ade8be6f019ea95f8cf85ed57b6c4ff0e91 Mon Sep 17 00:00:00 2001 From: semvis123 Date: Sat, 2 Jan 2021 19:49:09 +0100 Subject: [PATCH 27/55] Added bluetooth permissions --- Client/macos/info.plist | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Client/macos/info.plist b/Client/macos/info.plist index ef9892b..9f24237 100644 --- a/Client/macos/info.plist +++ b/Client/macos/info.plist @@ -16,6 +16,8 @@ public.app-category.utilities NSHighResolutionCapable True + NSBluetoothAlwaysUsageDescription + This app uses Bluetooth in order to connect to your headphones. NSMainStoryboardFile Main From 389062b6120ad813e75ad8f00addfdfee03c67fc Mon Sep 17 00:00:00 2001 From: semvis123 Date: Sat, 2 Jan 2021 20:02:36 +0100 Subject: [PATCH 28/55] Added compile instructions to the readme --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 0e05b29..efc1a65 100644 --- a/README.md +++ b/README.md @@ -75,6 +75,10 @@ It shouldn't be too much work to add support for a new platform. Open a PR if yo Use the provided solution file. +#### macOS + +Navigate to the `macos` folder inside `Client`, run this command: `make`. + ### Adding a new platform There are two platform dependent parts in the code - the GUI and Bluetooth communication. From 4ad157410a2e67424d429acb0b8a803df079010d Mon Sep 17 00:00:00 2001 From: semvis123 Date: Sat, 2 Jan 2021 20:06:54 +0100 Subject: [PATCH 29/55] removed unnecessary frameworks --- .../project.pbxproj | 6 ------ .../UserInterfaceState.xcuserstate | Bin 62694 -> 58280 bytes 2 files changed, 6 deletions(-) diff --git a/Client/macos/SonyHeadphonesClient.xcodeproj/project.pbxproj b/Client/macos/SonyHeadphonesClient.xcodeproj/project.pbxproj index 3309027..f3dfdc2 100644 --- a/Client/macos/SonyHeadphonesClient.xcodeproj/project.pbxproj +++ b/Client/macos/SonyHeadphonesClient.xcodeproj/project.pbxproj @@ -7,7 +7,6 @@ objects = { /* Begin PBXBuildFile section */ - A87B3287259FAA3300EA6551 /* AppKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A87B3283259FAA1400EA6551 /* AppKit.framework */; }; A87B328B259FAA8B00EA6551 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A87B328A259FAA8B00EA6551 /* Cocoa.framework */; }; A87B328E259FAB0E00EA6551 /* IOBluetoothUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A87B328D259FAB0E00EA6551 /* IOBluetoothUI.framework */; }; A8DC78EB2576923D00447738 /* main.mm in Sources */ = {isa = PBXBuildFile; fileRef = A8DC78EA2576923D00447738 /* main.mm */; }; @@ -24,10 +23,8 @@ /* Begin PBXFileReference section */ A87B327A259F69BA00EA6551 /* Constants.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Constants.h; path = ../Constants.h; sourceTree = ""; }; - A87B3283259FAA1400EA6551 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; }; A87B328A259FAA8B00EA6551 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; A87B328D259FAB0E00EA6551 /* IOBluetoothUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOBluetoothUI.framework; path = System/Library/Frameworks/IOBluetoothUI.framework; sourceTree = SDKROOT; }; - A8952E6C259F698D00B30ED6 /* Constants.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Constants.h; path = ../Constants.h; sourceTree = ""; }; A8DC78E32576922700447738 /* info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = info.plist; sourceTree = ""; }; A8DC78E62576922D00447738 /* SonyHeadphonesClient.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SonyHeadphonesClient.app; sourceTree = BUILT_PRODUCTS_DIR; }; A8DC78E72576923D00447738 /* MacOSBluetoothConnector.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MacOSBluetoothConnector.h; sourceTree = ""; }; @@ -58,7 +55,6 @@ files = ( A87B328E259FAB0E00EA6551 /* IOBluetoothUI.framework in Frameworks */, A87B328B259FAA8B00EA6551 /* Cocoa.framework in Frameworks */, - A87B3287259FAA3300EA6551 /* AppKit.framework in Frameworks */, A8DC790525769A6600447738 /* IOBluetooth.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -99,8 +95,6 @@ children = ( A87B328D259FAB0E00EA6551 /* IOBluetoothUI.framework */, A87B328A259FAA8B00EA6551 /* Cocoa.framework */, - A87B3283259FAA1400EA6551 /* AppKit.framework */, - A8952E6C259F698D00B30ED6 /* Constants.h */, A8DC790425769A6600447738 /* IOBluetooth.framework */, ); name = Frameworks; diff --git a/Client/macos/SonyHeadphonesClient.xcodeproj/project.xcworkspace/xcuserdata/semvi.xcuserdatad/UserInterfaceState.xcuserstate b/Client/macos/SonyHeadphonesClient.xcodeproj/project.xcworkspace/xcuserdata/semvi.xcuserdatad/UserInterfaceState.xcuserstate index 3b07a5b1c432caec25a6d0a7b4c14e59a9d32fa7..176c36ad1d78eaa783a9add45fddfba52f1be6ab 100644 GIT binary patch delta 28818 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 delta 32326 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 Date: Sat, 2 Jan 2021 20:10:28 +0100 Subject: [PATCH 30/55] Delete .DS_Store --- .DS_Store | Bin 10244 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 .DS_Store diff --git a/.DS_Store b/.DS_Store deleted file mode 100644 index 58b15a0fabade78dfc3154c20c4ca6fbb1b8e5d3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10244 zcmeHMU2GLa6h3Duuv-?`mICGS(+ia!<%%toLJfr5+ZI~>T6$aBQlRX;yR;kj?v~xX zEl@C3i9RU$X87^V7&YQg6ak+!CK}WS6Cfdwpb{T^!Nh2U7ZW_Qv$wPt@W}v)JIU;s zIWuQw=bP`$&ddS;CbC*3KokH(icBgpJ?;}&Ig9rMA<#@BiDVC8f!Ac(>6B@w?x`Ir zLIgqtLIgqtLIgqt9tQ;Io6UmAzTaU85eN|o5g3gCTOXnnnT!W=m`i`@pof11AXz|a zKTw*^0lrN%knuncbLpE>oBZ^Efhh(@4CLli9%a=@#sfLbB{v7;=72%Z7@Sbh@15+T zes#b&m*F!+AVlC^1lYHK0@Q&C2IzU`cjiiQip%c!fl_&OQ-f}QaMu4e)o&WES5a{V zg>ePrCrlK@!otGIg}ah{_F&Rey{wy1oo<$EQN6xYkZ!YWb0n>%wj26jk5W=+Tb^oI zy5k!gnod=Ab{Ljs4<_uarMZ4PNnRj|k|gygr9(s2RjXprRV$CgqC=Gx)itqb)r#sP zMHMtUF^Bz~G3Un^NuE4q zs!~)ut*E4E`t<2DW==1iHEVW{GA*U1_w_pLh3jn7b`oY*?=;f3l{60Not}QcV~HN6 zIImu-uI;|7YCG6ZbxQ6k{I)hYx^8v%I)>J~cdx5^ojuA_H|^M_*6s>LuT4D;5YEm0teU%BcU+S9*mriRj-y(=dg9w-({COL-RraMr_ zIXiAqZaS}Fz*&DXBW>;5JLIkh!Zdd99ckOlW-PZyDN3tmI%}$)UTd0cYDt$rDWj%6 zuc&i}YdaoIE;ZJpC|Or;)u}CGK(D73-4Ws_D1A6(=A8KppL(XMW^H2qrsm6xd~%6A zqhr8ujg+ak4;q@+*QL5?-O^}Ic95f3p0U@^9jORoQk$h_^vlIc(bUpekw|AYW$e!y z-a(~Y6nR_oB2h{COx&qa&s%JbS!#YsWM1S6QS4^=I!C7`SIdhdPfCg^wz)KF-b74Z zCMmAewvW7)n^wvzL`9R@eKK)XwY*wXHc1@=oP%6hBCipp&a|D$&`Y~qw=PmEDi_4v ztmDn9>oxc57WK`BP&Y3U>0L_h2>BWn_&+) zFa*coIJ^&M;4GYjZ{P>G0@vYJ_yhigTW}lx#_>1>6)eJHoQ-pE9+qJYS7J4;!aCfH zTd# z2bHbg(AXqzdVD?TDqpZmXt9nmM_RQeKEgOo&>Sa6bKR%+7^m>*?NcD1n&ert=ggJM z+KK=Afqak5d8#sz`J;H5)tp&nhw$v8#gv^u-odj=V`XKEKu*cC6_sVOGLBqM z@@*%@%H$xqx<;0j0&+cGvUV9d|ZrA z6M@%ZE!JZLt|t<2!z8x(MBYO*PNRkyw28_Nk@+w_hr{?hzJRabt9T6GAVQzSQ}`yn zjql*Q_#S?OXYeeZ!}It#eudu?v9IE_Jlbv^OI!RUpSA-@$1-iJm-OsoF_B!fi8ekB zu$4YJ4WoWrux-z2iletZ60}myT5{|yB$q)3w6PXgnrATqT<}1pXh1rz?$Lj%J8DyP zA?IF?YEw0HXsD*9G8SE3!!}hl%Pa1`r#epKq42;x729)-!6R=jeCzNLA`l`FA`l|* zun-u>JBqS9fQASE|9@Do6ZR7#5F+ph5Ws@^WPO4<&RwG9zXQ8#k5b%2kp)(7m`mS; w9{zPaN&h;YGVD6uKP!_icQ$5randt6%q68LJoKLdbb}S1|HJeD|M~p?53`-1x&QzG From 229ec3541ee64470fa977bfa8f245254aaf10215 Mon Sep 17 00:00:00 2001 From: semvis123 Date: Sat, 2 Jan 2021 20:11:06 +0100 Subject: [PATCH 31/55] Added compile instructions to the readme --- .../UserInterfaceState.xcuserstate | Bin 58280 -> 58280 bytes README.md | 4 ++++ 2 files changed, 4 insertions(+) diff --git a/Client/macos/SonyHeadphonesClient.xcodeproj/project.xcworkspace/xcuserdata/semvi.xcuserdatad/UserInterfaceState.xcuserstate b/Client/macos/SonyHeadphonesClient.xcodeproj/project.xcworkspace/xcuserdata/semvi.xcuserdatad/UserInterfaceState.xcuserstate index 176c36ad1d78eaa783a9add45fddfba52f1be6ab..7227dc98d8b4358d440acd72630bdb59b1375f85 100644 GIT binary patch delta 42 ucmZ2+oO#7@<_()fSnI?*t8Z@JF7lHf#B8{-d8^8)IuJA2Z*$9H6$b#0brJFa delta 42 vcmZ2+oO#7@<_()fSZh!1TY7) Date: Sat, 2 Jan 2021 22:23:30 +0100 Subject: [PATCH 32/55] We do not need this for the native ui version --- Client/macos/makefile | 70 ------------------------------------------- 1 file changed, 70 deletions(-) delete mode 100644 Client/macos/makefile diff --git a/Client/macos/makefile b/Client/macos/makefile deleted file mode 100644 index 3bd7d67..0000000 --- a/Client/macos/makefile +++ /dev/null @@ -1,70 +0,0 @@ -# -# You will need GLFW (http://www.glfw.org): -# brew install glfw -# - -#CXX = g++ -#CXX = clang++ - -EXE = sonyheadphonesclient -SOURCES = main.mm -SOURCES += ../GUI_Impls/MacOSGUI.cpp ../GUI_Impls/CrossPlatformGUI.cpp -SOURCES += MacOSBluetoothConnector.cpp BluetoothWrapper.cpp -SOURCES += TimedMessageQueue.cpp CascadiaCodeFont.cpp CommandSerializer.cpp -SOURCES += ByteMagic.cpp -SOURCES += ../imgui/examples/imgui_impl_glfw.cpp ../imgui/examples/imgui_impl_metal.mm -SOURCES += ../imgui/imgui.cpp ../imgui/imgui_widgets.cpp ../imgui/imgui_demo.cpp ../imgui/imgui_draw.cpp -OBJS = $(addsuffix .o, $(basename $(notdir $(SOURCES)))) - -LIBS = -framework IOBluetooth -framework Metal -framework MetalKit -framework Cocoa -framework IOKit -framework CoreVideo -framework QuartzCore -LIBS += -L/usr/local/lib -lglfw - -CXXFLAGS = -I../imgui/ -I../GUI_Impls/ -I../imgui/examples/ -I../ -I/usr/local/include -CXXFLAGS += -Wall -Wformat -std=c++17 -stdlib=libc++ -CFLAGS = $(CXXFLAGS) - -%.o:%.cpp - $(CXX) $(CXXFLAGS) -c -o $@ $< -%.o:../%.cpp - $(CXX) $(CXXFLAGS) -c -o $@ $< -%.o:../imgui/examples/%.cpp - $(CXX) $(CXXFLAGS) -c -o $@ $< - -%.o:../imgui/%.cpp - $(CXX) $(CXXFLAGS) -c -o $@ $< - -%.o:../GUI_Impls/%.cpp - $(CXX) $(CXXFLAGS) -c -o $@ $< - -%.o:../GUI_Impls/%.mm - $(CXX) $(CXXFLAGS) -ObjC++ -fobjc-weak -fobjc-arc -c -o $@ $< - -%.o:../imgui/examples/%.mm - $(CXX) $(CXXFLAGS) -ObjC++ -fobjc-weak -fobjc-arc -c -o $@ $< - -%.o:%.mm - $(CXX) $(CXXFLAGS) -ObjC++ -fobjc-weak -fobjc-arc -c -o $@ $< - -%.o:../%.mm - $(CXX) $(CXXFLAGS) -ObjC++ -fobjc-weak -fobjc-arc -c -o $@ $< - -all: $(EXE) - $(MAKE) clean_app - $(MAKE) package_app - $(MAKE) clean - @echo Build complete - -$(EXE): $(OBJS) - $(CXX) -o $@ $^ $(CXXFLAGS) $(LIBS) - -clean: - rm -f $(EXE) $(OBJS) - -clean_app: - rm -rf "./$(EXE).app/" - -package_app: - mkdir -p "./$(EXE).app"/Contents/{MacOS,Resources} - cp ./Info.plist "./$(EXE).app/Contents/" - sed -e "s/APP_NAME/$(EXE)/g" -i "" "./$(EXE).app/Contents/Info.plist" - cp ./$(EXE) "./$(EXE).app/Contents/MacOS/$(EXE)" \ No newline at end of file From d25e369c78e6071be5fe0a2144fca3fb5ed1668a Mon Sep 17 00:00:00 2001 From: semvis123 Date: Sat, 2 Jan 2021 22:26:31 +0100 Subject: [PATCH 33/55] Delete MacOSGUI.h --- Client/GUI_Impls/MacOSGUI.h | 20 -------------------- 1 file changed, 20 deletions(-) delete mode 100644 Client/GUI_Impls/MacOSGUI.h diff --git a/Client/GUI_Impls/MacOSGUI.h b/Client/GUI_Impls/MacOSGUI.h deleted file mode 100644 index 19c7ed9..0000000 --- a/Client/GUI_Impls/MacOSGUI.h +++ /dev/null @@ -1,20 +0,0 @@ -#include "imgui.h" -#include "imgui_impl_glfw.h" -#include "imgui_impl_metal.h" -#include - -#define GLFW_INCLUDE_NONE -#define GLFW_EXPOSE_NATIVE_COCOA -#include -#include - -#include -#include - -#include "Constants.h" -#include "TimedMessageQueue.h" -#include "BluetoothWrapper.h" -#include "CrossPlatformGUI.h" - -static void glfw_error_callback(int error, const char* description); -void EnterGUIMainLoop(BluetoothWrapper bt); \ No newline at end of file From f2c63f3171b2cedcec637d08c451b0786e73d9f6 Mon Sep 17 00:00:00 2001 From: semvis123 Date: Sat, 2 Jan 2021 22:26:41 +0100 Subject: [PATCH 34/55] Delete MacOSGUI.mm --- Client/GUI_Impls/MacOSGUI.mm | 90 ------------------------------------ 1 file changed, 90 deletions(-) delete mode 100644 Client/GUI_Impls/MacOSGUI.mm diff --git a/Client/GUI_Impls/MacOSGUI.mm b/Client/GUI_Impls/MacOSGUI.mm deleted file mode 100644 index f02f646..0000000 --- a/Client/GUI_Impls/MacOSGUI.mm +++ /dev/null @@ -1,90 +0,0 @@ -#include "MacOSGUI.h" - -static void glfw_error_callback(int error, const char* description) -{ - fprintf(stderr, "Glfw Error %d: %s\n", error, description); -} - -void EnterGUIMainLoop(BluetoothWrapper bt) -{ - // Setup Dear ImGui binding - IMGUI_CHECKVERSION(); - ImGui::CreateContext(); - - // init GUI - CrossPlatformGUI GUI = CrossPlatformGUI(std::move(bt)); - - // Setup window - glfwSetErrorCallback(glfw_error_callback); - if (!glfwInit()) - return; - - // Create window with graphics context - glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); - GLFWwindow* window = glfwCreateWindow(GUI_WIDTH, GUI_HEIGHT, "Sony Headphones App", NULL, NULL); - if (window == NULL) - return; - - id device = MTLCreateSystemDefaultDevice();; - id commandQueue = [device newCommandQueue]; - - ImGui_ImplGlfw_InitForOpenGL(window, true); - ImGui_ImplMetal_Init(device); - - NSWindow *nswin = glfwGetCocoaWindow(window); - CAMetalLayer *layer = [CAMetalLayer layer]; - layer.device = device; - layer.pixelFormat = MTLPixelFormatBGRA8Unorm; - nswin.contentView.layer = layer; - nswin.contentView.wantsLayer = YES; - - MTLRenderPassDescriptor *renderPassDescriptor = [MTLRenderPassDescriptor new]; - - float clear_color[4] = {0.45f, 0.55f, 0.60f, 1.00f}; - // Main loop - while (!glfwWindowShouldClose(window)) - { - @autoreleasepool - { - // Poll and handle events (inputs, window resize, etc.) - glfwPollEvents(); - - int width, height; - glfwGetFramebufferSize(window, &width, &height); - layer.drawableSize = CGSizeMake(width, height); - id drawable = [layer nextDrawable]; - - id commandBuffer = [commandQueue commandBuffer]; - renderPassDescriptor.colorAttachments[0].clearColor = MTLClearColorMake(clear_color[0], clear_color[1], clear_color[2], clear_color[3]); - renderPassDescriptor.colorAttachments[0].texture = drawable.texture; - renderPassDescriptor.colorAttachments[0].loadAction = MTLLoadActionClear; - renderPassDescriptor.colorAttachments[0].storeAction = MTLStoreActionStore; - id renderEncoder = [commandBuffer renderCommandEncoderWithDescriptor:renderPassDescriptor]; - - // Start the Dear ImGui frame - ImGui_ImplMetal_NewFrame(renderPassDescriptor); - ImGui_ImplGlfw_NewFrame(); - - // perform gui pass - GUI.performGUIPass(); - - // Rendering - ImGui::Render(); - ImGui_ImplMetal_RenderDrawData(ImGui::GetDrawData(), commandBuffer, renderEncoder); - - [renderEncoder popDebugGroup]; - [renderEncoder endEncoding]; - - [commandBuffer presentDrawable:drawable]; - [commandBuffer commit]; - } - } - - // Cleanup - ImGui_ImplMetal_Shutdown(); - ImGui_ImplGlfw_Shutdown(); - ImGui::DestroyContext(); - - glfwDestroyWindow(window); - glfwTerminate(); -}; From 793250ff2fc27231b5531583be6c6ba33f9c64af Mon Sep 17 00:00:00 2001 From: semvis123 Date: Sat, 2 Jan 2021 22:42:24 +0100 Subject: [PATCH 35/55] added entitlements file --- .../macos/SonyHeadphonesClient.entitlements | 12 ++++++++++++ .../project.pbxproj | 4 ++++ .../UserInterfaceState.xcuserstate | Bin 58280 -> 60252 bytes 3 files changed, 16 insertions(+) create mode 100644 Client/macos/SonyHeadphonesClient.entitlements diff --git a/Client/macos/SonyHeadphonesClient.entitlements b/Client/macos/SonyHeadphonesClient.entitlements new file mode 100644 index 0000000..e9da8e1 --- /dev/null +++ b/Client/macos/SonyHeadphonesClient.entitlements @@ -0,0 +1,12 @@ + + + + + com.apple.security.app-sandbox + + com.apple.security.device.bluetooth + + com.apple.security.files.user-selected.read-only + + + diff --git a/Client/macos/SonyHeadphonesClient.xcodeproj/project.pbxproj b/Client/macos/SonyHeadphonesClient.xcodeproj/project.pbxproj index f3dfdc2..d99e93a 100644 --- a/Client/macos/SonyHeadphonesClient.xcodeproj/project.pbxproj +++ b/Client/macos/SonyHeadphonesClient.xcodeproj/project.pbxproj @@ -22,6 +22,7 @@ /* End PBXBuildFile section */ /* Begin PBXFileReference section */ + A863B14925A11DF500101F3B /* SonyHeadphonesClient.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = SonyHeadphonesClient.entitlements; sourceTree = ""; }; A87B327A259F69BA00EA6551 /* Constants.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Constants.h; path = ../Constants.h; sourceTree = ""; }; A87B328A259FAA8B00EA6551 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; A87B328D259FAB0E00EA6551 /* IOBluetoothUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOBluetoothUI.framework; path = System/Library/Frameworks/IOBluetoothUI.framework; sourceTree = SDKROOT; }; @@ -65,6 +66,7 @@ A8DC78BB25757BF300447738 = { isa = PBXGroup; children = ( + A863B14925A11DF500101F3B /* SonyHeadphonesClient.entitlements */, A87B327A259F69BA00EA6551 /* Constants.h */, A8DC78E72576923D00447738 /* MacOSBluetoothConnector.h */, A8DC78E82576923D00447738 /* MacOSBluetoothConnector.mm */, @@ -301,6 +303,7 @@ CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; + DEVELOPMENT_TEAM = ""; INFOPLIST_FILE = "$(SRCROOT)/info.plist"; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", @@ -325,6 +328,7 @@ CODE_SIGN_IDENTITY = "-"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; + DEVELOPMENT_TEAM = ""; INFOPLIST_FILE = "$(SRCROOT)/info.plist"; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", diff --git a/Client/macos/SonyHeadphonesClient.xcodeproj/project.xcworkspace/xcuserdata/semvi.xcuserdatad/UserInterfaceState.xcuserstate b/Client/macos/SonyHeadphonesClient.xcodeproj/project.xcworkspace/xcuserdata/semvi.xcuserdatad/UserInterfaceState.xcuserstate index 7227dc98d8b4358d440acd72630bdb59b1375f85..ac977b0ea4de63123edcfdb9e5225dfb3373e730 100644 GIT binary patch delta 28636 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 From 341d870f919a262d4111f804ba0a76ad713c2de1 Mon Sep 17 00:00:00 2001 From: semvis123 Date: Sun, 3 Jan 2021 20:22:59 +0100 Subject: [PATCH 36/55] set the windowsize to a fixed value --- Client/macos/Main.storyboard | 4 +++- .../UserInterfaceState.xcuserstate | Bin 60252 -> 61827 bytes 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/Client/macos/Main.storyboard b/Client/macos/Main.storyboard index 200f949..6aa66a3 100644 --- a/Client/macos/Main.storyboard +++ b/Client/macos/Main.storyboard @@ -131,8 +131,10 @@ - + + + diff --git a/Client/macos/SonyHeadphonesClient.xcodeproj/project.xcworkspace/xcuserdata/semvi.xcuserdatad/UserInterfaceState.xcuserstate b/Client/macos/SonyHeadphonesClient.xcodeproj/project.xcworkspace/xcuserdata/semvi.xcuserdatad/UserInterfaceState.xcuserstate index ac977b0ea4de63123edcfdb9e5225dfb3373e730..294de3138fab0c1aec6ecb59134ec7d14428ee6a 100644 GIT binary patch delta 28540 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 bhc*vy9?_iiKj5`%*Z+Oc`~Us_x0(5Wyl_Nd delta 27307 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%0AXU&OXbYYyZZ+ z)y}c=?S*!+9kR>p#dek5Y$xqDyTe{(ciS1e*Ir`}+QarA?7ukPcMNwdb3hKtvD)jao2I*@yzkN<1fcsM=RBi>OiGY8B`|Kj~YM?qNY)cs9b6VwTfCtZJ_e00!oNc zAXP$Xs4_}V87VVGQZ~v@C8^_71Jy{Kq|Q+1sY}#P)K%&R)k3|Z-cY|&e^PI$)~a?@ z9je~1>QXhdYF-tuil|CdU8?%S*~dBAInz1EIp4X^ndjW#%y$+zw>Y;tw>crF%vtPI zIZC1e~3}6N^gPCk*EHj> &jH zY0Q_*Muy82GGeBPkuwTL#gs5c#>~)+kMT1hrk;s0NoEIglsV0uV=gk6nV*?!%&*L2 z<|*^sv)r@EQ|J+UAdk#b>`{48kJ?k_ad?~_+T-!mc!HjYr`{9yBt1=@A3eW%J9v9~ zhj=G@=XrCz%Q0`BcY}AMH{XkRwO*^&=Cyk%Z@?S&)_G&zgm=65xc9cV+561<-21}& zkFS%ji?6G%yRVn8kMCpOKwp+`ly8hL$2Y-e^Z9&!U(gq+d9Q6xnOW1XWIN#(BaUtaG&sm@bvJ^ z@SO0x@K@pW;Z5O!@HgT8;p5@6;mhGG;j7^r;d|kS;m6_T@bgHoNKRy7Brmc$vNp0l zvMmBdWRc>CDuPDTk+KLG!R(Q$h$})zn20x06JaBFYrEFw)aKR7YSCI#ZDp;kma28t zR@ZuK{k6f`cXRLG7IqPoJJ*azBKe~Q${nYy6dUbtS z{r~Du*Pn~_jD8&L9~~GS5gi@PiB5=4j!ubw9o-rQqeW3DD#fDeXjxPrC8DONCCWs1 zMUO=SIS@KgC*Nf5+R$yTnJwC&nkm=fzjX*T*--3*uYiyf_dS#f##ScsPD6 zel>nKjy;RNh`)~i9{(%;F5a5xmdHqCCi*1?BtA`imiRm|DlsOpE}>2ANE}EUOI%6Z zPdrULPrOXLNxV(8Cfg@FB|9h6lIh95$)U+n$+5}t$w|rS$(hMH$@$5J$-Lz1q#y|= z(WE+AmeeQBNiu0qRwZ3YU$QQhmP$`$VX0B6v8nN?NvSERX{i~hrK#nqywvK{+SK~g z##DYvoeHPUrT$_&uphF$*gouFb{IQ~oyLC2E?^h4OW9m@Bl|VGnf;dC#&TJZm9R1v zZuF;ca5!0?V36^ZEWH;@tc4qQPbt7yG{3-9yUGxcW=|a{lA^2`M3W+PfYng DrV~fD From 364ee1ace7260aff94ffd26b9e041752f4c07c28 Mon Sep 17 00:00:00 2001 From: semvis123 Date: Sun, 3 Jan 2021 20:26:43 +0100 Subject: [PATCH 37/55] increased text label size --- .../UserInterfaceState.xcuserstate | Bin 61827 -> 62614 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/Client/macos/SonyHeadphonesClient.xcodeproj/project.xcworkspace/xcuserdata/semvi.xcuserdatad/UserInterfaceState.xcuserstate b/Client/macos/SonyHeadphonesClient.xcodeproj/project.xcworkspace/xcuserdata/semvi.xcuserdatad/UserInterfaceState.xcuserstate index 294de3138fab0c1aec6ecb59134ec7d14428ee6a..1259a5a38c7b9d05d808eba473029bd463374dd7 100644 GIT binary patch delta 26827 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 From 3e1cd46218cd47bf7a0a17be5e9277c3472a997e Mon Sep 17 00:00:00 2001 From: semvis123 Date: Mon, 4 Jan 2021 14:27:37 +0100 Subject: [PATCH 38/55] Used condition variables where possible, and several other small changes --- Client/macos/MacOSBluetoothConnector.h | 9 ++-- Client/macos/MacOSBluetoothConnector.mm | 44 ++++++------------ Client/macos/Main.storyboard | 8 ++-- .../UserInterfaceState.xcuserstate | Bin 62614 -> 67765 bytes .../xcdebugger/Breakpoints_v2.xcbkptlist | 6 +++ Client/macos/ViewController.mm | 26 ++++------- 6 files changed, 37 insertions(+), 56 deletions(-) create mode 100644 Client/macos/SonyHeadphonesClient.xcodeproj/xcuserdata/semvi.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist diff --git a/Client/macos/MacOSBluetoothConnector.h b/Client/macos/MacOSBluetoothConnector.h index bb779be..d04bb88 100644 --- a/Client/macos/MacOSBluetoothConnector.h +++ b/Client/macos/MacOSBluetoothConnector.h @@ -21,13 +21,12 @@ class MacOSBluetoothConnector final : public IBluetoothConnector virtual std::vector getConnectedDevices() noexcept(false); char* receivedBytes; int receivedLength; - bool wantNewData = false; - NSRunLoop * runLoop; + std::mutex receiveDataMutex; + std::condition_variable receiveDataConditionVariable; + std::atomic running = false; private: void *rfcommDevice; void *rfcommchannel; std::thread* uthread = NULL; - int running = 0; - -}; \ No newline at end of file +}; diff --git a/Client/macos/MacOSBluetoothConnector.mm b/Client/macos/MacOSBluetoothConnector.mm index cb509a2..4914dd2 100644 --- a/Client/macos/MacOSBluetoothConnector.mm +++ b/Client/macos/MacOSBluetoothConnector.mm @@ -20,23 +20,16 @@ @interface AsyncCommDelegate : NSObject { @implementation AsyncCommDelegate { } - --(void)rfcommChannelOpenComplete:(IOBluetoothRFCOMMChannel *)rfcommChannel status:(IOReturn)error -{ - if ( error != kIOReturnSuccess ) { - fprintf(stderr,"Error - could not open the RFCOMM channel. Error code = %08x.\n",error); - return; - } - else{ - fprintf(stderr,"Connected. Yeah!\n"); - } +- (void)rfcommChannelClosed:(IOBluetoothRFCOMMChannel *)rfcommChannel{ + delegateCPP->disconnect(); } -(void)rfcommChannelData:(IOBluetoothRFCOMMChannel *)rfcommChannel data:(void *)dataPointer length:(size_t)dataLength { + std::lock_guard g(delegateCPP->receiveDataMutex); delegateCPP->receivedBytes = (char*)dataPointer; - delegateCPP->receivedLength = dataLength; - delegateCPP->wantNewData = false; + delegateCPP->receivedLength = (int)dataLength; + delegateCPP->receiveDataConditionVariable.notify_one(); } @@ -44,17 +37,14 @@ -(void)rfcommChannelData:(IOBluetoothRFCOMMChannel *)rfcommChannel data:(void *) int MacOSBluetoothConnector::send(char* buf, size_t length) { - int error = [(__bridge IOBluetoothRFCOMMChannel*)rfcommchannel writeSync:(void*)buf length:length]; - if ( error != kIOReturnSuccess ) { - fprintf(stderr,"Error - could send bluetooth command. Error code = %08x.\n",error); - } - return length; + [(__bridge IOBluetoothRFCOMMChannel*)rfcommchannel writeSync:(void*)buf length:length]; + return (int)length; } void MacOSBluetoothConnector::connectToMac(MacOSBluetoothConnector* macOSBluetoothConnector) { - macOSBluetoothConnector->running = 1; + macOSBluetoothConnector->running = true; //get device IOBluetoothDevice *device = (__bridge IOBluetoothDevice *)macOSBluetoothConnector->rfcommDevice; // create new channel @@ -76,11 +66,9 @@ -(void)rfcommChannelData:(IOBluetoothRFCOMMChannel *)rfcommChannel data:(void *) // store the channel macOSBluetoothConnector->rfcommchannel = (__bridge void*) channel; - printf("Successfully connected"); - // keep thread running while (macOSBluetoothConnector->running) { - [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:1]]; + [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:.1]]; } } void MacOSBluetoothConnector::connect(const std::string& addrStr){ @@ -100,19 +88,15 @@ -(void)rfcommChannelData:(IOBluetoothRFCOMMChannel *)rfcommChannel data:(void *) int MacOSBluetoothConnector::recv(char* buf, size_t length) { // wait for newly received data - wantNewData = true; + receivedLength = 0; + std::unique_lock g(receiveDataMutex); + receiveDataConditionVariable.wait(g, [this]{ return receivedLength!=0; }); - // wait until it has received data - while (wantNewData) { - // run the runLoop so it can actually receive data - [runLoop runUntilDate:[NSDate dateWithTimeIntervalSinceNow:10]]; - } // fill the buf with the new data for (int n=0;njoin(); // close connection @@ -150,8 +134,6 @@ -(void)rfcommChannelData:(IOBluetoothRFCOMMChannel *)rfcommChannel data:(void *) [chan setDelegate: nil]; // close the channel [chan closeChannel]; - - printf("closing"); } diff --git a/Client/macos/Main.storyboard b/Client/macos/Main.storyboard index 6aa66a3..efad2eb 100644 --- a/Client/macos/Main.storyboard +++ b/Client/macos/Main.storyboard @@ -184,7 +184,7 @@ - + - + - + ! This product is not affiliated with Sony. Use at your own risk. ! @@ -210,20 +202,24 @@ Source: https://github.com/Plutoberth/SonyHeadphonesClient - + - - - + @@ -231,8 +227,7 @@ Source: https://github.com/Plutoberth/SonyHeadphonesClient - - + diff --git a/Client/macos/SonyHeadphonesClient.xcodeproj/project.pbxproj b/Client/macos/SonyHeadphonesClient.xcodeproj/project.pbxproj index d99e93a..07168c1 100644 --- a/Client/macos/SonyHeadphonesClient.xcodeproj/project.pbxproj +++ b/Client/macos/SonyHeadphonesClient.xcodeproj/project.pbxproj @@ -309,6 +309,7 @@ "$(inherited)", "@executable_path/../Frameworks", ); + MACOSX_DEPLOYMENT_TARGET = 10.10; OTHER_CPLUSPLUSFLAGS = ( "-std=c++17", "-stdlib=libc++", @@ -334,6 +335,7 @@ "$(inherited)", "@executable_path/../Frameworks", ); + MACOSX_DEPLOYMENT_TARGET = 10.10; OTHER_CPLUSPLUSFLAGS = ( "-std=c++17", "-stdlib=libc++", diff --git a/Client/macos/ViewController.h b/Client/macos/ViewController.h index 841adbd..25e270c 100644 --- a/Client/macos/ViewController.h +++ b/Client/macos/ViewController.h @@ -13,8 +13,7 @@ BluetoothWrapper bt = (BluetoothWrapper)nil; @interface ViewController : NSViewController @property (weak, nonatomic) IBOutlet NSTextField *connectedLabel; @property (weak, nonatomic) IBOutlet NSTextField *ANCValueLabel; -@property (weak, nonatomic) IBOutlet NSTextField *focusOnVoiceLabel; -@property (weak, nonatomic) IBOutlet NSSwitch *focusOnVoice; +@property (weak, nonatomic) IBOutlet NSButton *focusOnVoice; @property (weak, nonatomic) IBOutlet NSButton *connectButton; @property (weak, nonatomic) IBOutlet NSSlider *ANCSlider; diff --git a/Client/macos/ViewController.mm b/Client/macos/ViewController.mm index c5b09fc..2aeaf16 100644 --- a/Client/macos/ViewController.mm +++ b/Client/macos/ViewController.mm @@ -8,7 +8,7 @@ #import "ViewController.h" @implementation ViewController -@synthesize connectedLabel, connectButton, ANCSlider, ANCValueLabel, focusOnVoice, focusOnVoiceLabel; +@synthesize connectedLabel, connectButton, ANCSlider, ANCValueLabel, focusOnVoice; - (void)viewDidLoad { [super viewDidLoad]; @@ -75,12 +75,12 @@ - (IBAction)sendData:(id)sender { [ANCValueLabel setStringValue:ANCSlider.stringValue]; if (ANCSlider.intValue >= MINIMUM_VOICE_FOCUS_STEP) { - [focusOnVoiceLabel setStringValue:@"Focus on Voice"]; + [focusOnVoice setTitle:@"Focus on Voice"]; [focusOnVoice setEnabled:TRUE]; } else { - [focusOnVoiceLabel setStringValue:@"Focus on Voice isn't enabled on this level."]; + [focusOnVoice setTitle:@"Focus on Voice isn't enabled on this level."]; [focusOnVoice setEnabled:FALSE]; } // send current settings From 5f196f27272115c4aa191344a5273f6fb534535f Mon Sep 17 00:00:00 2001 From: semvis123 Date: Fri, 15 Jan 2021 21:04:00 +0100 Subject: [PATCH 48/55] Used deque --- Client/macos/MacOSBluetoothConnector.h | 4 ++-- Client/macos/MacOSBluetoothConnector.mm | 15 +++++++-------- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/Client/macos/MacOSBluetoothConnector.h b/Client/macos/MacOSBluetoothConnector.h index e03f3df..14bd1f7 100644 --- a/Client/macos/MacOSBluetoothConnector.h +++ b/Client/macos/MacOSBluetoothConnector.h @@ -7,6 +7,7 @@ #include #include #include +#include class MacOSBluetoothConnector final : public IBluetoothConnector { @@ -22,8 +23,7 @@ class MacOSBluetoothConnector final : public IBluetoothConnector virtual void closeConnection(); virtual std::vector getConnectedDevices() noexcept(false); - std::vector receivedBytes; - int receivedLength; + std::deque> receivedBytes; std::mutex receiveDataMutex; std::condition_variable receiveDataConditionVariable; std::atomic running = false; diff --git a/Client/macos/MacOSBluetoothConnector.mm b/Client/macos/MacOSBluetoothConnector.mm index 9011fc6..3d18d58 100644 --- a/Client/macos/MacOSBluetoothConnector.mm +++ b/Client/macos/MacOSBluetoothConnector.mm @@ -29,9 +29,9 @@ -(void)rfcommChannelData:(IOBluetoothRFCOMMChannel *)rfcommChannel data:(void *) std::lock_guard g(delegateCPP->receiveDataMutex); unsigned char* buffer = (unsigned char*)dataPointer; - delegateCPP->receivedBytes.assign(buffer, buffer+dataLength); + std::vector vectorBuffer(buffer, buffer+dataLength); - delegateCPP->receivedLength = (int)dataLength; + delegateCPP->receivedBytes.push_back(vectorBuffer); delegateCPP->receiveDataConditionVariable.notify_one(); } @@ -91,16 +91,15 @@ -(void)rfcommChannelData:(IOBluetoothRFCOMMChannel *)rfcommChannel data:(void *) int MacOSBluetoothConnector::recv(char* buf, size_t length) { // wait for newly received data - receivedLength = 0; std::unique_lock g(receiveDataMutex); - receiveDataConditionVariable.wait(g, [this]{ return receivedLength!=0; }); + receiveDataConditionVariable.wait(g, [this]{ return !receivedBytes.empty(); }); // fill the buf with the new data - unsigned char *tempBuffer = receivedBytes.data(); - receivedBytes.clear(); + std::vector receivedVector = receivedBytes.front(); + receivedBytes.pop_front(); - std::memcpy(buf,tempBuffer, fmin(length, receivedLength)); - return fmin(length, receivedLength); + std::memcpy(buf, receivedVector.data(), receivedVector.size()); + return (int)receivedVector.size(); } std::vector MacOSBluetoothConnector::getConnectedDevices() From a4e329195350337a9ee4e5261c549c877d9dd6e4 Mon Sep 17 00:00:00 2001 From: semvis123 Date: Fri, 15 Jan 2021 22:41:27 +0100 Subject: [PATCH 49/55] Added remainder back into the deque --- Client/macos/MacOSBluetoothConnector.mm | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/Client/macos/MacOSBluetoothConnector.mm b/Client/macos/MacOSBluetoothConnector.mm index 3d18d58..ed35b87 100644 --- a/Client/macos/MacOSBluetoothConnector.mm +++ b/Client/macos/MacOSBluetoothConnector.mm @@ -98,8 +98,16 @@ -(void)rfcommChannelData:(IOBluetoothRFCOMMChannel *)rfcommChannel data:(void *) std::vector receivedVector = receivedBytes.front(); receivedBytes.pop_front(); - std::memcpy(buf, receivedVector.data(), receivedVector.size()); - return (int)receivedVector.size(); + // copy the first amount of bytes + std::memcpy(buf, receivedVector.data(), std::min(length, (size_t)receivedVector.size())); + + // too much data, save it for next time + if (receivedVector.size() > length){ + receivedVector.erase(receivedVector.begin(), receivedVector.begin() + receivedVector.size() - length); + receivedBytes.push_front(receivedVector); + } + + return (int)std::min(length, (size_t)receivedVector.size()); } std::vector MacOSBluetoothConnector::getConnectedDevices() From 7729787c011acba5e17e3a99e4afa986fae06bac Mon Sep 17 00:00:00 2001 From: semvis123 Date: Sat, 16 Jan 2021 00:56:36 +0100 Subject: [PATCH 50/55] Fixed the remainder vector --- Client/macos/MacOSBluetoothConnector.mm | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Client/macos/MacOSBluetoothConnector.mm b/Client/macos/MacOSBluetoothConnector.mm index ed35b87..205adfe 100644 --- a/Client/macos/MacOSBluetoothConnector.mm +++ b/Client/macos/MacOSBluetoothConnector.mm @@ -98,16 +98,18 @@ -(void)rfcommChannelData:(IOBluetoothRFCOMMChannel *)rfcommChannel data:(void *) std::vector receivedVector = receivedBytes.front(); receivedBytes.pop_front(); + size_t lengthCopied = std::min(length, receivedVector.size()); + // copy the first amount of bytes - std::memcpy(buf, receivedVector.data(), std::min(length, (size_t)receivedVector.size())); + std::memcpy(buf, receivedVector.data(), lengthCopied); // too much data, save it for next time if (receivedVector.size() > length){ - receivedVector.erase(receivedVector.begin(), receivedVector.begin() + receivedVector.size() - length); + receivedVector.erase(receivedVector.begin(), receivedVector.begin() + lengthCopied); receivedBytes.push_front(receivedVector); } - return (int)std::min(length, (size_t)receivedVector.size()); + return (int)lengthCopied; } std::vector MacOSBluetoothConnector::getConnectedDevices() From 7ed007c9b2231981f80113b9419a137db9589d55 Mon Sep 17 00:00:00 2001 From: semvis123 Date: Sun, 17 Jan 2021 17:04:42 +0100 Subject: [PATCH 51/55] Update info.plist --- Client/macos/info.plist | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Client/macos/info.plist b/Client/macos/info.plist index 9f24237..f2a1628 100644 --- a/Client/macos/info.plist +++ b/Client/macos/info.plist @@ -20,5 +20,7 @@ This app uses Bluetooth in order to connect to your headphones. NSMainStoryboardFile Main + NSPrincipalClass + NSApplication From daa83418211c9cf2c2a8b688c4bd810a2e10b2a1 Mon Sep 17 00:00:00 2001 From: semvis123 Date: Thu, 4 Feb 2021 11:01:36 +0100 Subject: [PATCH 52/55] Added a statusbar button for quick toggle, and small fixes. * improved isconnected function, it now also checks if the channel is open * fixed the timeout in the connect - statusbar button added - when pressed it changes between ambient sound and noise cancelling - still uses placeholder images (couldn't find great ones that are available on older macos versions) --- Client/macos/AppDelegate.h | 1 + Client/macos/AppDelegate.mm | 13 ++++++-- Client/macos/MacOSBluetoothConnector.mm | 3 +- Client/macos/ViewController.h | 1 + Client/macos/ViewController.mm | 40 +++++++++++++++++++------ 5 files changed, 45 insertions(+), 13 deletions(-) diff --git a/Client/macos/AppDelegate.h b/Client/macos/AppDelegate.h index de40df4..b932706 100644 --- a/Client/macos/AppDelegate.h +++ b/Client/macos/AppDelegate.h @@ -12,5 +12,6 @@ #import "MacOSBluetoothConnector.h" @interface AppDelegate : NSObject + @property (weak) NSWindow* window; @end diff --git a/Client/macos/AppDelegate.mm b/Client/macos/AppDelegate.mm index 5559526..5d09dc3 100644 --- a/Client/macos/AppDelegate.mm +++ b/Client/macos/AppDelegate.mm @@ -14,11 +14,18 @@ @interface AppDelegate () @implementation AppDelegate - (void)applicationDidFinishLaunching:(NSNotification *)aNotification { - + _window = [[[NSApplication sharedApplication] windows] firstObject]; } -- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)theApplication { - return YES; +- (BOOL)applicationShouldHandleReopen:(NSApplication *)theApplication hasVisibleWindows:(BOOL)flag +{ + if (flag) { + return NO; + } + else { + [_window makeKeyAndOrderFront:self]; + return YES; + } } - (void)applicationWillTerminate:(NSNotification *)aNotification { diff --git a/Client/macos/MacOSBluetoothConnector.mm b/Client/macos/MacOSBluetoothConnector.mm index 205adfe..8e67cfb 100644 --- a/Client/macos/MacOSBluetoothConnector.mm +++ b/Client/macos/MacOSBluetoothConnector.mm @@ -151,5 +151,6 @@ -(void)rfcommChannelData:(IOBluetoothRFCOMMChannel *)rfcommChannel data:(void *) bool MacOSBluetoothConnector::isConnected() noexcept { - return running; + IOBluetoothRFCOMMChannel *chan = (__bridge IOBluetoothRFCOMMChannel*) rfcommchannel; + return running and chan.isOpen; } diff --git a/Client/macos/ViewController.h b/Client/macos/ViewController.h index 25e270c..528f4a4 100644 --- a/Client/macos/ViewController.h +++ b/Client/macos/ViewController.h @@ -9,6 +9,7 @@ #import "AppDelegate.h" BluetoothWrapper bt = (BluetoothWrapper)nil; +NSStatusItem* statusItem; @interface ViewController : NSViewController @property (weak, nonatomic) IBOutlet NSTextField *connectedLabel; diff --git a/Client/macos/ViewController.mm b/Client/macos/ViewController.mm index 2aeaf16..f25ab3e 100644 --- a/Client/macos/ViewController.mm +++ b/Client/macos/ViewController.mm @@ -15,15 +15,33 @@ - (void)viewDidLoad { std::unique_ptr connector = std::make_unique(); // Wrap the connector using the bluetoothwrapper bt = BluetoothWrapper(std::move(connector)); + statusItem = [NSStatusBar.systemStatusBar statusItemWithLength: -1]; + statusItem.button.image = [NSImage imageNamed: @"NSRefreshTemplate"]; + [statusItem setTarget:self]; + [statusItem setAction:@selector(statusItemClick:)]; } +- (void)statusItemClick:(id)sender { + if (!bt.isConnected()) + return [self connectToDevice:self]; + + if ([focusOnVoice isEnabled]) { + [ANCSlider setIntValue:0]; + [focusOnVoice setEnabled:FALSE]; + } else { + [ANCSlider setIntValue:19]; + [focusOnVoice setEnabled:TRUE]; + } + [self sendData:self]; +} - (void)setRepresentedObject:(id)representedObject { [super setRepresentedObject:representedObject]; } - (IBAction)connectToDevice:(id)sender { - if (bt.isConnected()){ + statusItem.button.image = [NSImage imageNamed: @"NSRefreshTemplate"]; + if (bt.isConnected()) { bt.disconnect(); [ANCSlider setEnabled:FALSE]; [focusOnVoice setEnabled:FALSE]; @@ -42,19 +60,22 @@ - (IBAction)connectToDevice:(id)sender { // connect to device bt.connect([[device addressString] UTF8String]); // give it some time to connect - int timeout = 50; - while(!bt.isConnected() and timeout >= 0){ + int timeout = 5; + while(!bt.isConnected() and timeout >= 0) { [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; + timeout--; } - if (bt.isConnected()){ + if (bt.isConnected()) { IOBluetoothDevice *device = [[dSelector getResults] lastObject]; [connectedLabel setStringValue:[@"Connected: " stringByAppendingString:[device nameOrAddress]]]; [connectButton setTitle:@"Disconnect"]; [ANCSlider setEnabled:TRUE]; [focusOnVoice setEnabled:FALSE]; + statusItem.button.image = [NSImage imageNamed: @"NSHomeTemplate"]; } else { [connectedLabel setStringValue:@"Not connected, connection timed out."]; + bt.disconnect(); } } else { [connectedLabel setStringValue:@"Not connected, device selector canceled."]; @@ -63,24 +84,25 @@ - (IBAction)connectToDevice:(id)sender { } - (IBAction)sendData:(id)sender { - if (!bt.isConnected()){ + if (!bt.isConnected()) { [ANCSlider setEnabled:FALSE]; [ANCSlider setIntValue:0]; [focusOnVoice setEnabled:FALSE]; [connectButton setTitle:@"Connect to Bluetooth device"]; [connectedLabel setStringValue:@"Not connected, please reconnect."]; + statusItem.button.image = [NSImage imageNamed: @"NSRefreshTemplate"]; return; } [ANCValueLabel setStringValue:ANCSlider.stringValue]; - if (ANCSlider.intValue >= MINIMUM_VOICE_FOCUS_STEP) - { + if (ANCSlider.intValue >= MINIMUM_VOICE_FOCUS_STEP) { [focusOnVoice setTitle:@"Focus on Voice"]; [focusOnVoice setEnabled:TRUE]; + statusItem.button.image = [NSImage imageNamed: @"NSFlowViewTemplate"]; } - else - { + else { [focusOnVoice setTitle:@"Focus on Voice isn't enabled on this level."]; + statusItem.button.image = [NSImage imageNamed: @"NSHomeTemplate"]; [focusOnVoice setEnabled:FALSE]; } // send current settings From f4fcb1182755be55376204570f687ba6a75e6f3c Mon Sep 17 00:00:00 2001 From: semvis123 Date: Wed, 10 Feb 2021 16:29:46 +0100 Subject: [PATCH 53/55] added a space in a comment --- Client/macos/MacOSBluetoothConnector.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Client/macos/MacOSBluetoothConnector.mm b/Client/macos/MacOSBluetoothConnector.mm index 8e67cfb..471dda5 100644 --- a/Client/macos/MacOSBluetoothConnector.mm +++ b/Client/macos/MacOSBluetoothConnector.mm @@ -48,7 +48,7 @@ -(void)rfcommChannelData:(IOBluetoothRFCOMMChannel *)rfcommChannel data:(void *) void MacOSBluetoothConnector::connectToMac(MacOSBluetoothConnector* macOSBluetoothConnector) { macOSBluetoothConnector->running = true; - //get device + // get device IOBluetoothDevice *device = (__bridge IOBluetoothDevice *)macOSBluetoothConnector->rfcommDevice; // create new channel IOBluetoothRFCOMMChannel *channel = [[IOBluetoothRFCOMMChannel alloc] init]; From c855921d2848f262bef23a68544936f331e92e90 Mon Sep 17 00:00:00 2001 From: semvis123 Date: Thu, 11 Feb 2021 21:48:34 +0100 Subject: [PATCH 54/55] Added error handlers --- Client/macos/MacOSBluetoothConnector.mm | 10 ++++--- Client/macos/Main.storyboard | 2 +- Client/macos/ViewController.mm | 38 +++++++++++++++++++------ 3 files changed, 36 insertions(+), 14 deletions(-) diff --git a/Client/macos/MacOSBluetoothConnector.mm b/Client/macos/MacOSBluetoothConnector.mm index 471dda5..333f8b8 100644 --- a/Client/macos/MacOSBluetoothConnector.mm +++ b/Client/macos/MacOSBluetoothConnector.mm @@ -6,7 +6,7 @@ } MacOSBluetoothConnector::~MacOSBluetoothConnector() { - //onclose event + // onclose event if (isConnected()){ disconnect(); } @@ -47,7 +47,6 @@ -(void)rfcommChannelData:(IOBluetoothRFCOMMChannel *)rfcommChannel data:(void *) void MacOSBluetoothConnector::connectToMac(MacOSBluetoothConnector* macOSBluetoothConnector) { - macOSBluetoothConnector->running = true; // get device IOBluetoothDevice *device = (__bridge IOBluetoothDevice *)macOSBluetoothConnector->rfcommDevice; // create new channel @@ -64,11 +63,12 @@ -(void)rfcommChannelData:(IOBluetoothRFCOMMChannel *)rfcommChannel data:(void *) asyncCommDelegate->delegateCPP = macOSBluetoothConnector; // try to open channel if ( [device openRFCOMMChannelAsync:&channel withChannelID:rfcommChannelID delegate:asyncCommDelegate] != kIOReturnSuccess ) { - throw "Error - could not open the rfcomm.\n"; + throw RecoverableException("Error - could not open the rfcomm.\n", true); } // store the channel macOSBluetoothConnector->rfcommchannel = (__bridge void*) channel; + macOSBluetoothConnector->running = true; // keep thread running while (macOSBluetoothConnector->running) { [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:.1]]; @@ -151,6 +151,8 @@ -(void)rfcommChannelData:(IOBluetoothRFCOMMChannel *)rfcommChannel data:(void *) bool MacOSBluetoothConnector::isConnected() noexcept { + if (!running) + return false; IOBluetoothRFCOMMChannel *chan = (__bridge IOBluetoothRFCOMMChannel*) rfcommchannel; - return running and chan.isOpen; + return chan.isOpen; } diff --git a/Client/macos/Main.storyboard b/Client/macos/Main.storyboard index 2872965..6c54aa6 100644 --- a/Client/macos/Main.storyboard +++ b/Client/macos/Main.storyboard @@ -201,7 +201,7 @@ Source: https://github.com/Plutoberth/SonyHeadphonesClient - + diff --git a/Client/macos/ViewController.mm b/Client/macos/ViewController.mm index f25ab3e..13604ee 100644 --- a/Client/macos/ViewController.mm +++ b/Client/macos/ViewController.mm @@ -21,6 +21,18 @@ - (void)viewDidLoad { [statusItem setAction:@selector(statusItemClick:)]; } +- (void)displayError:(RecoverableException)exc { + if (exc.shouldDisconnect){ + bt.disconnect(); + [ANCSlider setEnabled:FALSE]; + [focusOnVoice setEnabled:FALSE]; + [connectButton setTitle:@"Connect to Bluetooth device"]; + [connectedLabel setStringValue:[@"Unexpected error occurred and disconnected: \n" stringByAppendingString:@(exc.what())]]; + } else { + [connectedLabel setStringValue:[@"Unexpected error occurred: \n" stringByAppendingString:@(exc.what())]]; + } +} + - (void)statusItemClick:(id)sender { if (!bt.isConnected()) return [self connectToDevice:self]; @@ -57,8 +69,12 @@ - (IBAction)connectToDevice:(id)sender { if (result == kIOBluetoothUISuccess) { // get device IOBluetoothDevice *device = [[dSelector getResults] lastObject]; - // connect to device - bt.connect([[device addressString] UTF8String]); + try { + // connect to device + bt.connect([[device addressString] UTF8String]); + } catch (RecoverableException& exc) { + [self displayError:exc]; + } // give it some time to connect int timeout = 5; while(!bt.isConnected() and timeout >= 0) { @@ -108,12 +124,16 @@ - (IBAction)sendData:(id)sender { // send current settings auto ncAsmEffect = NC_ASM_EFFECT::ADJUSTMENT_COMPLETION; auto asmId = focusOnVoice.state == NSControlStateValueOn ? ASM_ID::VOICE : ASM_ID::NORMAL; - bt.sendCommand(CommandSerializer::serializeNcAndAsmSetting( - ncAsmEffect, - NC_ASM_SETTING_TYPE::LEVEL_ADJUSTMENT, - ASM_SETTING_TYPE::LEVEL_ADJUSTMENT, - asmId, - ANCSlider.intValue - )); + try { + bt.sendCommand(CommandSerializer::serializeNcAndAsmSetting( + ncAsmEffect, + NC_ASM_SETTING_TYPE::LEVEL_ADJUSTMENT, + ASM_SETTING_TYPE::LEVEL_ADJUSTMENT, + asmId, + ANCSlider.intValue + )); + } catch (RecoverableException& exc) { + [self displayError:exc]; + } } @end From 2fe3c801e34474b8a31bc0dee991a10b94536a01 Mon Sep 17 00:00:00 2001 From: semvis123 Date: Thu, 11 Feb 2021 22:01:06 +0100 Subject: [PATCH 55/55] little cleanup --- Client/macos/ViewController.mm | 85 ++++++++++++++++++---------------- 1 file changed, 45 insertions(+), 40 deletions(-) diff --git a/Client/macos/ViewController.mm b/Client/macos/ViewController.mm index 13604ee..9711ab5 100644 --- a/Client/macos/ViewController.mm +++ b/Client/macos/ViewController.mm @@ -16,7 +16,7 @@ - (void)viewDidLoad { // Wrap the connector using the bluetoothwrapper bt = BluetoothWrapper(std::move(connector)); statusItem = [NSStatusBar.systemStatusBar statusItemWithLength: -1]; - statusItem.button.image = [NSImage imageNamed: @"NSRefreshTemplate"]; + statusItem.button.image = [NSImage imageNamed:@"NSRefreshTemplate"]; [statusItem setTarget:self]; [statusItem setAction:@selector(statusItemClick:)]; } @@ -27,6 +27,7 @@ - (void)displayError:(RecoverableException)exc { [ANCSlider setEnabled:FALSE]; [focusOnVoice setEnabled:FALSE]; [connectButton setTitle:@"Connect to Bluetooth device"]; + statusItem.button.image = [NSImage imageNamed:@"NSRefreshTemplate"]; [connectedLabel setStringValue:[@"Unexpected error occurred and disconnected: \n" stringByAppendingString:@(exc.what())]]; } else { [connectedLabel setStringValue:[@"Unexpected error occurred: \n" stringByAppendingString:@(exc.what())]]; @@ -36,7 +37,7 @@ - (void)displayError:(RecoverableException)exc { - (void)statusItemClick:(id)sender { if (!bt.isConnected()) return [self connectToDevice:self]; - + if ([focusOnVoice isEnabled]) { [ANCSlider setIntValue:0]; [focusOnVoice setEnabled:FALSE]; @@ -52,75 +53,79 @@ - (void)setRepresentedObject:(id)representedObject { } - (IBAction)connectToDevice:(id)sender { - statusItem.button.image = [NSImage imageNamed: @"NSRefreshTemplate"]; + statusItem.button.image = [NSImage imageNamed:@"NSRefreshTemplate"]; + + // check if it should disconnect if (bt.isConnected()) { bt.disconnect(); [ANCSlider setEnabled:FALSE]; [focusOnVoice setEnabled:FALSE]; [connectButton setTitle:@"Connect to Bluetooth device"]; [connectedLabel setStringValue:@"Not connected"]; + return; } - else { - // launch device selector modal - IOBluetoothDeviceSelectorController *dSelector = [IOBluetoothDeviceSelectorController deviceSelector]; - int result = [dSelector runModal]; - - - if (result == kIOBluetoothUISuccess) { - // get device + + // launch device selector modal + IOBluetoothDeviceSelectorController *dSelector = [IOBluetoothDeviceSelectorController deviceSelector]; + int result = [dSelector runModal]; + + + if (result == kIOBluetoothUISuccess) { + // get device + IOBluetoothDevice *device = [[dSelector getResults] lastObject]; + try { + // connect to device + bt.connect([[device addressString] UTF8String]); + } catch (RecoverableException& exc) { + [self displayError:exc]; + } + // give it some time to connect + int timeout = 5; + while(!bt.isConnected() and timeout >= 0) { + [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; + timeout--; + } + if (bt.isConnected()) { IOBluetoothDevice *device = [[dSelector getResults] lastObject]; - try { - // connect to device - bt.connect([[device addressString] UTF8String]); - } catch (RecoverableException& exc) { - [self displayError:exc]; - } - // give it some time to connect - int timeout = 5; - while(!bt.isConnected() and timeout >= 0) { - [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; - timeout--; - } - if (bt.isConnected()) { - IOBluetoothDevice *device = [[dSelector getResults] lastObject]; - [connectedLabel setStringValue:[@"Connected: " stringByAppendingString:[device nameOrAddress]]]; - [connectButton setTitle:@"Disconnect"]; - [ANCSlider setEnabled:TRUE]; - [focusOnVoice setEnabled:FALSE]; - statusItem.button.image = [NSImage imageNamed: @"NSHomeTemplate"]; - } - else { - [connectedLabel setStringValue:@"Not connected, connection timed out."]; - bt.disconnect(); - } + [connectedLabel setStringValue:[@"Connected: " stringByAppendingString:[device nameOrAddress]]]; + [connectButton setTitle:@"Disconnect"]; + [ANCSlider setEnabled:TRUE]; + [focusOnVoice setEnabled:FALSE]; + statusItem.button.image = [NSImage imageNamed:@"NSHomeTemplate"]; } else { - [connectedLabel setStringValue:@"Not connected, device selector canceled."]; + [connectedLabel setStringValue:@"Not connected, connection timed out."]; + bt.disconnect(); } + } else { + [connectedLabel setStringValue:@"Not connected, device selector canceled."]; } + } - (IBAction)sendData:(id)sender { + // check if the device is still connected if (!bt.isConnected()) { [ANCSlider setEnabled:FALSE]; [ANCSlider setIntValue:0]; [focusOnVoice setEnabled:FALSE]; [connectButton setTitle:@"Connect to Bluetooth device"]; [connectedLabel setStringValue:@"Not connected, please reconnect."]; - statusItem.button.image = [NSImage imageNamed: @"NSRefreshTemplate"]; + statusItem.button.image = [NSImage imageNamed:@"NSRefreshTemplate"]; return; } - + [ANCValueLabel setStringValue:ANCSlider.stringValue]; if (ANCSlider.intValue >= MINIMUM_VOICE_FOCUS_STEP) { [focusOnVoice setTitle:@"Focus on Voice"]; [focusOnVoice setEnabled:TRUE]; - statusItem.button.image = [NSImage imageNamed: @"NSFlowViewTemplate"]; + statusItem.button.image = [NSImage imageNamed:@"NSFlowViewTemplate"]; } else { [focusOnVoice setTitle:@"Focus on Voice isn't enabled on this level."]; - statusItem.button.image = [NSImage imageNamed: @"NSHomeTemplate"]; + statusItem.button.image = [NSImage imageNamed:@"NSHomeTemplate"]; [focusOnVoice setEnabled:FALSE]; } + // send current settings auto ncAsmEffect = NC_ASM_EFFECT::ADJUSTMENT_COMPLETION; auto asmId = focusOnVoice.state == NSControlStateValueOn ? ASM_ID::VOICE : ASM_ID::NORMAL;