From a161573df4b5455dada33bb6d5b36b053a3dd951 Mon Sep 17 00:00:00 2001 From: TimmyOVO Date: Sat, 20 Apr 2024 04:03:45 +0800 Subject: [PATCH 01/16] Complete output_name implementation in macos to select a different monitor to capture. --- src/platform/macos/display.mm | 6 ++++++ src/platform/macos/input.cpp | 16 ++++++++++++++++ src_assets/common/assets/web/config.html | 8 ++++++++ .../assets/web/public/assets/locale/en_US.json | 2 ++ .../assets/web/public/assets/locale/zh.json | 2 ++ 5 files changed, 34 insertions(+) diff --git a/src/platform/macos/display.mm b/src/platform/macos/display.mm index 6d757176006..79d32bb65fe 100644 --- a/src/platform/macos/display.mm +++ b/src/platform/macos/display.mm @@ -154,6 +154,12 @@ } } } + std::vector display_names = platf::display_names(mem_type_e::videotoolbox); + BOOST_LOG(info) << "Available displays:"sv; + for (const auto &name : display_names) { + BOOST_LOG(info) << " " << name; + } + BOOST_LOG(info) << "Selected display: "sv << display_name; display->av_capture = [[AVVideo alloc] initWithDisplay:display->display_id frameRate:config.framerate]; diff --git a/src/platform/macos/input.cpp b/src/platform/macos/input.cpp index 2aa6012ef51..fac950bb7df 100644 --- a/src/platform/macos/input.cpp +++ b/src/platform/macos/input.cpp @@ -510,7 +510,23 @@ const KeyCodeMap kKeyCodesMap[] = { auto macos_input = (macos_input_t *) result.get(); // If we don't use the main display in the future, this has to be adapted + macos_input->display = CGMainDisplayID(); + auto output_name = config::video.output_name; + if (!output_name.empty()) { + uint32_t max_display = 4; + uint32_t display_count; + CGDirectDisplayID displays[max_display]; + if (CGGetActiveDisplayList(max_display, displays, &display_count) != kCGErrorSuccess) { + BOOST_LOG(error) << "Unable to get active display list , error: "sv << std::endl; + } + for (int i = 0; i < display_count; i++) { + CGDirectDisplayID display_id = displays[i]; + if (display_id == std::atoi(output_name.c_str())) { + macos_input->display = display_id; + } + } + } // Input coordinates are based on the virtual resolution not the physical, so we need the scaling factor CGDisplayModeRef mode = CGDisplayCopyDisplayMode(macos_input->display); diff --git a/src_assets/common/assets/web/config.html b/src_assets/common/assets/web/config.html index 869b2417846..4387ba9184d 100644 --- a/src_assets/common/assets/web/config.html +++ b/src_assets/common/assets/web/config.html @@ -407,6 +407,14 @@

+
+ + +
+ {{ $t('config.output_name_desc_macos') }}
+
+
diff --git a/src_assets/common/assets/web/public/assets/locale/en_US.json b/src_assets/common/assets/web/public/assets/locale/en_US.json index 6fa1f3a04c4..3c29878287f 100644 --- a/src_assets/common/assets/web/public/assets/locale/en_US.json +++ b/src_assets/common/assets/web/public/assets/locale/en_US.json @@ -236,8 +236,10 @@ "origin_web_ui_allowed_wan": "Anyone may access Web UI", "output_name_desc_linux": "During Sunshine startup, you should see the list of detected monitors. You need to use the value before the colon in the output. e.g.:", "output_name_desc_win": "Manually specify a display to use for capture. If unset, the primary display is captured. Note: If you specified a GPU above, this display must be connected to that GPU. The appropriate values can be found using the following command:", + "output_name_desc_macos": "Manually specify a display to use for capture. If unset, the primary display is captured. Note: The display must be active. You can find a list of display IDs in the startup logs.", "output_name_linux": "Monitor number", "output_name_win": "Output Name", + "output_name_macos": "Display number", "ping_timeout": "Ping Timeout", "ping_timeout_desc": "How long to wait in milliseconds for data from moonlight before shutting down the stream", "pkey": "Private Key", diff --git a/src_assets/common/assets/web/public/assets/locale/zh.json b/src_assets/common/assets/web/public/assets/locale/zh.json index fac14e2b593..f9a27d0adec 100644 --- a/src_assets/common/assets/web/public/assets/locale/zh.json +++ b/src_assets/common/assets/web/public/assets/locale/zh.json @@ -236,8 +236,10 @@ "origin_web_ui_allowed_wan": "任何人都可以访问 Web UI", "output_name_desc_linux": "在阳光启动过程中,您应该看到检测到的显示器列表。您需要在输出中的冒号之前使用该值,例如:", "output_name_desc_win": "手动指定用于捕捉的显示器。如果未设置,则捕捉主显示屏。注意:如果在上面指定了 GPU,则该显示器必须连接到该 GPU。可以使用以下命令找到相应的值:", + "output_name_desc_macos": "手动指定用于捕捉的显示器。如果未设置,则捕捉主显示屏。注意:该显示器必须处于激活状态。你可以在启动日志中找到显示器编号列表。", "output_name_linux": "显示器编号", "output_name_win": "输出名称", + "output_name_macos": "显示器编号", "ping_timeout": "Ping 超时", "ping_timeout_desc": "关闭串流前等待 Moonlight 数据的时间(以毫秒计)", "pkey": "私钥", From 59c3978a0ab1fd9c9431fe2e9d3de0647919e4a9 Mon Sep 17 00:00:00 2001 From: TimmyOVO Date: Sat, 20 Apr 2024 04:11:57 +0800 Subject: [PATCH 02/16] Update locale for both en.json and en_GB.json --- src_assets/common/assets/web/public/assets/locale/en.json | 2 ++ src_assets/common/assets/web/public/assets/locale/en_GB.json | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src_assets/common/assets/web/public/assets/locale/en.json b/src_assets/common/assets/web/public/assets/locale/en.json index 4a56b2d659a..71c9c5e7ac0 100644 --- a/src_assets/common/assets/web/public/assets/locale/en.json +++ b/src_assets/common/assets/web/public/assets/locale/en.json @@ -245,8 +245,10 @@ "origin_web_ui_allowed_wan": "Anyone may access Web UI", "output_name_desc_linux": "During Sunshine startup, you should see the list of detected monitors. You need to use the value before the colon in the output. e.g.:", "output_name_desc_win": "Manually specify a display to use for capture. If unset, the primary display is captured. Note: If you specified a GPU above, this display must be connected to that GPU. The appropriate values can be found using the following command:", + "output_name_desc_macos": "Manually specify a display to use for capture. If unset, the primary display is captured. Note: The display must be active. You can find a list of display IDs in the startup logs.", "output_name_linux": "Monitor number", "output_name_win": "Output Name", + "output_name_macos": "Display number", "ping_timeout": "Ping Timeout", "ping_timeout_desc": "How long to wait in milliseconds for data from moonlight before shutting down the stream", "pkey": "Private Key", diff --git a/src_assets/common/assets/web/public/assets/locale/en_GB.json b/src_assets/common/assets/web/public/assets/locale/en_GB.json index bc10222217e..dfc1bb5a7a7 100644 --- a/src_assets/common/assets/web/public/assets/locale/en_GB.json +++ b/src_assets/common/assets/web/public/assets/locale/en_GB.json @@ -236,8 +236,10 @@ "origin_web_ui_allowed_wan": "Anyone may access Web UI", "output_name_desc_linux": "During Sunshine startup, you should see the list of detected monitors. You need to use the value before the colon in the output. e.g.:", "output_name_desc_win": "Manually specify a display to use for capture. If unset, the primary display is captured. Note: If you specified a GPU above, this display must be connected to that GPU. The appropriate values can be found using the following command:", + "output_name_desc_macos": "Manually specify a display to use for capture. If unset, the primary display is captured. Note: The display must be active. You can find a list of display IDs in the startup logs.", "output_name_linux": "Monitor number", "output_name_win": "Output Name", + "output_name_macos": "Display number", "ping_timeout": "Ping Timeout", "ping_timeout_desc": "How long to wait in milliseconds for data from moonlight before shutting down the stream", "pkey": "Private Key", From 81cf98fbbbf1cff834e88feea3513da8b9c62ef2 Mon Sep 17 00:00:00 2001 From: TimmyOVO Date: Sat, 20 Apr 2024 05:58:40 +0800 Subject: [PATCH 03/16] Improved detected displays startup log format (now every display has product name corresponds to its display id) --- cmake/compile_definitions/macos.cmake | 3 ++- cmake/dependencies/macos.cmake | 1 + src/platform/macos/av_video.h | 2 ++ src/platform/macos/av_video.m | 13 ++++++++++++- src/platform/macos/display.mm | 28 +++++++++++++-------------- src/platform/macos/input.cpp | 17 +++++++++------- 6 files changed, 40 insertions(+), 24 deletions(-) diff --git a/cmake/compile_definitions/macos.cmake b/cmake/compile_definitions/macos.cmake index fff301b856a..dc3b99a37b5 100644 --- a/cmake/compile_definitions/macos.cmake +++ b/cmake/compile_definitions/macos.cmake @@ -13,7 +13,8 @@ list(APPEND SUNSHINE_EXTERNAL_LIBRARIES ${CORE_MEDIA_LIBRARY} ${CORE_VIDEO_LIBRARY} ${VIDEO_TOOLBOX_LIBRARY} - ${FOUNDATION_LIBRARY}) + ${FOUNDATION_LIBRARY} + ${APP_KIT_LIBRARY}) set(PLATFORM_INCLUDE_DIRS ${Boost_INCLUDE_DIR}) diff --git a/cmake/dependencies/macos.cmake b/cmake/dependencies/macos.cmake index 7d8e211e242..886d09622f7 100644 --- a/cmake/dependencies/macos.cmake +++ b/cmake/dependencies/macos.cmake @@ -6,6 +6,7 @@ FIND_LIBRARY(CORE_MEDIA_LIBRARY CoreMedia) FIND_LIBRARY(CORE_VIDEO_LIBRARY CoreVideo) FIND_LIBRARY(FOUNDATION_LIBRARY Foundation) FIND_LIBRARY(VIDEO_TOOLBOX_LIBRARY VideoToolbox) +FIND_LIBRARY(APP_KIT_LIBRARY AppKit) if(SUNSHINE_ENABLE_TRAY) FIND_LIBRARY(COCOA Cocoa REQUIRED) diff --git a/src/platform/macos/av_video.h b/src/platform/macos/av_video.h index 4bfa00ac006..fac5a78c6e6 100644 --- a/src/platform/macos/av_video.h +++ b/src/platform/macos/av_video.h @@ -5,6 +5,7 @@ #pragma once #import +#import struct CaptureSession { AVCaptureVideoDataOutput *output; @@ -29,6 +30,7 @@ typedef bool (^FrameCallbackBlock)(CMSampleBufferRef); @property (nonatomic, assign) NSMapTable *captureSignals; + (NSArray *)displayNames; ++ (NSString *)getDisplayName:(CGDirectDisplayID)displayID; - (id)initWithDisplay:(CGDirectDisplayID)displayID frameRate:(int)frameRate; diff --git a/src/platform/macos/av_video.m b/src/platform/macos/av_video.m index 5cdf5a9898e..874a87f7b18 100644 --- a/src/platform/macos/av_video.m +++ b/src/platform/macos/av_video.m @@ -23,13 +23,24 @@ @implementation AVVideo for (uint32_t i = 0; i < count; i++) { [result addObject:@{ @"id": [NSNumber numberWithUnsignedInt:displays[i]], - @"name": [NSString stringWithFormat:@"%d", displays[i]] + @"name": [NSString stringWithFormat:@"%d", displays[i]], + @"displayName": [self getDisplayName:displays[i]], }]; } return [NSArray arrayWithArray:result]; } ++ (NSString *)getDisplayName:(CGDirectDisplayID)displayID { + NSScreen *screens = [NSScreen screens]; + for (NSScreen *screen in screens) { + if (screen.deviceDescription[@"NSScreenNumber"] == [NSNumber numberWithUnsignedInt:displayID]) { + return screen.localizedName; + } + } + return nil; +} + - (id)initWithDisplay:(CGDirectDisplayID)displayID frameRate:(int)frameRate { self = [super init]; diff --git a/src/platform/macos/display.mm b/src/platform/macos/display.mm index 79d32bb65fe..5f0835782cc 100644 --- a/src/platform/macos/display.mm +++ b/src/platform/macos/display.mm @@ -142,24 +142,22 @@ auto display = std::make_shared(); + // Default to main display display->display_id = CGMainDisplayID(); - if (!display_name.empty()) { - auto display_array = [AVVideo displayNames]; - - for (NSDictionary *item in display_array) { - NSString *name = item[@"name"]; - if (name.UTF8String == display_name) { - NSNumber *display_id = item[@"id"]; - display->display_id = [display_id unsignedIntValue]; - } + + // Print all displays available with it's name and id + auto display_array = [AVVideo displayNames]; + BOOST_LOG(info) << "Detecting displays..."sv; + for (NSDictionary *item in display_array) { + NSNumber *display_id = item[@"id"]; + // We need show display's product name and corresponding display number given by user + NSString *name = item[@"displayName"]; + BOOST_LOG(info) << "Detected display: "sv << name.UTF8String << " (id: "sv << [NSString stringWithFormat:@"%@", display_id].UTF8String << ")"sv; + if (!display_name.empty() && std::atoi(display_name.c_str()) == [display_id unsignedIntValue]) { + display->display_id = [display_id unsignedIntValue]; } } - std::vector display_names = platf::display_names(mem_type_e::videotoolbox); - BOOST_LOG(info) << "Available displays:"sv; - for (const auto &name : display_names) { - BOOST_LOG(info) << " " << name; - } - BOOST_LOG(info) << "Selected display: "sv << display_name; + BOOST_LOG(info) << "Selected display id: "sv << display->display_id; display->av_capture = [[AVVideo alloc] initWithDisplay:display->display_id frameRate:config.framerate]; diff --git a/src/platform/macos/input.cpp b/src/platform/macos/input.cpp index fac950bb7df..273416680ef 100644 --- a/src/platform/macos/input.cpp +++ b/src/platform/macos/input.cpp @@ -509,21 +509,24 @@ const KeyCodeMap kKeyCodesMap[] = { auto macos_input = (macos_input_t *) result.get(); - // If we don't use the main display in the future, this has to be adapted - + // Default to main display macos_input->display = CGMainDisplayID(); + auto output_name = config::video.output_name; + // If output_name is set, try to find the display with that display id if (!output_name.empty()) { - uint32_t max_display = 4; + uint32_t max_display = 32; uint32_t display_count; CGDirectDisplayID displays[max_display]; if (CGGetActiveDisplayList(max_display, displays, &display_count) != kCGErrorSuccess) { BOOST_LOG(error) << "Unable to get active display list , error: "sv << std::endl; } - for (int i = 0; i < display_count; i++) { - CGDirectDisplayID display_id = displays[i]; - if (display_id == std::atoi(output_name.c_str())) { - macos_input->display = display_id; + else { + for (int i = 0; i < display_count; i++) { + CGDirectDisplayID display_id = displays[i]; + if (display_id == std::atoi(output_name.c_str())) { + macos_input->display = display_id; + } } } } From 4d079a483f70bbf3d4d730383d5d9d1c204d2e2b Mon Sep 17 00:00:00 2001 From: TimmyOVO Date: Sat, 20 Apr 2024 06:09:22 +0800 Subject: [PATCH 04/16] Update macOS output_name doc --- docs/source/about/advanced_usage.rst | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/docs/source/about/advanced_usage.rst b/docs/source/about/advanced_usage.rst index 6aa33feee43..5d2b04f0c78 100644 --- a/docs/source/about/advanced_usage.rst +++ b/docs/source/about/advanced_usage.rst @@ -587,7 +587,16 @@ keybindings You need to use the value before the colon in the output, e.g. ``1``. - .. todo:: macOS + **macOS** + During Sunshine startup, you should see the list of detected displays: + + .. code-block:: text + + Info: Detecting displays... + Info: Detected display: M27P20 (id: 3) + Info: Detected display: 27M2U Pro (id: 2) + + You need to use the value inside the parenthesis, e.g. ``3``. **Windows** .. code-block:: batch From ecc86b88a1225caae8fe02f80fc42fce1938c312 Mon Sep 17 00:00:00 2001 From: TimmyOVO Date: Sat, 20 Apr 2024 06:11:17 +0800 Subject: [PATCH 05/16] Update macOS output_name example doc --- docs/source/about/advanced_usage.rst | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/source/about/advanced_usage.rst b/docs/source/about/advanced_usage.rst index 5d2b04f0c78..8334a7c34bf 100644 --- a/docs/source/about/advanced_usage.rst +++ b/docs/source/about/advanced_usage.rst @@ -612,7 +612,10 @@ keybindings output_name = 0 - .. todo:: macOS + **macOS** + .. code-block:: text + + output_name = 3 **Windows** .. code-block:: text From 50f47d5f8be49f9727a88a45f40572893cf55e6f Mon Sep 17 00:00:00 2001 From: TimmyOVO Date: Sat, 20 Apr 2024 16:38:42 +0800 Subject: [PATCH 06/16] Reordered some entries & locale cleanup. --- cmake/compile_definitions/macos.cmake | 4 ++-- cmake/dependencies/macos.cmake | 2 +- src_assets/common/assets/web/public/assets/locale/en.json | 4 ++-- src_assets/common/assets/web/public/assets/locale/en_GB.json | 2 -- src_assets/common/assets/web/public/assets/locale/en_US.json | 2 -- src_assets/common/assets/web/public/assets/locale/zh.json | 2 -- 6 files changed, 5 insertions(+), 11 deletions(-) diff --git a/cmake/compile_definitions/macos.cmake b/cmake/compile_definitions/macos.cmake index dc3b99a37b5..3a000247152 100644 --- a/cmake/compile_definitions/macos.cmake +++ b/cmake/compile_definitions/macos.cmake @@ -8,13 +8,13 @@ link_directories(/opt/homebrew/lib) ADD_DEFINITIONS(-DBOOST_LOG_DYN_LINK) list(APPEND SUNSHINE_EXTERNAL_LIBRARIES + ${APP_KIT_LIBRARY} ${APP_SERVICES_LIBRARY} ${AV_FOUNDATION_LIBRARY} ${CORE_MEDIA_LIBRARY} ${CORE_VIDEO_LIBRARY} ${VIDEO_TOOLBOX_LIBRARY} - ${FOUNDATION_LIBRARY} - ${APP_KIT_LIBRARY}) + ${FOUNDATION_LIBRARY}) set(PLATFORM_INCLUDE_DIRS ${Boost_INCLUDE_DIR}) diff --git a/cmake/dependencies/macos.cmake b/cmake/dependencies/macos.cmake index 886d09622f7..61efc6a902b 100644 --- a/cmake/dependencies/macos.cmake +++ b/cmake/dependencies/macos.cmake @@ -1,12 +1,12 @@ # macos specific dependencies +FIND_LIBRARY(APP_KIT_LIBRARY AppKit) FIND_LIBRARY(APP_SERVICES_LIBRARY ApplicationServices) FIND_LIBRARY(AV_FOUNDATION_LIBRARY AVFoundation) FIND_LIBRARY(CORE_MEDIA_LIBRARY CoreMedia) FIND_LIBRARY(CORE_VIDEO_LIBRARY CoreVideo) FIND_LIBRARY(FOUNDATION_LIBRARY Foundation) FIND_LIBRARY(VIDEO_TOOLBOX_LIBRARY VideoToolbox) -FIND_LIBRARY(APP_KIT_LIBRARY AppKit) if(SUNSHINE_ENABLE_TRAY) FIND_LIBRARY(COCOA Cocoa REQUIRED) diff --git a/src_assets/common/assets/web/public/assets/locale/en.json b/src_assets/common/assets/web/public/assets/locale/en.json index 71c9c5e7ac0..9ce41807484 100644 --- a/src_assets/common/assets/web/public/assets/locale/en.json +++ b/src_assets/common/assets/web/public/assets/locale/en.json @@ -244,11 +244,11 @@ "origin_web_ui_allowed_pc": "Only localhost may access Web UI", "origin_web_ui_allowed_wan": "Anyone may access Web UI", "output_name_desc_linux": "During Sunshine startup, you should see the list of detected monitors. You need to use the value before the colon in the output. e.g.:", - "output_name_desc_win": "Manually specify a display to use for capture. If unset, the primary display is captured. Note: If you specified a GPU above, this display must be connected to that GPU. The appropriate values can be found using the following command:", "output_name_desc_macos": "Manually specify a display to use for capture. If unset, the primary display is captured. Note: The display must be active. You can find a list of display IDs in the startup logs.", + "output_name_desc_win": "Manually specify a display to use for capture. If unset, the primary display is captured. Note: If you specified a GPU above, this display must be connected to that GPU. The appropriate values can be found using the following command:", "output_name_linux": "Monitor number", - "output_name_win": "Output Name", "output_name_macos": "Display number", + "output_name_win": "Output Name", "ping_timeout": "Ping Timeout", "ping_timeout_desc": "How long to wait in milliseconds for data from moonlight before shutting down the stream", "pkey": "Private Key", diff --git a/src_assets/common/assets/web/public/assets/locale/en_GB.json b/src_assets/common/assets/web/public/assets/locale/en_GB.json index dfc1bb5a7a7..bc10222217e 100644 --- a/src_assets/common/assets/web/public/assets/locale/en_GB.json +++ b/src_assets/common/assets/web/public/assets/locale/en_GB.json @@ -236,10 +236,8 @@ "origin_web_ui_allowed_wan": "Anyone may access Web UI", "output_name_desc_linux": "During Sunshine startup, you should see the list of detected monitors. You need to use the value before the colon in the output. e.g.:", "output_name_desc_win": "Manually specify a display to use for capture. If unset, the primary display is captured. Note: If you specified a GPU above, this display must be connected to that GPU. The appropriate values can be found using the following command:", - "output_name_desc_macos": "Manually specify a display to use for capture. If unset, the primary display is captured. Note: The display must be active. You can find a list of display IDs in the startup logs.", "output_name_linux": "Monitor number", "output_name_win": "Output Name", - "output_name_macos": "Display number", "ping_timeout": "Ping Timeout", "ping_timeout_desc": "How long to wait in milliseconds for data from moonlight before shutting down the stream", "pkey": "Private Key", diff --git a/src_assets/common/assets/web/public/assets/locale/en_US.json b/src_assets/common/assets/web/public/assets/locale/en_US.json index 3c29878287f..6fa1f3a04c4 100644 --- a/src_assets/common/assets/web/public/assets/locale/en_US.json +++ b/src_assets/common/assets/web/public/assets/locale/en_US.json @@ -236,10 +236,8 @@ "origin_web_ui_allowed_wan": "Anyone may access Web UI", "output_name_desc_linux": "During Sunshine startup, you should see the list of detected monitors. You need to use the value before the colon in the output. e.g.:", "output_name_desc_win": "Manually specify a display to use for capture. If unset, the primary display is captured. Note: If you specified a GPU above, this display must be connected to that GPU. The appropriate values can be found using the following command:", - "output_name_desc_macos": "Manually specify a display to use for capture. If unset, the primary display is captured. Note: The display must be active. You can find a list of display IDs in the startup logs.", "output_name_linux": "Monitor number", "output_name_win": "Output Name", - "output_name_macos": "Display number", "ping_timeout": "Ping Timeout", "ping_timeout_desc": "How long to wait in milliseconds for data from moonlight before shutting down the stream", "pkey": "Private Key", diff --git a/src_assets/common/assets/web/public/assets/locale/zh.json b/src_assets/common/assets/web/public/assets/locale/zh.json index f9a27d0adec..fac14e2b593 100644 --- a/src_assets/common/assets/web/public/assets/locale/zh.json +++ b/src_assets/common/assets/web/public/assets/locale/zh.json @@ -236,10 +236,8 @@ "origin_web_ui_allowed_wan": "任何人都可以访问 Web UI", "output_name_desc_linux": "在阳光启动过程中,您应该看到检测到的显示器列表。您需要在输出中的冒号之前使用该值,例如:", "output_name_desc_win": "手动指定用于捕捉的显示器。如果未设置,则捕捉主显示屏。注意:如果在上面指定了 GPU,则该显示器必须连接到该 GPU。可以使用以下命令找到相应的值:", - "output_name_desc_macos": "手动指定用于捕捉的显示器。如果未设置,则捕捉主显示屏。注意:该显示器必须处于激活状态。你可以在启动日志中找到显示器编号列表。", "output_name_linux": "显示器编号", "output_name_win": "输出名称", - "output_name_macos": "显示器编号", "ping_timeout": "Ping 超时", "ping_timeout_desc": "关闭串流前等待 Moonlight 数据的时间(以毫秒计)", "pkey": "私钥", From 6a377ec33dda8a2e1e8fd883289a38ffbfb5a2f8 Mon Sep 17 00:00:00 2001 From: TimmyOVO Date: Sat, 20 Apr 2024 17:13:11 +0800 Subject: [PATCH 07/16] Unify startup display detection log format in macOS and Linux --- src/platform/linux/x11grab.cpp | 6 +++--- src/platform/macos/display.mm | 7 ++++--- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/platform/linux/x11grab.cpp b/src/platform/linux/x11grab.cpp index 0d4c3d38c30..c3b23a4c97e 100644 --- a/src/platform/linux/x11grab.cpp +++ b/src/platform/linux/x11grab.cpp @@ -421,7 +421,7 @@ namespace platf { } if (streamedMonitor != -1) { - BOOST_LOG(info) << "Configuring selected monitor ("sv << streamedMonitor << ") to stream"sv; + BOOST_LOG(info) << "Configuring selected display ("sv << streamedMonitor << ") to stream"sv; screen_res_t screenr { x11::rr::GetScreenResources(xdisplay.get(), xwindow) }; int output = screenr->noutput; @@ -806,7 +806,7 @@ namespace platf { return {}; } - BOOST_LOG(info) << "Detecting monitors"sv; + BOOST_LOG(info) << "Detecting displays"sv; x11::xdisplay_t xdisplay { x11::OpenDisplay(nullptr) }; if (!xdisplay) { @@ -821,7 +821,7 @@ namespace platf { for (int x = 0; x < output; ++x) { output_info_t out_info { x11::rr::GetOutputInfo(xdisplay.get(), screenr.get(), screenr->outputs[x]) }; if (out_info) { - BOOST_LOG(info) << "Detected monitor "sv << monitor << ": "sv << out_info->name << ", connected: "sv << (out_info->connection == RR_Connected); + BOOST_LOG(info) << "Detected display: "sv << out_info->name << " (id: "sv << monitor << ")"sv << out_info->name << " connected: "sv << (out_info->connection == RR_Connected); ++monitor; } } diff --git a/src/platform/macos/display.mm b/src/platform/macos/display.mm index 5f0835782cc..3468d46f55e 100644 --- a/src/platform/macos/display.mm +++ b/src/platform/macos/display.mm @@ -147,17 +147,18 @@ // Print all displays available with it's name and id auto display_array = [AVVideo displayNames]; - BOOST_LOG(info) << "Detecting displays..."sv; + BOOST_LOG(info) << "Detecting displays"sv; for (NSDictionary *item in display_array) { NSNumber *display_id = item[@"id"]; // We need show display's product name and corresponding display number given by user NSString *name = item[@"displayName"]; - BOOST_LOG(info) << "Detected display: "sv << name.UTF8String << " (id: "sv << [NSString stringWithFormat:@"%@", display_id].UTF8String << ")"sv; + // We are using CGGetActiveDisplayList that only returns active displays so hardcoded connected value in log to true + BOOST_LOG(info) << "Detected display: "sv << name.UTF8String << " (id: "sv << [NSString stringWithFormat:@"%@", display_id].UTF8String << ") connected: true"sv; if (!display_name.empty() && std::atoi(display_name.c_str()) == [display_id unsignedIntValue]) { display->display_id = [display_id unsignedIntValue]; } } - BOOST_LOG(info) << "Selected display id: "sv << display->display_id; + BOOST_LOG(info) << "Configuring selected display ("sv << display->display_id << ") to stream"sv; display->av_capture = [[AVVideo alloc] initWithDisplay:display->display_id frameRate:config.framerate]; From 72865023e0602c74f9f9f75b64fc52616d8bc8c8 Mon Sep 17 00:00:00 2001 From: TimmyOVO Date: Sat, 20 Apr 2024 17:15:09 +0800 Subject: [PATCH 08/16] Merge output_name doc Linux and macOS section into one. --- docs/source/about/advanced_usage.rst | 27 +++++++-------------------- 1 file changed, 7 insertions(+), 20 deletions(-) diff --git a/docs/source/about/advanced_usage.rst b/docs/source/about/advanced_usage.rst index 8334a7c34bf..102ac114c15 100644 --- a/docs/source/about/advanced_usage.rst +++ b/docs/source/about/advanced_usage.rst @@ -573,30 +573,17 @@ keybindings .. tip:: To find the name of the appropriate values follow these instructions. - **Linux** - During Sunshine startup, you should see the list of detected monitors: + **Linux&macOS** + During Sunshine startup, you should see the list of detected displays: .. code-block:: text - Info: Detecting connected monitors - Info: Detected monitor 0: DVI-D-0, connected: false - Info: Detected monitor 1: HDMI-0, connected: true - Info: Detected monitor 2: DP-0, connected: true - Info: Detected monitor 3: DP-1, connected: false - Info: Detected monitor 4: DVI-D-1, connected: false + Info: Detecting displays... + Info: Detected display: Monitor-3 (id: 4) connected: true + Info: Detected display: Monitor-2 (id: 3) connected: true + Info: Detected display: Monitor-1 (id: 2) connected: false - You need to use the value before the colon in the output, e.g. ``1``. - - **macOS** - During Sunshine startup, you should see the list of detected displays: - - .. code-block:: text - - Info: Detecting displays... - Info: Detected display: M27P20 (id: 3) - Info: Detected display: 27M2U Pro (id: 2) - - You need to use the value inside the parenthesis, e.g. ``3``. + You need to use the value inside the parenthesis, e.g. ``3``. **Windows** .. code-block:: batch From 22762e78069ff0bb2521cdfaf171e356286fd782 Mon Sep 17 00:00:00 2001 From: TimmyOVO Date: Sat, 20 Apr 2024 17:17:39 +0800 Subject: [PATCH 09/16] Update config.html to match the macOS & Linux display detection code. --- src_assets/common/assets/web/config.html | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src_assets/common/assets/web/config.html b/src_assets/common/assets/web/config.html index 4387ba9184d..e26b9a5ff64 100644 --- a/src_assets/common/assets/web/config.html +++ b/src_assets/common/assets/web/config.html @@ -398,12 +398,12 @@

