Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
99 changes: 99 additions & 0 deletions .github/workflows/libmoq.yml
Original file line number Diff line number Diff line change
Expand Up @@ -108,3 +108,102 @@ jobs:
RELEASE_TITLE: "libmoq v${{ steps.parse.outputs.version }}"
RELEASE_PREV_TAG: ${{ steps.prev_tag.outputs.tag }}
run: .github/scripts/release.sh create artifacts

# The OBS plugin (cpp/obs) statically links libmoq, so it ships with every
# libmoq release: rebuild it against the release we just published (no
# second cargo build, guaranteed-matching ABI) and cut a parallel
# obs-moq-v<version> release. Runs after `release` so the libmoq archives
# the plugin's CMake fetches are already live.
obs-build:
name: OBS plugin (${{ matrix.target }})
needs: release
runs-on: ${{ matrix.os }}

# macOS + Windows only. These link the ffmpeg the obs-deps bundle ships
# (the same one OBS uses), so the binaries are portable. A Linux build
# would link nix/distro ffmpeg and not be portable, so Linux is
# build-from-source (see doc/bin/obs.md) and ships no prebuilt binary.
strategy:
fail-fast: false
matrix:
include:
- target: aarch64-apple-darwin
os: macos-latest
- target: x86_64-pc-windows-msvc
os: windows-latest

steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
with:
fetch-depth: 0
persist-credentials: false

- name: Parse version
id: parse
shell: bash
run: .github/scripts/release.sh parse-version libmoq

# Native Xcode / Visual Studio; libobs/Qt6/ffmpeg come from the obs-deps
# bundle and libmoq from the release we just published (--libmoq-release).
- name: Build and package
shell: bash
env:
TARGET: ${{ matrix.target }}
VERSION: ${{ steps.parse.outputs.version }}
run: |
./cpp/obs/build.sh --target "$TARGET" --libmoq-release "$VERSION" --output dist

