From 74b3dc2831d3157994d4fe748d7cbff6bf0c0438 Mon Sep 17 00:00:00 2001 From: Chris Angelico Date: Tue, 14 May 2019 04:05:22 +1000 Subject: [PATCH 01/55] Show alignment (gravity) of scene elements when querying/switching scenes --- src/Utils.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Utils.cpp b/src/Utils.cpp index 1215bf6a..609c5f3d 100644 --- a/src/Utils.cpp +++ b/src/Utils.cpp @@ -126,6 +126,7 @@ obs_data_t* Utils::GetSceneItemData(obs_sceneitem_t* item) { obs_data_set_double(data, "y", pos.y); obs_data_set_int(data, "source_cx", (int)item_width); obs_data_set_int(data, "source_cy", (int)item_height); + obs_data_set_int(data, "alignment", (int)obs_sceneitem_get_alignment(item)); obs_data_set_double(data, "cx", item_width * scale.x); obs_data_set_double(data, "cy", item_height * scale.y); obs_data_set_bool(data, "render", obs_sceneitem_visible(item)); From 2622eb4663dc4e9143b9b0e91a9a01ff09581146 Mon Sep 17 00:00:00 2001 From: Chris Angelico Date: Tue, 14 May 2019 04:09:18 +1000 Subject: [PATCH 02/55] Add alignment to the documented definition of a Source --- docs/generated/comments.json | 8 +++++++- docs/generated/protocol.md | 1 + src/WSRequestHandler_SceneItems.cpp | 1 + 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/docs/generated/comments.json b/docs/generated/comments.json index 0c6dd592..af6f9aed 100644 --- a/docs/generated/comments.json +++ b/docs/generated/comments.json @@ -231,7 +231,8 @@ "{String} `type` Source type. Value is one of the following: \"input\", \"filter\", \"transition\", \"scene\" or \"unknown\"", "{Number} `volume`", "{Number} `x`", - "{Number} `y`" + "{Number} `y`", + "{int} `alignment` The point on the source that the item is manipulated from." ], "properties": [ { @@ -293,6 +294,11 @@ "type": "Number", "name": "y", "description": "" + }, + { + "type": "int", + "name": "alignment", + "description": "The point on the source that the item is manipulated from." } ], "typedefs": [ diff --git a/docs/generated/protocol.md b/docs/generated/protocol.md index 96af5b91..f5b7a976 100644 --- a/docs/generated/protocol.md +++ b/docs/generated/protocol.md @@ -252,6 +252,7 @@ These are complex types, such as `Source` and `Scene`, which are used as argumen | `volume` | _Number_ | | | `x` | _Number_ | | | `y` | _Number_ | | +| `alignment` | _int_ | The point on the source that the item is manipulated from. | ## Scene | Name | Type | Description | | ---- | :---: | ------------| diff --git a/src/WSRequestHandler_SceneItems.cpp b/src/WSRequestHandler_SceneItems.cpp index f30538e1..b3d7a6e3 100644 --- a/src/WSRequestHandler_SceneItems.cpp +++ b/src/WSRequestHandler_SceneItems.cpp @@ -16,6 +16,7 @@ * @property {Number} `volume` * @property {Number} `x` * @property {Number} `y` +* @property {int} `alignment` The point on the source that the item is manipulated from. */ /** From fd32f7f43516528c9730ddba23b2e61d553aad99 Mon Sep 17 00:00:00 2001 From: Chris Angelico Date: Mon, 20 May 2019 00:44:11 +1000 Subject: [PATCH 03/55] Explain how OBS interprets alignment numbers --- src/WSRequestHandler_SceneItems.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/WSRequestHandler_SceneItems.cpp b/src/WSRequestHandler_SceneItems.cpp index 530926fe..7db5c3a3 100644 --- a/src/WSRequestHandler_SceneItems.cpp +++ b/src/WSRequestHandler_SceneItems.cpp @@ -30,7 +30,7 @@ * @return {int} `sourceHeight` Base source (without scaling) of the source * @return {double} `width` Scene item width (base source width multiplied by the horizontal scaling factor) * @return {double} `height` Scene item height (base source height multiplied by the vertical scaling factor) -* @property {int} `alignment` The point on the source that the item is manipulated from. +* @property {int} `alignment` The point on the source that the item is manipulated from. The sum of 1=Left or 2=Right, and 4=Top or 8=Bottom, or omit to center on that axis. * @property {String (optional)} `parentGroupName` Name of the item's parent (if this item belongs to a group) * @property {Array (optional)} `groupChildren` List of children (if this item is a group) * From 47b485819fe8ca4856adeeb4e743cf0c8e58fef3 Mon Sep 17 00:00:00 2001 From: Chris Angelico Date: Mon, 20 May 2019 01:47:25 +1000 Subject: [PATCH 04/55] Update property -> return as this isn't a typedef --- docs/generated/comments.json | 38 +++++++++++++---------------- docs/generated/protocol.md | 3 +++ src/WSRequestHandler_SceneItems.cpp | 6 ++--- 3 files changed, 23 insertions(+), 24 deletions(-) diff --git a/docs/generated/comments.json b/docs/generated/comments.json index 8c7ccfec..1f442e50 100644 --- a/docs/generated/comments.json +++ b/docs/generated/comments.json @@ -3537,10 +3537,8 @@ "{int} `sourceWidth` Base width (without scaling) of the source", "{int} `sourceHeight` Base source (without scaling) of the source", "{double} `width` Scene item width (base source width multiplied by the horizontal scaling factor)", - "{double} `height` Scene item height (base source height multiplied by the vertical scaling factor)" - ], - "property": [ - "{int} `alignment` The point on the source that the item is manipulated from.", + "{double} `height` Scene item height (base source height multiplied by the vertical scaling factor)", + "{int} `alignment` The point on the source that the item is manipulated from. The sum of 1=Left or 2=Right, and 4=Top or 8=Bottom, or omit to center on that axis.", "{String (optional)} `parentGroupName` Name of the item's parent (if this item belongs to a group)", "{Array (optional)} `groupChildren` List of children (if this item is a group)" ], @@ -3653,6 +3651,21 @@ "type": "double", "name": "height", "description": "Scene item height (base source height multiplied by the vertical scaling factor)" + }, + { + "type": "int", + "name": "alignment", + "description": "The point on the source that the item is manipulated from. The sum of 1=Left or 2=Right, and 4=Top or 8=Bottom, or omit to center on that axis." + }, + { + "type": "String (optional)", + "name": "parentGroupName", + "description": "Name of the item's parent (if this item belongs to a group)" + }, + { + "type": "Array (optional)", + "name": "groupChildren", + "description": "List of children (if this item is a group)" } ], "params": [ @@ -3667,23 +3680,6 @@ "description": "The name of the source." } ], - "properties": [ - { - "type": "int", - "name": "alignment", - "description": "The point on the source that the item is manipulated from." - }, - { - "type": "String (optional)", - "name": "parentGroupName", - "description": "Name of the item's parent (if this item belongs to a group)" - }, - { - "type": "Array (optional)", - "name": "groupChildren", - "description": "List of children (if this item is a group)" - } - ], "names": [ { "name": "", diff --git a/docs/generated/protocol.md b/docs/generated/protocol.md index d5e803bd..43a64558 100644 --- a/docs/generated/protocol.md +++ b/docs/generated/protocol.md @@ -1559,6 +1559,9 @@ Coordinates are relative to the item's parent (the scene or group it belongs to) | `sourceHeight` | _int_ | Base source (without scaling) of the source | | `width` | _double_ | Scene item width (base source width multiplied by the horizontal scaling factor) | | `height` | _double_ | Scene item height (base source height multiplied by the vertical scaling factor) | +| `alignment` | _int_ | The point on the source that the item is manipulated from. The sum of 1=Left or 2=Right, and 4=Top or 8=Bottom, or omit to center on that axis. | +| `parentGroupName` | _String (optional)_ | Name of the item's parent (if this item belongs to a group) | +| `groupChildren` | _Array<SceneItemTransform> (optional)_ | List of children (if this item is a group) | --- diff --git a/src/WSRequestHandler_SceneItems.cpp b/src/WSRequestHandler_SceneItems.cpp index 7db5c3a3..200244c7 100644 --- a/src/WSRequestHandler_SceneItems.cpp +++ b/src/WSRequestHandler_SceneItems.cpp @@ -30,9 +30,9 @@ * @return {int} `sourceHeight` Base source (without scaling) of the source * @return {double} `width` Scene item width (base source width multiplied by the horizontal scaling factor) * @return {double} `height` Scene item height (base source height multiplied by the vertical scaling factor) -* @property {int} `alignment` The point on the source that the item is manipulated from. The sum of 1=Left or 2=Right, and 4=Top or 8=Bottom, or omit to center on that axis. -* @property {String (optional)} `parentGroupName` Name of the item's parent (if this item belongs to a group) -* @property {Array (optional)} `groupChildren` List of children (if this item is a group) +* @return {int} `alignment` The point on the source that the item is manipulated from. The sum of 1=Left or 2=Right, and 4=Top or 8=Bottom, or omit to center on that axis. +* @return {String (optional)} `parentGroupName` Name of the item's parent (if this item belongs to a group) +* @return {Array (optional)} `groupChildren` List of children (if this item is a group) * * @api requests * @name GetSceneItemProperties From 6d0d07abfe5151d53ef0ddcf4c5c064dc34bf54f Mon Sep 17 00:00:00 2001 From: Chris Angelico Date: Sat, 11 May 2019 05:46:47 +1000 Subject: [PATCH 05/55] Fire an event whenever an item is locked/unlocked --- src/WSEvents.cpp | 42 ++++++++++++++++++++++++++++++++++++++++++ src/WSEvents.h | 1 + 2 files changed, 43 insertions(+) diff --git a/src/WSEvents.cpp b/src/WSEvents.cpp index 4e978cc4..405cdebe 100644 --- a/src/WSEvents.cpp +++ b/src/WSEvents.cpp @@ -304,6 +304,8 @@ void WSEvents::connectSourceSignals(obs_source_t* source) { signal_handler_connect(sh, "item_remove", OnSceneItemDelete, this); signal_handler_connect(sh, "item_visible", OnSceneItemVisibilityChanged, this); + signal_handler_connect(sh, + "item_locked", OnSceneItemLockedChanged, this); signal_handler_connect(sh, "item_transform", OnSceneItemTransform, this); signal_handler_connect(sh, "item_select", OnSceneItemSelected, this); signal_handler_connect(sh, "item_deselect", OnSceneItemDeselected, this); @@ -333,6 +335,8 @@ void WSEvents::disconnectSourceSignals(obs_source_t* source) { signal_handler_disconnect(sh, "item_remove", OnSceneItemDelete, this); signal_handler_disconnect(sh, "item_visible", OnSceneItemVisibilityChanged, this); + signal_handler_disconnect(sh, + "item_locked", OnSceneItemLockedChanged, this); signal_handler_disconnect(sh, "item_transform", OnSceneItemTransform, this); signal_handler_disconnect(sh, "item_select", OnSceneItemSelected, this); signal_handler_disconnect(sh, "item_deselect", OnSceneItemDeselected, this); @@ -1453,6 +1457,44 @@ void WSEvents::OnSceneItemVisibilityChanged(void* param, calldata_t* data) { instance->broadcastUpdate("SceneItemVisibilityChanged", fields); } +/** + * An item's locked status has been toggled. + * + * @return {String} `scene-name` Name of the scene. + * @return {String} `item-name` Name of the item in the scene. + * @return {int} `item-id` Scene item ID + * @return {boolean} `item-locked` New locked state of the item. + * + * @api events + * @name SceneItemLockedChanged + * @category sources + * @since 4.7.0 + */ +void WSEvents::OnSceneItemLockedChanged(void* param, calldata_t* data) { + auto instance = reinterpret_cast(param); + + obs_scene_t* scene = nullptr; + calldata_get_ptr(data, "scene", &scene); + + obs_sceneitem_t* sceneItem = nullptr; + calldata_get_ptr(data, "item", &sceneItem); + + bool locked = false; + calldata_get_bool(data, "locked", &locked); + + const char* sceneName = + obs_source_get_name(obs_scene_get_source(scene)); + const char* sceneItemName = + obs_source_get_name(obs_sceneitem_get_source(sceneItem)); + + OBSDataAutoRelease fields = obs_data_create(); + obs_data_set_string(fields, "scene-name", sceneName); + obs_data_set_string(fields, "item-name", sceneItemName); + obs_data_set_int(fields, "item-id", obs_sceneitem_get_id(sceneItem)); + obs_data_set_bool(fields, "item-locked", locked); + instance->broadcastUpdate("SceneItemLockedChanged", fields); +} + /** * An item's transform has been changed. * diff --git a/src/WSEvents.h b/src/WSEvents.h index 684fe654..ec2621fe 100644 --- a/src/WSEvents.h +++ b/src/WSEvents.h @@ -136,6 +136,7 @@ private: static void OnSceneItemAdd(void* param, calldata_t* data); static void OnSceneItemDelete(void* param, calldata_t* data); static void OnSceneItemVisibilityChanged(void* param, calldata_t* data); + static void OnSceneItemLockedChanged(void* param, calldata_t* data); static void OnSceneItemTransform(void* param, calldata_t* data); static void OnSceneItemSelected(void* param, calldata_t* data); static void OnSceneItemDeselected(void* param, calldata_t* data); From 3b7e9b4eba6ddea067689859e99ca6981665fa58 Mon Sep 17 00:00:00 2001 From: Chris Angelico Date: Tue, 21 May 2019 12:36:57 +1000 Subject: [PATCH 06/55] Create a command for opening a projector. Depends on obs-studio#1910 for back end functionality. --- src/WSRequestHandler.cpp | 1 + src/WSRequestHandler.h | 1 + src/WSRequestHandler_General.cpp | 25 +++++++++++++++++++++++++ 3 files changed, 27 insertions(+) diff --git a/src/WSRequestHandler.cpp b/src/WSRequestHandler.cpp index 8b31c0b7..3458a043 100644 --- a/src/WSRequestHandler.cpp +++ b/src/WSRequestHandler.cpp @@ -32,6 +32,7 @@ QHash WSRequestHandler::messageM { "GetStats", WSRequestHandler::HandleGetStats }, { "SetHeartbeat", WSRequestHandler::HandleSetHeartbeat }, { "GetVideoInfo", WSRequestHandler::HandleGetVideoInfo }, + { "OpenProjector", WSRequestHandler::HandleOpenProjector }, { "SetFilenameFormatting", WSRequestHandler::HandleSetFilenameFormatting }, { "GetFilenameFormatting", WSRequestHandler::HandleGetFilenameFormatting }, diff --git a/src/WSRequestHandler.h b/src/WSRequestHandler.h index 0e729e55..62bbc01d 100644 --- a/src/WSRequestHandler.h +++ b/src/WSRequestHandler.h @@ -79,6 +79,7 @@ class WSRequestHandler : public QObject { static HandlerResponse HandleGetStats(WSRequestHandler* req); static HandlerResponse HandleSetHeartbeat(WSRequestHandler* req); static HandlerResponse HandleGetVideoInfo(WSRequestHandler* req); + static HandlerResponse HandleOpenProjector(WSRequestHandler* req); static HandlerResponse HandleSetFilenameFormatting(WSRequestHandler* req); static HandlerResponse HandleGetFilenameFormatting(WSRequestHandler* req); diff --git a/src/WSRequestHandler_General.cpp b/src/WSRequestHandler_General.cpp index ecb3f48f..d98d0c4f 100644 --- a/src/WSRequestHandler_General.cpp +++ b/src/WSRequestHandler_General.cpp @@ -298,3 +298,28 @@ HandlerResponse WSRequestHandler::HandleGetVideoInfo(WSRequestHandler* req) { obs_data_set_string(response, "scaleType", describe_scale_type(ovi.scale_type)); return req->SendOKResponse(response); } + +/** + * Open a projector window or create a projector on a monitor. + * + * @param {String (Optional)} `type` Type of projector: Preview (default), Source, Scene, StudioProgram, or Multiview (case insensitive). + * @param {int (Optional)} `monitor` Monitor to open the projector on. If -1 or omitted, opens a window. + * @param {String (Optional)} `geometry` Size and position of the projector window (only if monitor is -1). Encoded in base 64. + * @param {String (Optional)} `name` Name of the source or scene to be displayed (ignored for other projector types). + * + * @api requests + * @name OpenProjector + * @category general + * @since 4.7.0 + */ +HandlerResponse WSRequestHandler::HandleOpenProjector(WSRequestHandler* req) { + const char *type = obs_data_get_string(req->data, "type"); + int monitor = -1; + if (req->hasField("monitor")) { + monitor = obs_data_get_int(req->data, "monitor"); + } + const char *geometry = obs_data_get_string(req->data, "geometry"); + const char *name = obs_data_get_string(req->data, "name"); + obs_frontend_open_projector(type, monitor, geometry, name); + return req->SendOKResponse(); +} From edbb28038f1de5a54ce19aa5b8eb00ffefa6ebaf Mon Sep 17 00:00:00 2001 From: Chris Angelico Date: Mon, 25 Nov 2019 22:36:17 +1100 Subject: [PATCH 07/55] Guard open_projector() with a version check. I can't find a way to probe for an actual feature here. --- src/WSRequestHandler_General.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/WSRequestHandler_General.cpp b/src/WSRequestHandler_General.cpp index d98d0c4f..b4654db1 100644 --- a/src/WSRequestHandler_General.cpp +++ b/src/WSRequestHandler_General.cpp @@ -313,6 +313,7 @@ HandlerResponse WSRequestHandler::HandleGetVideoInfo(WSRequestHandler* req) { * @since 4.7.0 */ HandlerResponse WSRequestHandler::HandleOpenProjector(WSRequestHandler* req) { + #if LIBOBS_API_VER >= 0x18000003 const char *type = obs_data_get_string(req->data, "type"); int monitor = -1; if (req->hasField("monitor")) { @@ -322,4 +323,7 @@ HandlerResponse WSRequestHandler::HandleOpenProjector(WSRequestHandler* req) { const char *name = obs_data_get_string(req->data, "name"); obs_frontend_open_projector(type, monitor, geometry, name); return req->SendOKResponse(); + #else + return req->SendErrorResponse("Projector opening requires libobs v21.0.3 or newer."); + #endif } From c0eb4d652b244ae89b4ab9a364c484ec26496c34 Mon Sep 17 00:00:00 2001 From: Chris Angelico Date: Tue, 26 Nov 2019 00:48:24 +1100 Subject: [PATCH 08/55] Mention the OBS version requirement in the docos --- docs/generated/comments.json | 61 ++++++++++++++++++++++++++++++++ docs/generated/protocol.md | 24 +++++++++++++ src/WSRequestHandler_General.cpp | 6 ++-- 3 files changed, 88 insertions(+), 3 deletions(-) diff --git a/docs/generated/comments.json b/docs/generated/comments.json index 559467e0..2a03e6f2 100644 --- a/docs/generated/comments.json +++ b/docs/generated/comments.json @@ -3287,6 +3287,67 @@ "lead": "", "type": "class", "examples": [] + }, + { + "subheads": [], + "description": "Open a projector window or create a projector on a monitor. Requires OBS v24.0.4 or newer.", + "param": [ + "{String (Optional)} `type` Type of projector: Preview (default), Source, Scene, StudioProgram, or Multiview (case insensitive).", + "{int (Optional)} `monitor` Monitor to open the projector on. If -1 or omitted, opens a window.", + "{String (Optional)} `geometry` Size and position of the projector window (only if monitor is -1). Encoded in base 64.", + "{String (Optional)} `name` Name of the source or scene to be displayed (ignored for other projector types)." + ], + "api": "requests", + "name": "OpenProjector", + "category": "general", + "since": "4.7.0", + "params": [ + { + "type": "String (Optional)", + "name": "type", + "description": "Type of projector: Preview (default), Source, Scene, StudioProgram, or Multiview (case insensitive)." + }, + { + "type": "int (Optional)", + "name": "monitor", + "description": "Monitor to open the projector on. If -1 or omitted, opens a window." + }, + { + "type": "String (Optional)", + "name": "geometry", + "description": "Size and position of the projector window (only if monitor is -1). Encoded in base 64." + }, + { + "type": "String (Optional)", + "name": "name", + "description": "Name of the source or scene to be displayed (ignored for other projector types)." + } + ], + "names": [ + { + "name": "", + "description": "OpenProjector" + } + ], + "categories": [ + { + "name": "", + "description": "general" + } + ], + "sinces": [ + { + "name": "", + "description": "4.7.0" + } + ], + "heading": { + "level": 2, + "text": "OpenProjector" + }, + "lead": "", + "type": "class", + "examples": [] } ], "outputs": [ diff --git a/docs/generated/protocol.md b/docs/generated/protocol.md index 81edecea..114fb463 100644 --- a/docs/generated/protocol.md +++ b/docs/generated/protocol.md @@ -118,6 +118,7 @@ auth_response = base64_encode(auth_response_hash) + [GetStats](#getstats) + [BroadcastCustomMessage](#broadcastcustommessage-1) + [GetVideoInfo](#getvideoinfo) + + [OpenProjector](#openprojector) * [Outputs](#outputs) + [ListOutputs](#listoutputs) + [GetOutputInfo](#getoutputinfo) @@ -1332,6 +1333,29 @@ _No specified parameters._ | `colorRange` | _String_ | Color range (full or partial) | +--- + +### OpenProjector + + +- Added in v4.7.0 + +Open a projector window or create a projector on a monitor. Requires OBS v24.0.4 or newer. + +**Request Fields:** + +| Name | Type | Description | +| ---- | :---: | ------------| +| `type` | _String (Optional)_ | Type of projector: Preview (default), Source, Scene, StudioProgram, or Multiview (case insensitive). | +| `monitor` | _int (Optional)_ | Monitor to open the projector on. If -1 or omitted, opens a window. | +| `geometry` | _String (Optional)_ | Size and position of the projector window (only if monitor is -1). Encoded in base 64. | +| `name` | _String (Optional)_ | Name of the source or scene to be displayed (ignored for other projector types). | + + +**Response Items:** + +_No additional response items._ + --- ## Outputs diff --git a/src/WSRequestHandler_General.cpp b/src/WSRequestHandler_General.cpp index b4654db1..821a87a8 100644 --- a/src/WSRequestHandler_General.cpp +++ b/src/WSRequestHandler_General.cpp @@ -300,7 +300,7 @@ HandlerResponse WSRequestHandler::HandleGetVideoInfo(WSRequestHandler* req) { } /** - * Open a projector window or create a projector on a monitor. + * Open a projector window or create a projector on a monitor. Requires OBS v24.0.4 or newer. * * @param {String (Optional)} `type` Type of projector: Preview (default), Source, Scene, StudioProgram, or Multiview (case insensitive). * @param {int (Optional)} `monitor` Monitor to open the projector on. If -1 or omitted, opens a window. @@ -313,7 +313,7 @@ HandlerResponse WSRequestHandler::HandleGetVideoInfo(WSRequestHandler* req) { * @since 4.7.0 */ HandlerResponse WSRequestHandler::HandleOpenProjector(WSRequestHandler* req) { - #if LIBOBS_API_VER >= 0x18000003 + #if LIBOBS_API_VER >= 0x18000004 const char *type = obs_data_get_string(req->data, "type"); int monitor = -1; if (req->hasField("monitor")) { @@ -324,6 +324,6 @@ HandlerResponse WSRequestHandler::HandleOpenProjector(WSRequestHandler* req) { obs_frontend_open_projector(type, monitor, geometry, name); return req->SendOKResponse(); #else - return req->SendErrorResponse("Projector opening requires libobs v21.0.3 or newer."); + return req->SendErrorResponse("Projector opening requires libobs v21.0.4 or newer."); #endif } From 78584b31942ab468b75616b9e88440a23c55fb65 Mon Sep 17 00:00:00 2001 From: Chris Angelico Date: Tue, 26 Nov 2019 00:59:57 +1100 Subject: [PATCH 09/55] Fix version number in message --- src/WSRequestHandler_General.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/WSRequestHandler_General.cpp b/src/WSRequestHandler_General.cpp index 821a87a8..43bf3783 100644 --- a/src/WSRequestHandler_General.cpp +++ b/src/WSRequestHandler_General.cpp @@ -324,6 +324,6 @@ HandlerResponse WSRequestHandler::HandleOpenProjector(WSRequestHandler* req) { obs_frontend_open_projector(type, monitor, geometry, name); return req->SendOKResponse(); #else - return req->SendErrorResponse("Projector opening requires libobs v21.0.4 or newer."); + return req->SendErrorResponse("Projector opening requires libobs v24.0.4 or newer."); #endif } From b3b2ae267a2951399ed2edaeb68963b7ccab02e3 Mon Sep 17 00:00:00 2001 From: tt2468 Date: Sat, 15 Feb 2020 07:39:01 -0800 Subject: [PATCH 10/55] Update WSRequestHandler_Streaming.cpp --- src/WSRequestHandler_Streaming.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/WSRequestHandler_Streaming.cpp b/src/WSRequestHandler_Streaming.cpp index 4ee77d8b..67655021 100644 --- a/src/WSRequestHandler_Streaming.cpp +++ b/src/WSRequestHandler_Streaming.cpp @@ -212,7 +212,7 @@ RpcResponse WSRequestHandler::SetStreamSettings(const RpcRequest& request) { if (requestedType != nullptr && requestedType != serviceType) { OBSDataAutoRelease hotkeys = obs_hotkeys_save_service(service); service = obs_service_create( - requestedType.toUtf8(), STREAM_SERVICE_ID, requestSettings, hotkeys); + STREAM_SERVICE_ID, requestedType.toUtf8(), requestSettings, hotkeys); } else { // If type isn't changing, we should overlay the settings we got // to the existing settings. By doing so, you can send a request that From 30db1a8a63d5a166f1a405122dc58eaf5ccc1590 Mon Sep 17 00:00:00 2001 From: tt2468 Date: Sat, 15 Feb 2020 08:50:09 -0800 Subject: [PATCH 11/55] Update WSRequestHandler_Streaming.cpp --- src/WSRequestHandler_Streaming.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/WSRequestHandler_Streaming.cpp b/src/WSRequestHandler_Streaming.cpp index 67655021..7471bb1a 100644 --- a/src/WSRequestHandler_Streaming.cpp +++ b/src/WSRequestHandler_Streaming.cpp @@ -137,13 +137,13 @@ RpcResponse WSRequestHandler::StartStreaming(const RpcRequest& request) { obs_data_apply(updatedSettings, newSettings); //then apply the settings from the request should they exist newService = obs_service_create( - newType.toUtf8(), STREAM_SERVICE_ID, + STREAM_SERVICE_ID, newType.toUtf8(), updatedSettings, csHotkeys); } else { // Service type changed: override service settings newService = obs_service_create( - newType.toUtf8(), STREAM_SERVICE_ID, + STREAM_SERVICE_ID, newType.toUtf8(), newSettings, csHotkeys); } From 1057d765f77cfbe7656c3350f37ae30a41ef0a09 Mon Sep 17 00:00:00 2001 From: Alex Van Camp Date: Thu, 6 Feb 2020 18:44:28 -0600 Subject: [PATCH 12/55] feat(events): add "TransitionEnd" and "TransitionVideoEnd" events Adds events for `TransitionEnd` and `TransitionVideoEnd`. `TransitionVideoEnd` is specific to Stinger transitions. It is fired when their video has actually completed playback. This is important, because `TransitionEnd` is fired at the cut point of the Stinger, which is nice to have but isn't always what the user might want. This builds on #409, and should be merged after it. --- src/Utils.cpp | 24 +++++++++++++ src/Utils.h | 1 + src/WSEvents.cpp | 93 ++++++++++++++++++++++++++++++++++-------------- src/WSEvents.h | 6 ++-- 4 files changed, 96 insertions(+), 28 deletions(-) diff --git a/src/Utils.cpp b/src/Utils.cpp index cb381d0f..6e5f98db 100644 --- a/src/Utils.cpp +++ b/src/Utils.cpp @@ -413,6 +413,30 @@ bool Utils::SetTransitionByName(QString transitionName) { } } +obs_data_t* Utils::GetTransitionData(obs_source_t* transition) { + int duration = Utils::GetTransitionDuration(transition); + if (duration < 0) { + blog(LOG_WARNING, "GetTransitionData: duration is negative !"); + } + + obs_data_t* transitionData = obs_data_create(); + obs_data_set_string(transitionData, "name", obs_source_get_name(transition)); + obs_data_set_string(transitionData, "type", obs_source_get_id(transition)); + obs_data_set_int(transitionData, "duration", duration); + + OBSSourceAutoRelease sourceScene = obs_transition_get_source(transition, OBS_TRANSITION_SOURCE_A); + if (sourceScene) { + obs_data_set_string(transitionData, "from-scene", obs_source_get_name(sourceScene)); + } + + OBSSourceAutoRelease destinationScene = obs_transition_get_active_source(transition); + if (destinationScene) { + obs_data_set_string(transitionData, "to-scene", obs_source_get_name(destinationScene)); + } + + return transitionData; +} + QString Utils::OBSVersionString() { uint32_t version = obs_get_version(); diff --git a/src/Utils.h b/src/Utils.h index 4259c2e6..4f8a8e7e 100644 --- a/src/Utils.h +++ b/src/Utils.h @@ -60,6 +60,7 @@ namespace Utils { int GetTransitionDuration(obs_source_t* transition); obs_source_t* GetTransitionFromName(QString transitionName); bool SetTransitionByName(QString transitionName); + obs_data_t* GetTransitionData(obs_source_t* transition); QString OBSVersionString(); diff --git a/src/WSEvents.cpp b/src/WSEvents.cpp index 619aea7a..d964efdc 100644 --- a/src/WSEvents.cpp +++ b/src/WSEvents.cpp @@ -122,7 +122,7 @@ void WSEvents::FrontendEventHandler(enum obs_frontend_event event, void* private switch (event) { case OBS_FRONTEND_EVENT_FINISHED_LOADING: - owner->hookTransitionBeginEvent(); + owner->hookTransitionPlaybackEvents(); break; case OBS_FRONTEND_EVENT_SCENE_CHANGED: @@ -134,7 +134,7 @@ void WSEvents::FrontendEventHandler(enum obs_frontend_event event, void* private break; case OBS_FRONTEND_EVENT_SCENE_COLLECTION_CHANGED: - owner->hookTransitionBeginEvent(); + owner->hookTransitionPlaybackEvents(); owner->OnSceneCollectionChange(); break; @@ -147,7 +147,7 @@ void WSEvents::FrontendEventHandler(enum obs_frontend_event event, void* private break; case OBS_FRONTEND_EVENT_TRANSITION_LIST_CHANGED: - owner->hookTransitionBeginEvent(); + owner->hookTransitionPlaybackEvents(); owner->OnTransitionListChange(); break; @@ -231,7 +231,7 @@ void WSEvents::FrontendEventHandler(enum obs_frontend_event event, void* private break; case OBS_FRONTEND_EVENT_EXIT: - owner->unhookTransitionBeginEvent(); + owner->unhookTransitionPlaybackEvents(); owner->OnExit(); break; } @@ -309,6 +309,8 @@ void WSEvents::disconnectSourceSignals(obs_source_t* source) { signal_handler_disconnect(sh, "item_deselect", OnSceneItemDeselected, this); signal_handler_disconnect(sh, "transition_start", OnTransitionBegin, this); + signal_handler_disconnect(sh, "transition_stop", OnTransitionEnd, this); + signal_handler_disconnect(sh, "transition_video_stop", OnTransitionVideoEnd, this); } void WSEvents::connectFilterSignals(obs_source_t* filter) { @@ -331,7 +333,7 @@ void WSEvents::disconnectFilterSignals(obs_source_t* filter) { signal_handler_disconnect(sh, "enable", OnSourceFilterVisibilityChanged, this); } -void WSEvents::hookTransitionBeginEvent() { +void WSEvents::hookTransitionPlaybackEvents() { obs_frontend_source_list transitions = {}; obs_frontend_get_transitions(&transitions); @@ -340,12 +342,16 @@ void WSEvents::hookTransitionBeginEvent() { signal_handler_t* sh = obs_source_get_signal_handler(transition); signal_handler_disconnect(sh, "transition_start", OnTransitionBegin, this); signal_handler_connect(sh, "transition_start", OnTransitionBegin, this); + signal_handler_disconnect(sh, "transition_stop", OnTransitionEnd, this); + signal_handler_connect(sh, "transition_stop", OnTransitionEnd, this); + signal_handler_disconnect(sh, "transition_video_stop", OnTransitionVideoEnd, this); + signal_handler_connect(sh, "transition_video_stop", OnTransitionVideoEnd, this); } obs_frontend_source_list_free(&transitions); } -void WSEvents::unhookTransitionBeginEvent() { +void WSEvents::unhookTransitionPlaybackEvents() { obs_frontend_source_list transitions = {}; obs_frontend_get_transitions(&transitions); @@ -353,6 +359,8 @@ void WSEvents::unhookTransitionBeginEvent() { obs_source_t* transition = transitions.sources.array[i]; signal_handler_t* sh = obs_source_get_signal_handler(transition); signal_handler_disconnect(sh, "transition_start", OnTransitionBegin, this); + signal_handler_disconnect(sh, "transition_stop", OnTransitionEnd, this); + signal_handler_disconnect(sh, "transition_video_stop", OnTransitionVideoEnd, this); } obs_frontend_source_list_free(&transitions); @@ -895,29 +903,62 @@ void WSEvents::OnTransitionBegin(void* param, calldata_t* data) { return; } - int duration = Utils::GetTransitionDuration(transition); - if (duration < 0) { - blog(LOG_WARNING, "OnTransitionBegin: duration is negative !"); - } - - OBSDataAutoRelease fields = obs_data_create(); - obs_data_set_string(fields, "name", obs_source_get_name(transition)); - obs_data_set_string(fields, "type", obs_source_get_id(transition)); - obs_data_set_int(fields, "duration", duration); - - OBSSourceAutoRelease sourceScene = obs_transition_get_source(transition, OBS_TRANSITION_SOURCE_A); - if (sourceScene) { - obs_data_set_string(fields, "from-scene", obs_source_get_name(sourceScene)); - } - - OBSSourceAutoRelease destinationScene = obs_transition_get_active_source(transition); - if (destinationScene) { - obs_data_set_string(fields, "to-scene", obs_source_get_name(destinationScene)); - } - + OBSDataAutoRelease fields = Utils::GetTransitionData(transition); instance->broadcastUpdate("TransitionBegin", fields); } +/** +* A transition (other than "cut") has ended. +* +* @return {String} `name` Transition name. +* @return {String} `type` Transition type. +* @return {int} `duration` Transition duration (in milliseconds). +* @return {String} `from-scene` Source scene of the transition +* @return {String} `to-scene` Destination scene of the transition +* +* @api events +* @name TransitionEnd +* @category transitions +* @since 4.8.0 +*/ +void WSEvents::OnTransitionEnd(void* param, calldata_t* data) { + auto instance = reinterpret_cast(param); + + OBSSource transition = calldata_get_pointer(data, "source"); + if (!transition) { + return; + } + + OBSDataAutoRelease fields = Utils::GetTransitionData(transition); + instance->broadcastUpdate("TransitionEnd", fields); +} + +/** +* A stinger transition has finished playing its video. +* +* @return {String} `name` Transition name. +* @return {String} `type` Transition type. +* @return {int} `duration` Transition duration (in milliseconds). +* @return {String} `from-scene` Source scene of the transition +* @return {String} `to-scene` Destination scene of the transition +* +* @api events +* @name TransitionVideoEnd +* @category transitions +* @since 4.8.0 +*/ +void WSEvents::OnTransitionVideoEnd(void* param, calldata_t* data) { + auto instance = reinterpret_cast(param); + + OBSSource transition = calldata_get_pointer(data, "source"); + if (!transition) { + return; + } + + OBSDataAutoRelease fields = Utils::GetTransitionData(transition); + instance->broadcastUpdate("TransitionVideoEnd", fields); +} + /** * A source has been created. A source can be an input, a scene or a transition. * diff --git a/src/WSEvents.h b/src/WSEvents.h index 684fe654..05972fd0 100644 --- a/src/WSEvents.h +++ b/src/WSEvents.h @@ -43,8 +43,8 @@ public: void connectFilterSignals(obs_source_t* filter); void disconnectFilterSignals(obs_source_t* filter); - void hookTransitionBeginEvent(); - void unhookTransitionBeginEvent(); + void hookTransitionPlaybackEvents(); + void unhookTransitionPlaybackEvents(); uint64_t getStreamingTime(); uint64_t getRecordingTime(); @@ -116,6 +116,8 @@ private: enum obs_frontend_event event, void* privateData); static void OnTransitionBegin(void* param, calldata_t* data); + static void OnTransitionEnd(void* param, calldata_t* data); + static void OnTransitionVideoEnd(void* param, calldata_t* data); static void OnSourceCreate(void* param, calldata_t* data); static void OnSourceDestroy(void* param, calldata_t* data); From e1cb57563a6a08353581e4a9b6b233440f182af6 Mon Sep 17 00:00:00 2001 From: Alex Van Camp Date: Thu, 6 Feb 2020 19:28:05 -0600 Subject: [PATCH 13/55] fix(events): don't advertise a false duration for fixed transitions Some transitions, such as Stingers, have a fixed duration. There is currently no way to retrieve this value from the API, and `obs-websocket` will currently return an incorrect value when one of these transitions begins. For now, I think it is better to explicitly return -1, which is a better indicator that we have no idea what the real duration is, instead of a misleading number which users might think looks correct at first glance. --- src/Utils.cpp | 7 +++++++ src/WSEvents.cpp | 4 +++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/Utils.cpp b/src/Utils.cpp index cb381d0f..bf0ade73 100644 --- a/src/Utils.cpp +++ b/src/Utils.cpp @@ -387,6 +387,13 @@ int Utils::GetTransitionDuration(obs_source_t* transition) { return 0; } + if (obs_transition_fixed(transition)) { + // If this transition has a fixed duration (such as a Stinger), + // we don't currently have a way of retrieving that number. + // For now, return -1 to indicate that we don't know the actual duration. + return -1; + } + OBSSourceAutoRelease destinationScene = obs_transition_get_active_source(transition); OBSDataAutoRelease destinationSettings = obs_source_get_private_settings(destinationScene); diff --git a/src/WSEvents.cpp b/src/WSEvents.cpp index 619aea7a..4bb4cdc3 100644 --- a/src/WSEvents.cpp +++ b/src/WSEvents.cpp @@ -878,7 +878,9 @@ void WSEvents::TransitionDurationChanged(int ms) { * * @return {String} `name` Transition name. * @return {String} `type` Transition type. - * @return {int} `duration` Transition duration (in milliseconds). + * @return {int} `duration` Transition duration (in milliseconds). + * Will be -1 for any transition with a fixed duration, + * such as a Stinger, due to limitations of the OBS API. * @return {String} `from-scene` Source scene of the transition * @return {String} `to-scene` Destination scene of the transition * From 9c11bbc7a16f8f7e245135648c897692785cd55f Mon Sep 17 00:00:00 2001 From: tt2468 Date: Sat, 15 Feb 2020 10:58:10 -0800 Subject: [PATCH 14/55] Update WSRequestHandler_Streaming.cpp --- src/WSRequestHandler_Streaming.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/WSRequestHandler_Streaming.cpp b/src/WSRequestHandler_Streaming.cpp index 7471bb1a..f1c631f7 100644 --- a/src/WSRequestHandler_Streaming.cpp +++ b/src/WSRequestHandler_Streaming.cpp @@ -213,6 +213,7 @@ RpcResponse WSRequestHandler::SetStreamSettings(const RpcRequest& request) { OBSDataAutoRelease hotkeys = obs_hotkeys_save_service(service); service = obs_service_create( STREAM_SERVICE_ID, requestedType.toUtf8(), requestSettings, hotkeys); + obs_frontend_set_streaming_service(service); } else { // If type isn't changing, we should overlay the settings we got // to the existing settings. By doing so, you can send a request that From 79a7b444a2029947e861c74d6a97cfb986c07a6d Mon Sep 17 00:00:00 2001 From: tt2468 Date: Sat, 15 Feb 2020 11:00:24 -0800 Subject: [PATCH 15/55] Update WSRequestHandler_Streaming.cpp --- src/WSRequestHandler_Streaming.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/WSRequestHandler_Streaming.cpp b/src/WSRequestHandler_Streaming.cpp index f1c631f7..c6ac2952 100644 --- a/src/WSRequestHandler_Streaming.cpp +++ b/src/WSRequestHandler_Streaming.cpp @@ -212,7 +212,7 @@ RpcResponse WSRequestHandler::SetStreamSettings(const RpcRequest& request) { if (requestedType != nullptr && requestedType != serviceType) { OBSDataAutoRelease hotkeys = obs_hotkeys_save_service(service); service = obs_service_create( - STREAM_SERVICE_ID, requestedType.toUtf8(), requestSettings, hotkeys); + requestedType.toUtf8(), STREAM_SERVICE_ID, requestSettings, hotkeys); obs_frontend_set_streaming_service(service); } else { // If type isn't changing, we should overlay the settings we got From c02f40beb60e3be5134a4635c09d505aa0210471 Mon Sep 17 00:00:00 2001 From: tt2468 Date: Sat, 15 Feb 2020 14:18:25 -0800 Subject: [PATCH 16/55] Update WSRequestHandler_Streaming.cpp --- src/WSRequestHandler_Streaming.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/WSRequestHandler_Streaming.cpp b/src/WSRequestHandler_Streaming.cpp index c6ac2952..fc60a4d3 100644 --- a/src/WSRequestHandler_Streaming.cpp +++ b/src/WSRequestHandler_Streaming.cpp @@ -137,13 +137,13 @@ RpcResponse WSRequestHandler::StartStreaming(const RpcRequest& request) { obs_data_apply(updatedSettings, newSettings); //then apply the settings from the request should they exist newService = obs_service_create( - STREAM_SERVICE_ID, newType.toUtf8(), + newType.toUtf8(), STREAM_SERVICE_ID, updatedSettings, csHotkeys); } else { // Service type changed: override service settings newService = obs_service_create( - STREAM_SERVICE_ID, newType.toUtf8(), + newType.toUtf8(), STREAM_SERVICE_ID, newSettings, csHotkeys); } From 2845fd07a7f3aafbe703bfc6f1ddbc2891662aa2 Mon Sep 17 00:00:00 2001 From: tt2468 Date: Sat, 15 Feb 2020 14:22:35 -0800 Subject: [PATCH 17/55] Final fixes before testing --- src/WSRequestHandler_Streaming.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/WSRequestHandler_Streaming.cpp b/src/WSRequestHandler_Streaming.cpp index fc60a4d3..4746e4c2 100644 --- a/src/WSRequestHandler_Streaming.cpp +++ b/src/WSRequestHandler_Streaming.cpp @@ -236,7 +236,9 @@ RpcResponse WSRequestHandler::SetStreamSettings(const RpcRequest& request) { obs_frontend_save_streaming_service(); } - OBSDataAutoRelease serviceSettings = obs_service_get_settings(service); + OBSService responseService = obs_frontend_get_streaming_service(); + OBSDataAutoRelease serviceSettings = obs_service_get_settings(responseService); + const char* responseType = obs_service_get_type(responseService); OBSDataAutoRelease response = obs_data_create(); obs_data_set_string(response, "type", requestedType.toUtf8()); From 22fbb4262ccc41eda3eccbca95f5d9b27ca6ef1a Mon Sep 17 00:00:00 2001 From: tt2468 Date: Sat, 15 Feb 2020 14:47:46 -0800 Subject: [PATCH 18/55] Return check type instead of type provided in request --- src/WSRequestHandler_Streaming.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/WSRequestHandler_Streaming.cpp b/src/WSRequestHandler_Streaming.cpp index 4746e4c2..99bd419c 100644 --- a/src/WSRequestHandler_Streaming.cpp +++ b/src/WSRequestHandler_Streaming.cpp @@ -241,7 +241,7 @@ RpcResponse WSRequestHandler::SetStreamSettings(const RpcRequest& request) { const char* responseType = obs_service_get_type(responseService); OBSDataAutoRelease response = obs_data_create(); - obs_data_set_string(response, "type", requestedType.toUtf8()); + obs_data_set_string(response, "type", responseType.toUtf8()); obs_data_set_obj(response, "settings", serviceSettings); return request.success(response); From ca938828704e639f759f2489ffcd6b88f2da913c Mon Sep 17 00:00:00 2001 From: tt2468 Date: Sat, 15 Feb 2020 14:51:59 -0800 Subject: [PATCH 19/55] Remove unnecessary utf8 string conversion --- src/WSRequestHandler_Streaming.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/WSRequestHandler_Streaming.cpp b/src/WSRequestHandler_Streaming.cpp index 99bd419c..5c4bb227 100644 --- a/src/WSRequestHandler_Streaming.cpp +++ b/src/WSRequestHandler_Streaming.cpp @@ -241,7 +241,7 @@ RpcResponse WSRequestHandler::SetStreamSettings(const RpcRequest& request) { const char* responseType = obs_service_get_type(responseService); OBSDataAutoRelease response = obs_data_create(); - obs_data_set_string(response, "type", responseType.toUtf8()); + obs_data_set_string(response, "type", responseType); obs_data_set_obj(response, "settings", serviceSettings); return request.success(response); From e1c92956f8a282996bb6e51261b56af7cad4b63f Mon Sep 17 00:00:00 2001 From: Travis CI <> Date: Wed, 4 Mar 2020 09:57:04 +0000 Subject: [PATCH 20/55] docs(travis): Update protocol.md - 9233d4f [skip ci] --- docs/generated/comments.json | 4 ++-- docs/generated/protocol.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/generated/comments.json b/docs/generated/comments.json index e21f0201..77a21a0e 100644 --- a/docs/generated/comments.json +++ b/docs/generated/comments.json @@ -769,7 +769,7 @@ "return": [ "{String} `name` Transition name.", "{String} `type` Transition type.", - "{int} `duration` Transition duration (in milliseconds).", + "{int} `duration` Transition duration (in milliseconds). Will be -1 for any transition with a fixed duration, such as a Stinger, due to limitations of the OBS API.", "{String} `from-scene` Source scene of the transition", "{String} `to-scene` Destination scene of the transition" ], @@ -791,7 +791,7 @@ { "type": "int", "name": "duration", - "description": "Transition duration (in milliseconds)." + "description": "Transition duration (in milliseconds). Will be -1 for any transition with a fixed duration, such as a Stinger, due to limitations of the OBS API." }, { "type": "String", diff --git a/docs/generated/protocol.md b/docs/generated/protocol.md index bf1cb9e0..8f066073 100644 --- a/docs/generated/protocol.md +++ b/docs/generated/protocol.md @@ -433,7 +433,7 @@ A transition (other than "cut") has begun. | ---- | :---: | ------------| | `name` | _String_ | Transition name. | | `type` | _String_ | Transition type. | -| `duration` | _int_ | Transition duration (in milliseconds). | +| `duration` | _int_ | Transition duration (in milliseconds). Will be -1 for any transition with a fixed duration, such as a Stinger, due to limitations of the OBS API. | | `from-scene` | _String_ | Source scene of the transition | | `to-scene` | _String_ | Destination scene of the transition | From ec1926f7a687507ecd67512986f045837e80ad32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Lepin?= Date: Wed, 4 Mar 2020 11:26:48 +0100 Subject: [PATCH 21/55] events: fix @since value for SceneItemLockedChanged --- src/WSEvents.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/WSEvents.cpp b/src/WSEvents.cpp index 405cdebe..7a4e488a 100644 --- a/src/WSEvents.cpp +++ b/src/WSEvents.cpp @@ -1468,7 +1468,7 @@ void WSEvents::OnSceneItemVisibilityChanged(void* param, calldata_t* data) { * @api events * @name SceneItemLockedChanged * @category sources - * @since 4.7.0 + * @since unreleased */ void WSEvents::OnSceneItemLockedChanged(void* param, calldata_t* data) { auto instance = reinterpret_cast(param); From 45d5f4a760d5bf7871f829c22708264f256f6325 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Lepin?= Date: Wed, 4 Mar 2020 14:04:26 +0100 Subject: [PATCH 22/55] events: rename SceneItemLockedChanged to SceneItemLockChanged --- src/WSEvents.cpp | 10 +++++----- src/WSEvents.h | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/WSEvents.cpp b/src/WSEvents.cpp index 7a4e488a..efc5980b 100644 --- a/src/WSEvents.cpp +++ b/src/WSEvents.cpp @@ -305,7 +305,7 @@ void WSEvents::connectSourceSignals(obs_source_t* source) { signal_handler_connect(sh, "item_visible", OnSceneItemVisibilityChanged, this); signal_handler_connect(sh, - "item_locked", OnSceneItemLockedChanged, this); + "item_locked", OnSceneItemLockChanged, this); signal_handler_connect(sh, "item_transform", OnSceneItemTransform, this); signal_handler_connect(sh, "item_select", OnSceneItemSelected, this); signal_handler_connect(sh, "item_deselect", OnSceneItemDeselected, this); @@ -336,7 +336,7 @@ void WSEvents::disconnectSourceSignals(obs_source_t* source) { signal_handler_disconnect(sh, "item_visible", OnSceneItemVisibilityChanged, this); signal_handler_disconnect(sh, - "item_locked", OnSceneItemLockedChanged, this); + "item_locked", OnSceneItemLockChanged, this); signal_handler_disconnect(sh, "item_transform", OnSceneItemTransform, this); signal_handler_disconnect(sh, "item_select", OnSceneItemSelected, this); signal_handler_disconnect(sh, "item_deselect", OnSceneItemDeselected, this); @@ -1466,11 +1466,11 @@ void WSEvents::OnSceneItemVisibilityChanged(void* param, calldata_t* data) { * @return {boolean} `item-locked` New locked state of the item. * * @api events - * @name SceneItemLockedChanged + * @name SceneItemLockChanged * @category sources * @since unreleased */ -void WSEvents::OnSceneItemLockedChanged(void* param, calldata_t* data) { +void WSEvents::OnSceneItemLockChanged(void* param, calldata_t* data) { auto instance = reinterpret_cast(param); obs_scene_t* scene = nullptr; @@ -1492,7 +1492,7 @@ void WSEvents::OnSceneItemLockedChanged(void* param, calldata_t* data) { obs_data_set_string(fields, "item-name", sceneItemName); obs_data_set_int(fields, "item-id", obs_sceneitem_get_id(sceneItem)); obs_data_set_bool(fields, "item-locked", locked); - instance->broadcastUpdate("SceneItemLockedChanged", fields); + instance->broadcastUpdate("SceneItemLockChanged", fields); } /** diff --git a/src/WSEvents.h b/src/WSEvents.h index ec2621fe..bca3ce87 100644 --- a/src/WSEvents.h +++ b/src/WSEvents.h @@ -136,7 +136,7 @@ private: static void OnSceneItemAdd(void* param, calldata_t* data); static void OnSceneItemDelete(void* param, calldata_t* data); static void OnSceneItemVisibilityChanged(void* param, calldata_t* data); - static void OnSceneItemLockedChanged(void* param, calldata_t* data); + static void OnSceneItemLockChanged(void* param, calldata_t* data); static void OnSceneItemTransform(void* param, calldata_t* data); static void OnSceneItemSelected(void* param, calldata_t* data); static void OnSceneItemDeselected(void* param, calldata_t* data); From a0e0910117b229134f86ded2c73d452498c7d1e5 Mon Sep 17 00:00:00 2001 From: Travis CI <> Date: Wed, 4 Mar 2020 13:11:56 +0000 Subject: [PATCH 23/55] docs(travis): Update protocol.md - 8a7d7a4 [skip ci] --- docs/generated/comments.json | 61 ++++++++++++++++++++++++++++++++++++ docs/generated/protocol.md | 20 ++++++++++++ 2 files changed, 81 insertions(+) diff --git a/docs/generated/comments.json b/docs/generated/comments.json index d4f06420..f7406bda 100644 --- a/docs/generated/comments.json +++ b/docs/generated/comments.json @@ -2566,6 +2566,67 @@ "type": "class", "examples": [] }, + { + "subheads": [], + "description": "An item's locked status has been toggled.", + "return": [ + "{String} `scene-name` Name of the scene.", + "{String} `item-name` Name of the item in the scene.", + "{int} `item-id` Scene item ID", + "{boolean} `item-locked` New locked state of the item." + ], + "api": "events", + "name": "SceneItemLockChanged", + "category": "sources", + "since": "unreleased", + "returns": [ + { + "type": "String", + "name": "scene-name", + "description": "Name of the scene." + }, + { + "type": "String", + "name": "item-name", + "description": "Name of the item in the scene." + }, + { + "type": "int", + "name": "item-id", + "description": "Scene item ID" + }, + { + "type": "boolean", + "name": "item-locked", + "description": "New locked state of the item." + } + ], + "names": [ + { + "name": "", + "description": "SceneItemLockChanged" + } + ], + "categories": [ + { + "name": "", + "description": "sources" + } + ], + "sinces": [ + { + "name": "", + "description": "unreleased" + } + ], + "heading": { + "level": 2, + "text": "SceneItemLockChanged" + }, + "lead": "", + "type": "class", + "examples": [] + }, { "subheads": [], "description": "An item's transform has been changed.", diff --git a/docs/generated/protocol.md b/docs/generated/protocol.md index cd0f1cb9..5c4782bb 100644 --- a/docs/generated/protocol.md +++ b/docs/generated/protocol.md @@ -101,6 +101,7 @@ auth_response = base64_encode(auth_response_hash) + [SceneItemAdded](#sceneitemadded) + [SceneItemRemoved](#sceneitemremoved) + [SceneItemVisibilityChanged](#sceneitemvisibilitychanged) + + [SceneItemLockChanged](#sceneitemlockchanged) + [SceneItemTransformChanged](#sceneitemtransformchanged) + [SceneItemSelected](#sceneitemselected) + [SceneItemDeselected](#sceneitemdeselected) @@ -1030,6 +1031,25 @@ An item's visibility has been toggled. | `item-visible` | _boolean_ | New visibility state of the item. | +--- + +### SceneItemLockChanged + + +- Unreleased + +An item's locked status has been toggled. + +**Response Items:** + +| Name | Type | Description | +| ---- | :---: | ------------| +| `scene-name` | _String_ | Name of the scene. | +| `item-name` | _String_ | Name of the item in the scene. | +| `item-id` | _int_ | Scene item ID | +| `item-locked` | _boolean_ | New locked state of the item. | + + --- ### SceneItemTransformChanged From 9fc41e4245c5d168c45bccd1338c457b78101642 Mon Sep 17 00:00:00 2001 From: Chris Angelico Date: Thu, 5 Mar 2020 05:14:46 +1100 Subject: [PATCH 24/55] Apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes all the easy ones. I'll look into the more substantive changes in a bit. Co-Authored-By: Stéphane Lepin --- src/WSRequestHandler_General.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/WSRequestHandler_General.cpp b/src/WSRequestHandler_General.cpp index 8d3794ed..762dcea7 100644 --- a/src/WSRequestHandler_General.cpp +++ b/src/WSRequestHandler_General.cpp @@ -316,10 +316,10 @@ RpcResponse WSRequestHandler::GetVideoInfo(const RpcRequest& request) { * @api requests * @name OpenProjector * @category general - * @since 4.7.0 + * @since unreleased */ RpcResponse WSRequestHandler::OpenProjector(const RpcRequest& request) { - #if LIBOBS_API_VER >= 0x18000004 +#if LIBOBS_API_VER >= 0x18000004 const char *type = obs_data_get_string(request.parameters(), "type"); int monitor = -1; if (request.hasField("monitor")) { @@ -329,7 +329,7 @@ RpcResponse WSRequestHandler::OpenProjector(const RpcRequest& request) { const char *name = obs_data_get_string(request.parameters(), "name"); obs_frontend_open_projector(type, monitor, geometry, name); return request.success(); - #else +#else return request.failed("Projector opening requires libobs v24.0.4 or newer."); - #endif +#endif } From afcc11af570574b95fa25350ead04e8e70739050 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Lepin?= Date: Thu, 5 Mar 2020 10:08:59 +0100 Subject: [PATCH 25/55] docs: replace stream service option use-auth with use_auth --- src/WSRequestHandler_Streaming.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/WSRequestHandler_Streaming.cpp b/src/WSRequestHandler_Streaming.cpp index 5c4bb227..a39f0cce 100644 --- a/src/WSRequestHandler_Streaming.cpp +++ b/src/WSRequestHandler_Streaming.cpp @@ -67,9 +67,9 @@ RpcResponse WSRequestHandler::StartStopStreaming(const RpcRequest& request) { * @param {Object (optional)} `stream.settings` Settings for the stream. * @param {String (optional)} `stream.settings.server` The publish URL. * @param {String (optional)} `stream.settings.key` The publish key of the stream. - * @param {boolean (optional)} `stream.settings.use-auth` Indicates whether authentication should be used when connecting to the streaming server. - * @param {String (optional)} `stream.settings.username` If authentication is enabled, the username for the streaming server. Ignored if `use-auth` is not set to `true`. - * @param {String (optional)} `stream.settings.password` If authentication is enabled, the password for the streaming server. Ignored if `use-auth` is not set to `true`. + * @param {boolean (optional)} `stream.settings.use_auth` Indicates whether authentication should be used when connecting to the streaming server. + * @param {String (optional)} `stream.settings.username` If authentication is enabled, the username for the streaming server. Ignored if `use_auth` is not set to `true`. + * @param {String (optional)} `stream.settings.password` If authentication is enabled, the password for the streaming server. Ignored if `use_auth` is not set to `true`. * * @api requests * @name StartStreaming @@ -188,7 +188,7 @@ RpcResponse WSRequestHandler::StopStreaming(const RpcRequest& request) { * @param {Object} `settings` The actual settings of the stream. * @param {String (optional)} `settings.server` The publish URL. * @param {String (optional)} `settings.key` The publish key. - * @param {boolean (optional)} `settings.use-auth` Indicates whether authentication should be used when connecting to the streaming server. + * @param {boolean (optional)} `settings.use_auth` Indicates whether authentication should be used when connecting to the streaming server. * @param {String (optional)} `settings.username` The username for the streaming service. * @param {String (optional)} `settings.password` The password for the streaming service. * @param {boolean} `save` Persist the settings to disk. @@ -254,9 +254,9 @@ RpcResponse WSRequestHandler::SetStreamSettings(const RpcRequest& request) { * @return {Object} `settings` Stream settings object. * @return {String} `settings.server` The publish URL. * @return {String} `settings.key` The publish key of the stream. - * @return {boolean} `settings.use-auth` Indicates whether authentication should be used when connecting to the streaming server. - * @return {String} `settings.username` The username to use when accessing the streaming server. Only present if `use-auth` is `true`. - * @return {String} `settings.password` The password to use when accessing the streaming server. Only present if `use-auth` is `true`. + * @return {boolean} `settings.use_auth` Indicates whether authentication should be used when connecting to the streaming server. + * @return {String} `settings.username` The username to use when accessing the streaming server. Only present if `use_auth` is `true`. + * @return {String} `settings.password` The password to use when accessing the streaming server. Only present if `use_auth` is `true`. * * @api requests * @name GetStreamSettings From 0eaef1ac3be2954a454ebb044848cc68364fb2db Mon Sep 17 00:00:00 2001 From: Travis CI <> Date: Thu, 5 Mar 2020 09:24:10 +0000 Subject: [PATCH 26/55] docs(travis): Update protocol.md - 27245cc [skip ci] --- docs/generated/comments.json | 28 ++++++++++++++-------------- docs/generated/protocol.md | 14 +++++++------- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/docs/generated/comments.json b/docs/generated/comments.json index f7406bda..6d24c74a 100644 --- a/docs/generated/comments.json +++ b/docs/generated/comments.json @@ -7540,9 +7540,9 @@ "{Object (optional)} `stream.settings` Settings for the stream.", "{String (optional)} `stream.settings.server` The publish URL.", "{String (optional)} `stream.settings.key` The publish key of the stream.", - "{boolean (optional)} `stream.settings.use-auth` Indicates whether authentication should be used when connecting to the streaming server.", - "{String (optional)} `stream.settings.username` If authentication is enabled, the username for the streaming server. Ignored if `use-auth` is not set to `true`.", - "{String (optional)} `stream.settings.password` If authentication is enabled, the password for the streaming server. Ignored if `use-auth` is not set to `true`." + "{boolean (optional)} `stream.settings.use_auth` Indicates whether authentication should be used when connecting to the streaming server.", + "{String (optional)} `stream.settings.username` If authentication is enabled, the username for the streaming server. Ignored if `use_auth` is not set to `true`.", + "{String (optional)} `stream.settings.password` If authentication is enabled, the password for the streaming server. Ignored if `use_auth` is not set to `true`." ], "api": "requests", "name": "StartStreaming", @@ -7581,18 +7581,18 @@ }, { "type": "boolean (optional)", - "name": "stream.settings.use-auth", + "name": "stream.settings.use_auth", "description": "Indicates whether authentication should be used when connecting to the streaming server." }, { "type": "String (optional)", "name": "stream.settings.username", - "description": "If authentication is enabled, the username for the streaming server. Ignored if `use-auth` is not set to `true`." + "description": "If authentication is enabled, the username for the streaming server. Ignored if `use_auth` is not set to `true`." }, { "type": "String (optional)", "name": "stream.settings.password", - "description": "If authentication is enabled, the password for the streaming server. Ignored if `use-auth` is not set to `true`." + "description": "If authentication is enabled, the password for the streaming server. Ignored if `use_auth` is not set to `true`." } ], "names": [ @@ -7662,7 +7662,7 @@ "{Object} `settings` The actual settings of the stream.", "{String (optional)} `settings.server` The publish URL.", "{String (optional)} `settings.key` The publish key.", - "{boolean (optional)} `settings.use-auth` Indicates whether authentication should be used when connecting to the streaming server.", + "{boolean (optional)} `settings.use_auth` Indicates whether authentication should be used when connecting to the streaming server.", "{String (optional)} `settings.username` The username for the streaming service.", "{String (optional)} `settings.password` The password for the streaming service.", "{boolean} `save` Persist the settings to disk." @@ -7694,7 +7694,7 @@ }, { "type": "boolean (optional)", - "name": "settings.use-auth", + "name": "settings.use_auth", "description": "Indicates whether authentication should be used when connecting to the streaming server." }, { @@ -7747,9 +7747,9 @@ "{Object} `settings` Stream settings object.", "{String} `settings.server` The publish URL.", "{String} `settings.key` The publish key of the stream.", - "{boolean} `settings.use-auth` Indicates whether authentication should be used when connecting to the streaming server.", - "{String} `settings.username` The username to use when accessing the streaming server. Only present if `use-auth` is `true`.", - "{String} `settings.password` The password to use when accessing the streaming server. Only present if `use-auth` is `true`." + "{boolean} `settings.use_auth` Indicates whether authentication should be used when connecting to the streaming server.", + "{String} `settings.username` The username to use when accessing the streaming server. Only present if `use_auth` is `true`.", + "{String} `settings.password` The password to use when accessing the streaming server. Only present if `use_auth` is `true`." ], "api": "requests", "name": "GetStreamSettings", @@ -7778,18 +7778,18 @@ }, { "type": "boolean", - "name": "settings.use-auth", + "name": "settings.use_auth", "description": "Indicates whether authentication should be used when connecting to the streaming server." }, { "type": "String", "name": "settings.username", - "description": "The username to use when accessing the streaming server. Only present if `use-auth` is `true`." + "description": "The username to use when accessing the streaming server. Only present if `use_auth` is `true`." }, { "type": "String", "name": "settings.password", - "description": "The password to use when accessing the streaming server. Only present if `use-auth` is `true`." + "description": "The password to use when accessing the streaming server. Only present if `use_auth` is `true`." } ], "names": [ diff --git a/docs/generated/protocol.md b/docs/generated/protocol.md index 5c4782bb..34e5e574 100644 --- a/docs/generated/protocol.md +++ b/docs/generated/protocol.md @@ -2926,9 +2926,9 @@ Will return an `error` if streaming is already active. | `stream.settings` | _Object (optional)_ | Settings for the stream. | | `stream.settings.server` | _String (optional)_ | The publish URL. | | `stream.settings.key` | _String (optional)_ | The publish key of the stream. | -| `stream.settings.use-auth` | _boolean (optional)_ | Indicates whether authentication should be used when connecting to the streaming server. | -| `stream.settings.username` | _String (optional)_ | If authentication is enabled, the username for the streaming server. Ignored if `use-auth` is not set to `true`. | -| `stream.settings.password` | _String (optional)_ | If authentication is enabled, the password for the streaming server. Ignored if `use-auth` is not set to `true`. | +| `stream.settings.use_auth` | _boolean (optional)_ | Indicates whether authentication should be used when connecting to the streaming server. | +| `stream.settings.username` | _String (optional)_ | If authentication is enabled, the username for the streaming server. Ignored if `use_auth` is not set to `true`. | +| `stream.settings.password` | _String (optional)_ | If authentication is enabled, the password for the streaming server. Ignored if `use_auth` is not set to `true`. | **Response Items:** @@ -2970,7 +2970,7 @@ Sets one or more attributes of the current streaming server settings. Any option | `settings` | _Object_ | The actual settings of the stream. | | `settings.server` | _String (optional)_ | The publish URL. | | `settings.key` | _String (optional)_ | The publish key. | -| `settings.use-auth` | _boolean (optional)_ | Indicates whether authentication should be used when connecting to the streaming server. | +| `settings.use_auth` | _boolean (optional)_ | Indicates whether authentication should be used when connecting to the streaming server. | | `settings.username` | _String (optional)_ | The username for the streaming service. | | `settings.password` | _String (optional)_ | The password for the streaming service. | | `save` | _boolean_ | Persist the settings to disk. | @@ -3001,9 +3001,9 @@ _No specified parameters._ | `settings` | _Object_ | Stream settings object. | | `settings.server` | _String_ | The publish URL. | | `settings.key` | _String_ | The publish key of the stream. | -| `settings.use-auth` | _boolean_ | Indicates whether authentication should be used when connecting to the streaming server. | -| `settings.username` | _String_ | The username to use when accessing the streaming server. Only present if `use-auth` is `true`. | -| `settings.password` | _String_ | The password to use when accessing the streaming server. Only present if `use-auth` is `true`. | +| `settings.use_auth` | _boolean_ | Indicates whether authentication should be used when connecting to the streaming server. | +| `settings.username` | _String_ | The username to use when accessing the streaming server. Only present if `use_auth` is `true`. | +| `settings.password` | _String_ | The password to use when accessing the streaming server. Only present if `use_auth` is `true`. | --- From f4f760a231b9fe9988c901d7e8a8a6785eb6b3e1 Mon Sep 17 00:00:00 2001 From: Chris Angelico Date: Wed, 11 Mar 2020 22:05:37 +1100 Subject: [PATCH 27/55] Punt on explaining what the geometry string actually means --- src/WSRequestHandler_General.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/WSRequestHandler_General.cpp b/src/WSRequestHandler_General.cpp index 762dcea7..aca02d59 100644 --- a/src/WSRequestHandler_General.cpp +++ b/src/WSRequestHandler_General.cpp @@ -310,13 +310,13 @@ RpcResponse WSRequestHandler::GetVideoInfo(const RpcRequest& request) { * * @param {String (Optional)} `type` Type of projector: Preview (default), Source, Scene, StudioProgram, or Multiview (case insensitive). * @param {int (Optional)} `monitor` Monitor to open the projector on. If -1 or omitted, opens a window. - * @param {String (Optional)} `geometry` Size and position of the projector window (only if monitor is -1). Encoded in base 64. + * @param {String (Optional)} `geometry` Size and position of the projector window (only if monitor is -1). Encoded in base 64. Corresponds to OBS's saved projectors. * @param {String (Optional)} `name` Name of the source or scene to be displayed (ignored for other projector types). * * @api requests * @name OpenProjector * @category general - * @since unreleased + * @since unreleased */ RpcResponse WSRequestHandler::OpenProjector(const RpcRequest& request) { #if LIBOBS_API_VER >= 0x18000004 From 62ad1a483c91dc21b4186c8325586fbf04a90668 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Lepin?= Date: Wed, 11 Mar 2020 12:09:08 +0100 Subject: [PATCH 28/55] docs(OpenProjector): add info on geometry encoding --- src/WSRequestHandler_General.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/WSRequestHandler_General.cpp b/src/WSRequestHandler_General.cpp index aca02d59..c957da49 100644 --- a/src/WSRequestHandler_General.cpp +++ b/src/WSRequestHandler_General.cpp @@ -310,7 +310,7 @@ RpcResponse WSRequestHandler::GetVideoInfo(const RpcRequest& request) { * * @param {String (Optional)} `type` Type of projector: Preview (default), Source, Scene, StudioProgram, or Multiview (case insensitive). * @param {int (Optional)} `monitor` Monitor to open the projector on. If -1 or omitted, opens a window. - * @param {String (Optional)} `geometry` Size and position of the projector window (only if monitor is -1). Encoded in base 64. Corresponds to OBS's saved projectors. + * @param {String (Optional)} `geometry` Size and position of the projector window (only if monitor is -1). Encoded in Base64 using Qt's geometry encoding (https://doc.qt.io/qt-5/qwidget.html#saveGeometry). Corresponds to OBS's saved projectors. * @param {String (Optional)} `name` Name of the source or scene to be displayed (ignored for other projector types). * * @api requests From 053faa16618653e81c59626e64a911f74cc1ae3c Mon Sep 17 00:00:00 2001 From: Travis CI <> Date: Wed, 11 Mar 2020 11:12:19 +0000 Subject: [PATCH 29/55] docs(travis): Update protocol.md - 6d63779 [skip ci] --- docs/generated/comments.json | 8 ++++---- docs/generated/protocol.md | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/generated/comments.json b/docs/generated/comments.json index 83c1a9b3..64706283 100644 --- a/docs/generated/comments.json +++ b/docs/generated/comments.json @@ -3361,13 +3361,13 @@ "param": [ "{String (Optional)} `type` Type of projector: Preview (default), Source, Scene, StudioProgram, or Multiview (case insensitive).", "{int (Optional)} `monitor` Monitor to open the projector on. If -1 or omitted, opens a window.", - "{String (Optional)} `geometry` Size and position of the projector window (only if monitor is -1). Encoded in base 64.", + "{String (Optional)} `geometry` Size and position of the projector window (only if monitor is -1). Encoded in Base64 using Qt's geometry encoding (https://doc.qt.io/qt-5/qwidget.html#saveGeometry). Corresponds to OBS's saved projectors.", "{String (Optional)} `name` Name of the source or scene to be displayed (ignored for other projector types)." ], "api": "requests", "name": "OpenProjector", "category": "general", - "since": "4.7.0", + "since": "unreleased", "params": [ { "type": "String (Optional)", @@ -3382,7 +3382,7 @@ { "type": "String (Optional)", "name": "geometry", - "description": "Size and position of the projector window (only if monitor is -1). Encoded in base 64." + "description": "Size and position of the projector window (only if monitor is -1). Encoded in Base64 using Qt's geometry encoding (https://doc.qt.io/qt-5/qwidget.html#saveGeometry). Corresponds to OBS's saved projectors." }, { "type": "String (Optional)", @@ -3405,7 +3405,7 @@ "sinces": [ { "name": "", - "description": "4.7.0" + "description": "unreleased" } ], "heading": { diff --git a/docs/generated/protocol.md b/docs/generated/protocol.md index c0ecefc7..7e6dbbec 100644 --- a/docs/generated/protocol.md +++ b/docs/generated/protocol.md @@ -1359,7 +1359,7 @@ _No specified parameters._ ### OpenProjector -- Added in v4.7.0 +- Unreleased Open a projector window or create a projector on a monitor. Requires OBS v24.0.4 or newer. @@ -1369,7 +1369,7 @@ Open a projector window or create a projector on a monitor. Requires OBS v24.0.4 | ---- | :---: | ------------| | `type` | _String (Optional)_ | Type of projector: Preview (default), Source, Scene, StudioProgram, or Multiview (case insensitive). | | `monitor` | _int (Optional)_ | Monitor to open the projector on. If -1 or omitted, opens a window. | -| `geometry` | _String (Optional)_ | Size and position of the projector window (only if monitor is -1). Encoded in base 64. | +| `geometry` | _String (Optional)_ | Size and position of the projector window (only if monitor is -1). Encoded in Base64 using Qt's geometry encoding (https://doc.qt.io/qt-5/qwidget.html#saveGeometry). Corresponds to OBS's saved projectors. | | `name` | _String (Optional)_ | Name of the source or scene to be displayed (ignored for other projector types). | From ef47c172c52178a4e3ed357342e50b943061a15d Mon Sep 17 00:00:00 2001 From: Chris Angelico Date: Wed, 11 Mar 2020 22:52:33 +1100 Subject: [PATCH 30/55] Utils: Add a 'muted' flag to GetSceneItems --- src/Utils.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Utils.cpp b/src/Utils.cpp index 9146457c..43d1ad83 100644 --- a/src/Utils.cpp +++ b/src/Utils.cpp @@ -146,6 +146,7 @@ obs_data_t* Utils::GetSceneItemData(obs_sceneitem_t* item) { obs_data_set_double(data, "y", pos.y); obs_data_set_int(data, "source_cx", (int)item_width); obs_data_set_int(data, "source_cy", (int)item_height); + obs_data_set_bool(data, "muted", obs_source_muted(itemSource)); obs_data_set_int(data, "alignment", (int)obs_sceneitem_get_alignment(item)); obs_data_set_double(data, "cx", item_width * scale.x); obs_data_set_double(data, "cy", item_height * scale.y); From be1022782944415be452834eac1a914a54ec890f Mon Sep 17 00:00:00 2001 From: Chris Angelico Date: Wed, 11 Mar 2020 23:01:25 +1100 Subject: [PATCH 31/55] Utils,GetSceneItemProperties: Document both muted and alignment --- docs/generated/comments.json | 26 ++++++++++++++++++++++---- docs/generated/protocol.md | 7 +++++-- src/Utils.cpp | 2 ++ src/WSRequestHandler_SceneItems.cpp | 1 + 4 files changed, 30 insertions(+), 6 deletions(-) diff --git a/docs/generated/comments.json b/docs/generated/comments.json index 83c1a9b3..67755474 100644 --- a/docs/generated/comments.json +++ b/docs/generated/comments.json @@ -6,9 +6,11 @@ "property": [ "{Number} `cy`", "{Number} `cx`", + "{Number} `alignment` The point on the source that the item is manipulated from. The sum of 1=Left or 2=Right, and 4=Top or 8=Bottom, or omit to center on that axis.", "{String} `name` The name of this Scene Item.", "{int} `id` Scene item ID", "{Boolean} `render` Whether or not this Scene Item is set to \"visible\".", + "{Boolean} `muted` Whether or not this Scene Item is muted.", "{Boolean} `locked` Whether or not this Scene Item is locked and can't be moved around", "{Number} `source_cx`", "{Number} `source_cy`", @@ -30,6 +32,11 @@ "name": "cx", "description": "" }, + { + "type": "Number", + "name": "alignment", + "description": "The point on the source that the item is manipulated from. The sum of 1=Left or 2=Right, and 4=Top or 8=Bottom, or omit to center on that axis." + }, { "type": "String", "name": "name", @@ -45,6 +52,11 @@ "name": "render", "description": "Whether or not this Scene Item is set to \"visible\"." }, + { + "type": "Boolean", + "name": "muted", + "description": "Whether or not this Scene Item is muted." + }, { "type": "Boolean", "name": "locked", @@ -3361,13 +3373,13 @@ "param": [ "{String (Optional)} `type` Type of projector: Preview (default), Source, Scene, StudioProgram, or Multiview (case insensitive).", "{int (Optional)} `monitor` Monitor to open the projector on. If -1 or omitted, opens a window.", - "{String (Optional)} `geometry` Size and position of the projector window (only if monitor is -1). Encoded in base 64.", + "{String (Optional)} `geometry` Size and position of the projector window (only if monitor is -1). Encoded in Base64 using Qt's geometry encoding (https://doc.qt.io/qt-5/qwidget.html#saveGeometry). Corresponds to OBS's saved projectors.", "{String (Optional)} `name` Name of the source or scene to be displayed (ignored for other projector types)." ], "api": "requests", "name": "OpenProjector", "category": "general", - "since": "4.7.0", + "since": "unreleased", "params": [ { "type": "String (Optional)", @@ -3382,7 +3394,7 @@ { "type": "String (Optional)", "name": "geometry", - "description": "Size and position of the projector window (only if monitor is -1). Encoded in base 64." + "description": "Size and position of the projector window (only if monitor is -1). Encoded in Base64 using Qt's geometry encoding (https://doc.qt.io/qt-5/qwidget.html#saveGeometry). Corresponds to OBS's saved projectors." }, { "type": "String (Optional)", @@ -3405,7 +3417,7 @@ "sinces": [ { "name": "", - "description": "4.7.0" + "description": "unreleased" } ], "heading": { @@ -4253,6 +4265,7 @@ "{int} `crop.bottom` The number of pixels cropped off the bottom of the source before scaling.", "{int} `crop.left` The number of pixels cropped off the left of the source before scaling.", "{bool} `visible` If the source is visible.", + "{bool} `muted` If the source is muted.", "{bool} `locked` If the source's transform is locked.", "{String} `bounds.type` Type of bounding box. Can be \"OBS_BOUNDS_STRETCH\", \"OBS_BOUNDS_SCALE_INNER\", \"OBS_BOUNDS_SCALE_OUTER\", \"OBS_BOUNDS_SCALE_TO_WIDTH\", \"OBS_BOUNDS_SCALE_TO_HEIGHT\", \"OBS_BOUNDS_MAX_ONLY\" or \"OBS_BOUNDS_NONE\".", "{int} `bounds.alignment` Alignment of the bounding box.", @@ -4331,6 +4344,11 @@ "name": "visible", "description": "If the source is visible." }, + { + "type": "bool", + "name": "muted", + "description": "If the source is muted." + }, { "type": "bool", "name": "locked", diff --git a/docs/generated/protocol.md b/docs/generated/protocol.md index c0ecefc7..9114a712 100644 --- a/docs/generated/protocol.md +++ b/docs/generated/protocol.md @@ -224,9 +224,11 @@ These are complex types, such as `Source` and `Scene`, which are used as argumen | ---- | :---: | ------------| | `cy` | _Number_ | | | `cx` | _Number_ | | +| `alignment` | _Number_ | The point on the source that the item is manipulated from. The sum of 1=Left or 2=Right, and 4=Top or 8=Bottom, or omit to center on that axis. | | `name` | _String_ | The name of this Scene Item. | | `id` | _int_ | Scene item ID | | `render` | _Boolean_ | Whether or not this Scene Item is set to "visible". | +| `muted` | _Boolean_ | Whether or not this Scene Item is muted. | | `locked` | _Boolean_ | Whether or not this Scene Item is locked and can't be moved around | | `source_cx` | _Number_ | | | `source_cy` | _Number_ | | @@ -1359,7 +1361,7 @@ _No specified parameters._ ### OpenProjector -- Added in v4.7.0 +- Unreleased Open a projector window or create a projector on a monitor. Requires OBS v24.0.4 or newer. @@ -1369,7 +1371,7 @@ Open a projector window or create a projector on a monitor. Requires OBS v24.0.4 | ---- | :---: | ------------| | `type` | _String (Optional)_ | Type of projector: Preview (default), Source, Scene, StudioProgram, or Multiview (case insensitive). | | `monitor` | _int (Optional)_ | Monitor to open the projector on. If -1 or omitted, opens a window. | -| `geometry` | _String (Optional)_ | Size and position of the projector window (only if monitor is -1). Encoded in base 64. | +| `geometry` | _String (Optional)_ | Size and position of the projector window (only if monitor is -1). Encoded in Base64 using Qt's geometry encoding (https://doc.qt.io/qt-5/qwidget.html#saveGeometry). Corresponds to OBS's saved projectors. | | `name` | _String (Optional)_ | Name of the source or scene to be displayed (ignored for other projector types). | @@ -1835,6 +1837,7 @@ Coordinates are relative to the item's parent (the scene or group it belongs to) | `crop.bottom` | _int_ | The number of pixels cropped off the bottom of the source before scaling. | | `crop.left` | _int_ | The number of pixels cropped off the left of the source before scaling. | | `visible` | _bool_ | If the source is visible. | +| `muted` | _bool_ | If the source is muted. | | `locked` | _bool_ | If the source's transform is locked. | | `bounds.type` | _String_ | Type of bounding box. Can be "OBS_BOUNDS_STRETCH", "OBS_BOUNDS_SCALE_INNER", "OBS_BOUNDS_SCALE_OUTER", "OBS_BOUNDS_SCALE_TO_WIDTH", "OBS_BOUNDS_SCALE_TO_HEIGHT", "OBS_BOUNDS_MAX_ONLY" or "OBS_BOUNDS_NONE". | | `bounds.alignment` | _int_ | Alignment of the bounding box. | diff --git a/src/Utils.cpp b/src/Utils.cpp index 43d1ad83..687dd0cd 100644 --- a/src/Utils.cpp +++ b/src/Utils.cpp @@ -104,9 +104,11 @@ obs_data_array_t* Utils::GetSceneItems(obs_source_t* source) { * @typedef {Object} `SceneItem` An OBS Scene Item. * @property {Number} `cy` * @property {Number} `cx` + * @property {Number} `alignment` The point on the source that the item is manipulated from. The sum of 1=Left or 2=Right, and 4=Top or 8=Bottom, or omit to center on that axis. * @property {String} `name` The name of this Scene Item. * @property {int} `id` Scene item ID * @property {Boolean} `render` Whether or not this Scene Item is set to "visible". + * @property {Boolean} `muted` Whether or not this Scene Item is muted. * @property {Boolean} `locked` Whether or not this Scene Item is locked and can't be moved around * @property {Number} `source_cx` * @property {Number} `source_cy` diff --git a/src/WSRequestHandler_SceneItems.cpp b/src/WSRequestHandler_SceneItems.cpp index 92adeab0..5e736802 100644 --- a/src/WSRequestHandler_SceneItems.cpp +++ b/src/WSRequestHandler_SceneItems.cpp @@ -21,6 +21,7 @@ * @return {int} `crop.bottom` The number of pixels cropped off the bottom of the source before scaling. * @return {int} `crop.left` The number of pixels cropped off the left of the source before scaling. * @return {bool} `visible` If the source is visible. +* @return {bool} `muted` If the source is muted. * @return {bool} `locked` If the source's transform is locked. * @return {String} `bounds.type` Type of bounding box. Can be "OBS_BOUNDS_STRETCH", "OBS_BOUNDS_SCALE_INNER", "OBS_BOUNDS_SCALE_OUTER", "OBS_BOUNDS_SCALE_TO_WIDTH", "OBS_BOUNDS_SCALE_TO_HEIGHT", "OBS_BOUNDS_MAX_ONLY" or "OBS_BOUNDS_NONE". * @return {int} `bounds.alignment` Alignment of the bounding box. From 5088d7dd8641f71fa4c8443394fcb562deb2dd54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Lepin?= Date: Wed, 11 Mar 2020 14:10:38 +0100 Subject: [PATCH 32/55] requests(SetSyncOffset): allow negative offsets --- src/WSRequestHandler_Sources.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/WSRequestHandler_Sources.cpp b/src/WSRequestHandler_Sources.cpp index 2feca185..e043ee0e 100644 --- a/src/WSRequestHandler_Sources.cpp +++ b/src/WSRequestHandler_Sources.cpp @@ -335,7 +335,7 @@ RpcResponse WSRequestHandler::SetSyncOffset(const RpcRequest& request) QString sourceName = obs_data_get_string(request.parameters(), "source"); int64_t sourceSyncOffset = (int64_t)obs_data_get_int(request.parameters(), "offset"); - if (sourceName.isEmpty() || sourceSyncOffset < 0) { + if (sourceName.isEmpty()) { return request.failed("invalid request parameters"); } From 866733341644dd9a8cdc27d41f3e3819cda35306 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Lepin?= Date: Wed, 11 Mar 2020 14:13:22 +0100 Subject: [PATCH 33/55] ci(macos): switch to macOS 10.14 --- azure-pipelines.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index ec85baf6..717e0dfa 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -1,5 +1,5 @@ pool: - vmImage: 'macOS-10.13' + vmImage: 'macOS-10.14' steps: - checkout: self From b26cd901caa03c721219a934589e48bee8064ee1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Lepin?= Date: Thu, 12 Mar 2020 10:58:30 +0100 Subject: [PATCH 34/55] request(GetVersion): add supported image export formats list --- src/WSRequestHandler_General.cpp | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/WSRequestHandler_General.cpp b/src/WSRequestHandler_General.cpp index c957da49..686f56bb 100644 --- a/src/WSRequestHandler_General.cpp +++ b/src/WSRequestHandler_General.cpp @@ -1,10 +1,13 @@ +#include "WSRequestHandler.h" + +#include +#include + #include "obs-websocket.h" #include "Config.h" #include "Utils.h" #include "WSEvents.h" -#include "WSRequestHandler.h" - #define CASE(x) case x: return #x; const char *describe_output_format(int format) { switch (format) { @@ -60,6 +63,7 @@ const char *describe_scale_type(int scale) { * @return {String} `obs-websocket-version` obs-websocket plugin version. * @return {String} `obs-studio-version` OBS Studio program version. * @return {String} `available-requests` List of available request types, formatted as a comma-separated list string (e.g. : "Method1,Method2,Method3"). + * @return {String} `supported-image-export-formats` List of supported formats for features that use image export (like the TakeSourceScreenshot request type) formatted as a comma-separated list string * * @api requests * @name GetVersion @@ -70,20 +74,28 @@ RpcResponse WSRequestHandler::GetVersion(const RpcRequest& request) { QString obsVersion = Utils::OBSVersionString(); QList names = messageMap.keys(); - names.sort(Qt::CaseInsensitive); + QList imageWriterFormats = QImageWriter::supportedImageFormats(); // (Palakis) OBS' data arrays only support object arrays, so I improvised. QString requests; + names.sort(Qt::CaseInsensitive); requests += names.takeFirst(); - for (QString reqName : names) { + for (const QString& reqName : names) { requests += ("," + reqName); } + QString supportedImageExportFormats; + supportedImageExportFormats += QString::fromUtf8(imageWriterFormats.takeFirst()); + for (const QByteArray& format : imageWriterFormats) { + supportedImageExportFormats += ("," + QString::fromUtf8(format)); + } + OBSDataAutoRelease data = obs_data_create(); obs_data_set_double(data, "version", 1.1); obs_data_set_string(data, "obs-websocket-version", OBS_WEBSOCKET_VERSION); obs_data_set_string(data, "obs-studio-version", obsVersion.toUtf8()); obs_data_set_string(data, "available-requests", requests.toUtf8()); + obs_data_set_string(data, "supported-image-export-formats", supportedImageExportFormats.toUtf8()); return request.success(data); } From a8b00b026edc2db87868591f422fa5f6cb8e670b Mon Sep 17 00:00:00 2001 From: Travis CI <> Date: Thu, 12 Mar 2020 13:55:33 +0000 Subject: [PATCH 35/55] docs(travis): Update protocol.md - d4db0bd [skip ci] --- docs/generated/comments.json | 8 +++++++- docs/generated/protocol.md | 1 + 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/docs/generated/comments.json b/docs/generated/comments.json index 67755474..6418f12b 100644 --- a/docs/generated/comments.json +++ b/docs/generated/comments.json @@ -2913,7 +2913,8 @@ "{double} `version` OBSRemote compatible API version. Fixed to 1.1 for retrocompatibility.", "{String} `obs-websocket-version` obs-websocket plugin version.", "{String} `obs-studio-version` OBS Studio program version.", - "{String} `available-requests` List of available request types, formatted as a comma-separated list string (e.g. : \"Method1,Method2,Method3\")." + "{String} `available-requests` List of available request types, formatted as a comma-separated list string (e.g. : \"Method1,Method2,Method3\").", + "{String} `supported-image-export-formats` List of supported formats for features that use image export (like the TakeSourceScreenshot request type) formatted as a comma-separated list string" ], "api": "requests", "name": "GetVersion", @@ -2939,6 +2940,11 @@ "type": "String", "name": "available-requests", "description": "List of available request types, formatted as a comma-separated list string (e.g. : \"Method1,Method2,Method3\")." + }, + { + "type": "String", + "name": "supported-image-export-formats", + "description": "List of supported formats for features that use image export (like the TakeSourceScreenshot request type) formatted as a comma-separated list string" } ], "names": [ diff --git a/docs/generated/protocol.md b/docs/generated/protocol.md index 9114a712..67743ab5 100644 --- a/docs/generated/protocol.md +++ b/docs/generated/protocol.md @@ -1182,6 +1182,7 @@ _No specified parameters._ | `obs-websocket-version` | _String_ | obs-websocket plugin version. | | `obs-studio-version` | _String_ | OBS Studio program version. | | `available-requests` | _String_ | List of available request types, formatted as a comma-separated list string (e.g. : "Method1,Method2,Method3"). | +| `supported-image-export-formats` | _String_ | List of supported formats for features that use image export (like the TakeSourceScreenshot request type) formatted as a comma-separated list string | --- From 5173338949f00e8d50c6419a8dc4973fe0992f78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Lepin?= Date: Thu, 12 Mar 2020 15:40:28 +0100 Subject: [PATCH 36/55] linux: add proper dependencies list in Deb package --- CI/package-xenial.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/CI/package-xenial.sh b/CI/package-xenial.sh index dde64929..8986aecd 100755 --- a/CI/package-xenial.sh +++ b/CI/package-xenial.sh @@ -19,6 +19,7 @@ PAGER=cat checkinstall -y --type=debian --fstrans=no --nodoc \ --pkglicense="GPLv2.0" --maintainer="contact@slepin.fr" \ --pkggroup="video" \ --pkgsource="https://github.com/Palakis/obs-websocket" \ + --requires="obs-studio libqt5core5a libqt5widgets5" \ --pakdir="/package" chmod ao+r /package/* From d8f2aeb0046ec4537522bbd8bb6e991de043b27d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Lepin?= Date: Thu, 12 Mar 2020 17:03:00 +0100 Subject: [PATCH 37/55] requests(OpenProjector): refactor libobs version check --- src/WSRequestHandler_General.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/WSRequestHandler_General.cpp b/src/WSRequestHandler_General.cpp index 686f56bb..dbf9b9ab 100644 --- a/src/WSRequestHandler_General.cpp +++ b/src/WSRequestHandler_General.cpp @@ -331,7 +331,7 @@ RpcResponse WSRequestHandler::GetVideoInfo(const RpcRequest& request) { * @since unreleased */ RpcResponse WSRequestHandler::OpenProjector(const RpcRequest& request) { -#if LIBOBS_API_VER >= 0x18000004 +#if LIBOBS_API_VER >= MAKE_SEMANTIC_VERSION(24, 0, 4) const char *type = obs_data_get_string(request.parameters(), "type"); int monitor = -1; if (request.hasField("monitor")) { From 010102da2523c2f8306647b05247b81a499dfda1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Lepin?= Date: Thu, 12 Mar 2020 17:06:09 +0100 Subject: [PATCH 38/55] ci(linux): download frontend API headers from stable --- CI/install-dependencies-xenial.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CI/install-dependencies-xenial.sh b/CI/install-dependencies-xenial.sh index bd9dd03d..aa5390ab 100755 --- a/CI/install-dependencies-xenial.sh +++ b/CI/install-dependencies-xenial.sh @@ -14,6 +14,6 @@ apt-get install -y \ qtbase5-dev # Dirty hack -wget -O /usr/include/obs/obs-frontend-api.h https://raw.githubusercontent.com/obsproject/obs-studio/master/UI/obs-frontend-api/obs-frontend-api.h +wget -O /usr/include/obs/obs-frontend-api.h https://raw.githubusercontent.com/obsproject/obs-studio/24.0.3/UI/obs-frontend-api/obs-frontend-api.h ldconfig From 796bdebd90819c54c3eeb01132c4da189e4323db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Lepin?= Date: Thu, 12 Mar 2020 17:27:28 +0100 Subject: [PATCH 39/55] requests(OpenProjector): wrap version check with parentheses --- src/WSRequestHandler_General.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/WSRequestHandler_General.cpp b/src/WSRequestHandler_General.cpp index dbf9b9ab..057b8bae 100644 --- a/src/WSRequestHandler_General.cpp +++ b/src/WSRequestHandler_General.cpp @@ -331,7 +331,7 @@ RpcResponse WSRequestHandler::GetVideoInfo(const RpcRequest& request) { * @since unreleased */ RpcResponse WSRequestHandler::OpenProjector(const RpcRequest& request) { -#if LIBOBS_API_VER >= MAKE_SEMANTIC_VERSION(24, 0, 4) +#if (LIBOBS_API_VER >= MAKE_SEMANTIC_VERSION(24, 0, 4)) const char *type = obs_data_get_string(request.parameters(), "type"); int monitor = -1; if (request.hasField("monitor")) { From 061f5d509950b712787a38042aca7da36f11aef8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Lepin?= Date: Thu, 12 Mar 2020 17:44:56 +0100 Subject: [PATCH 40/55] requests(OpenProjector): get function pointer from lib dynamically --- src/Utils.cpp | 30 ++++++++++++++++++++++++++++-- src/Utils.h | 3 +++ src/WSRequestHandler_General.cpp | 19 +++++++++++-------- 3 files changed, 42 insertions(+), 10 deletions(-) diff --git a/src/Utils.cpp b/src/Utils.cpp index 687dd0cd..d1f0f254 100644 --- a/src/Utils.cpp +++ b/src/Utils.cpp @@ -798,8 +798,6 @@ void getPauseRecordingFunctions(RecordingPausedFunction* recPausedFuncPtr, Pause if (pauseRecFuncPtr) { *pauseRecFuncPtr = (PauseRecordingFunction)os_dlsym(frontendApi, "obs_frontend_recording_pause"); } - - os_dlclose(frontendApi); } bool Utils::RecordingPauseSupported() @@ -835,6 +833,34 @@ void Utils::PauseRecording(bool pause) pauseRecording(pause); } +bool Utils::OpenProjectorSupported() +{ + void* frontendApi = os_dlopen("obs-frontend-api"); + if (!frontendApi) { + return false; + } + + void* openProjectorFunc = os_dlsym(frontendApi, "obs_frontend_open_projector"); + return (openProjectorFunc != nullptr); +} + +void Utils::OpenProjector(const char* type, int monitor, const char* geometry, const char* name) +{ + typedef void(*OpenProjectorFunc)(const char*, int monitor, const char* geometry, const char* name); + + void* frontendApi = os_dlopen("obs-frontend-api"); + if (!frontendApi) { + return; + } + + OpenProjectorFunc openProjectorFunc = (OpenProjectorFunc)os_dlsym(frontendApi, "obs_frontend_open_projector"); + if (!openProjectorFunc) { + return; + } + + openProjectorFunc(type, monitor, geometry, name); +} + QString Utils::nsToTimestamp(uint64_t ns) { uint64_t ms = ns / 1000000ULL; diff --git a/src/Utils.h b/src/Utils.h index 4259c2e6..d778a882 100644 --- a/src/Utils.h +++ b/src/Utils.h @@ -86,5 +86,8 @@ namespace Utils { bool RecordingPaused(); void PauseRecording(bool pause); + bool OpenProjectorSupported(); + void OpenProjector(const char* type, int monitor, const char* geometry, const char* name); + QString nsToTimestamp(uint64_t ns); }; diff --git a/src/WSRequestHandler_General.cpp b/src/WSRequestHandler_General.cpp index 057b8bae..e1187e5b 100644 --- a/src/WSRequestHandler_General.cpp +++ b/src/WSRequestHandler_General.cpp @@ -331,17 +331,20 @@ RpcResponse WSRequestHandler::GetVideoInfo(const RpcRequest& request) { * @since unreleased */ RpcResponse WSRequestHandler::OpenProjector(const RpcRequest& request) { -#if (LIBOBS_API_VER >= MAKE_SEMANTIC_VERSION(24, 0, 4)) - const char *type = obs_data_get_string(request.parameters(), "type"); + if (!Utils::OpenProjectorSupported()) { + return request.failed("Projector opening requires OBS 24.0.4 or newer."); + } + + const char* type = obs_data_get_string(request.parameters(), "type"); + int monitor = -1; if (request.hasField("monitor")) { monitor = obs_data_get_int(request.parameters(), "monitor"); } - const char *geometry = obs_data_get_string(request.parameters(), "geometry"); - const char *name = obs_data_get_string(request.parameters(), "name"); - obs_frontend_open_projector(type, monitor, geometry, name); + + const char* geometry = obs_data_get_string(request.parameters(), "geometry"); + const char* name = obs_data_get_string(request.parameters(), "name"); + + Utils::OpenProjector(type, monitor, geometry, name); return request.success(); -#else - return request.failed("Projector opening requires libobs v24.0.4 or newer."); -#endif } From 2a7aa432a9b4ab2fa2900ba91a69c39bd33d8491 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Lepin?= Date: Sun, 15 Mar 2020 23:20:56 +0100 Subject: [PATCH 41/55] events(TransitionEnd): remove `from-scene` because it's not available in transition_stop --- src/Utils.cpp | 21 ++++++++++++++------- src/WSEvents.cpp | 2 +- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/src/Utils.cpp b/src/Utils.cpp index 6e5f98db..cf0bcfb5 100644 --- a/src/Utils.cpp +++ b/src/Utils.cpp @@ -419,20 +419,27 @@ obs_data_t* Utils::GetTransitionData(obs_source_t* transition) { blog(LOG_WARNING, "GetTransitionData: duration is negative !"); } + OBSSourceAutoRelease sourceScene = obs_transition_get_source(transition, OBS_TRANSITION_SOURCE_A); + OBSSourceAutoRelease destinationScene = obs_transition_get_active_source(transition); + obs_data_t* transitionData = obs_data_create(); obs_data_set_string(transitionData, "name", obs_source_get_name(transition)); obs_data_set_string(transitionData, "type", obs_source_get_id(transition)); obs_data_set_int(transitionData, "duration", duration); - OBSSourceAutoRelease sourceScene = obs_transition_get_source(transition, OBS_TRANSITION_SOURCE_A); - if (sourceScene) { + // When a transition starts and while it is running, SOURCE_A is the source scene + // and SOURCE_B is the destination scene. + // Before the transition_end event is triggered on a transition, the destination scene + // goes into SOURCE_A and SOURCE_B becomes null. This means that, in transition_stop + // we don't know what was the source scene + // TODO fix this in libobs + + bool isTransitionEndEvent = (sourceScene == destinationScene); + if (!isTransitionEndEvent) { obs_data_set_string(transitionData, "from-scene", obs_source_get_name(sourceScene)); } - - OBSSourceAutoRelease destinationScene = obs_transition_get_active_source(transition); - if (destinationScene) { - obs_data_set_string(transitionData, "to-scene", obs_source_get_name(destinationScene)); - } + + obs_data_set_string(transitionData, "to-scene", obs_source_get_name(destinationScene)); return transitionData; } diff --git a/src/WSEvents.cpp b/src/WSEvents.cpp index d964efdc..1bee974c 100644 --- a/src/WSEvents.cpp +++ b/src/WSEvents.cpp @@ -909,11 +909,11 @@ void WSEvents::OnTransitionBegin(void* param, calldata_t* data) { /** * A transition (other than "cut") has ended. +* Please note that the `from-scene` field is not available in TransitionEnd. * * @return {String} `name` Transition name. * @return {String} `type` Transition type. * @return {int} `duration` Transition duration (in milliseconds). -* @return {String} `from-scene` Source scene of the transition * @return {String} `to-scene` Destination scene of the transition * * @api events From 86191aff7f69a8b612ff03c3d37eab1860736ee8 Mon Sep 17 00:00:00 2001 From: Travis CI <> Date: Sun, 15 Mar 2020 22:22:42 +0000 Subject: [PATCH 42/55] docs(travis): Update protocol.md - 6bed39e [skip ci] --- docs/generated/comments.json | 128 +++++++++++++++++++++++++++++++++++ docs/generated/protocol.md | 42 ++++++++++++ 2 files changed, 170 insertions(+) diff --git a/docs/generated/comments.json b/docs/generated/comments.json index 6418f12b..2c54dc9a 100644 --- a/docs/generated/comments.json +++ b/docs/generated/comments.json @@ -841,6 +841,134 @@ "lead": "", "type": "class", "examples": [] + }, + { + "subheads": [], + "description": "A transition (other than \"cut\") has ended.\nPlease note that the `from-scene` field is not available in TransitionEnd.", + "return": [ + "{String} `name` Transition name.", + "{String} `type` Transition type.", + "{int} `duration` Transition duration (in milliseconds).", + "{String} `to-scene` Destination scene of the transition" + ], + "api": "events", + "name": "TransitionEnd", + "category": "transitions", + "since": "4.8.0", + "returns": [ + { + "type": "String", + "name": "name", + "description": "Transition name." + }, + { + "type": "String", + "name": "type", + "description": "Transition type." + }, + { + "type": "int", + "name": "duration", + "description": "Transition duration (in milliseconds)." + }, + { + "type": "String", + "name": "to-scene", + "description": "Destination scene of the transition" + } + ], + "names": [ + { + "name": "", + "description": "TransitionEnd" + } + ], + "categories": [ + { + "name": "", + "description": "transitions" + } + ], + "sinces": [ + { + "name": "", + "description": "4.8.0" + } + ], + "heading": { + "level": 2, + "text": "TransitionEnd" + }, + "lead": "", + "type": "class", + "examples": [] + }, + { + "subheads": [], + "description": "A stinger transition has finished playing its video.", + "return": [ + "{String} `name` Transition name.", + "{String} `type` Transition type.", + "{int} `duration` Transition duration (in milliseconds).", + "{String} `from-scene` Source scene of the transition", + "{String} `to-scene` Destination scene of the transition" + ], + "api": "events", + "name": "TransitionVideoEnd", + "category": "transitions", + "since": "4.8.0", + "returns": [ + { + "type": "String", + "name": "name", + "description": "Transition name." + }, + { + "type": "String", + "name": "type", + "description": "Transition type." + }, + { + "type": "int", + "name": "duration", + "description": "Transition duration (in milliseconds)." + }, + { + "type": "String", + "name": "from-scene", + "description": "Source scene of the transition" + }, + { + "type": "String", + "name": "to-scene", + "description": "Destination scene of the transition" + } + ], + "names": [ + { + "name": "", + "description": "TransitionVideoEnd" + } + ], + "categories": [ + { + "name": "", + "description": "transitions" + } + ], + "sinces": [ + { + "name": "", + "description": "4.8.0" + } + ], + "heading": { + "level": 2, + "text": "TransitionVideoEnd" + }, + "lead": "", + "type": "class", + "examples": [] } ], "profiles": [ diff --git a/docs/generated/protocol.md b/docs/generated/protocol.md index 67743ab5..77f780d5 100644 --- a/docs/generated/protocol.md +++ b/docs/generated/protocol.md @@ -59,6 +59,8 @@ auth_response = base64_encode(auth_response_hash) + [TransitionListChanged](#transitionlistchanged) + [TransitionDurationChanged](#transitiondurationchanged) + [TransitionBegin](#transitionbegin) + + [TransitionEnd](#transitionend) + + [TransitionVideoEnd](#transitionvideoend) * [Profiles](#profiles) + [ProfileChanged](#profilechanged) + [ProfileListChanged](#profilelistchanged) @@ -442,6 +444,46 @@ A transition (other than "cut") has begun. | `to-scene` | _String_ | Destination scene of the transition | +--- + +### TransitionEnd + + +- Added in v4.8.0 + +A transition (other than "cut") has ended. +Please note that the `from-scene` field is not available in TransitionEnd. + +**Response Items:** + +| Name | Type | Description | +| ---- | :---: | ------------| +| `name` | _String_ | Transition name. | +| `type` | _String_ | Transition type. | +| `duration` | _int_ | Transition duration (in milliseconds). | +| `to-scene` | _String_ | Destination scene of the transition | + + +--- + +### TransitionVideoEnd + + +- Added in v4.8.0 + +A stinger transition has finished playing its video. + +**Response Items:** + +| Name | Type | Description | +| ---- | :---: | ------------| +| `name` | _String_ | Transition name. | +| `type` | _String_ | Transition type. | +| `duration` | _int_ | Transition duration (in milliseconds). | +| `from-scene` | _String_ | Source scene of the transition | +| `to-scene` | _String_ | Destination scene of the transition | + + --- ## Profiles From e0a25dbf485056ea5924fab625ac7c492b526527 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Lepin?= Date: Tue, 17 Mar 2020 18:16:26 +0100 Subject: [PATCH 43/55] package(deb): add Qt image formats plugins dependency --- CI/package-xenial.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CI/package-xenial.sh b/CI/package-xenial.sh index 8986aecd..40b901dc 100755 --- a/CI/package-xenial.sh +++ b/CI/package-xenial.sh @@ -19,7 +19,7 @@ PAGER=cat checkinstall -y --type=debian --fstrans=no --nodoc \ --pkglicense="GPLv2.0" --maintainer="contact@slepin.fr" \ --pkggroup="video" \ --pkgsource="https://github.com/Palakis/obs-websocket" \ - --requires="obs-studio libqt5core5a libqt5widgets5" \ + --requires="obs-studio libqt5core5a libqt5widgets5 qt5-image-formats-plugins" \ --pakdir="/package" chmod ao+r /package/* From fe217ef5df2485b83327a829aaeb1a8d6935edc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Lepin?= Date: Tue, 17 Mar 2020 18:43:01 +0100 Subject: [PATCH 44/55] package(deb): fix email address --- CI/package-xenial.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CI/package-xenial.sh b/CI/package-xenial.sh index 40b901dc..59ed4e49 100755 --- a/CI/package-xenial.sh +++ b/CI/package-xenial.sh @@ -16,7 +16,7 @@ cd /root/obs-websocket/build PAGER=cat checkinstall -y --type=debian --fstrans=no --nodoc \ --backup=no --deldoc=yes --install=no \ --pkgname=obs-websocket --pkgversion="$PKG_VERSION" \ - --pkglicense="GPLv2.0" --maintainer="contact@slepin.fr" \ + --pkglicense="GPLv2.0" --maintainer="stephane.lepin@gmail.com" \ --pkggroup="video" \ --pkgsource="https://github.com/Palakis/obs-websocket" \ --requires="obs-studio libqt5core5a libqt5widgets5 qt5-image-formats-plugins" \ From a5b6ea6c4c5b274607103b6a3dd4d4f642c1fd40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Lepin?= Date: Tue, 17 Mar 2020 19:34:53 +0100 Subject: [PATCH 45/55] cmake(windows): copy qt image format plugins --- CMakeLists.txt | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 520d4254..b31e98c3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,8 +23,7 @@ if (WIN32 OR APPLE) endif() find_package(LibObs REQUIRED) -find_package(Qt5Core REQUIRED) -find_package(Qt5Widgets REQUIRED) +find_package(Qt5 REQUIRED COMPONENTS Core Widgets) set(obs-websocket_SOURCES src/obs-websocket.cpp @@ -128,6 +127,11 @@ if(WIN32) "$" "${RELEASE_DIR}/obs-plugins/${ARCH_NAME}") + # In Release mode, copy Qt image format plugins + COMMAND if $==1 ("${CMAKE_COMMAND}" -E copy + "${RELEASE_DIR}/plugins/imageformats/qjpeg.dll" + "${CMAKE_BINARY_DIR}/bin/${ARCH_NAME}$") + # If config is RelWithDebInfo, package release files COMMAND if $==1 ( "${CMAKE_COMMAND}" -E make_directory From a6698526949dab7dc45b4da0819f16c6258eb774 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Lepin?= Date: Tue, 17 Mar 2020 19:37:39 +0100 Subject: [PATCH 46/55] cmake(windows): oops, fix copy command --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b31e98c3..c9b27deb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -129,8 +129,8 @@ if(WIN32) # In Release mode, copy Qt image format plugins COMMAND if $==1 ("${CMAKE_COMMAND}" -E copy - "${RELEASE_DIR}/plugins/imageformats/qjpeg.dll" - "${CMAKE_BINARY_DIR}/bin/${ARCH_NAME}$") + "${QTDIR}/plugins/imageformats/qjpeg.dll" + "${RELEASE_DIR}/bin/${ARCH_NAME}/qjpeg.dll") # If config is RelWithDebInfo, package release files COMMAND if $==1 ( From 1ada33a4f02e146900348e516795f0999059932a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Lepin?= Date: Tue, 17 Mar 2020 19:41:43 +0100 Subject: [PATCH 47/55] package(deb): fix ambiguous syntax --- CI/package-xenial.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CI/package-xenial.sh b/CI/package-xenial.sh index 59ed4e49..276584a1 100755 --- a/CI/package-xenial.sh +++ b/CI/package-xenial.sh @@ -13,7 +13,7 @@ fi cd /root/obs-websocket/build -PAGER=cat checkinstall -y --type=debian --fstrans=no --nodoc \ +PAGER="cat" checkinstall -y --type=debian --fstrans=no --nodoc \ --backup=no --deldoc=yes --install=no \ --pkgname=obs-websocket --pkgversion="$PKG_VERSION" \ --pkglicense="GPLv2.0" --maintainer="stephane.lepin@gmail.com" \ From 3450c6b9a3a59081b671c9d895d8175bbefd8ea3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Lepin?= Date: Tue, 17 Mar 2020 19:52:49 +0100 Subject: [PATCH 48/55] cmake(windows): copy qjpeg on RelWithDebInfo as well --- CMakeLists.txt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c9b27deb..2682cc89 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -128,7 +128,12 @@ if(WIN32) "${RELEASE_DIR}/obs-plugins/${ARCH_NAME}") # In Release mode, copy Qt image format plugins - COMMAND if $==1 ("${CMAKE_COMMAND}" -E copy + COMMAND if $==1 ( + "${CMAKE_COMMAND}" -E copy + "${QTDIR}/plugins/imageformats/qjpeg.dll" + "${RELEASE_DIR}/bin/${ARCH_NAME}/qjpeg.dll") + COMMAND if $==1 ( + "${CMAKE_COMMAND}" -E copy "${QTDIR}/plugins/imageformats/qjpeg.dll" "${RELEASE_DIR}/bin/${ARCH_NAME}/qjpeg.dll") From c418cbf4efde0ee3ab00469c098eb4a2a49d7d17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Lepin?= Date: Tue, 17 Mar 2020 20:08:46 +0100 Subject: [PATCH 49/55] cmake(windows): fix qjpeg path --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2682cc89..788960c9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -131,11 +131,11 @@ if(WIN32) COMMAND if $==1 ( "${CMAKE_COMMAND}" -E copy "${QTDIR}/plugins/imageformats/qjpeg.dll" - "${RELEASE_DIR}/bin/${ARCH_NAME}/qjpeg.dll") + "${RELEASE_DIR}/bin/${ARCH_NAME}/imageformats/qjpeg.dll") COMMAND if $==1 ( "${CMAKE_COMMAND}" -E copy "${QTDIR}/plugins/imageformats/qjpeg.dll" - "${RELEASE_DIR}/bin/${ARCH_NAME}/qjpeg.dll") + "${RELEASE_DIR}/bin/${ARCH_NAME}/imageformats/qjpeg.dll") # If config is RelWithDebInfo, package release files COMMAND if $==1 ( From dc04cb54abb9ec4eced66c484e36b58a7af5ba31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Lepin?= Date: Tue, 17 Mar 2020 23:37:49 +0100 Subject: [PATCH 50/55] chore: bump to 4.8.0 --- src/obs-websocket.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/obs-websocket.h b/src/obs-websocket.h index 1a4dec48..5f118d28 100644 --- a/src/obs-websocket.h +++ b/src/obs-websocket.h @@ -56,6 +56,6 @@ ConfigPtr GetConfig(); WSServerPtr GetServer(); WSEventsPtr GetEventsSystem(); -#define OBS_WEBSOCKET_VERSION "4.7.0" +#define OBS_WEBSOCKET_VERSION "4.8.0" #define blog(level, msg, ...) blog(level, "[obs-websocket] " msg, ##__VA_ARGS__) From a5af45fb317a532e23225417e852aa06ea61fcd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Lepin?= Date: Tue, 17 Mar 2020 23:41:00 +0100 Subject: [PATCH 51/55] ci(xenial): update frontend api to 25.0.0 --- CI/install-dependencies-xenial.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CI/install-dependencies-xenial.sh b/CI/install-dependencies-xenial.sh index aa5390ab..c55d82d7 100755 --- a/CI/install-dependencies-xenial.sh +++ b/CI/install-dependencies-xenial.sh @@ -14,6 +14,6 @@ apt-get install -y \ qtbase5-dev # Dirty hack -wget -O /usr/include/obs/obs-frontend-api.h https://raw.githubusercontent.com/obsproject/obs-studio/24.0.3/UI/obs-frontend-api/obs-frontend-api.h +wget -O /usr/include/obs/obs-frontend-api.h https://raw.githubusercontent.com/obsproject/obs-studio/25.0.0/UI/obs-frontend-api/obs-frontend-api.h ldconfig From 88d39ab47a12fa756bdd1fb70d02144d2ea9b249 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Lepin?= Date: Tue, 17 Mar 2020 23:45:57 +0100 Subject: [PATCH 52/55] utils: remove dynamic loaded functions for recording pause --- src/Utils.cpp | 33 ------------------------------ src/Utils.h | 3 --- src/WSEvents.cpp | 4 ++-- src/WSRequestHandler_Recording.cpp | 12 ++++------- src/WSRequestHandler_Streaming.cpp | 2 +- 5 files changed, 7 insertions(+), 47 deletions(-) diff --git a/src/Utils.cpp b/src/Utils.cpp index 097689cf..cb394886 100644 --- a/src/Utils.cpp +++ b/src/Utils.cpp @@ -831,39 +831,6 @@ void getPauseRecordingFunctions(RecordingPausedFunction* recPausedFuncPtr, Pause } } -bool Utils::RecordingPauseSupported() -{ - RecordingPausedFunction recordingPaused = nullptr; - PauseRecordingFunction pauseRecording = nullptr; - getPauseRecordingFunctions(&recordingPaused, &pauseRecording); - - return (recordingPaused && pauseRecording); -} - -bool Utils::RecordingPaused() -{ - RecordingPausedFunction recordingPaused = nullptr; - getPauseRecordingFunctions(&recordingPaused, nullptr); - - if (recordingPaused == nullptr) { - return false; - } - - return recordingPaused(); -} - -void Utils::PauseRecording(bool pause) -{ - PauseRecordingFunction pauseRecording = nullptr; - getPauseRecordingFunctions(nullptr, &pauseRecording); - - if (pauseRecording == nullptr) { - return; - } - - pauseRecording(pause); -} - bool Utils::OpenProjectorSupported() { void* frontendApi = os_dlopen("obs-frontend-api"); diff --git a/src/Utils.h b/src/Utils.h index 611e80da..89e67d87 100644 --- a/src/Utils.h +++ b/src/Utils.h @@ -83,9 +83,6 @@ namespace Utils { const char* GetFilenameFormatting(); bool SetFilenameFormatting(const char* filenameFormatting); - bool RecordingPauseSupported(); - bool RecordingPaused(); - void PauseRecording(bool pause); bool OpenProjectorSupported(); void OpenProjector(const char* type, int monitor, const char* geometry, const char* name); diff --git a/src/WSEvents.cpp b/src/WSEvents.cpp index 816ca76f..6010275f 100644 --- a/src/WSEvents.cpp +++ b/src/WSEvents.cpp @@ -747,7 +747,7 @@ void WSEvents::OnExit() { void WSEvents::StreamStatus() { bool streamingActive = obs_frontend_streaming_active(); bool recordingActive = obs_frontend_recording_active(); - bool recordingPaused = Utils::RecordingPaused(); + bool recordingPaused = obs_frontend_recording_paused(); bool replayBufferActive = obs_frontend_replay_buffer_active(); OBSOutputAutoRelease streamOutput = obs_frontend_get_streaming_output(); @@ -831,7 +831,7 @@ void WSEvents::Heartbeat() { bool streamingActive = obs_frontend_streaming_active(); bool recordingActive = obs_frontend_recording_active(); - bool recordingPaused = Utils::RecordingPaused(); + bool recordingPaused = obs_frontend_recording_paused(); OBSDataAutoRelease data = obs_data_create(); OBSOutputAutoRelease recordOutput = obs_frontend_get_recording_output(); diff --git a/src/WSRequestHandler_Recording.cpp b/src/WSRequestHandler_Recording.cpp index 330843d3..df2ed4a0 100644 --- a/src/WSRequestHandler_Recording.cpp +++ b/src/WSRequestHandler_Recording.cpp @@ -10,10 +10,6 @@ RpcResponse ifCanPause(const RpcRequest& request, std::function c return request.failed("recording is not active"); } - if (!Utils::RecordingPauseSupported()) { - return request.failed("recording pauses are not available in this version of OBS Studio"); - } - return callback(); } @@ -77,11 +73,11 @@ RpcResponse WSRequestHandler::StartRecording(const RpcRequest& request) { */ RpcResponse WSRequestHandler::PauseRecording(const RpcRequest& request) { return ifCanPause(request, [request]() { - if (Utils::RecordingPaused()) { + if (obs_frontend_recording_paused()) { return request.failed("recording already paused"); } - Utils::PauseRecording(true); + obs_frontend_recording_pause(true); return request.success(); }); } @@ -97,11 +93,11 @@ RpcResponse WSRequestHandler::PauseRecording(const RpcRequest& request) { */ RpcResponse WSRequestHandler::ResumeRecording(const RpcRequest& request) { return ifCanPause(request, [request]() { - if (!Utils::RecordingPaused()) { + if (!obs_frontend_recording_paused()) { return request.failed("recording is not paused"); } - Utils::PauseRecording(false); + obs_frontend_recording_pause(false); return request.success(); }); } diff --git a/src/WSRequestHandler_Streaming.cpp b/src/WSRequestHandler_Streaming.cpp index a39f0cce..744a691f 100644 --- a/src/WSRequestHandler_Streaming.cpp +++ b/src/WSRequestHandler_Streaming.cpp @@ -26,7 +26,7 @@ RpcResponse WSRequestHandler::GetStreamingStatus(const RpcRequest& request) { OBSDataAutoRelease data = obs_data_create(); obs_data_set_bool(data, "streaming", obs_frontend_streaming_active()); obs_data_set_bool(data, "recording", obs_frontend_recording_active()); - obs_data_set_bool(data, "recording-paused", Utils::RecordingPaused()); + obs_data_set_bool(data, "recording-paused", obs_frontend_recording_paused()); obs_data_set_bool(data, "preview-only", false); if (obs_frontend_streaming_active()) { From 247ca71bf916a6e96113cf22203fa466365d14bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Lepin?= Date: Tue, 17 Mar 2020 23:46:24 +0100 Subject: [PATCH 53/55] utils: remove dynloaded function for projector open --- src/Utils.cpp | 28 ---------------------------- src/Utils.h | 4 ---- src/WSRequestHandler_General.cpp | 6 +----- 3 files changed, 1 insertion(+), 37 deletions(-) diff --git a/src/Utils.cpp b/src/Utils.cpp index cb394886..978162be 100644 --- a/src/Utils.cpp +++ b/src/Utils.cpp @@ -831,34 +831,6 @@ void getPauseRecordingFunctions(RecordingPausedFunction* recPausedFuncPtr, Pause } } -bool Utils::OpenProjectorSupported() -{ - void* frontendApi = os_dlopen("obs-frontend-api"); - if (!frontendApi) { - return false; - } - - void* openProjectorFunc = os_dlsym(frontendApi, "obs_frontend_open_projector"); - return (openProjectorFunc != nullptr); -} - -void Utils::OpenProjector(const char* type, int monitor, const char* geometry, const char* name) -{ - typedef void(*OpenProjectorFunc)(const char*, int monitor, const char* geometry, const char* name); - - void* frontendApi = os_dlopen("obs-frontend-api"); - if (!frontendApi) { - return; - } - - OpenProjectorFunc openProjectorFunc = (OpenProjectorFunc)os_dlsym(frontendApi, "obs_frontend_open_projector"); - if (!openProjectorFunc) { - return; - } - - openProjectorFunc(type, monitor, geometry, name); -} - QString Utils::nsToTimestamp(uint64_t ns) { uint64_t ms = ns / 1000000ULL; diff --git a/src/Utils.h b/src/Utils.h index 89e67d87..5934ad4e 100644 --- a/src/Utils.h +++ b/src/Utils.h @@ -83,9 +83,5 @@ namespace Utils { const char* GetFilenameFormatting(); bool SetFilenameFormatting(const char* filenameFormatting); - - bool OpenProjectorSupported(); - void OpenProjector(const char* type, int monitor, const char* geometry, const char* name); - QString nsToTimestamp(uint64_t ns); }; diff --git a/src/WSRequestHandler_General.cpp b/src/WSRequestHandler_General.cpp index e1187e5b..56eeec8b 100644 --- a/src/WSRequestHandler_General.cpp +++ b/src/WSRequestHandler_General.cpp @@ -331,10 +331,6 @@ RpcResponse WSRequestHandler::GetVideoInfo(const RpcRequest& request) { * @since unreleased */ RpcResponse WSRequestHandler::OpenProjector(const RpcRequest& request) { - if (!Utils::OpenProjectorSupported()) { - return request.failed("Projector opening requires OBS 24.0.4 or newer."); - } - const char* type = obs_data_get_string(request.parameters(), "type"); int monitor = -1; @@ -345,6 +341,6 @@ RpcResponse WSRequestHandler::OpenProjector(const RpcRequest& request) { const char* geometry = obs_data_get_string(request.parameters(), "geometry"); const char* name = obs_data_get_string(request.parameters(), "name"); - Utils::OpenProjector(type, monitor, geometry, name); + obs_frontend_open_projector(type, monitor, geometry, name); return request.success(); } From bfcd16ea28e58b080de38a24293e3a7197d5107e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Lepin?= Date: Sun, 15 Mar 2020 22:33:44 +0100 Subject: [PATCH 54/55] requests(studio mode): fix crash when calling frontend_set_preview_program_mode --- src/WSRequestHandler_StudioMode.cpp | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/src/WSRequestHandler_StudioMode.cpp b/src/WSRequestHandler_StudioMode.cpp index 67928ee4..fb958f3b 100644 --- a/src/WSRequestHandler_StudioMode.cpp +++ b/src/WSRequestHandler_StudioMode.cpp @@ -133,7 +133,11 @@ RpcResponse WSRequestHandler::TransitionToProgram(const RpcRequest& request) { * @since 4.1.0 */ RpcResponse WSRequestHandler::EnableStudioMode(const RpcRequest& request) { - obs_frontend_set_preview_program_mode(true); + obs_queue_task(OBS_TASK_UI, [](void* param) { + obs_frontend_set_preview_program_mode(true); + + UNUSED_PARAMETER(param); + }, nullptr, true); return request.success(); } @@ -146,7 +150,12 @@ RpcResponse WSRequestHandler::EnableStudioMode(const RpcRequest& request) { * @since 4.1.0 */ RpcResponse WSRequestHandler::DisableStudioMode(const RpcRequest& request) { - obs_frontend_set_preview_program_mode(false); + obs_queue_task(OBS_TASK_UI, [](void* param) { + obs_frontend_set_preview_program_mode(false); + + UNUSED_PARAMETER(param); + }, nullptr, true); + return request.success(); } @@ -159,7 +168,12 @@ RpcResponse WSRequestHandler::DisableStudioMode(const RpcRequest& request) { * @since 4.1.0 */ RpcResponse WSRequestHandler::ToggleStudioMode(const RpcRequest& request) { - bool previewProgramMode = obs_frontend_preview_program_mode_active(); - obs_frontend_set_preview_program_mode(!previewProgramMode); + obs_queue_task(OBS_TASK_UI, [](void* param) { + bool previewProgramMode = obs_frontend_preview_program_mode_active(); + obs_frontend_set_preview_program_mode(!previewProgramMode); + + UNUSED_PARAMETER(param); + }, nullptr, true); + return request.success(); } From 6a733bbb136f7e0a84df32a4f6ca41cdd87bf844 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Lepin?= Date: Sat, 28 Mar 2020 19:13:55 +0100 Subject: [PATCH 55/55] Migrate Windows & Linux builds to Azure Pipelines (#422) --- .gitignore | 1 + .travis.yml | 49 ----- CI/{build-xenial.sh => build-ubuntu.sh} | 2 - ...obs.cmd => checkout-cmake-obs-windows.cmd} | 80 +++++---- CI/download-obs-deps.cmd | 6 + CI/generate-docs.sh | 14 +- CI/install-dependencies-ubuntu.sh | 19 ++ CI/install-dependencies-xenial.sh | 19 -- CI/install-qt-win.cmd | 8 + CI/install-setup-qt.cmd | 6 - CI/package-macos.sh | 2 - CI/package-ubuntu.sh | 23 +++ CI/package-windows.cmd | 12 ++ CI/package-xenial.sh | 25 --- CI/prepare-windows.cmd | 7 + CMakeLists.txt | 11 +- appveyor.yml | 40 ----- azure-pipelines.yml | 169 ++++++++++++++++-- 18 files changed, 282 insertions(+), 211 deletions(-) delete mode 100644 .travis.yml rename CI/{build-xenial.sh => build-ubuntu.sh} (78%) rename CI/{install-build-obs.cmd => checkout-cmake-obs-windows.cmd} (50%) create mode 100644 CI/download-obs-deps.cmd create mode 100755 CI/install-dependencies-ubuntu.sh delete mode 100755 CI/install-dependencies-xenial.sh create mode 100644 CI/install-qt-win.cmd delete mode 100644 CI/install-setup-qt.cmd create mode 100755 CI/package-ubuntu.sh create mode 100644 CI/package-windows.cmd delete mode 100755 CI/package-xenial.sh create mode 100644 CI/prepare-windows.cmd delete mode 100644 appveyor.yml diff --git a/.gitignore b/.gitignore index c60fdf06..b7e57102 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ /build32/ /build64/ /release/ +/package/ /installer/Output/ .idea .vscode diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 8e712fbb..00000000 --- a/.travis.yml +++ /dev/null @@ -1,49 +0,0 @@ -language: cpp - -env: - global: - # AWS key ID - - secure: pAiNUGVbjP12BfnWPk0FFTkbnk4Tocvv88XiT3rzRqkQaD7/iyEogLBfHM4nOEgFiIMHbC41aE83w5JgRNPwn6mTgoQBOglzqq1tGuXfqPyV2VStk8beji1evubGoVjjPaoPTFyIdQc5GGxdHyogI/ed9Hb3ccyykYvjyolj9XoCiW42QHx60AHGwl+So+dEa8xydj9SLRPlZ/AitmI/cPVN3YotA7s37BLFiab54enxk7T4rwpR1nU0HVfoCpn5F4wZYxRq+LlSVFzC8vVE9cpDSLS5kjrZIZaT18tYG1/untCj+wqMIZbghaJXLtPSRW2YPHcJTz8q1YSXnJ19+0uiAIMAqaVv0kD5BAM97byYDBW+b9H6SYFkb/Pw/qcK9amMzMBjDPFpYFkl9Q2kzhsNs3HsZf/flSZjtrkQJiP3SOi/KvKzVK9X4Wym6hYZWHgmMTTYFrvr6BYnf2GkpfKNjm1d2kc0NNrq4d5H4NOEQB8MP+QH+o+BPeM6d9dthrUc1Pw+BXzOAr85CN4qtpPGoAl/Dbfgd6eu/88E2LpUufW2VFAOPWjykSOqzSN3orh7AaWuE34VFEnQ+2y3uIE8AKoyXzJv6zYkyNnNewKZeGe2kKYNwLn5UxQA9JEj7a+tvVevk4xBSkkjFAvjSG2z8/F1FXNbEfoLX1Hz/bU= - # AWS key secret - - secure: bGwljoP3E1OVBXLXox0O6p8kwQXLcNQ8YDKVa4H8u9Y+Ic7uqE4iV3rYS3ynNWSBMVRWY3ZbyClnhrCNwRhBAlcd8qWSJdpjVzs6HdQyzhuKa1P3V4FJPb7upGP/5R/DECGwex8Mun9dmXpYDak75LxfKIJUidPis5VDCYqul7k/xVVCou6Ctjpj7vQhWXDj2G/py+mdB8DERhymnQCtyK1Ziu8c4QlFKByZmnD72GFm/h3JPI1Pq1V2mz3x6x6GaYjb9Rdbd0UNwqjGQX4q2M/c3GEJa6B2JBCoTncawNZBNnPUF9qtv+zh0TNaNHMRWX13AJ/qYB+nVDub0C9b/6Mc48mt0Tv4ze15MproVrylZdV6qHYEG8yGPBqpTVbRP6gv6Y2TXIHWoTzqA+F/Gv2IDChyHXsld/MQQS2MSo5iaYktIrZKtX8Z0qAmTzPwIVBromaSI3vrE7UH0fRSQ6fAM8+Tn+MRthOBdqu23kS1dnG+X2CPbUhBfsJp0OSwVQD5jQtA51/sREVeGFiJvzQIkvwQDjb5MYilsRnwmoBXemkLmqaviXVY4rz1o5AIvz2pgZS2YggK1xHZCuI5tSjcNEkb77VwZTfsqrdDo9EJh6VgfdnGlHQhR2/A5hUJ4ANpJ/LgZlgfVp71Xg2GWQW6M4Znc5uj6A6xLBkO6FA= - -cache: - directories: - - node_modules - -matrix: - include: - - os: linux - env: _generate_docs - script: "./CI/generate-docs.sh" - - - os: linux - env: _linux_build - dist: trusty - sudo: required - services: - - docker - before_install: - - docker run -d --name xenial -v $(dirname $(pwd)):/root -v /home/travis/package:/package - -e TRAVIS_BRANCH="$TRAVIS_BRANCH" -e TRAVIS_TAG="$TRAVIS_TAG" -w /root nimmis/ubuntu:16.04 - - docker exec -it xenial /root/obs-websocket/CI/install-dependencies-xenial.sh - script: - - docker exec -it xenial /root/obs-websocket/CI/build-xenial.sh - after_success: - - docker exec -it xenial /root/obs-websocket/CI/package-xenial.sh - -deploy: -- provider: s3 - region: eu-central-1 - bucket: obs-websocket-linux-builds - access_key_id: "$AWS_ID" - secret_access_key: "$AWS_SECRET" - local_dir: /home/travis/package - skip_cleanup: true - acl: public_read - on: - repo: Palakis/obs-websocket - condition: - - "$TRAVIS_OS_NAME = linux" - - "-d /home/travis/package" - all_branches: true diff --git a/CI/build-xenial.sh b/CI/build-ubuntu.sh similarity index 78% rename from CI/build-xenial.sh rename to CI/build-ubuntu.sh index cc7e53ef..b19158ae 100755 --- a/CI/build-xenial.sh +++ b/CI/build-ubuntu.sh @@ -1,8 +1,6 @@ #!/bin/sh set -ex -cd /root/obs-websocket - mkdir build && cd build cmake -DCMAKE_INSTALL_PREFIX=/usr .. make -j4 diff --git a/CI/install-build-obs.cmd b/CI/checkout-cmake-obs-windows.cmd similarity index 50% rename from CI/install-build-obs.cmd rename to CI/checkout-cmake-obs-windows.cmd index 9f73b3e0..0fc6c12c 100644 --- a/CI/install-build-obs.cmd +++ b/CI/checkout-cmake-obs-windows.cmd @@ -18,25 +18,25 @@ REM Set up the build flag as undefined. set "BuildOBS=" REM Check the last tag successfully built by CI. -if exist C:\projects\obs-studio-last-tag-built.txt ( - set /p OBSLastTagBuilt= C:\projects\latest-obs-studio-tag-pre-pull.txt - set /p OBSLatestTagPrePull= "%OBSPath%\latest-obs-studio-tag-pre-pull.txt" + set /p OBSLatestTagPrePull=<"%OBSPath%\latest-obs-studio-tag-pre-pull.txt" git checkout master git pull - git describe --tags --abbrev=0 --exclude="*-rc*" > C:\projects\latest-obs-studio-tag-post-pull.txt - set /p OBSLatestTagPostPull= C:\projects\latest-obs-studio-tag.txt + git describe --tags --abbrev=0 --exclude="*-rc*" > "%OBSPath%\latest-obs-studio-tag-post-pull.txt" + set /p OBSLatestTagPostPull=<"%OBSPath%\latest-obs-studio-tag-post-pull.txt" + set /p OBSLatestTag=<"%OBSPath%\latest-obs-studio-tag-post-pull.txt" + echo %OBSLatestTagPostPull%> "%OBSPath%\latest-obs-studio-tag.txt" ) REM Check the obs-studio tags for mismatches. @@ -58,22 +58,22 @@ if not %OBSLatestTagPostPull%==%OBSLastTagBuilt% ( REM If obs-studio directory does not exist, clone the git repo, get the latest REM tag number, and set the build flag. -if not exist C:\projects\obs-studio ( +if not exist %OBSPath% ( echo obs-studio directory does not exist - git clone https://github.com/obsproject/obs-studio - cd C:\projects\obs-studio\ - git describe --tags --abbrev=0 --exclude="*-rc*" > C:\projects\obs-studio-latest-tag.txt - set /p OBSLatestTag= "%OBSPath%\obs-studio-latest-tag.txt" + set /p OBSLatestTag=<"%OBSPath%\obs-studio-latest-tag.txt" set BuildOBS=true ) REM If the needed obs-studio libs for this build_config do not exist, REM set the build flag. -if not exist C:\projects\obs-studio\build32\libobs\%build_config%\obs.lib ( +if not exist %OBSPath%\build32\libobs\%build_config%\obs.lib ( echo obs-studio\build32\libobs\%build_config%\obs.lib does not exist set BuildOBS=true ) -if not exist C:\projects\obs-studio\build32\UI\obs-frontend-api\%build_config%\obs-frontend-api.lib ( +if not exist %OBSPath%\build32\UI\obs-frontend-api\%build_config%\obs-frontend-api.lib ( echo obs-studio\build32\UI\obs-frontend-api\%build_config%\obs-frontend-api.lib does not exist set BuildOBS=true ) @@ -95,35 +95,43 @@ echo: REM If the build flag is set, build obs-studio. if defined BuildOBS ( echo Building obs-studio... + cd /D %OBSPath% echo git checkout %OBSLatestTag% git checkout %OBSLatestTag% echo: - echo Removing previous build dirs... - if exist build rmdir /s /q C:\projects\obs-studio\build - if exist build32 rmdir /s /q C:\projects\obs-studio\build32 - if exist build64 rmdir /s /q C:\projects\obs-studio\build64 - echo Making new build dirs... - mkdir build + + echo Removing previous build dirs... + if exist build32 rmdir /s /q "%OBSPath%\build32" + if exist build64 rmdir /s /q "%OBSPath%\build64" + + echo Making new build dirs... mkdir build32 mkdir build64 - echo Running cmake for obs-studio %OBSLatestTag% 32-bit... - cd ./build32 - cmake -G "Visual Studio 14 2015" -DBUILD_CAPTIONS=true -DDISABLE_PLUGINS=true -DCOPIED_DEPENDENCIES=false -DCOPY_DEPENDENCIES=true .. + + echo Running cmake for obs-studio %OBSLatestTag% 32-bit... + cd build32 + cmake -G "Visual Studio 16 2019" -A Win32 -DCMAKE_SYSTEM_VERSION=10.0 -DQTDIR="%QTDIR32%" -DDepsPath="%DepsPath32%" -DBUILD_CAPTIONS=true -DDISABLE_PLUGINS=true -DCOPIED_DEPENDENCIES=false -DCOPY_DEPENDENCIES=true .. echo: echo: - echo Running cmake for obs-studio %OBSLatestTag% 64-bit... - cd ../build64 - cmake -G "Visual Studio 14 2015 Win64" -DBUILD_CAPTIONS=true -DDISABLE_PLUGINS=true -DCOPIED_DEPENDENCIES=false -DCOPY_DEPENDENCIES=true .. + + echo Running cmake for obs-studio %OBSLatestTag% 64-bit... + cd ..\build64 + cmake -G "Visual Studio 16 2019" -A x64 -DCMAKE_SYSTEM_VERSION=10.0 -DQTDIR="%QTDIR64%" -DDepsPath="%DepsPath64%" -DBUILD_CAPTIONS=true -DDISABLE_PLUGINS=true -DCOPIED_DEPENDENCIES=false -DCOPY_DEPENDENCIES=true .. echo: echo: - echo Building obs-studio %OBSLatestTag% 32-bit ^(Build Config: %build_config%^)... - call msbuild /m /p:Configuration=%build_config% C:\projects\obs-studio\build32\obs-studio.sln /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" - echo Building obs-studio %OBSLatestTag% 64-bit ^(Build Config: %build_config%^)... - call msbuild /m /p:Configuration=%build_config% C:\projects\obs-studio\build64\obs-studio.sln /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" - cd .. - git describe --tags --abbrev=0 > C:\projects\obs-studio-last-tag-built.txt - set /p OBSLastTagBuilt= "%OBSPath%\obs-studio-last-tag-built.txt" + set /p OBSLastTagBuilt=<"%OBSPath%\obs-studio-last-tag-built.txt" ) else ( echo Last OBS tag built is: %OBSLastTagBuilt% echo No need to rebuild OBS. ) + +dir "%OBSPath%\libobs" diff --git a/CI/download-obs-deps.cmd b/CI/download-obs-deps.cmd new file mode 100644 index 00000000..ff4ffd57 --- /dev/null +++ b/CI/download-obs-deps.cmd @@ -0,0 +1,6 @@ +if not exist %DepsBasePath% ( + curl -o %DepsBasePath%.zip -kLO https://obsproject.com/downloads/dependencies2017.zip -f --retry 5 -C - + 7z x %DepsBasePath%.zip -o%DepsBasePath% +) else ( + echo "OBS dependencies are already there. Download skipped." +) diff --git a/CI/generate-docs.sh b/CI/generate-docs.sh index 5e7d6d01..bb1d3dfd 100755 --- a/CI/generate-docs.sh +++ b/CI/generate-docs.sh @@ -4,6 +4,9 @@ echo "-- Generating documentation." echo "-- Node version: $(node -v)" echo "-- NPM version: $(npm -v)" +git fetch origin +git checkout ${CHECKOUT_REF/refs\/heads\//} + cd docs npm install npm run build @@ -15,19 +18,14 @@ if git diff --quiet; then exit 0 fi -if [ "$TRAVIS_PULL_REQUEST" != "false" -o "$TRAVIS_BRANCH" != "4.x-current" ]; then - echo "-- Skipping documentation deployment because this is either a pull request or a non-master branch." - exit 0 -fi - REMOTE_URL="$(git config remote.origin.url)" TARGET_REPO=${REMOTE_URL/https:\/\/github.com\//github.com/} GITHUB_REPO=https://${GH_TOKEN:-git}@${TARGET_REPO} -git config user.name "Travis CI" +git config user.name "Azure CI" git config user.email "$COMMIT_AUTHOR_EMAIL" git add ./generated git pull -git commit -m "docs(travis): Update protocol.md - $(git rev-parse --short HEAD) [skip ci]" -git push -q $GITHUB_REPO HEAD:$TRAVIS_BRANCH +git commit -m "docs(ci): Update protocol.md - $(git rev-parse --short HEAD) [skip ci]" +git push -q $GITHUB_REPO diff --git a/CI/install-dependencies-ubuntu.sh b/CI/install-dependencies-ubuntu.sh new file mode 100755 index 00000000..d0e16f53 --- /dev/null +++ b/CI/install-dependencies-ubuntu.sh @@ -0,0 +1,19 @@ +#!/bin/sh +set -ex + +sudo add-apt-repository -y ppa:obsproject/obs-studio +sudo apt-get -qq update + +sudo apt-get install -y \ + libc-dev-bin \ + libc6-dev git \ + build-essential \ + checkinstall \ + cmake \ + obs-studio \ + qtbase5-dev + +# Dirty hack +sudo wget -O /usr/include/obs/obs-frontend-api.h https://raw.githubusercontent.com/obsproject/obs-studio/25.0.0/UI/obs-frontend-api/obs-frontend-api.h + +sudo ldconfig diff --git a/CI/install-dependencies-xenial.sh b/CI/install-dependencies-xenial.sh deleted file mode 100755 index c55d82d7..00000000 --- a/CI/install-dependencies-xenial.sh +++ /dev/null @@ -1,19 +0,0 @@ -#!/bin/sh -set -ex - -add-apt-repository -y ppa:obsproject/obs-studio -apt-get -qq update - -apt-get install -y \ - libc-dev-bin \ - libc6-dev git \ - build-essential \ - checkinstall \ - cmake \ - obs-studio \ - qtbase5-dev - -# Dirty hack -wget -O /usr/include/obs/obs-frontend-api.h https://raw.githubusercontent.com/obsproject/obs-studio/25.0.0/UI/obs-frontend-api/obs-frontend-api.h - -ldconfig diff --git a/CI/install-qt-win.cmd b/CI/install-qt-win.cmd new file mode 100644 index 00000000..e0537fe8 --- /dev/null +++ b/CI/install-qt-win.cmd @@ -0,0 +1,8 @@ +if not exist %QtBaseDir% ( + curl -kLO https://cdn-fastly.obsproject.com/downloads/Qt_5.10.1.7z -f --retry 5 -z Qt_5.10.1.7z + 7z x Qt_5.10.1.7z -o%QtBaseDir% +) else ( + echo "Qt is already installed. Download skipped." +) + +dir %QtBaseDir% diff --git a/CI/install-setup-qt.cmd b/CI/install-setup-qt.cmd deleted file mode 100644 index e7dc3784..00000000 --- a/CI/install-setup-qt.cmd +++ /dev/null @@ -1,6 +0,0 @@ -@echo off - -REM Set default values to use AppVeyor's built-in Qt. -set QTDIR32=C:\Qt\5.10.1\msvc2015 -set QTDIR64=C:\Qt\5.10.1\msvc2015_64 -set QTCompileVersion=5.10.1 diff --git a/CI/package-macos.sh b/CI/package-macos.sh index b68c40a8..5210ba5b 100755 --- a/CI/package-macos.sh +++ b/CI/package-macos.sh @@ -19,7 +19,6 @@ export VERSION="$GIT_HASH-$GIT_BRANCH_OR_TAG" export LATEST_VERSION="$GIT_BRANCH_OR_TAG" export FILENAME="obs-websocket-$VERSION.pkg" -export LATEST_FILENAME="obs-websocket-latest-$LATEST_VERSION.pkg" echo "[obs-websocket] Modifying obs-websocket.so" install_name_tool \ @@ -40,4 +39,3 @@ packagesbuild ./CI/macos/obs-websocket.pkgproj echo "[obs-websocket] Renaming obs-websocket.pkg to $FILENAME" mv ./release/obs-websocket.pkg ./release/$FILENAME -cp ./release/$FILENAME ./release/$LATEST_FILENAME diff --git a/CI/package-ubuntu.sh b/CI/package-ubuntu.sh new file mode 100755 index 00000000..367e002c --- /dev/null +++ b/CI/package-ubuntu.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +set -e + +export GIT_HASH=$(git rev-parse --short HEAD) +export PKG_VERSION="1-$GIT_HASH-$BRANCH_SHORT_NAME-git" + +if [[ "$BRANCH_FULL_NAME" =~ "^refs/tags/" ]]; then + export PKG_VERSION="$BRANCH_SHORT_NAME" +fi + +cd ./build + +PAGER="cat" sudo checkinstall -y --type=debian --fstrans=no --nodoc \ + --backup=no --deldoc=yes --install=no \ + --pkgname=obs-websocket --pkgversion="$PKG_VERSION" \ + --pkglicense="GPLv2.0" --maintainer="stephane.lepin@gmail.com" \ + --pkggroup="video" \ + --pkgsource="https://github.com/Palakis/obs-websocket" \ + --requires="obs-studio,libqt5core5a,libqt5widgets5,qt5-image-formats-plugins" \ + --pakdir="../package" + +sudo chmod ao+r ../package/* diff --git a/CI/package-windows.cmd b/CI/package-windows.cmd new file mode 100644 index 00000000..fe752995 --- /dev/null +++ b/CI/package-windows.cmd @@ -0,0 +1,12 @@ +mkdir package +cd package + +git rev-parse --short HEAD > package-version.txt +set /p PackageVersion=