{{ $t('config.output_name_desc_linux') }}

-              Info: Detecting connected monitors
-              Info: Detected monitor 0: DVI-D-0, connected: false
-              Info: Detected monitor 1: HDMI-0, connected: true
-              Info: Detected monitor 2: DP-0, connected: true
-              Info: Detected monitor 3: DP-1, connected: false
-              Info: Detected monitor 4: DVI-D-1, connected: false
+              Info: Detecting displays...
+              Info: Detected display: DVI-D-0 (id: 0) connected: false
+              Info: Detected display: HDMI-0 (id: 1) connected: true
+              Info: Detected display: DP-0 (id: 2) connected: true
+              Info: Detected display: DP-1 (id: 3) connected: false
+              Info: Detected display: DVI-D-1 (id: 4) connected: false
             

@@ -414,6 +414,12 @@

{{ $t('config.output_name_desc_macos') }}
+
+            Info: Detecting displays...
+            Info: Detected display: Monitor-2 (id: 4) connected: true
+            Info: Detected display: Monitor-1 (id: 3) connected: true
+            Info: Detected display: Monitor-0 (id: 2) connected: true
+          
From a3c3f012d7d843cb8e18c04944141e9e707fc091 Mon Sep 17 00:00:00 2001 From: TimmyOVO Date: Sat, 20 Apr 2024 17:27:00 +0800 Subject: [PATCH 10/16] Merge macOS and linux output_name config ui into one. --- src_assets/common/assets/web/config.html | 20 +++---------------- .../assets/web/public/assets/locale/en.json | 6 ++---- 2 files changed, 5 insertions(+), 21 deletions(-) diff --git a/src_assets/common/assets/web/config.html b/src_assets/common/assets/web/config.html index e26b9a5ff64..e3f7e95eb20 100644 --- a/src_assets/common/assets/web/config.html +++ b/src_assets/common/assets/web/config.html @@ -391,11 +391,11 @@