- name: Upload artifact
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: obs-moq-${{ matrix.target }}
path: dist/*

obs-release:
name: OBS plugin release
needs: obs-build
runs-on: ubuntu-latest
permissions:
contents: write

steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
with:
fetch-depth: 0
persist-credentials: false

- name: Parse version
id: parse
run: .github/scripts/release.sh parse-version libmoq

# Only the obs-moq archives: the libmoq-* artifacts from the build job
# belong to the libmoq release, not this one.
- name: Download artifacts
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
with:
path: artifacts
pattern: obs-moq-*
merge-multiple: true

# release.sh prev-tag keys off the current tag, but the trigger here is a
# libmoq-v* tag, so it can't find the previous obs-moq tag. Take the
# newest existing obs-moq tag (excluding this version, for safe re-runs)
# so the release notes span only since the last obs-moq release.
- name: Find previous obs-moq tag
id: prev_tag
env:
VERSION: ${{ steps.parse.outputs.version }}
run: |
cur="obs-moq-v${VERSION}"
prev=$(git tag --list 'obs-moq-v*' --sort=-v:refname | grep -vx "$cur" | head -n1)
echo "tag=${prev}" >>"$GITHUB_OUTPUT"

# Cut a parallel obs-moq-v<version> release at this commit (gh creates
# the tag).
- name: Create or update release
env:
GH_TOKEN: ${{ github.token }}
RELEASE_TAG: "obs-moq-v${{ steps.parse.outputs.version }}"
RELEASE_TITLE: "obs-moq v${{ steps.parse.outputs.version }}"
RELEASE_PREV_TAG: ${{ steps.prev_tag.outputs.tag }}
run: .github/scripts/release.sh create artifacts
4 changes: 4 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,9 @@ Key architectural rule: The CDN/relay does not know anything about media. Anythi
# CI mirrors them to moq-dev/moq-{swift,kotlin,go}
# on each moq-ffi-v* tag.

/cpp/ # C/C++ consumers of libmoq
obs/ # OBS Studio plugin (CMake; links libmoq via MOQ_LOCAL). GPL-2.0-or-later.

/demo/ # Demos and test media
boy/ # MoQ Boy demo (ROM hosting, orchestration justfile)
relay/ # Relay server configs (relay.toml, root.toml, leaf*.toml)
Expand Down Expand Up @@ -193,6 +196,7 @@ Changes in one area usually need matching updates elsewhere, including docs. If
| `rs/moq-relay` config/behavior | `doc/bin/relay/` |
| `rs/moq-cli` | `doc/bin/cli.md` |
| `rs/moq-gst` | `doc/bin/gstreamer.md` |
| `rs/libmoq` C ABI (`moq.h`) | `cpp/obs/src`, `doc/bin/obs.md` |
| `js/{watch,publish}` UI/API | `demo/web` if it consumes the API |

## Branch Targeting
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -135,3 +135,5 @@ Licensed under either:

- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or https://www.apache.org/licenses/LICENSE-2.0)
- MIT license ([LICENSE-MIT](LICENSE-MIT) or https://opensource.org/licenses/MIT)

**Exception:** the OBS plugin under [`cpp/obs/`](cpp/obs) is licensed under **GPL-2.0-or-later** (see [`cpp/obs/LICENSE`](cpp/obs/LICENSE)), because it links OBS Studio's `libobs`, which is GPL-2.0. This is a separately-distributable work; per GPLv2 its presence in this repository is mere aggregation and does not affect the MIT/Apache licensing of the rest of the project. `libmoq` and the other moq crates remain MIT/Apache.
209 changes: 209 additions & 0 deletions cpp/obs/.clang-format
Original file line number Diff line number Diff line change
@@ -0,0 +1,209 @@
# please use clang-format version 16 or later

Standard: c++17
AccessModifierOffset: -8
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignEscapedNewlines: Left
AlignOperands: true
AlignTrailingComments: true
AllowAllArgumentsOnNextLine: false
AllowAllConstructorInitializersOnNextLine: false
AllowAllParametersOfDeclarationOnNextLine: false
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: Inline
AllowShortIfStatementsOnASingleLine: false
AllowShortLambdasOnASingleLine: Inline
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: false
BinPackArguments: true
BinPackParameters: true
BraceWrapping:
AfterClass: false
AfterControlStatement: false
AfterEnum: false
AfterFunction: true
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
AfterExternBlock: false
BeforeCatch: false
BeforeElse: false
IndentBraces: false
SplitEmptyFunction: true
SplitEmptyRecord: true
SplitEmptyNamespace: true
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Custom
BreakBeforeTernaryOperators: true
BreakConstructorInitializers: BeforeColon
BreakStringLiterals: false # apparently unpredictable
ColumnLimit: 120
CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: true
ConstructorInitializerIndentWidth: 8
ContinuationIndentWidth: 8
Cpp11BracedListStyle: true
DerivePointerAlignment: false
DisableFormat: false
FixNamespaceComments: true
ForEachMacros:
- 'json_object_foreach'
- 'json_object_foreach_safe'
- 'json_array_foreach'
- 'HASH_ITER'
IncludeBlocks: Preserve
IndentCaseLabels: false
IndentPPDirectives: None
IndentWidth: 8
IndentWrappedFunctionNames: false
KeepEmptyLinesAtTheStartOfBlocks: true
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCBinPackProtocolList: Auto
ObjCBlockIndentWidth: 8
ObjCSpaceAfterProperty: true
ObjCSpaceBeforeProtocolList: true

PenaltyBreakAssignment: 10
PenaltyBreakBeforeFirstCallParameter: 30
PenaltyBreakComment: 10
PenaltyBreakFirstLessLess: 0
PenaltyBreakString: 10
PenaltyExcessCharacter: 100
PenaltyReturnTypeOnItsOwnLine: 60

PointerAlignment: Right
ReflowComments: false
SkipMacroDefinitionBody: true
SortIncludes: false
SortUsingDeclarations: false
SpaceAfterCStyleCast: false
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: false
SpaceBeforeAssignmentOperators: true
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatements
SpaceBeforeRangeBasedForLoopColon: true
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: false
SpacesInCStyleCastParentheses: false
SpacesInContainerLiterals: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
StatementMacros:
- 'Q_OBJECT'
TabWidth: 8
TypenameMacros:
- 'DARRAY'
UseTab: ForContinuationAndIndentation
---
Language: ObjC
AccessModifierOffset: 2
AlignArrayOfStructures: Right
AlignConsecutiveAssignments: None
AlignConsecutiveBitFields: None
AlignConsecutiveDeclarations: None
AlignConsecutiveMacros:
Enabled: true
AcrossEmptyLines: false
AcrossComments: true
AllowShortBlocksOnASingleLine: Never
AllowShortEnumsOnASingleLine: false
AllowShortFunctionsOnASingleLine: Empty
AllowShortIfStatementsOnASingleLine: Never
AllowShortLambdasOnASingleLine: None
AttributeMacros: ['__unused', '__autoreleasing', '_Nonnull', '__bridge']
BitFieldColonSpacing: Both
#BreakBeforeBraces: Webkit
BreakBeforeBraces: Custom
BraceWrapping:
AfterCaseLabel: false
AfterClass: true
AfterControlStatement: Never
AfterEnum: false
AfterFunction: true
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
AfterExternBlock: false
BeforeCatch: false
BeforeElse: false
BeforeLambdaBody: false
BeforeWhile: false
IndentBraces: false
SplitEmptyFunction: false
SplitEmptyRecord: false
SplitEmptyNamespace: true
BreakAfterAttributes: Never
BreakArrays: false
BreakBeforeConceptDeclarations: Allowed
BreakBeforeInlineASMColon: OnlyMultiline
BreakConstructorInitializers: AfterColon
BreakInheritanceList: AfterComma
ColumnLimit: 120
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
EmptyLineAfterAccessModifier: Never
EmptyLineBeforeAccessModifier: LogicalBlock
ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: true
IndentAccessModifiers: false
IndentCaseBlocks: false
IndentCaseLabels: true
IndentExternBlock: Indent
IndentGotoLabels: false
IndentRequiresClause: true
IndentWidth: 4
IndentWrappedFunctionNames: true
InsertBraces: false
InsertNewlineAtEOF: true
KeepEmptyLinesAtTheStartOfBlocks: false
LambdaBodyIndentation: Signature
NamespaceIndentation: All
ObjCBinPackProtocolList: Auto
ObjCBlockIndentWidth: 4
ObjCBreakBeforeNestedBlockParam: false
ObjCSpaceAfterProperty: true
ObjCSpaceBeforeProtocolList: true
PPIndentWidth: -1
PackConstructorInitializers: NextLine
QualifierAlignment: Leave
ReferenceAlignment: Right
RemoveSemicolon: false
RequiresClausePosition: WithPreceding
RequiresExpressionIndentation: OuterScope
SeparateDefinitionBlocks: Leave
ShortNamespaceLines: 1
SortIncludes: false
#SortUsingDeclarations: LexicographicNumeric
SortUsingDeclarations: true
SpaceAfterCStyleCast: true
SpaceAfterLogicalNot: false
SpaceAroundPointerQualifiers: Default
SpaceBeforeCaseColon: false
SpaceBeforeCpp11BracedList: true
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatements
SpaceBeforeRangeBasedForLoopColon: true
SpaceBeforeSquareBrackets: false
SpaceInEmptyBlock: false
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 2
SpacesInConditionalStatement: false
SpacesInLineCommentPrefix:
Minimum: 1
Maximum: -1
Standard: c++17
TabWidth: 4
UseTab: Never
8 changes: 8 additions & 0 deletions cpp/obs/.gersemirc
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# yaml-language-server: $schema=https://raw.githubusercontent.com/BlankSpruce/gersemi/master/gersemi/configuration.schema.json

definitions: []
line_length: 120
indent: 2
list_expansion: favour-inlining
unsafe: false
warn_about_unknown_commands: false
11 changes: 11 additions & 0 deletions cpp/obs/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# CMake build trees (per the platform presets) and CPack output.
build_macos/
build_x64/
build_x86_64/
release/

# Downloaded OBS sources + prebuilt obs-deps/Qt6 (macOS/Windows buildspec).
.deps/

# Generated build counter.
cmake/.CMakeBuildNumber
Loading