tools\dxgi-info.exe
-
- +
+
- {{ $t('config.output_name_desc_linux') }}
+ {{ $t('config.output_name_desc_unix') }}

               Info: Detecting displays...
@@ -407,20 +407,6 @@ 

-
- - -
- {{ $t('config.output_name_desc_macos') }}
-
-
-            Info: Detecting displays...
-            Info: Detected display: Monitor-2 (id: 4) connected: true
-            Info: Detected display: Monitor-1 (id: 3) connected: true
-            Info: Detected display: Monitor-0 (id: 2) connected: true
-          
-
diff --git a/src_assets/common/assets/web/public/assets/locale/en.json b/src_assets/common/assets/web/public/assets/locale/en.json index 9ce41807484..80ccb5f70e9 100644 --- a/src_assets/common/assets/web/public/assets/locale/en.json +++ b/src_assets/common/assets/web/public/assets/locale/en.json @@ -243,11 +243,9 @@ "origin_web_ui_allowed_lan": "Only those in LAN may access Web UI", "origin_web_ui_allowed_pc": "Only localhost may access Web UI", "origin_web_ui_allowed_wan": "Anyone may access Web UI", - "output_name_desc_linux": "During Sunshine startup, you should see the list of detected monitors. You need to use the value before the colon in the output. e.g.:", - "output_name_desc_macos": "Manually specify a display to use for capture. If unset, the primary display is captured. Note: The display must be active. You can find a list of display IDs in the startup logs.", + "output_name_desc_unix": "During Sunshine startup, you should see the list of detected displays. Note: You need to use the value inside the parenthesis, e.g.:", "output_name_desc_win": "Manually specify a display to use for capture. If unset, the primary display is captured. Note: If you specified a GPU above, this display must be connected to that GPU. The appropriate values can be found using the following command:", - "output_name_linux": "Monitor number", - "output_name_macos": "Display number", + "output_name_unix": "Display number", "output_name_win": "Output Name", "ping_timeout": "Ping Timeout", "ping_timeout_desc": "How long to wait in milliseconds for data from moonlight before shutting down the stream", From 70447d6250bb8b967948a47334df5780c3d7b0a4 Mon Sep 17 00:00:00 2001 From: TimmyOVO Date: Mon, 22 Apr 2024 20:53:14 +0800 Subject: [PATCH 11/16] Separated output_name linux and macos in doc examples and config ui --- docs/source/about/advanced_usage.rst | 25 ++++++++++++++----- src_assets/common/assets/web/config.html | 9 +++++-- .../assets/web/public/assets/locale/en.json | 2 +- 3 files changed, 27 insertions(+), 9 deletions(-) diff --git a/docs/source/about/advanced_usage.rst b/docs/source/about/advanced_usage.rst index 102ac114c15..2603e687f9b 100644 --- a/docs/source/about/advanced_usage.rst +++ b/docs/source/about/advanced_usage.rst @@ -573,17 +573,30 @@ keybindings .. tip:: To find the name of the appropriate values follow these instructions. - **Linux&macOS** + **Linux** During Sunshine startup, you should see the list of detected displays: .. code-block:: text - Info: Detecting displays... - Info: Detected display: Monitor-3 (id: 4) connected: true - Info: Detected display: Monitor-2 (id: 3) connected: true - Info: Detected display: Monitor-1 (id: 2) connected: false + Info: Detecting displays + Info: Detected display: DVI-D-0 (id: 0) connected: false + Info: Detected display: HDMI-0 (id: 1) connected: true + Info: Detected display: DP-0 (id: 2) connected: true + Info: Detected display: DP-1 (id: 3) connected: false + Info: Detected display: DVI-D-1 (id: 4) connected: false - You need to use the value inside the parenthesis, e.g. ``3``. + You need to use the id value inside the parenthesis, e.g. ``1``. + + **macOS** + During Sunshine startup, you should see the list of detected displays: + + .. code-block:: text + + Info: Detecting displays + Info: Detected display: Monitor-0 (id: 3) connected: true + Info: Detected display: Monitor-1 (id: 2) connected: true + + You need to use the id value inside the parenthesis, e.g. ``3``. **Windows** .. code-block:: batch diff --git a/src_assets/common/assets/web/config.html b/src_assets/common/assets/web/config.html index e3f7e95eb20..dbc32a4843a 100644 --- a/src_assets/common/assets/web/config.html +++ b/src_assets/common/assets/web/config.html @@ -397,14 +397,19 @@

{{ $t('config.output_name_desc_unix') }}

-
-              Info: Detecting displays...
+            
+              Info: Detecting displays
               Info: Detected display: DVI-D-0 (id: 0) connected: false
               Info: Detected display: HDMI-0 (id: 1) connected: true
               Info: Detected display: DP-0 (id: 2) connected: true
               Info: Detected display: DP-1 (id: 3) connected: false
               Info: Detected display: DVI-D-1 (id: 4) connected: false
             
+
+              Info: Detecting displays
+              Info: Detected display: Monitor-0 (id: 3) connected: true
+              Info: Detected display: Monitor-1 (id: 2) connected: true
+            

diff --git a/src_assets/common/assets/web/public/assets/locale/en.json b/src_assets/common/assets/web/public/assets/locale/en.json index 80ccb5f70e9..3ea6eefc51b 100644 --- a/src_assets/common/assets/web/public/assets/locale/en.json +++ b/src_assets/common/assets/web/public/assets/locale/en.json @@ -243,7 +243,7 @@ "origin_web_ui_allowed_lan": "Only those in LAN may access Web UI", "origin_web_ui_allowed_pc": "Only localhost may access Web UI", "origin_web_ui_allowed_wan": "Anyone may access Web UI", - "output_name_desc_unix": "During Sunshine startup, you should see the list of detected displays. Note: You need to use the value inside the parenthesis, e.g.:", + "output_name_desc_unix": "During Sunshine startup, you should see the list of detected displays. Note: You need to use the id value inside the parenthesis.", "output_name_desc_win": "Manually specify a display to use for capture. If unset, the primary display is captured. Note: If you specified a GPU above, this display must be connected to that GPU. The appropriate values can be found using the following command:", "output_name_unix": "Display number", "output_name_win": "Output Name", From 32f5c1cb9c12531b6c55416f1eb3748d2c6f1d81 Mon Sep 17 00:00:00 2001 From: TimmyOVO Date: Mon, 22 Apr 2024 20:57:51 +0800 Subject: [PATCH 12/16] SUNSHINE_EXTERNAL_LIBRARIES in macos reordered. --- cmake/compile_definitions/macos.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/compile_definitions/macos.cmake b/cmake/compile_definitions/macos.cmake index 3a000247152..549ea1d0f1e 100644 --- a/cmake/compile_definitions/macos.cmake +++ b/cmake/compile_definitions/macos.cmake @@ -13,8 +13,8 @@ list(APPEND SUNSHINE_EXTERNAL_LIBRARIES ${AV_FOUNDATION_LIBRARY} ${CORE_MEDIA_LIBRARY} ${CORE_VIDEO_LIBRARY} - ${VIDEO_TOOLBOX_LIBRARY} - ${FOUNDATION_LIBRARY}) + ${FOUNDATION_LIBRARY} + ${VIDEO_TOOLBOX_LIBRARY}) set(PLATFORM_INCLUDE_DIRS ${Boost_INCLUDE_DIR}) From a755c7e8ed278adaf29f0df2950ca03ae259745b Mon Sep 17 00:00:00 2001 From: TimmyOVO Date: Tue, 23 Apr 2024 01:05:59 +0800 Subject: [PATCH 13/16] doc spacing issue fixed. --- docs/source/about/advanced_usage.rst | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/source/about/advanced_usage.rst b/docs/source/about/advanced_usage.rst index 3d5a35a1690..ae15a8704ef 100644 --- a/docs/source/about/advanced_usage.rst +++ b/docs/source/about/advanced_usage.rst @@ -580,12 +580,12 @@ keybindings .. code-block:: text - Info: Detecting displays - Info: Detected display: DVI-D-0 (id: 0) connected: false - Info: Detected display: HDMI-0 (id: 1) connected: true - Info: Detected display: DP-0 (id: 2) connected: true - Info: Detected display: DP-1 (id: 3) connected: false - Info: Detected display: DVI-D-1 (id: 4) connected: false + Info: Detecting displays + Info: Detected display: DVI-D-0 (id: 0) connected: false + Info: Detected display: HDMI-0 (id: 1) connected: true + Info: Detected display: DP-0 (id: 2) connected: true + Info: Detected display: DP-1 (id: 3) connected: false + Info: Detected display: DVI-D-1 (id: 4) connected: false You need to use the id value inside the parenthesis, e.g. ``1``. @@ -594,9 +594,9 @@ keybindings .. code-block:: text - Info: Detecting displays - Info: Detected display: Monitor-0 (id: 3) connected: true - Info: Detected display: Monitor-1 (id: 2) connected: true + Info: Detecting displays + Info: Detected display: Monitor-0 (id: 3) connected: true + Info: Detected display: Monitor-1 (id: 2) connected: true You need to use the id value inside the parenthesis, e.g. ``3``. From 111e6de444660b6b7644b9e55ea364845d8bea98 Mon Sep 17 00:00:00 2001 From: TimmyOVO Date: Tue, 23 Apr 2024 06:14:14 +0800 Subject: [PATCH 14/16] fix: abs mouse input not working in macOS fix: wrong abs mouse coordinates when capturing non-main display in macOS fix: wrong mouse coordinates correction when capturing non-main display in macOS --- src/platform/macos/display.mm | 4 ++++ src/platform/macos/input.cpp | 29 +++++++++++++++++++---------- 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/src/platform/macos/display.mm b/src/platform/macos/display.mm index 3468d46f55e..c01993d9a8f 100644 --- a/src/platform/macos/display.mm +++ b/src/platform/macos/display.mm @@ -145,6 +145,7 @@ // Default to main display display->display_id = CGMainDisplayID(); + // Print all displays available with it's name and id auto display_array = [AVVideo displayNames]; BOOST_LOG(info) << "Detecting displays"sv; @@ -169,6 +170,9 @@ display->width = display->av_capture.frameWidth; display->height = display->av_capture.frameHeight; + // We also need set env_width and env_height for absolute mouse coordinates + display->env_width = display->width; + display->env_height = display->height; return display; } diff --git a/src/platform/macos/input.cpp b/src/platform/macos/input.cpp index 273416680ef..0d308341971 100644 --- a/src/platform/macos/input.cpp +++ b/src/platform/macos/input.cpp @@ -328,15 +328,19 @@ const KeyCodeMap kKeyCodesMap[] = { auto display = macos_input->display; auto event = macos_input->mouse_event; - if (location.x < 0) - location.x = 0; - if (location.x >= (double) CGDisplayPixelsWide(display)) - location.x = (double) CGDisplayPixelsWide(display) - 1; + // get display bounds for current display + CGRect display_bounds = CGDisplayBounds(display); - if (location.y < 0) - location.y = 0; - if (location.y >= (double) CGDisplayPixelsHigh(display)) - location.y = (double) CGDisplayPixelsHigh(display) - 1; + // limit mouse to current display bounds + if (location.x < display_bounds.origin.x) + location.x = display_bounds.origin.x; + if (location.x >= display_bounds.origin.x + display_bounds.size.width) + location.x = display_bounds.origin.x + display_bounds.size.width - 1; + + if (location.y < display_bounds.origin.y) + location.y = display_bounds.origin.y; + if (location.y >= display_bounds.origin.y + display_bounds.size.height) + location.y = display_bounds.origin.y + display_bounds.size.height - 1; CGEventSetType(event, type); CGEventSetLocation(event, location); @@ -379,10 +383,15 @@ const KeyCodeMap kKeyCodesMap[] = { void abs_mouse(input_t &input, const touch_port_t &touch_port, float x, float y) { - auto scaling = ((macos_input_t *) input.get())->displayScaling; + auto macos_input = static_cast(input.get()); + auto scaling = macos_input->displayScaling; + auto display = macos_input->display; CGPoint location = CGPointMake(x * scaling, y * scaling); - + CGRect display_bounds = CGDisplayBounds(display); + // in order to get the correct mouse location for capturing display , we need to add the display bounds to the location + location.x += display_bounds.origin.x; + location.y += display_bounds.origin.y; post_mouse(input, kCGMouseButtonLeft, event_type_mouse(input), location, 0); } From 9f44d3e6998e9c18769a1a1915ae2848ef833115 Mon Sep 17 00:00:00 2001 From: TimmyOVO Date: Tue, 23 Apr 2024 07:49:28 +0800 Subject: [PATCH 15/16] reformat using clang-format --- src/platform/macos/display.mm | 1 - 1 file changed, 1 deletion(-) diff --git a/src/platform/macos/display.mm b/src/platform/macos/display.mm index c01993d9a8f..47b83435e87 100644 --- a/src/platform/macos/display.mm +++ b/src/platform/macos/display.mm @@ -145,7 +145,6 @@ // Default to main display display->display_id = CGMainDisplayID(); - // Print all displays available with it's name and id auto display_array = [AVVideo displayNames]; BOOST_LOG(info) << "Detecting displays"sv; From 4d89d734b70e7e2963aa75ee4a094313c0686712 Mon Sep 17 00:00:00 2001 From: TimmyOVO Date: Wed, 1 May 2024 07:39:44 +0800 Subject: [PATCH 16/16] use std::clamp instead of if statement. --- src/platform/macos/input.cpp | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/src/platform/macos/input.cpp b/src/platform/macos/input.cpp index 0d308341971..11c6d228421 100644 --- a/src/platform/macos/input.cpp +++ b/src/platform/macos/input.cpp @@ -332,15 +332,8 @@ const KeyCodeMap kKeyCodesMap[] = { CGRect display_bounds = CGDisplayBounds(display); // limit mouse to current display bounds - if (location.x < display_bounds.origin.x) - location.x = display_bounds.origin.x; - if (location.x >= display_bounds.origin.x + display_bounds.size.width) - location.x = display_bounds.origin.x + display_bounds.size.width - 1; - - if (location.y < display_bounds.origin.y) - location.y = display_bounds.origin.y; - if (location.y >= display_bounds.origin.y + display_bounds.size.height) - location.y = display_bounds.origin.y + display_bounds.size.height - 1; + location.x = std::clamp(location.x, display_bounds.origin.x, display_bounds.origin.x + display_bounds.size.width - 1); + location.y = std::clamp(location.y, display_bounds.origin.y, display_bounds.origin.y + display_bounds.size.height - 1); CGEventSetType(event, type); CGEventSetLocation(event, location);