├── .gitattributes ├── .github └── workflows │ ├── build.yml │ ├── metrics.yml │ └── release.yml ├── .gitignore ├── BlazorHelloWorld ├── BlazorHelloWorld.csproj ├── Components │ ├── App.razor │ ├── Layout │ │ ├── MainLayout.razor │ │ ├── MainLayout.razor.css │ │ ├── NavMenu.razor │ │ └── NavMenu.razor.css │ ├── Pages │ │ └── Home.razor │ ├── Routes.razor │ └── _Imports.razor ├── Infrastructure │ └── VideoService.cs ├── Program.cs ├── Properties │ └── launchSettings.json ├── appsettings.Development.json ├── appsettings.json └── wwwroot │ ├── app.css │ ├── bootstrap │ ├── bootstrap.min.css │ └── bootstrap.min.css.map │ ├── content │ └── customScripts.js │ └── favicon.png ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── DEVELOPING.md ├── LICENSE ├── OpenTok.sln ├── OpenTok ├── Archive.cs ├── ArchiveLayout.cs ├── ArchiveList.cs ├── AudioConnector.cs ├── AudioConnectorStartRequest.cs ├── Broadcast.cs ├── BroadcastBitrate.cs ├── BroadcastLayout.cs ├── Caption.cs ├── CaptionOptions.cs ├── Constants │ └── OpenTokVersion.cs ├── DialAuth.cs ├── DialOptions.cs ├── Exception │ ├── OpenTokArgumentException.cs │ ├── OpenTokException.cs │ └── OpenTokWebException.cs ├── LayoutType.cs ├── OpenTok.AudioConnector.cs ├── OpenTok.Captions.cs ├── OpenTok.Render.cs ├── OpenTok.cs ├── OpenTok.csproj ├── Render │ ├── ListRendersRequest.cs │ ├── ListRendersResponse.cs │ ├── RenderItem.cs │ ├── RenderResolution.cs │ ├── RenderResolutionConverter.cs │ └── StartRenderRequest.cs ├── Role.cs ├── Rtmp.cs ├── ScreenShareLayoutType.cs ├── Session.cs ├── SignalProperties.cs ├── Sip.cs ├── Stream.cs ├── StreamList.cs ├── StreamMode.cs ├── StreamProperties.cs ├── Util │ ├── HttpClient.cs │ ├── OpenTokUtils.cs │ └── TokenGenerator.cs └── app.config ├── OpenTokTest ├── ArchiveTests.cs ├── AudioConnectorStartRequestDataBuilder.cs ├── AudioConnectorStartRequestTests.cs ├── BroadcastBitrateTest.cs ├── BroadcastTests.cs ├── CaptionOptionsTest.cs ├── Data │ ├── ArchiveTests │ │ ├── GetArchive-response.json │ │ ├── GetArchiveAsync-response.json │ │ ├── GetArchiveWithUnknownProperties-response.json │ │ ├── GetArchiveWithUnknownPropertiesAsync-response.json │ │ ├── GetExpiredArchive-response.json │ │ ├── GetExpiredArchiveAsync-response.json │ │ ├── ListArchives-response.json │ │ ├── ListArchivesAsync-response.json │ │ ├── ListArchivesAsyncWithValidSessionId-response.json │ │ ├── ListArchivesWithValidSessionId-response.json │ │ ├── StartArchive-response.json │ │ ├── StartArchiveAsync-response.json │ │ ├── StartArchiveAsyncAutoStreamMode-response.json │ │ ├── StartArchiveAsyncCreateInvalidIndividualModeArchivingWithResolution-response.json │ │ ├── StartArchiveAsyncCustomLayout-response.json │ │ ├── StartArchiveAsyncCustomLayoutMissingStylesheet-response.json │ │ ├── StartArchiveAsyncIndividual-response.json │ │ ├── StartArchiveAsyncManualStreamMode-response.json │ │ ├── StartArchiveAsyncNoResolution-response.json │ │ ├── StartArchiveAsyncVerticalLayout-response.json │ │ ├── StartArchiveAsyncVerticalLayoutWithStyleSheet-response.json │ │ ├── StartArchiveAsyncVoiceOnly-response.json │ │ ├── StartArchiveAsyncWithHDResolution-response.json │ │ ├── StartArchiveAsyncWithSDResolution-response.json │ │ ├── StartArchiveAutoStreamMode-response.json │ │ ├── StartArchiveCreateInvalidIndividualModeArchivingWithResolution-response.json │ │ ├── StartArchiveCustomLayout-response.json │ │ ├── StartArchiveCustomLayoutMissingStylesheet-response.json │ │ ├── StartArchiveIndividual-response.json │ │ ├── StartArchiveManualStreamMode-response.json │ │ ├── StartArchiveNoResolution-response.json │ │ ├── StartArchiveVerticalLayout-response.json │ │ ├── StartArchiveVerticalLayoutWithStyleSheet-response.json │ │ ├── StartArchiveVoiceOnly-response.json │ │ ├── StartArchiveWithHDResolution-response.json │ │ ├── StartArchiveWithMultiArchiveTag-response.json │ │ ├── StartArchiveWithMultiArchiveTagAsync-response.json │ │ ├── StartArchiveWithSDResolution-response.json │ │ ├── StopArchive-response.json │ │ ├── StopArchiveAsync-response.json │ │ ├── StopArchiveAsyncFromArchiveObject-response.json │ │ └── StopArchiveFromArchiveObject-response.json │ ├── BroadcastTests │ │ ├── GetBroadcast-response.json │ │ ├── GetBroadcastAsync-response.json │ │ ├── StartBroadcast-response.json │ │ ├── StartBroadcastAsync-response.json │ │ ├── StartBroadcastOnlyWithRTMP-response.json │ │ ├── StartBroadcastOnlyWithRTMPAsync-response.json │ │ ├── StartBroadcastWithAutoStreamMode-response.json │ │ ├── StartBroadcastWithAutoStreamModeAsync-response.json │ │ ├── StartBroadcastWithDvr-response.json │ │ ├── StartBroadcastWithDvrAsync-response.json │ │ ├── StartBroadcastWithHDResolution-response.json │ │ ├── StartBroadcastWithHDResolutionAsync-response.json │ │ ├── StartBroadcastWithLowLatency-response.json │ │ ├── StartBroadcastWithLowLatencyAsync-response.json │ │ ├── StartBroadcastWithManualStreamMode-response.json │ │ ├── StartBroadcastWithManualStreamModeAsync-response.json │ │ ├── StartBroadcastWithMultiBroadcastTag-response.json │ │ ├── StartBroadcastWithRTMPandHLS-response.json │ │ ├── StartBroadcastWithRTMPandHLSAsync-response.json │ │ ├── StartBroadcastWithSDResolution-response.json │ │ ├── StartBroadcastWithSDResolutionAsync-response.json │ │ ├── StartBroadcastWithScreenShareType-response.json │ │ ├── StartBroadcastWithScreenShareTypeAsync-response.json │ │ ├── StopBroadcast-response.json │ │ └── StopBroadcastAsync-response.json │ ├── DialTests │ │ ├── DialAsyncCorrectHeaders-response.json │ │ ├── DialAsyncCorrectResponse-response.json │ │ ├── DialCorrectData-response.json │ │ ├── DialCorrectHeaders-response.json │ │ └── DialCorrectResponse-response.json │ └── StreamTests │ │ ├── GetStream-response.json │ │ ├── GetStreamAsync-response.json │ │ ├── GetStreamAsyncEmpty-response.json │ │ ├── GetStreamEmpty-response.json │ │ ├── ListStreams-response.json │ │ └── ListStreamsAsync-response.json ├── DialTests.cs ├── DisableForceMuteTests.cs ├── ForceDisconnect.cs ├── ForceMuteAllTests.cs ├── ForceMuteStreamTests.cs ├── OpenTok.AudioConnectorTests.cs ├── OpenTok.CaptionsTests.cs ├── OpenTok.RenderTests.cs ├── OpenTokTest.csproj ├── OpenTokTests.cs ├── PlayDtmfTests.cs ├── Render │ ├── ListRendersRequestTests.cs │ ├── StartRenderRequestDataBuilder.cs │ └── StartRenderRequestTest.cs ├── Session.cs ├── SignalTests.cs ├── StreamTests.cs ├── TestBase.cs ├── TokenTests.cs └── app.config ├── README.md └── Samples ├── Archiving ├── App.config ├── App.config.sample ├── Archiving.csproj ├── Bootstrapper.cs ├── Content │ ├── css │ │ └── sample.css │ ├── img │ │ ├── archiving-off.png │ │ ├── archiving-on-idle.png │ │ └── archiving-on-message.png │ └── js │ │ ├── host.js │ │ └── participant.js ├── MainModule.cs ├── OpenTokService.cs ├── Program.cs ├── README.md ├── Startup.cs └── views │ ├── History.cshtml │ ├── Host.cshtml │ ├── Index.cshtml │ ├── Participant.cshtml │ ├── Shared │ └── Layout.cshtml │ ├── _ViewStart.cshtml │ └── history.sshtml ├── Broadcasting ├── App.config ├── App.config.sample ├── Bootstrapper.cs ├── Broadcasting.csproj ├── Content │ ├── css │ │ └── sample.css │ └── js │ │ ├── host.js │ │ └── participant.js ├── MainModule.cs ├── OpenTokService.cs ├── Program.cs ├── README.md ├── Startup.cs └── views │ ├── Host.cshtml │ ├── Index.cshtml │ ├── Participant.cshtml │ ├── Shared │ └── Layout.cshtml │ └── _ViewStart.cshtml └── HelloWorld ├── App.config ├── App.config.sample ├── Bootstrapper.cs ├── Content └── js │ └── helloworld.js ├── HelloWorld.csproj ├── MainModule.cs ├── OpenTokService.cs ├── Program.cs ├── README.md ├── Startup.cs └── views └── index.html /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # These files are text and should be normalized (convert crlf => lf) 5 | *.cs text diff=csharp 6 | *.xaml text 7 | *.csproj text 8 | *.sln text 9 | *.tt text 10 | *.ps1 text 11 | *.cmd text 12 | *.msbuild text 13 | *.md text 14 | 15 | # Images should be treated as binary 16 | # (binary is a macro for -text -diff) 17 | *.png binary 18 | *.jpeg binary 19 | *.sdf binary 20 | 21 | # Custom for Visual Studio 22 | *.cs diff=csharp 23 | *.sln merge=union 24 | *.csproj merge=union 25 | *.vbproj merge=union 26 | *.fsproj merge=union 27 | *.dbproj merge=union 28 | 29 | # Standard to msysgit 30 | *.doc diff=astextplain 31 | *.DOC diff=astextplain 32 | *.docx diff=astextplain 33 | *.DOCX diff=astextplain 34 | *.dot diff=astextplain 35 | *.DOT diff=astextplain 36 | *.pdf diff=astextplain 37 | *.PDF diff=astextplain 38 | *.rtf diff=astextplain 39 | *.RTF diff=astextplain 40 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: "Build & Test" 2 | 3 | on: 4 | push: 5 | branches: [ main, dev ] 6 | pull_request: 7 | branches: [ main, dev ] 8 | 9 | env: 10 | CONFIGURATION: "Release" 11 | 12 | jobs: 13 | build: 14 | env: 15 | DOTNET_NOLOGO: true 16 | runs-on: windows-latest 17 | 18 | steps: 19 | - uses: actions/checkout@v2 20 | - name: Setup .NET Core 21 | uses: actions/setup-dotnet@v1 22 | with: 23 | dotnet-version: 8.0.x 24 | - name: Clean 25 | run: dotnet clean OpenTok.sln --configuration ${{ env.CONFIGURATION }} && dotnet nuget locals all --clear 26 | - name: Install dependencies 27 | run: dotnet restore 28 | - name: Build 29 | run: dotnet build OpenTok.sln --configuration ${{ env.CONFIGURATION }} --no-restore 30 | - name: Test 31 | run: dotnet test OpenTokTest/OpenTokTest.csproj --configuration ${{ env.CONFIGURATION }} --no-build -------------------------------------------------------------------------------- /.github/workflows/metrics.yml: -------------------------------------------------------------------------------- 1 | name: Aggregit 2 | 3 | on: 4 | schedule: 5 | - cron: "0 0 * * *" 6 | 7 | jobs: 8 | recordMetrics: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: michaeljolley/aggregit@v1 12 | with: 13 | githubToken: ${{ secrets.GITHUB_TOKEN }} 14 | project_id: ${{ secrets.project_id }} 15 | private_key: ${{ secrets.private_key }} 16 | client_email: ${{ secrets.client_email }} 17 | firebaseDbUrl: ${{ secrets.firebaseDbUrl }} 18 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Nuget Release 2 | on: 3 | release: 4 | types: [published] 5 | jobs: 6 | build: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - uses: actions/checkout@v2 10 | with: 11 | ref: ${{ github.event.release.target_commitish }} 12 | - name: Release Nuget 13 | uses: nexmo/github-actions/nuget-release@main 14 | env: 15 | PROJECT_FILE : OpenTok/OpenTok.csproj 16 | BRANCH: main 17 | ORGANIZATION: opentok 18 | REPO: Opentok-.NET-SDK 19 | TAG: ${{ github.event.release.tag_name }} 20 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 21 | NUGET_API_KEY: ${{ secrets.NUGET_API_KEY }} 22 | GITHUB_USER_NAME: NexmoDev 23 | GITHUB_EMAIL: 44278943+NexmoDev@users.noreply.github.com 24 | OUTPUT_PATH: OpenTok/bin/Release -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ################# 2 | ## Eclipse 3 | ################# 4 | 5 | *.pydevproject 6 | .project 7 | .metadata 8 | bin/ 9 | tmp/ 10 | *.tmp 11 | *.bak 12 | *.swp 13 | *~.nib 14 | local.properties 15 | .classpath 16 | .settings/ 17 | .loadpath 18 | 19 | # External tool builders 20 | .externalToolBuilders/ 21 | 22 | # Locally stored "Eclipse launch configurations" 23 | *.launch 24 | 25 | # CDT-specific 26 | .cproject 27 | 28 | # PDT-specific 29 | .buildpath 30 | 31 | .vs 32 | 33 | ################# 34 | ## Visual Studio 35 | ################# 36 | 37 | ## Ignore Visual Studio temporary files, build results, and 38 | ## files generated by popular Visual Studio add-ons. 39 | 40 | # User-specific files 41 | *.suo 42 | *.user 43 | *.sln.docstates 44 | *.vs 45 | 46 | # Build results 47 | 48 | [Dd]ebug/ 49 | [Rr]elease/ 50 | x64/ 51 | build/ 52 | [Bb]in/ 53 | [Oo]bj/ 54 | 55 | # MSTest test Results 56 | [Tt]est[Rr]esult*/ 57 | [Bb]uild[Ll]og.* 58 | 59 | *_i.c 60 | *_p.c 61 | *.ilk 62 | *.meta 63 | *.obj 64 | *.pch 65 | *.pdb 66 | *.pgc 67 | *.pgd 68 | *.rsp 69 | *.sbr 70 | *.tlb 71 | *.tli 72 | *.tlh 73 | *.tmp 74 | *.tmp_proj 75 | *.log 76 | *.vspscc 77 | *.vssscc 78 | .builds 79 | *.pidb 80 | *.log 81 | *.scc 82 | 83 | # Visual C++ cache files 84 | ipch/ 85 | *.aps 86 | *.ncb 87 | *.opensdf 88 | *.sdf 89 | *.cachefile 90 | 91 | # Visual Studio profiler 92 | *.psess 93 | *.vsp 94 | *.vspx 95 | 96 | # Guidance Automation Toolkit 97 | *.gpState 98 | 99 | # ReSharper is a .NET coding add-in 100 | _ReSharper*/ 101 | *.[Rr]e[Ss]harper 102 | 103 | # TeamCity is a build add-in 104 | _TeamCity* 105 | 106 | # DotCover is a Code Coverage Tool 107 | *.dotCover 108 | 109 | # NCrunch 110 | *.ncrunch* 111 | .*crunch*.local.xml 112 | 113 | # Installshield output folder 114 | [Ee]xpress/ 115 | 116 | # DocProject is a documentation generator add-in 117 | DocProject/buildhelp/ 118 | DocProject/Help/*.HxT 119 | DocProject/Help/*.HxC 120 | DocProject/Help/*.hhc 121 | DocProject/Help/*.hhk 122 | DocProject/Help/*.hhp 123 | DocProject/Help/Html2 124 | DocProject/Help/html 125 | 126 | # Click-Once directory 127 | publish/ 128 | 129 | # Publish Web Output 130 | *.Publish.xml 131 | *.pubxml 132 | 133 | # NuGet Packages Directory 134 | ## TODO: If you have NuGet Package Restore enabled, uncomment the next line 135 | packages/ 136 | 137 | # Windows Azure Build Output 138 | csx 139 | *.build.csdef 140 | 141 | # Windows Store app package directory 142 | AppPackages/ 143 | 144 | # Others 145 | sql/ 146 | *.Cache 147 | ClientBin/ 148 | [Ss]tyle[Cc]op.* 149 | ~$* 150 | *~ 151 | *.dbmdl 152 | *.[Pp]ublish.xml 153 | *.pfx 154 | *.publishsettings 155 | 156 | # RIA/Silverlight projects 157 | Generated_Code/ 158 | 159 | # Backup & report files from converting an old project file to a newer 160 | # Visual Studio version. Backup files are not needed, because we have git ;-) 161 | _UpgradeReport_Files/ 162 | Backup*/ 163 | UpgradeLog*.XML 164 | UpgradeLog*.htm 165 | 166 | # SQL Server files 167 | App_Data/*.mdf 168 | App_Data/*.ldf 169 | 170 | ############# 171 | ## Windows detritus 172 | ############# 173 | 174 | # Windows image file caches 175 | Thumbs.db 176 | ehthumbs.db 177 | 178 | # Folder config file 179 | Desktop.ini 180 | 181 | # Recycle Bin used on file shares 182 | $RECYCLE.BIN/ 183 | 184 | # Mac crap 185 | .DS_Store 186 | 187 | 188 | ############# 189 | ## Python 190 | ############# 191 | 192 | *.py[co] 193 | 194 | # Packages 195 | *.egg 196 | *.egg-info 197 | dist/ 198 | build/ 199 | eggs/ 200 | parts/ 201 | var/ 202 | sdist/ 203 | develop-eggs/ 204 | .installed.cfg 205 | 206 | # Installer logs 207 | pip-log.txt 208 | 209 | # Unit test / coverage reports 210 | .coverage 211 | .tox 212 | 213 | #Translations 214 | *.mo 215 | 216 | #Mr Developer 217 | .mr.developer.cfg 218 | 219 | ## Samples 220 | #Samples/HelloWorld/App.config 221 | #Samples/Archiving/App.config 222 | 223 | ## Jetbrains Rider files 224 | .idea/ -------------------------------------------------------------------------------- /BlazorHelloWorld/BlazorHelloWorld.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net8.0 5 | disable 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /BlazorHelloWorld/Components/App.razor: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /BlazorHelloWorld/Components/Layout/MainLayout.razor: -------------------------------------------------------------------------------- 1 | @inherits LayoutComponentBase 2 | 3 |
4 | 7 | 8 |
9 |
10 | About 11 |
12 | 13 |
14 | @Body 15 |
16 |
17 |
-------------------------------------------------------------------------------- /BlazorHelloWorld/Components/Layout/MainLayout.razor.css: -------------------------------------------------------------------------------- 1 | .page { 2 | position: relative; 3 | display: flex; 4 | flex-direction: column; 5 | } 6 | 7 | main { 8 | flex: 1; 9 | } 10 | 11 | .sidebar { 12 | background-image: linear-gradient(180deg, rgb(5, 39, 103) 0%, #3a0647 70%); 13 | } 14 | 15 | .top-row { 16 | background-color: #f7f7f7; 17 | border-bottom: 1px solid #d6d5d5; 18 | justify-content: flex-end; 19 | height: 3.5rem; 20 | display: flex; 21 | align-items: center; 22 | } 23 | 24 | .top-row ::deep a, .top-row ::deep .btn-link { 25 | white-space: nowrap; 26 | margin-left: 1.5rem; 27 | text-decoration: none; 28 | } 29 | 30 | .top-row ::deep a:hover, .top-row ::deep .btn-link:hover { 31 | text-decoration: underline; 32 | } 33 | 34 | .top-row ::deep a:first-child { 35 | overflow: hidden; 36 | text-overflow: ellipsis; 37 | } 38 | 39 | @media (max-width: 640.98px) { 40 | .top-row { 41 | justify-content: space-between; 42 | } 43 | 44 | .top-row ::deep a, .top-row ::deep .btn-link { 45 | margin-left: 0; 46 | } 47 | } 48 | 49 | @media (min-width: 641px) { 50 | .page { 51 | flex-direction: row; 52 | } 53 | 54 | .sidebar { 55 | width: 250px; 56 | height: 100vh; 57 | position: sticky; 58 | top: 0; 59 | } 60 | 61 | .top-row { 62 | position: sticky; 63 | top: 0; 64 | z-index: 1; 65 | } 66 | 67 | .top-row.auth ::deep a:first-child { 68 | flex: 1; 69 | text-align: right; 70 | width: 0; 71 | } 72 | 73 | .top-row, article { 74 | padding-left: 2rem !important; 75 | padding-right: 1.5rem !important; 76 | } 77 | } 78 | 79 | #blazor-error-ui { 80 | background: lightyellow; 81 | bottom: 0; 82 | box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2); 83 | display: none; 84 | left: 0; 85 | padding: 0.6rem 1.25rem 0.7rem 1.25rem; 86 | position: fixed; 87 | width: 100%; 88 | z-index: 1000; 89 | } 90 | 91 | #blazor-error-ui .dismiss { 92 | cursor: pointer; 93 | position: absolute; 94 | right: 0.75rem; 95 | top: 0.5rem; 96 | } 97 | -------------------------------------------------------------------------------- /BlazorHelloWorld/Components/Layout/NavMenu.razor: -------------------------------------------------------------------------------- 1 |  6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /BlazorHelloWorld/Components/Layout/NavMenu.razor.css: -------------------------------------------------------------------------------- 1 | .navbar-toggler { 2 | appearance: none; 3 | cursor: pointer; 4 | width: 3.5rem; 5 | height: 2.5rem; 6 | color: white; 7 | position: absolute; 8 | top: 0.5rem; 9 | right: 1rem; 10 | border: 1px solid rgba(255, 255, 255, 0.1); 11 | background: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 0.55%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e") no-repeat center/1.75rem rgba(255, 255, 255, 0.1); 12 | } 13 | 14 | .navbar-toggler:checked { 15 | background-color: rgba(255, 255, 255, 0.5); 16 | } 17 | 18 | .top-row { 19 | height: 3.5rem; 20 | background-color: rgba(0,0,0,0.4); 21 | } 22 | 23 | .navbar-brand { 24 | font-size: 1.1rem; 25 | } 26 | 27 | .bi { 28 | display: inline-block; 29 | position: relative; 30 | width: 1.25rem; 31 | height: 1.25rem; 32 | margin-right: 0.75rem; 33 | top: -1px; 34 | background-size: cover; 35 | } 36 | 37 | .bi-house-door-fill-nav-menu { 38 | background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='white' class='bi bi-house-door-fill' viewBox='0 0 16 16'%3E%3Cpath d='M6.5 14.5v-3.505c0-.245.25-.495.5-.495h2c.25 0 .5.25.5.5v3.5a.5.5 0 0 0 .5.5h4a.5.5 0 0 0 .5-.5v-7a.5.5 0 0 0-.146-.354L13 5.793V2.5a.5.5 0 0 0-.5-.5h-1a.5.5 0 0 0-.5.5v1.293L8.354 1.146a.5.5 0 0 0-.708 0l-6 6A.5.5 0 0 0 1.5 7.5v7a.5.5 0 0 0 .5.5h4a.5.5 0 0 0 .5-.5Z'/%3E%3C/svg%3E"); 39 | } 40 | 41 | .bi-plus-square-fill-nav-menu { 42 | background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='white' class='bi bi-plus-square-fill' viewBox='0 0 16 16'%3E%3Cpath d='M2 0a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2H2zm6.5 4.5v3h3a.5.5 0 0 1 0 1h-3v3a.5.5 0 0 1-1 0v-3h-3a.5.5 0 0 1 0-1h3v-3a.5.5 0 0 1 1 0z'/%3E%3C/svg%3E"); 43 | } 44 | 45 | .bi-list-nested-nav-menu { 46 | background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='white' class='bi bi-list-nested' viewBox='0 0 16 16'%3E%3Cpath fill-rule='evenodd' d='M4.5 11.5A.5.5 0 0 1 5 11h10a.5.5 0 0 1 0 1H5a.5.5 0 0 1-.5-.5zm-2-4A.5.5 0 0 1 3 7h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5zm-2-4A.5.5 0 0 1 1 3h10a.5.5 0 0 1 0 1H1a.5.5 0 0 1-.5-.5z'/%3E%3C/svg%3E"); 47 | } 48 | 49 | .nav-item { 50 | font-size: 0.9rem; 51 | padding-bottom: 0.5rem; 52 | } 53 | 54 | .nav-item:first-of-type { 55 | padding-top: 1rem; 56 | } 57 | 58 | .nav-item:last-of-type { 59 | padding-bottom: 1rem; 60 | } 61 | 62 | .nav-item ::deep .nav-link { 63 | color: #d7d7d7; 64 | background: none; 65 | border: none; 66 | border-radius: 4px; 67 | height: 3rem; 68 | display: flex; 69 | align-items: center; 70 | line-height: 3rem; 71 | width: 100%; 72 | } 73 | 74 | .nav-item ::deep a.active { 75 | background-color: rgba(255,255,255,0.37); 76 | color: white; 77 | } 78 | 79 | .nav-item ::deep .nav-link:hover { 80 | background-color: rgba(255,255,255,0.1); 81 | color: white; 82 | } 83 | 84 | .nav-scrollable { 85 | display: none; 86 | } 87 | 88 | .navbar-toggler:checked ~ .nav-scrollable { 89 | display: block; 90 | } 91 | 92 | @media (min-width: 641px) { 93 | .navbar-toggler { 94 | display: none; 95 | } 96 | 97 | .nav-scrollable { 98 | /* Never collapse the sidebar for wide screens */ 99 | display: block; 100 | 101 | /* Allow sidebar to scroll for tall menus */ 102 | height: calc(100vh - 3.5rem); 103 | overflow-y: auto; 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /BlazorHelloWorld/Components/Pages/Home.razor: -------------------------------------------------------------------------------- 1 | @page "/" 2 | @using BlazorHelloWorld.Infrastructure 3 | @rendermode InteractiveServer 4 | @attribute [StreamRendering] 5 | @inject IJSRuntime JavascriptRuntime 6 | @inject VideoService Service 7 | 8 | Weather 9 | 10 |
11 |
12 |

Your stream

13 |
14 |
15 | 16 |
17 | 18 |
19 |
20 |
21 |

Other streams

22 |

This part contains all other streams from your session.

23 |
24 |
25 |
26 |
27 | 28 | 29 |
30 |
31 | 32 | @code { 33 | private bool isArchiving => this.archiveId != Guid.Empty; 34 | private SessionCredentials session; 35 | private Guid archiveId; 36 | 37 | protected override async Task OnAfterRenderAsync(bool firstRender) 38 | { 39 | await base.OnAfterRenderAsync(firstRender); 40 | if (firstRender) 41 | { 42 | this.session = Service.CreateSession(); 43 | await JavascriptRuntime.InvokeVoidAsync("initializeStream", Service.GetOpenTokId(), session.SessionId, session.Token); 44 | } 45 | } 46 | 47 | private async Task StartArchiving() 48 | { 49 | var archive = await Service.StartArchiving(this.session.SessionId); 50 | this.archiveId = archive.Id; 51 | } 52 | 53 | private Task StopArchiving() => Service.StopArchiving(this.archiveId.ToString()); 54 | } -------------------------------------------------------------------------------- /BlazorHelloWorld/Components/Routes.razor: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /BlazorHelloWorld/Components/_Imports.razor: -------------------------------------------------------------------------------- 1 | @using System.Net.Http 2 | @using System.Net.Http.Json 3 | @using Microsoft.AspNetCore.Components.Forms 4 | @using Microsoft.AspNetCore.Components.Routing 5 | @using Microsoft.AspNetCore.Components.Web 6 | @using static Microsoft.AspNetCore.Components.Web.RenderMode 7 | @using Microsoft.AspNetCore.Components.Web.Virtualization 8 | @using Microsoft.JSInterop 9 | @using BlazorHelloWorld 10 | @using BlazorHelloWorld.Components -------------------------------------------------------------------------------- /BlazorHelloWorld/Infrastructure/VideoService.cs: -------------------------------------------------------------------------------- 1 | #region 2 | 3 | using System.Net; 4 | using OpenTokSDK; 5 | 6 | #endregion 7 | 8 | namespace BlazorHelloWorld.Infrastructure; 9 | 10 | public class VideoService 11 | { 12 | private readonly OpenTok openTok; 13 | private readonly string apiKey; 14 | 15 | public VideoService(OpenTokOptions options) 16 | { 17 | ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; 18 | this.openTok = InitializeClient(options); 19 | } 20 | 21 | private OpenTok InitializeClient(OpenTokOptions options) 22 | { 23 | if (!string.IsNullOrEmpty(options.ApplicationId) && !string.IsNullOrEmpty(options.PrivateKey)) 24 | { 25 | return new OpenTok(options.ApplicationId, options.PrivateKey); 26 | } 27 | 28 | if (!string.IsNullOrEmpty(options.ApiKey) && !string.IsNullOrEmpty(options.ApiSecret) 29 | && int.TryParse(options.ApiKey, out var key)) 30 | { 31 | return new OpenTok(key, options.ApiSecret); 32 | } 33 | 34 | throw new ArgumentException("Missing credentials"); 35 | } 36 | 37 | public SessionCredentials CreateSession() 38 | { 39 | var session = openTok.CreateSession(mediaMode: MediaMode.ROUTED); 40 | return new SessionCredentials(session.Id, session.GenerateToken()); 41 | } 42 | 43 | public string GetOpenTokId() => this.openTok.GetOpenTokId(); 44 | 45 | public async Task StartArchiving(string sessionId) 46 | { 47 | return await openTok.StartArchiveAsync(sessionId); 48 | } 49 | 50 | public async Task StopArchiving(string archiveId) 51 | { 52 | await openTok.StopArchiveAsync(archiveId); 53 | } 54 | } 55 | 56 | public record OpenTokOptions(string ApiKey, string ApiSecret, string ApplicationId, string PrivateKey); 57 | 58 | public record SessionCredentials(string SessionId, string Token); -------------------------------------------------------------------------------- /BlazorHelloWorld/Program.cs: -------------------------------------------------------------------------------- 1 | using BlazorHelloWorld.Components; 2 | using BlazorHelloWorld.Infrastructure; 3 | 4 | var builder = WebApplication.CreateBuilder(args); 5 | var options = builder.Configuration.GetSection(nameof(OpenTokOptions)).Get(); 6 | builder.Services.AddRazorComponents().AddInteractiveServerComponents(); 7 | builder.Services.AddServerSideBlazor(); 8 | builder.Services.AddSingleton(options); 9 | builder.Services.AddScoped(); 10 | var app = builder.Build(); 11 | app.UseHttpsRedirection(); 12 | app.UseStaticFiles(); 13 | app.MapRazorComponents().AddInteractiveServerRenderMode(); 14 | app.UseAntiforgery(); 15 | app.Run(); -------------------------------------------------------------------------------- /BlazorHelloWorld/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json.schemastore.org/launchsettings.json", 3 | "iisSettings": { 4 | "windowsAuthentication": false, 5 | "anonymousAuthentication": true, 6 | "iisExpress": { 7 | "applicationUrl": "http://localhost:60640", 8 | "sslPort": 44362 9 | } 10 | }, 11 | "profiles": { 12 | "http": { 13 | "commandName": "Project", 14 | "dotnetRunMessages": true, 15 | "launchBrowser": true, 16 | "applicationUrl": "http://localhost:5261", 17 | "environmentVariables": { 18 | "ASPNETCORE_ENVIRONMENT": "Development" 19 | } 20 | }, 21 | "https": { 22 | "commandName": "Project", 23 | "dotnetRunMessages": true, 24 | "launchBrowser": true, 25 | "applicationUrl": "https://localhost:7195;http://localhost:5261", 26 | "environmentVariables": { 27 | "ASPNETCORE_ENVIRONMENT": "Development" 28 | } 29 | }, 30 | "IIS Express": { 31 | "commandName": "IISExpress", 32 | "launchBrowser": true, 33 | "environmentVariables": { 34 | "ASPNETCORE_ENVIRONMENT": "Development" 35 | } 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /BlazorHelloWorld/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /BlazorHelloWorld/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | }, 8 | "AllowedHosts": "*", 9 | "OpenTokOptions": { 10 | "ApiKey": "", 11 | "ApiSecret": "", 12 | "ApplicationId": "", 13 | "PrivateKey": "" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /BlazorHelloWorld/wwwroot/app.css: -------------------------------------------------------------------------------- 1 | html, body { 2 | font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; 3 | } 4 | 5 | a, .btn-link { 6 | color: #006bb7; 7 | } 8 | 9 | .btn-primary { 10 | color: #fff; 11 | background-color: #1b6ec2; 12 | border-color: #1861ac; 13 | } 14 | 15 | .btn:focus, .btn:active:focus, .btn-link.nav-link:focus, .form-control:focus, .form-check-input:focus { 16 | box-shadow: 0 0 0 0.1rem white, 0 0 0 0.25rem #258cfb; 17 | } 18 | 19 | .content { 20 | padding-top: 1.1rem; 21 | } 22 | 23 | h1:focus { 24 | outline: none; 25 | } 26 | 27 | .valid.modified:not([type=checkbox]) { 28 | outline: 1px solid #26b050; 29 | } 30 | 31 | .invalid { 32 | outline: 1px solid #e50000; 33 | } 34 | 35 | .validation-message { 36 | color: #e50000; 37 | } 38 | 39 | .blazor-error-boundary { 40 | background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121; 41 | padding: 1rem 1rem 1rem 3.7rem; 42 | color: white; 43 | } 44 | 45 | .blazor-error-boundary::after { 46 | content: "An error has occurred." 47 | } 48 | 49 | .darker-border-checkbox.form-check-input { 50 | border-color: #929292; 51 | } 52 | -------------------------------------------------------------------------------- /BlazorHelloWorld/wwwroot/content/customScripts.js: -------------------------------------------------------------------------------- 1 | var session, publisher; 2 | 3 | window.initializeStream = (apiKey, sessionId, token) => { 4 | session = OT.initSession(apiKey, sessionId) 5 | publisher = OT.initPublisher('publisher') 6 | session.connect(token, function (error) { 7 | if (error) { 8 | console.error('Failed to connect', error); 9 | } else { 10 | console.log('Session connected.') 11 | session.publish(publisher, function (error) { 12 | if (error) { 13 | console.error('Failed to publish', error); 14 | } 15 | }); 16 | } 17 | }); 18 | 19 | session.on('streamCreated', function (event) { 20 | console.log('Stream created.') 21 | session.subscribe(event.stream, 'subscribers', { 22 | insertMode: 'append' 23 | }, function (error) { 24 | if (error) { 25 | console.error('Failed to subscribe', error); 26 | } 27 | }); 28 | }); 29 | 30 | }; 31 | 32 | window.disposeStream = () => { 33 | publisher.publishVideo(false); 34 | session.disconnect(); 35 | session.unpublish(publisher); 36 | publisher.destroy(); 37 | }; 38 | 39 | window.onbeforeunload = function () { 40 | disposeStream(); 41 | } -------------------------------------------------------------------------------- /BlazorHelloWorld/wwwroot/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opentok/Opentok-.NET-SDK/25f7185a0aa34e561c14e3e4a5041a236813326d/BlazorHelloWorld/wwwroot/favicon.png -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing Guidelines 2 | 3 | If you're interested in contributing to this project, here are a few ways to do so: 4 | 5 | * Bug fixes 6 | - If you find a bug, please first report it using Github Issues. 7 | - Issues that have already been identified as a bug will be labelled `bug`. 8 | - If you'd like to submit a fix for a bug, send a Pull Request from your own fork and mention the Issue number. 9 | + Include a test that isolates the bug and verifies that it was fixed. 10 | * New Features 11 | - If you'd like to add a feature to the library that doesn't already exist, feel free to describe the feature in a new 12 | Github Issue. 13 | - Issues that have been identified as a feature request will be labelled `enhancement`. 14 | - If you'd like to implement the new feature, please wait for feedback from the project maintainers before spending 15 | too much time writing the code. In some cases, `enhancement`s may not align well with the project objectives at 16 | the time. 17 | * Tests, Documentation, Miscellaneous 18 | - If you think the test coverage could be improved, the documentation could be clearer, or you have an alternative 19 | implementation of something that may have more advantages, we would love to hear it. 20 | - If its a trivial change, go ahead and send a Pull Request with the changes you have in mind 21 | - If not, open a Github Issue to discuss the idea first. 22 | 23 | ## Requirements 24 | 25 | For a contribution to be accepted: 26 | 27 | * The test suite must be complete and pass 28 | * Code must follow existing styling conventions 29 | * Commit messages must be descriptive. Related issues should be mentioned by number. 30 | 31 | If the contribution doesn't meet these criteria, a maintainer will discuss it with you on the Issue. You can still 32 | continue to add more commits to the branch you have sent the Pull Request from. 33 | 34 | ## How To 35 | 36 | 1. Fork this repository on GitHub. 37 | 1. Clone/fetch your fork to your local development machine. 38 | 1. Create a new branch (e.g. `issue-12`, `feat.add_foo`, etc) and check it out. 39 | 1. Make your changes and commit them. (Did the tests pass?) 40 | 1. Push your new branch to your fork. (e.g. `git push myname issue-12`) 41 | 1. Open a Pull Request from your new branch to the original fork's `master` branch. 42 | 43 | ## Developer Guidelines 44 | 45 | See DEVELOPING.md for guidelines for developing this project. 46 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014-2022 TokBox, Inc. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. -------------------------------------------------------------------------------- /OpenTok.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.1.31903.286 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{DC02B3EA-F1B3-4A39-A151-4FE61A39F209}" 7 | ProjectSection(SolutionItems) = preProject 8 | .gitattributes = .gitattributes 9 | .gitignore = .gitignore 10 | .github\workflows\build.yml = .github\workflows\build.yml 11 | CONTRIBUTING.md = CONTRIBUTING.md 12 | DEVELOPING.md = DEVELOPING.md 13 | README.md = README.md 14 | .github\workflows\release.yml = .github\workflows\release.yml 15 | EndProjectSection 16 | EndProject 17 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HelloWorld", "Samples\HelloWorld\HelloWorld.csproj", "{F8A5A9AD-F680-46F4-806F-653E7E51A030}" 18 | EndProject 19 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Archiving", "Samples\Archiving\Archiving.csproj", "{B6EFF9BA-20CD-4BDE-B67B-C8E22F00E640}" 20 | EndProject 21 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Broadcasting", "Samples\Broadcasting\Broadcasting.csproj", "{D593D74C-46D3-4947-9F57-B40D978C40B7}" 22 | EndProject 23 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTok", "OpenTok\OpenTok.csproj", "{C770C266-B8E6-413A-B5AB-68EB218DC76C}" 24 | EndProject 25 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTokTest", "OpenTokTest\OpenTokTest.csproj", "{034F54A8-74D7-4EA5-A923-DC45F709A826}" 26 | EndProject 27 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BlazorHelloWorld", "BlazorHelloWorld\BlazorHelloWorld.csproj", "{74D2A3BF-0942-4391-A31E-FD3011B73B00}" 28 | EndProject 29 | Global 30 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 31 | Debug|Any CPU = Debug|Any CPU 32 | Release|Any CPU = Release|Any CPU 33 | EndGlobalSection 34 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 35 | {F8A5A9AD-F680-46F4-806F-653E7E51A030}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 36 | {F8A5A9AD-F680-46F4-806F-653E7E51A030}.Debug|Any CPU.Build.0 = Debug|Any CPU 37 | {F8A5A9AD-F680-46F4-806F-653E7E51A030}.Release|Any CPU.ActiveCfg = Release|Any CPU 38 | {F8A5A9AD-F680-46F4-806F-653E7E51A030}.Release|Any CPU.Build.0 = Release|Any CPU 39 | {B6EFF9BA-20CD-4BDE-B67B-C8E22F00E640}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 40 | {B6EFF9BA-20CD-4BDE-B67B-C8E22F00E640}.Debug|Any CPU.Build.0 = Debug|Any CPU 41 | {B6EFF9BA-20CD-4BDE-B67B-C8E22F00E640}.Release|Any CPU.ActiveCfg = Release|Any CPU 42 | {B6EFF9BA-20CD-4BDE-B67B-C8E22F00E640}.Release|Any CPU.Build.0 = Release|Any CPU 43 | {D593D74C-46D3-4947-9F57-B40D978C40B7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 44 | {D593D74C-46D3-4947-9F57-B40D978C40B7}.Debug|Any CPU.Build.0 = Debug|Any CPU 45 | {D593D74C-46D3-4947-9F57-B40D978C40B7}.Release|Any CPU.ActiveCfg = Release|Any CPU 46 | {D593D74C-46D3-4947-9F57-B40D978C40B7}.Release|Any CPU.Build.0 = Release|Any CPU 47 | {C770C266-B8E6-413A-B5AB-68EB218DC76C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 48 | {C770C266-B8E6-413A-B5AB-68EB218DC76C}.Debug|Any CPU.Build.0 = Debug|Any CPU 49 | {C770C266-B8E6-413A-B5AB-68EB218DC76C}.Release|Any CPU.ActiveCfg = Release|Any CPU 50 | {C770C266-B8E6-413A-B5AB-68EB218DC76C}.Release|Any CPU.Build.0 = Release|Any CPU 51 | {034F54A8-74D7-4EA5-A923-DC45F709A826}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 52 | {034F54A8-74D7-4EA5-A923-DC45F709A826}.Debug|Any CPU.Build.0 = Debug|Any CPU 53 | {034F54A8-74D7-4EA5-A923-DC45F709A826}.Release|Any CPU.ActiveCfg = Release|Any CPU 54 | {034F54A8-74D7-4EA5-A923-DC45F709A826}.Release|Any CPU.Build.0 = Release|Any CPU 55 | {74D2A3BF-0942-4391-A31E-FD3011B73B00}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 56 | {74D2A3BF-0942-4391-A31E-FD3011B73B00}.Debug|Any CPU.Build.0 = Debug|Any CPU 57 | {74D2A3BF-0942-4391-A31E-FD3011B73B00}.Release|Any CPU.ActiveCfg = Release|Any CPU 58 | {74D2A3BF-0942-4391-A31E-FD3011B73B00}.Release|Any CPU.Build.0 = Release|Any CPU 59 | EndGlobalSection 60 | GlobalSection(SolutionProperties) = preSolution 61 | HideSolutionNode = FALSE 62 | EndGlobalSection 63 | GlobalSection(ExtensibilityGlobals) = postSolution 64 | SolutionGuid = {710D3B9A-19F7-4510-9A03-1295461158D6} 65 | EndGlobalSection 66 | EndGlobal 67 | -------------------------------------------------------------------------------- /OpenTok/ArchiveLayout.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using Newtonsoft.Json.Converters; 3 | using System.ComponentModel; 4 | 5 | namespace OpenTokSDK 6 | { 7 | /// 8 | /// Layout the archive is going to use 9 | /// 10 | public class ArchiveLayout 11 | { 12 | /// 13 | /// The type of layout you'd like to use 14 | /// 15 | [JsonProperty("type")] 16 | [JsonConverter(typeof(StringEnumConverter))] 17 | public LayoutType Type { get; set; } 18 | 19 | /// 20 | /// The stylesheet to use for the layout. Must be set if using custom. 21 | /// 22 | [JsonProperty("stylesheet", DefaultValueHandling = DefaultValueHandling.Ignore, NullValueHandling = NullValueHandling.Ignore)] 23 | [DefaultValue("")] 24 | public string StyleSheet { get; set; } 25 | 26 | /// 27 | /// The to use when there is a screen-sharing 28 | /// stream in the session. Note that to use this property, 29 | /// you must set the property to 30 | /// and leave the property unset. 31 | /// For more information, see Layout types for screen sharing. 32 | /// NOTE: is not valid for this property 33 | /// 34 | [JsonConverter(typeof(StringEnumConverter), true)] 35 | [JsonProperty("screensharetype", NullValueHandling = NullValueHandling.Ignore)] 36 | public ScreenShareLayoutType? ScreenShareType { get; set; } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /OpenTok/ArchiveList.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace OpenTokSDK 7 | { 8 | /// 9 | /// A class for accessing an array of Archive objects. 10 | /// 11 | public class ArchiveList : List 12 | { 13 | /// 14 | /// The total number of archives (associated with your OpenTok API key). 15 | /// 16 | public int TotalCount { get; private set; } 17 | 18 | internal ArchiveList(List items, int totalCount) 19 | : base(items) 20 | { 21 | TotalCount = totalCount; 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /OpenTok/AudioConnector.cs: -------------------------------------------------------------------------------- 1 | namespace OpenTokSDK 2 | { 3 | /// 4 | /// Represents an Audio Connector. 5 | /// 6 | public struct AudioConnector 7 | { 8 | /// 9 | /// The OpenTok connection ID for the Audio Connector WebSocket connection in the OpenTok session. 10 | /// 11 | public string ConnectionId { get; set; } 12 | 13 | /// 14 | /// A unique ID identifying the Audio Connector WebSocket connection. 15 | /// 16 | public string Id { get; set; } 17 | 18 | 19 | } 20 | } -------------------------------------------------------------------------------- /OpenTok/BroadcastBitrate.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Newtonsoft.Json; 3 | using OpenTokSDK.Exception; 4 | 5 | namespace OpenTokSDK 6 | { 7 | /// 8 | /// Represents a BitRate for broadcasts. 9 | /// 10 | public class BroadcastBitrate 11 | { 12 | private const int MaxBitrate = 2000000; 13 | private const int MinBitrate = 400000; 14 | 15 | /// 16 | /// The maximum BitRate allowed for the broadcast composing. 17 | /// 18 | public long Bitrate { get; } 19 | 20 | /// 21 | /// Creates a BroadcastBitrate with the maximum BitRate. 22 | /// 23 | public BroadcastBitrate() => this.Bitrate = MaxBitrate; 24 | 25 | /// 26 | /// Creates a BroadcastBitrate with a specific Bitrate. 27 | /// 28 | /// The Bitrate. 29 | /// 30 | /// When specified bitrate is lower than the minimum value, or higher than the 31 | /// maximum value. 32 | /// 33 | public BroadcastBitrate(long bitrate) => 34 | this.Bitrate = ValidateBitrate(bitrate) 35 | ? bitrate 36 | : throw new OpenTokArgumentException($"Bitrate value must be between {MinBitrate} and {MaxBitrate}."); 37 | 38 | private static bool ValidateBitrate(long bitrate) => bitrate <= MaxBitrate && bitrate >= MinBitrate; 39 | } 40 | 41 | internal class BroadcastBitrateConverter : JsonConverter 42 | { 43 | public override void WriteJson(JsonWriter writer, BroadcastBitrate value, JsonSerializer serializer) => 44 | writer.WriteValue(value?.Bitrate); 45 | 46 | public override BroadcastBitrate ReadJson(JsonReader reader, Type objectType, BroadcastBitrate existingValue, bool hasExistingValue, 47 | JsonSerializer serializer) 48 | { 49 | var value = (long?)reader.Value; 50 | return value.HasValue ? new BroadcastBitrate(value.Value) : null; 51 | } 52 | } 53 | } -------------------------------------------------------------------------------- /OpenTok/BroadcastLayout.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using Newtonsoft.Json; 6 | using Newtonsoft.Json.Converters; 7 | using System.Runtime.Serialization; 8 | 9 | 10 | namespace OpenTokSDK 11 | { 12 | /// 13 | /// Represents a broadcast layout of an OpenTok session. 14 | /// 15 | public class BroadcastLayout 16 | { 17 | /// 18 | /// Defines values for the layout parameter of the StartBroadcast method of the OpenTok class. 19 | /// 20 | public enum LayoutType 21 | { 22 | /// 23 | /// Picture-in-Picture 24 | /// 25 | Pip, 26 | /// 27 | /// Best Fit 28 | /// 29 | BestFit, 30 | /// 31 | /// Vertical Presentation 32 | /// 33 | VerticalPresentation, 34 | /// 35 | /// Horizontal Presentation 36 | /// 37 | HorizontalPresentation, 38 | /// 39 | /// Custom Layout 40 | /// 41 | Custom 42 | } 43 | 44 | /// 45 | /// Initalizes a Broadcast layout with the given , automatically 46 | /// setting the Type to BestFit. 47 | /// 48 | /// 49 | public BroadcastLayout(ScreenShareLayoutType type) 50 | { 51 | Type = LayoutType.BestFit; 52 | ScreenShareType = type; 53 | } 54 | 55 | /// 56 | /// Initalizes a BroadcastLayout with the given 57 | /// 58 | /// 59 | public BroadcastLayout(LayoutType type) 60 | { 61 | Type = type; 62 | } 63 | 64 | /// 65 | /// Initalizes a BroadcastLayout with the given and stylesheet - note Type must be 66 | /// 67 | /// 68 | /// A string de 69 | public BroadcastLayout(LayoutType type, string stylesheet) 70 | { 71 | Type = type; 72 | Stylesheet = stylesheet; 73 | } 74 | 75 | /// 76 | /// The Layout type 77 | /// 78 | [JsonConverter(typeof(StringEnumConverter), true)] 79 | [JsonProperty("type")] 80 | public LayoutType Type { get; set; } 81 | 82 | /// 83 | /// The Stylesheet for the Custom Layout 84 | /// 85 | [JsonProperty("stylesheet")] 86 | public string Stylesheet { get; set; } 87 | 88 | /// 89 | /// The to use when there is a screen-sharing 90 | /// stream in the session. Note that to use this property, 91 | /// you must set the property to 92 | /// and leave the property unset. 93 | /// For more information, see Layout types for screen sharing. 94 | /// NOTE: is not valid for this property 95 | /// 96 | [JsonConverter(typeof(StringEnumConverter), true)] 97 | [JsonProperty("screensharetype", NullValueHandling = NullValueHandling.Ignore)] 98 | public ScreenShareLayoutType? ScreenShareType { get; set; } 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /OpenTok/Caption.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace OpenTokSDK 4 | { 5 | /// 6 | /// Represents a success caption. 7 | /// 8 | public struct Caption 9 | { 10 | /// 11 | /// The unique ID for the audio captioning session. 12 | /// 13 | public Guid CaptionsId { get; set; } 14 | } 15 | } -------------------------------------------------------------------------------- /OpenTok/Constants/OpenTokVersion.cs: -------------------------------------------------------------------------------- 1 | namespace OpenTokSDK.Constants 2 | { 3 | /// 4 | /// For internal use. 5 | /// 6 | internal class OpenTokVersion 7 | { 8 | private static string Version = "Opentok-DotNet-SDK/" + typeof(OpenTokVersion).Assembly.GetName().Version; 9 | 10 | public static string GetVersion() 11 | { 12 | return Version; 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /OpenTok/DialAuth.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.Serialization; 2 | using Newtonsoft.Json; 3 | 4 | namespace OpenTokSDK 5 | { 6 | /// 7 | /// Used to set the username and password to be used in the method. 8 | /// These are used in the SIP INVITE​ request for HTTP digest authentication, if it is required 9 | /// by your SIP platform. See the class. 10 | /// 11 | public class DialAuth 12 | { 13 | /// 14 | /// The username. 15 | /// 16 | [JsonProperty("username")] 17 | public string Username { get; set; } 18 | 19 | /// 20 | /// The password. 21 | /// 22 | [JsonProperty("password")] 23 | public string Password { get; set; } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /OpenTok/DialOptions.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace OpenTokSDK 4 | { 5 | /// 6 | /// Used to define options for the the method. These are 7 | /// custom headers to be added to the SIP ​INVITE​ request initiated from OpenTok to 8 | /// your SIP platform. 9 | /// 10 | public class DialOptions 11 | { 12 | /// 13 | /// A dictionary of custom headers to be added to the SIP ​INVITE​ request initiated 14 | /// from OpenTok to your SIP platform. 15 | /// 16 | public Dictionary Headers { get; set; } 17 | 18 | /// 19 | /// Contains the username and password to be used in the the SIP INVITE​ request. 20 | /// 21 | public DialAuth Auth { get; set; } 22 | 23 | /// 24 | /// Indicates whether the media must be transmitted encrypted (​true​) or not (​false​, the default). 25 | /// 26 | public bool? Secure { get; set; } 27 | 28 | /// 29 | /// The number or string that will be sent to the final SIP number as the caller. 30 | /// 31 | /// 32 | /// This must be a string in the form of "from@example.com", where from can be a string or a number. If it is set 33 | /// to a number (for example, "14155550101@example.com"), it will show up as the incoming number on PSTN phones. 34 | /// If it is undefined or set to a string (for example, "joe@example.com"), +00000000 will show up as the incoming 35 | /// number on PSTN phones. 36 | /// 37 | public string From { get; set; } 38 | 39 | /// 40 | /// Whether the SIP call will include video (​true​) or not (​false​, the default). 41 | /// 42 | /// With video included, the SIP client's video is included in the OpenTok stream 43 | /// that is sent to the OpenTok session. The SIP client will receive a single composed video of the published streams 44 | /// in the OpenTok session. 45 | public bool? Video { get; set; } 46 | 47 | /// 48 | /// Whether the SIP endpoint observes 49 | /// force mute moderation 50 | /// (true) or not (false, the default). 51 | /// 52 | public bool? ObserveForceMute { get; set; } 53 | 54 | /// 55 | /// The stream IDs of the participants' which will be subscribed by the SIP participant. If not provided, all streams in session will be selected. 56 | /// 57 | public string[] Streams { get; set; } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /OpenTok/Exception/OpenTokArgumentException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace OpenTokSDK.Exception 4 | { 5 | /// 6 | /// Defines an exception object thrown when an invalid argument is passed into a method. 7 | /// 8 | public class OpenTokArgumentException : ArgumentException 9 | { 10 | /// 11 | public OpenTokArgumentException(string message) 12 | :base(message) 13 | { 14 | 15 | } 16 | 17 | /// 18 | public OpenTokArgumentException(string message, string paramName) 19 | : base(message, paramName) 20 | { 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /OpenTok/Exception/OpenTokException.cs: -------------------------------------------------------------------------------- 1 | namespace OpenTokSDK.Exception 2 | { 3 | /// 4 | /// Defines exceptions in the OpenTok SDK. 5 | /// 6 | public class OpenTokException : System.Exception 7 | { 8 | 9 | /// 10 | public OpenTokException() 11 | { 12 | } 13 | 14 | /// 15 | /// Construct OpentTokException with a message 16 | /// 17 | /// 18 | public OpenTokException(string message) 19 | : base(message) { } 20 | 21 | /// 22 | /// Construct OpenTokException with a message and an inner exception 23 | /// 24 | /// 25 | /// 26 | public OpenTokException(string message, System.Exception exception) 27 | : base(message, exception) { } 28 | 29 | /// 30 | /// Get's the message of the exception 31 | /// 32 | /// 33 | public string GetMessage() 34 | { 35 | return Message; 36 | } 37 | 38 | /// 39 | /// Get's the inner exception 40 | /// 41 | /// 42 | public System.Exception GetException() 43 | { 44 | return InnerException; 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /OpenTok/Exception/OpenTokWebException.cs: -------------------------------------------------------------------------------- 1 | namespace OpenTokSDK.Exception 2 | { 3 | /// 4 | /// Defines an exception object thrown when a REST API call results in an error response. 5 | /// 6 | public class OpenTokWebException : OpenTokException 7 | { 8 | /// 9 | /// Constructor. Do not use. 10 | /// 11 | /// 12 | /// 13 | public OpenTokWebException(string message, System.Exception exception) 14 | : base(message, exception) 15 | { 16 | } 17 | 18 | /// 19 | /// Constructor. Do not use. 20 | /// 21 | /// 22 | public OpenTokWebException(string message) 23 | : base(message) 24 | { 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /OpenTok/LayoutType.cs: -------------------------------------------------------------------------------- 1 | namespace OpenTokSDK 2 | { 3 | /// 4 | /// The Layout Type for the an Archive. 5 | /// 6 | public enum LayoutType 7 | { 8 | /// 9 | /// Best fit layout. 10 | /// 11 | bestFit, 12 | /// 13 | /// Use a Custom layout (stylesheet property must be set). 14 | /// 15 | custom, 16 | /// 17 | /// Horizontal presentation. 18 | /// 19 | horizontalPresentation, 20 | /// 21 | /// Picture-in-picture. 22 | /// 23 | pip, 24 | /// 25 | /// Vertical presentation. 26 | /// 27 | verticalPresentation 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /OpenTok/OpenTok.AudioConnector.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading.Tasks; 3 | using Newtonsoft.Json; 4 | 5 | namespace OpenTokSDK 6 | { 7 | public partial class OpenTok 8 | { 9 | /// 10 | /// Sends audio from a Vonage Video API session to a WebSocket. For more information, see the Audio Connector developer guide. 11 | /// 12 | /// The request to start the audio connector. 13 | /// The response object from the server. 14 | public async Task StartAudioConnectorAsync(AudioConnectorStartRequest request) 15 | { 16 | var response = await this.Client.PostAsync( 17 | $"v2/project/{this.GetOpenTokId()}/connect", 18 | GetHeaderDictionary("application/json"), 19 | request.ToDataDictionary()); 20 | return JsonConvert.DeserializeObject(response); 21 | } 22 | 23 | /// 24 | /// Stops sending audio for a Vonage Video API session. 25 | /// 26 | /// The OpenTok connection ID for the Audio Connector WebSocket connection in the OpenTok session. See . 27 | public async Task StopAudioConnectorAsync(string connectionId) => 28 | _ = await this.Client.PostAsync( 29 | $"v2/project/{this.GetOpenTokId()}/connect/{connectionId}/stop", 30 | new Dictionary(), 31 | new Dictionary()); 32 | } 33 | } -------------------------------------------------------------------------------- /OpenTok/OpenTok.Captions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Threading.Tasks; 4 | using Newtonsoft.Json; 5 | 6 | namespace OpenTokSDK 7 | { 8 | public partial class OpenTok 9 | { 10 | private const string CaptionsEndpoint = "/captions"; 11 | 12 | /// 13 | /// 14 | /// 15 | /// 16 | public async Task StartLiveCaptionsAsync(CaptionOptions options) 17 | { 18 | var response = await this.Client.PostAsync( 19 | this.BuildUrl(CaptionsEndpoint), 20 | GetHeaderDictionary("application/json"), 21 | options.ToDataDictionary()); 22 | return JsonConvert.DeserializeObject(response); 23 | } 24 | 25 | /// 26 | /// 27 | /// 28 | public Task StopLiveCaptionsAsync(Guid captionId) => 29 | this.Client.PostAsync( 30 | $"{this.BuildUrlWithRouteParameter(CaptionsEndpoint, captionId.ToString())}/stop", 31 | GetHeaderDictionary("application/json"), new Dictionary()); 32 | } 33 | } -------------------------------------------------------------------------------- /OpenTok/OpenTok.Render.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading.Tasks; 3 | using Newtonsoft.Json; 4 | using OpenTokSDK.Render; 5 | 6 | namespace OpenTokSDK 7 | { 8 | public partial class OpenTok 9 | { 10 | private const string RenderEndpoint = "/render"; 11 | 12 | /// 13 | /// Retrieves an Experience Composer renderer. 14 | /// 15 | /// The Id of the rendering. 16 | public async Task GetRenderAsync(string renderId) 17 | { 18 | var url = this.BuildUrlWithRouteParameter(RenderEndpoint, renderId); 19 | var response = await this.Client.GetAsync(url); 20 | return JsonConvert.DeserializeObject(response); 21 | } 22 | 23 | /// 24 | /// Retrieves all Experience Composer renderers matching the provided request. 25 | /// 26 | /// The request containing filtering options. 27 | /// The list of rendering. 28 | public async Task ListRendersAsync(ListRendersRequest request) 29 | { 30 | var url = this.BuildUrlWithQueryParameter(RenderEndpoint, request.ToQueryParameters()); 31 | var response = await this.Client.GetAsync(url); 32 | return JsonConvert.DeserializeObject(response); 33 | } 34 | 35 | /// 36 | /// Starts a new Experience Composer renderer for an OpenTok session. 37 | /// 38 | /// 39 | /// For more information, see the . 40 | /// Experience Composer developer guide. 41 | /// 42 | /// The rendering request. 43 | /// The generated rendering. 44 | public async Task StartRenderAsync(StartRenderRequest request) 45 | { 46 | var response = await this.Client.PostAsync( 47 | this.BuildUrl(RenderEndpoint), 48 | GetHeaderDictionary("application/json"), 49 | request.ToDataDictionary()); 50 | return JsonConvert.DeserializeObject(response); 51 | } 52 | 53 | /// 54 | /// Stops an Experience Composer renderer. 55 | /// 56 | /// The Id of the rendering. 57 | public async Task StopRenderAsync(string renderId) => 58 | await this.Client.DeleteAsync( 59 | this.BuildUrlWithRouteParameter(RenderEndpoint, renderId), 60 | new Dictionary()); 61 | 62 | private string BuildUrl(string endpoint) => $"v2/project/{this.GetOpenTokId()}{endpoint}"; 63 | 64 | private string BuildUrlWithQueryParameter(string endpoint, string queryParameter) => 65 | $"{this.BuildUrl(endpoint)}?{queryParameter}"; 66 | 67 | private string BuildUrlWithRouteParameter(string endpoint, string routeParameter) => 68 | $"{this.BuildUrl(endpoint)}/{routeParameter}"; 69 | 70 | private static Dictionary GetHeaderDictionary(string contentType) => 71 | new Dictionary {{"Content-Type", contentType}}; 72 | } 73 | } -------------------------------------------------------------------------------- /OpenTok/OpenTok.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.0 5 | 3.16.1 6 | OpenTok is an API from TokBox that enables websites to weave live group video communication into their online experience. 7 | https://github.com/opentok/Opentok-.NET-SDK 8 | https://github.com/opentok/Opentok-.NET-SDK 9 | git 10 | true 11 | https://github.com/opentok/Opentok-.NET-SDK/releases/tag/v3.16.1 12 | true 13 | true 14 | {C770C266-B8E6-413A-B5AB-68EB218DC76C} 15 | 671ed443 16 | MIT 17 | Copyright © Vonage 2020 18 | OpenTokSDK 19 | true 20 | snupkg 21 | true 22 | true 23 | true 24 | 8 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | <_Parameter1>OpenTokTest 38 | 39 | 40 | <_Parameter1>DynamicProxyGenAssembly2 41 | 42 | 43 | -------------------------------------------------------------------------------- /OpenTok/Render/ListRendersRequest.cs: -------------------------------------------------------------------------------- 1 | using OpenTokSDK.Exception; 2 | 3 | namespace OpenTokSDK.Render 4 | { 5 | /// 6 | /// Represents a request for retrieving Experience Composer renderers. 7 | /// (). 8 | /// 9 | public class ListRendersRequest 10 | { 11 | private const int DefaultCount = 50; 12 | private const int MaximumCount = 1000; 13 | private const int MinimumCount = 0; 14 | private const int MinimumOffset = 0; 15 | 16 | /// 17 | /// Indicates the maximum count has been exceeded. 18 | /// 19 | public const string CountExceeded = "Count cannot be higher than 1000."; 20 | 21 | /// 22 | /// Indicates the provided count is negative. 23 | /// 24 | public const string NegativeCount = "Count cannot be negative."; 25 | 26 | /// 27 | /// Indicates the provided offset is negative. 28 | /// 29 | public const string NegativeOffset = "Offset cannot be negative."; 30 | 31 | /// 32 | /// Initializes a ListRendersRequest with default values. The Count is set to 50. 33 | /// 34 | public ListRendersRequest() 35 | { 36 | this.Count = DefaultCount; 37 | } 38 | 39 | /// 40 | /// Initializes a ListRendersRequest. 41 | /// 42 | /// 43 | /// The number of Renders to retrieve starting at the offset. The default is 50, and the maximum is 1000. 44 | /// 45 | public ListRendersRequest(int count) 46 | : this() 47 | { 48 | ValidateCount(count); 49 | this.Count = count; 50 | } 51 | 52 | /// 53 | /// Initializes a ListRendersRequest. 54 | /// 55 | /// 56 | /// The start offset in the list of existing Renders. 57 | /// 58 | /// 59 | /// The number of Renders to retrieve, starting at offset. The default is 50, and the maximum is 1000. 60 | /// 61 | public ListRendersRequest(int offset, int count) 62 | : this(count) 63 | { 64 | ValidateOffset(offset); 65 | this.Offset = offset; 66 | this.Count = count; 67 | } 68 | 69 | /// 70 | /// The start offset in the list of existing Renders. 71 | /// 72 | public int? Offset { get; } 73 | 74 | /// 75 | /// The number of Renders to retrieve, starting at offset. 76 | /// 77 | public int Count { get; } 78 | 79 | private static void ValidateCount(int count) 80 | { 81 | if (count > MaximumCount) 82 | { 83 | throw new OpenTokException(CountExceeded); 84 | } 85 | 86 | if (count < MinimumCount) 87 | { 88 | throw new OpenTokException(NegativeCount); 89 | } 90 | } 91 | 92 | private static void ValidateOffset(int offset) 93 | { 94 | if (offset < MinimumOffset) 95 | { 96 | throw new OpenTokException(NegativeOffset); 97 | } 98 | } 99 | 100 | /// 101 | /// Converts the request to query parameters. 102 | /// 103 | /// The query parameters equivalent. 104 | public string ToQueryParameters() 105 | { 106 | var parameters = $"count={this.Count}"; 107 | if (this.Offset.HasValue) 108 | { 109 | parameters += $"&offset={this.Offset}"; 110 | } 111 | 112 | return parameters; 113 | } 114 | } 115 | } -------------------------------------------------------------------------------- /OpenTok/Render/ListRendersResponse.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace OpenTokSDK.Render 4 | { 5 | /// 6 | /// Represents a response from a ListRenders 7 | /// request. 8 | /// 9 | public struct ListRendersResponse 10 | { 11 | /// 12 | /// Constructor. 13 | /// 14 | /// The total number of Renders. 15 | /// The list of renderings items. 16 | public ListRendersResponse(int count, IEnumerable items) 17 | { 18 | this.Count = count; 19 | this.Items = items; 20 | } 21 | 22 | /// 23 | /// Number of rendering items. 24 | /// 25 | public int Count { get; set; } 26 | 27 | /// 28 | /// Rendering items contained in the response. 29 | /// 30 | public IEnumerable Items { get; set; } 31 | } 32 | } -------------------------------------------------------------------------------- /OpenTok/Render/RenderItem.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Newtonsoft.Json; 3 | 4 | namespace OpenTokSDK.Render 5 | { 6 | /// 7 | /// Represents a rendering. 8 | /// 9 | public struct RenderItem 10 | { 11 | /// 12 | /// Constructor. 13 | /// 14 | /// The ID of the rendering. 15 | /// The session ID. 16 | /// The project ID. 17 | /// The creation date. 18 | /// The last update date. 19 | /// The URL. 20 | /// The screen resolution. 21 | /// The status. 22 | /// The stream ID. 23 | /// The reason. 24 | public RenderItem(string id, string sessionId, string projectId, int createdAt, int updatedAt, Uri url, 25 | RenderResolution resolution, string status, string streamId, string reason) 26 | { 27 | this.Id = id; 28 | this.SessionId = sessionId; 29 | this.ProjectId = projectId; 30 | this.CreatedAt = createdAt; 31 | this.UpdatedAt = updatedAt; 32 | this.Url = url; 33 | this.Resolution = resolution; 34 | this.Status = status; 35 | this.StreamId = streamId; 36 | this.Reason = reason; 37 | } 38 | 39 | /// 40 | /// The ID of the rendering. 41 | /// 42 | public string Id { get; set; } 43 | 44 | /// 45 | /// The session ID. 46 | /// 47 | public string SessionId { get; set; } 48 | 49 | /// 50 | /// The project ID. 51 | /// 52 | public string ProjectId { get; set; } 53 | 54 | /// 55 | /// The creation date. 56 | /// 57 | public double CreatedAt { get; set; } 58 | 59 | /// 60 | /// The last update date. 61 | /// 62 | public double UpdatedAt { get; set; } 63 | 64 | /// 65 | /// The URL. 66 | /// 67 | public Uri Url { get; set; } 68 | 69 | /// 70 | /// The Experience Composer renderer resolution. 71 | /// 72 | [JsonConverter(typeof(RenderResolutionConverter))] 73 | public RenderResolution Resolution { get; set; } 74 | 75 | /// 76 | /// The status. 77 | /// 78 | public string Status { get; set; } 79 | 80 | /// 81 | /// The stream ID. 82 | /// 83 | public string StreamId { get; set; } 84 | 85 | /// 86 | /// The reason, when the status is either "stopped" or "failed". If the status is "stopped", 87 | /// the reason field will contain either "Max Duration Exceeded" or "Stop Requested." 88 | /// If the status is "failed", the reason will contain a more specific error message. 89 | /// 90 | public string Reason { get; set; } 91 | } 92 | } -------------------------------------------------------------------------------- /OpenTok/Render/RenderResolution.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | namespace OpenTokSDK.Render 4 | { 5 | /// 6 | /// Enum for representing resolutions with orientation. 7 | /// 8 | public enum RenderResolution 9 | { 10 | /// 11 | /// Standard definition (SD) resolution with landscape orientation (640x480) 12 | /// 13 | [Description("640x480")] StandardDefinitionLandscape, 14 | 15 | /// 16 | /// Standard definition (SD) resolution with portrait orientation (480x640) 17 | /// 18 | [Description("480x640")] StandardDefinitionPortrait, 19 | 20 | /// 21 | /// High definition (HD) resolution with landscape orientation (1280x780) 22 | /// 23 | [Description("1280x720")] HighDefinitionLandscape, 24 | 25 | /// 26 | /// High definition (HD) resolution with portrait orientation (780x1280) 27 | /// 28 | [Description("720x1280")] HighDefinitionPortrait, 29 | 30 | /// 31 | /// Full high definition (FHD) resolution with landscape orientation (1920x1080) 32 | /// 33 | [Description("1920x1080")] FullHighDefinitionLandscape, 34 | 35 | /// 36 | /// Full high definition (FHD) resolution with portrait orientation (1080x1920) 37 | /// 38 | [Description("1080x1920")] FullHighDefinitionPortrait, 39 | } 40 | } -------------------------------------------------------------------------------- /OpenTok/Render/RenderResolutionConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using EnumsNET; 3 | using Newtonsoft.Json; 4 | 5 | namespace OpenTokSDK.Render 6 | { 7 | /// 8 | /// Custom converter for serializing RenderResolution. 9 | /// 10 | class RenderResolutionConverter : JsonConverter 11 | { 12 | /// 13 | public override void WriteJson(JsonWriter writer, RenderResolution value, JsonSerializer serializer) => 14 | writer.WriteValue(value.AsString(EnumFormat.Description)); 15 | 16 | /// 17 | public override RenderResolution ReadJson(JsonReader reader, Type objectType, RenderResolution existingValue, 18 | bool hasExistingValue, 19 | JsonSerializer serializer) => 20 | reader.Value != null 21 | ? Enums.Parse(reader.Value.ToString(), false, EnumFormat.Description) 22 | : existingValue; 23 | } 24 | } -------------------------------------------------------------------------------- /OpenTok/Role.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace OpenTokSDK 7 | { 8 | /// 9 | /// Defines values for the role parameter of the GenerateToken method of the OpenTok class. 10 | /// 11 | public enum Role 12 | { 13 | /// 14 | /// A publisher can publish streams, subscribe to streams, and signal. (This is the default 15 | /// value if you do not set a role when calling GenerateToken method of the OpenTok class. 16 | /// 17 | PUBLISHER, 18 | /// 19 | /// A subscriber can only subscribe to streams. 20 | /// 21 | SUBSCRIBER, 22 | /// 23 | /// In addition to the privileges granted to a publisher, a moderator can perform moderation 24 | /// functions, such as forcing clients to disconnect, to stop publishing streams, or to 25 | /// mute audio in published streams. See the 26 | /// Moderation developer guide. 27 | /// 28 | MODERATOR, 29 | /// 30 | /// A publisher-only role can publish streams, but not signal. 31 | /// 32 | PUBLISHERONLY, 33 | } 34 | 35 | /// 36 | /// For internal use. 37 | /// 38 | internal static class RoleExtensions 39 | { 40 | public static string ToString(this Role role) 41 | { 42 | return role.ToString().ToLowerInvariant(); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /OpenTok/Rtmp.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Newtonsoft.Json; 3 | 4 | namespace OpenTokSDK 5 | { 6 | /// 7 | /// Represents an RTMP stream in an OpenTok session. 8 | /// 9 | public class Rtmp 10 | { 11 | /// 12 | /// The stream ID. 13 | /// 14 | [JsonProperty("id")] 15 | public string Id { get; set; } 16 | 17 | /// 18 | /// The server URL. 19 | /// 20 | [JsonProperty("serverUrl")] 21 | public string ServerUrl { get; set; } 22 | 23 | /// 24 | /// The stream name. 25 | /// 26 | [JsonProperty("streamName")] 27 | public string StreamName { get; set; } 28 | 29 | /// 30 | /// Initializes a new instance of the class. 31 | /// 32 | public Rtmp() 33 | { 34 | } 35 | 36 | /// 37 | /// Initializes a new instance of the class. 38 | /// 39 | /// The stream ID. 40 | /// The server URL. 41 | /// The stream name. 42 | public Rtmp(string id, string serverUrl, string streamName) 43 | { 44 | Id = id; 45 | ServerUrl = serverUrl; 46 | StreamName = streamName; 47 | } 48 | 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /OpenTok/ScreenShareLayoutType.cs: -------------------------------------------------------------------------------- 1 | namespace OpenTokSDK 2 | { 3 | 4 | /// 5 | /// For archive and broadcast layouts, the layout type to use with screen shares. 6 | /// If this enum is used, the Type property should be set to BestFit. 7 | /// 8 | public enum ScreenShareLayoutType 9 | { 10 | /// 11 | /// Picture-in-Picture 12 | /// 13 | Pip, 14 | /// 15 | /// Best Fit 16 | /// 17 | BestFit, 18 | /// 19 | /// Vertical Presentation 20 | /// 21 | VerticalPresentation, 22 | /// 23 | /// Horizontal Presentation 24 | /// 25 | HorizontalPresentation 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /OpenTok/SignalProperties.cs: -------------------------------------------------------------------------------- 1 | namespace OpenTokSDK 2 | { 3 | /// 4 | /// Defines signal payload for the Signal API. 5 | /// 6 | public class SignalProperties 7 | { 8 | internal SignalProperties() 9 | { 10 | 11 | } 12 | 13 | /// 14 | /// Defines signal payload for the Signal API. 15 | /// 16 | /// 17 | /// 18 | public SignalProperties(string data = null, string type = null) 19 | { 20 | this.data = data; 21 | this.type = type; 22 | } 23 | 24 | /// 25 | /// Defines signal payload for the Signal API. 26 | /// 27 | /// 28 | public SignalProperties(string data = null) 29 | { 30 | this.data = data; 31 | } 32 | 33 | public string data { get; set; } 34 | public string type { get; set; } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /OpenTok/Sip.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace OpenTokSDK 4 | { 5 | /// 6 | /// Dial response object containing SIP information 7 | /// 8 | public class Sip 9 | { 10 | /// 11 | /// A unique ID for the SIP call. 12 | /// 13 | public Guid Id { get; set; } 14 | 15 | /// 16 | /// The OpenTok connection ID for the SIP call's connection in the 17 | /// OpenTok session. You can use this connection ID to terminate the 18 | /// SIP call. 19 | /// 20 | public Guid ConnectionId { get; set; } 21 | 22 | /// 23 | /// The OpenTok stream ID for the SIP call's stream in the OpenTok session. 24 | /// 25 | public Guid StreamId { get; set; } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /OpenTok/Stream.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Newtonsoft.Json; 7 | 8 | 9 | namespace OpenTokSDK 10 | { 11 | /// 12 | /// Represents a stream in an OpenTok session. 13 | /// 14 | public class Stream 15 | { 16 | 17 | internal Stream() 18 | { 19 | } 20 | 21 | internal void CopyStream(Stream stream) 22 | { 23 | this.Id = stream.Id; 24 | this.Name = stream.Name; 25 | this.LayoutClassList = stream.LayoutClassList; 26 | this.VideoType = stream.VideoType; 27 | } 28 | 29 | /// 30 | /// The layout class list as a list of strings. 31 | /// 32 | [JsonProperty("layoutClassList")] 33 | public List LayoutClassList { get; set; } 34 | 35 | /// 36 | /// The video type as a string. 37 | /// 38 | [JsonProperty("videoType")] 39 | public string VideoType { get; set; } 40 | 41 | /// 42 | /// The stream ID. 43 | /// 44 | [JsonProperty("id")] 45 | public string Id { get; set; } 46 | 47 | /// 48 | /// The name of the stream. 49 | /// 50 | [JsonProperty("name")] 51 | public string Name { get; set; } 52 | 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /OpenTok/StreamList.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace OpenTokSDK 7 | { 8 | /// 9 | /// A class for accessing an array of Stream objects. 10 | /// 11 | public class StreamList : List 12 | { 13 | /// 14 | /// The total number of streams (associated with the sessionId). 15 | /// 16 | public int TotalCount { get; private set; } 17 | 18 | internal StreamList(List items, int totalCount) 19 | : base(items) 20 | { 21 | TotalCount = totalCount; 22 | } 23 | } 24 | } 25 | 26 | -------------------------------------------------------------------------------- /OpenTok/StreamMode.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | namespace OpenTokSDK 4 | { 5 | /// 6 | /// Whether streams included in an archive or broadcast are selected automatically or manually. 7 | /// See the streamMode parameter of the and 8 | /// methods). 9 | /// 10 | public enum StreamMode 11 | { 12 | /// 13 | /// All streams in the session can be included. 14 | /// 15 | [Description("auto")] 16 | Auto, 17 | /// 18 | /// You will specify streams to be included in the archive or broadcast. 19 | /// For an archive, use the and 20 | /// methods (or the 21 | /// and 22 | /// methods). 23 | /// For a broadcast, use the and 24 | /// methods (or the 25 | /// and 26 | /// methods). 27 | /// 28 | [Description("manual")] 29 | Manual 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /OpenTok/StreamProperties.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using Newtonsoft.Json; 3 | 4 | namespace OpenTokSDK 5 | { 6 | /// 7 | /// Defines class lists for one or more streams in the session. Used by the 8 | /// OpenTok.SetStreamClassLists() method. 9 | /// 10 | public class StreamProperties 11 | { 12 | 13 | internal StreamProperties() 14 | { 15 | } 16 | 17 | /// 18 | /// Initializes a new instance of the class. 19 | /// 20 | /// The stream ID. 21 | /// The layout class list as a list of strings. 22 | public StreamProperties(string Id = null, List LayoutClassList = null) 23 | { 24 | this.Id = Id; 25 | if (LayoutClassList != null) 26 | { 27 | this.LayoutClassList = LayoutClassList; 28 | } else 29 | { 30 | this.LayoutClassList = new List(); 31 | } 32 | 33 | } 34 | 35 | public void addLayoutClass(string layoutClass) 36 | { 37 | LayoutClassList.Add(layoutClass); 38 | } 39 | 40 | /// 41 | /// The stream ID. 42 | /// 43 | [JsonProperty("id")] 44 | public string Id { get; set; } 45 | 46 | /// 47 | /// The layout class list as a list of strings. 48 | /// 49 | [JsonProperty("layoutClassList")] 50 | public List LayoutClassList { get; set; } 51 | 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /OpenTok/app.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /OpenTokTest/AudioConnectorStartRequestDataBuilder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using AutoFixture; 4 | using OpenTokSDK; 5 | 6 | namespace OpenTokSDKTest 7 | { 8 | public class AudioConnectorStartRequestDataBuilder 9 | { 10 | private Dictionary headers; 11 | private string sessionId; 12 | private List streams; 13 | private string token; 14 | private Uri uri; 15 | 16 | private AudioConnectorStartRequestDataBuilder() 17 | { 18 | var fixture = new Fixture(); 19 | this.sessionId = fixture.Create(); 20 | this.token = fixture.Create(); 21 | this.uri = fixture.Create(); 22 | } 23 | 24 | public static AudioConnectorStartRequestDataBuilder Build() => new AudioConnectorStartRequestDataBuilder(); 25 | 26 | public AudioConnectorStartRequestDataBuilder WithSessionId(string value) 27 | { 28 | this.sessionId = value; 29 | return this; 30 | } 31 | 32 | public AudioConnectorStartRequestDataBuilder WithToken(string value) 33 | { 34 | this.token = value; 35 | return this; 36 | } 37 | 38 | public AudioConnectorStartRequestDataBuilder WithUri(Uri value) 39 | { 40 | this.uri = value; 41 | return this; 42 | } 43 | 44 | public AudioConnectorStartRequestDataBuilder WithStream(string value) 45 | { 46 | if (this.streams is null) 47 | { 48 | this.streams = new List(); 49 | } 50 | 51 | this.streams.Add(value); 52 | return this; 53 | } 54 | 55 | public AudioConnectorStartRequestDataBuilder WithHeader(string key, string value) 56 | { 57 | if (this.headers is null) 58 | { 59 | this.headers = new Dictionary(); 60 | } 61 | 62 | this.headers.Add(key, value); 63 | return this; 64 | } 65 | 66 | public AudioConnectorStartRequest Create() => 67 | new AudioConnectorStartRequest(this.sessionId, this.token, new AudioConnectorStartRequest.WebSocket(this.uri, this.streams?.ToArray(), this.headers)); 68 | } 69 | } -------------------------------------------------------------------------------- /OpenTokTest/BroadcastBitrateTest.cs: -------------------------------------------------------------------------------- 1 | using OpenTokSDK; 2 | using OpenTokSDK.Exception; 3 | using Xunit; 4 | 5 | namespace OpenTokSDKTest 6 | { 7 | public class BroadcastBitrateTest 8 | { 9 | [Fact] 10 | public void Bitrate_ShouldHaveDefaultValue() => 11 | Assert.Equal(2000000, new BroadcastBitrate().Bitrate); 12 | 13 | [Fact] 14 | public void Bitrate_ShouldAllowMaximumValue()=> 15 | Assert.Equal(2000000, new BroadcastBitrate(2000000).Bitrate); 16 | 17 | [Fact] 18 | public void Bitrate_ShouldAllowMinimumValue()=> 19 | Assert.Equal(400000, new BroadcastBitrate(400000).Bitrate); 20 | 21 | [Theory] 22 | [InlineData(399999)] 23 | [InlineData(2000001)] 24 | public void Bitrate_ShouldThrowException_GivenValueIsOutsideRange(int invalidBitrate) 25 | { 26 | var exception = Assert.Throws(() => new BroadcastBitrate(invalidBitrate)); 27 | Assert.Equal("Bitrate value must be between 400000 and 2000000.", exception.Message); 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /OpenTokTest/Data/ArchiveTests/GetArchive-response.json: -------------------------------------------------------------------------------- 1 | { 2 | "createdAt": 1395187836000, 3 | "duration": 62, 4 | "id": "$archiveId$", 5 | "name": "", 6 | "partnerId": 123456, 7 | "reason": "", 8 | "sessionId": "SESSIONID", 9 | "size": 8347554, 10 | "status": "available", 11 | "url": 12 | "http://tokbox.com.archive2.s3.amazonaws.com/123456%2F$archiveId$%2Farchive.mp4?Expires=1395194362&AWSAccessKeyId=AKIAI6LQCPIXYVWCQV6Q&Signature=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", 13 | "maxBitrate": 1000, 14 | "quantizationParameter": 40 15 | } -------------------------------------------------------------------------------- /OpenTokTest/Data/ArchiveTests/GetArchiveAsync-response.json: -------------------------------------------------------------------------------- 1 | { 2 | "createdAt": 1395187836000, 3 | "duration": 62, 4 | "id": "$archiveId$", 5 | "name": "", 6 | "partnerId": 123456, 7 | "reason": "", 8 | "sessionId": "SESSIONID", 9 | "size": 8347554, 10 | "status": "available", 11 | "url": 12 | "http://tokbox.com.archive2.s3.amazonaws.com/123456%2F$archiveId$%2Farchive.mp4?Expires=1395194362&AWSAccessKeyId=AKIAI6LQCPIXYVWCQV6Q&Signature=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" 13 | } -------------------------------------------------------------------------------- /OpenTokTest/Data/ArchiveTests/GetArchiveWithUnknownProperties-response.json: -------------------------------------------------------------------------------- 1 | { 2 | "createdAt": 1395187836000, 3 | "duration": 62, 4 | "id": "$archiveId$", 5 | "name": "", 6 | "partnerId": 123456, 7 | "reason": "", 8 | "sessionId": "SESSIONID", 9 | "size": 8347554, 10 | "status": "expired", 11 | "notarealproperty": "not a real value", 12 | "url": null 13 | } -------------------------------------------------------------------------------- /OpenTokTest/Data/ArchiveTests/GetArchiveWithUnknownPropertiesAsync-response.json: -------------------------------------------------------------------------------- 1 | { 2 | "createdAt": 1395187836000, 3 | "duration": 62, 4 | "id": "$archiveId$", 5 | "name": "", 6 | "partnerId": 123456, 7 | "reason": "", 8 | "sessionId": "SESSIONID", 9 | "size": 8347554, 10 | "status": "expired", 11 | "notarealproperty": "not a real value", 12 | "url": null 13 | } -------------------------------------------------------------------------------- /OpenTokTest/Data/ArchiveTests/GetExpiredArchive-response.json: -------------------------------------------------------------------------------- 1 | { 2 | "createdAt": 1395187836000, 3 | "duration": 62, 4 | "id": "$archiveId$", 5 | "name": "", 6 | "partnerId": 123456, 7 | "reason": "", 8 | "sessionId": "SESSIONID", 9 | "size": 8347554, 10 | "status": "expired", 11 | "url": null 12 | } -------------------------------------------------------------------------------- /OpenTokTest/Data/ArchiveTests/GetExpiredArchiveAsync-response.json: -------------------------------------------------------------------------------- 1 | { 2 | "createdAt": 1395187836000, 3 | "duration": 62, 4 | "id": "$archiveId$", 5 | "name": "", 6 | "partnerId": 123456, 7 | "reason": "", 8 | "sessionId": "SESSIONID", 9 | "size": 8347554, 10 | "status": "expired", 11 | "url": null 12 | } -------------------------------------------------------------------------------- /OpenTokTest/Data/ArchiveTests/ListArchives-response.json: -------------------------------------------------------------------------------- 1 | { 2 | "count": 6, 3 | "items": [ 4 | { 5 | "createdAt": 1395187930000, 6 | "duration": 22, 7 | "id": "ef546c5a-4fd7-4e59-ab3d-f1cfb4148d1d", 8 | "name": "", 9 | "partnerId": 123456, 10 | "reason": "", 11 | "sessionId": "SESSIONID", 12 | "size": 2909274, 13 | "status": "available", 14 | "url": "http://tokbox.com.archive2.s3.amazonaws.com/123456%2Fef546c5a-4fd7-4e59-ab3d-f1cfb4148d1d%2Farchive.mp4?Expires=1395188695&AWSAccessKeyId=AKIAI6LQCPIXYVWCQV6Q&Signature=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" 15 | }, 16 | { 17 | "createdAt": 1395187910000, 18 | "duration": 14, 19 | "id": "5350f06f-0166-402e-bc27-09ba54948512", 20 | "name": "", 21 | "partnerId": 123456, 22 | "reason": "", 23 | "sessionId": "SESSIONID", 24 | "size": 1952651, 25 | "status": "available", 26 | "url": "http://tokbox.com.archive2.s3.amazonaws.com/123456%2F5350f06f-0166-402e-bc27-09ba54948512%2Farchive.mp4?Expires=1395188695&AWSAccessKeyId=AKIAI6LQCPIXYVWCQV6Q&Signature=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" 27 | }, 28 | { 29 | "createdAt": 1395187836000, 30 | "duration": 62, 31 | "id": "f6e7ee58-d6cf-4a59-896b-6d56b158ec71", 32 | "name": "", 33 | "partnerId": 123456, 34 | "reason": "", 35 | "sessionId": "SESSIONID", 36 | "size": 8347554, 37 | "status": "available", 38 | "url": "http://tokbox.com.archive2.s3.amazonaws.com/123456%2Ff6e7ee58-d6cf-4a59-896b-6d56b158ec71%2Farchive.mp4?Expires=1395188695&AWSAccessKeyId=AKIAI6LQCPIXYVWCQV6Q&Signature=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" 39 | }, 40 | { 41 | "createdAt": 1395183243000, 42 | "duration": 544, 43 | "id": "30b3ebf1-ba36-4f5b-8def-6f70d9986fe9", 44 | "name": "", 45 | "partnerId": 123456, 46 | "reason": "", 47 | "sessionId": "SESSIONID", 48 | "size": 78499758, 49 | "status": "available", 50 | "url": "http://tokbox.com.archive2.s3.amazonaws.com/123456%2F30b3ebf1-ba36-4f5b-8def-6f70d9986fe9%2Farchive.mp4?Expires=1395188695&AWSAccessKeyId=AKIAI6LQCPIXYVWCQV6Q&Signature=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" 51 | }, 52 | { 53 | "createdAt": 1394396753000, 54 | "duration": 24, 55 | "id": "b8f64de1-e218-4091-9544-4cbf369fc238", 56 | "name": "showtime again", 57 | "partnerId": 123456, 58 | "reason": "", 59 | "sessionId": "SESSIONID", 60 | "size": 2227849, 61 | "status": "available", 62 | "url": "http://tokbox.com.archive2.s3.amazonaws.com/123456%2Fb8f64de1-e218-4091-9544-4cbf369fc238%2Farchive.mp4?Expires=1395188695&AWSAccessKeyId=AKIAI6LQCPIXYVWCQV6Q&Signature=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" 63 | }, 64 | { 65 | "createdAt": 1394321113000, 66 | "duration": 1294, 67 | "id": "832641bf-5dbf-41a1-ad94-fea213e59a92", 68 | "name": "showtime", 69 | "partnerId": 123456, 70 | "reason": "", 71 | "sessionId": "SESSIONID", 72 | "size": 42165242, 73 | "status": "available", 74 | "url": "http://tokbox.com.archive2.s3.amazonaws.com/123456%2F832641bf-5dbf-41a1-ad94-fea213e59a92%2Farchive.mp4?Expires=1395188695&AWSAccessKeyId=AKIAI6LQCPIXYVWCQV6Q&Signature=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" 75 | } 76 | ] 77 | } -------------------------------------------------------------------------------- /OpenTokTest/Data/ArchiveTests/ListArchivesAsync-response.json: -------------------------------------------------------------------------------- 1 | { 2 | "count": 6, 3 | "items": [ 4 | { 5 | "createdAt": 1395187930000, 6 | "duration": 22, 7 | "id": "ef546c5a-4fd7-4e59-ab3d-f1cfb4148d1d", 8 | "name": "", 9 | "partnerId": 123456, 10 | "reason": "", 11 | "sessionId": "SESSIONID", 12 | "size": 2909274, 13 | "status": "available", 14 | "url": "http://tokbox.com.archive2.s3.amazonaws.com/123456%2Fef546c5a-4fd7-4e59-ab3d-f1cfb4148d1d%2Farchive.mp4?Expires=1395188695&AWSAccessKeyId=AKIAI6LQCPIXYVWCQV6Q&Signature=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" 15 | }, 16 | { 17 | "createdAt": 1395187910000, 18 | "duration": 14, 19 | "id": "5350f06f-0166-402e-bc27-09ba54948512", 20 | "name": "", 21 | "partnerId": 123456, 22 | "reason": "", 23 | "sessionId": "SESSIONID", 24 | "size": 1952651, 25 | "status": "available", 26 | "url": "http://tokbox.com.archive2.s3.amazonaws.com/123456%2F5350f06f-0166-402e-bc27-09ba54948512%2Farchive.mp4?Expires=1395188695&AWSAccessKeyId=AKIAI6LQCPIXYVWCQV6Q&Signature=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" 27 | }, 28 | { 29 | "createdAt": 1395187836000, 30 | "duration": 62, 31 | "id": "f6e7ee58-d6cf-4a59-896b-6d56b158ec71", 32 | "name": "", 33 | "partnerId": 123456, 34 | "reason": "", 35 | "sessionId": "SESSIONID", 36 | "size": 8347554, 37 | "status": "available", 38 | "url": "http://tokbox.com.archive2.s3.amazonaws.com/123456%2Ff6e7ee58-d6cf-4a59-896b-6d56b158ec71%2Farchive.mp4?Expires=1395188695&AWSAccessKeyId=AKIAI6LQCPIXYVWCQV6Q&Signature=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" 39 | }, 40 | { 41 | "createdAt": 1395183243000, 42 | "duration": 544, 43 | "id": "30b3ebf1-ba36-4f5b-8def-6f70d9986fe9", 44 | "name": "", 45 | "partnerId": 123456, 46 | "reason": "", 47 | "sessionId": "SESSIONID", 48 | "size": 78499758, 49 | "status": "available", 50 | "url": "http://tokbox.com.archive2.s3.amazonaws.com/123456%2F30b3ebf1-ba36-4f5b-8def-6f70d9986fe9%2Farchive.mp4?Expires=1395188695&AWSAccessKeyId=AKIAI6LQCPIXYVWCQV6Q&Signature=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" 51 | }, 52 | { 53 | "createdAt": 1394396753000, 54 | "duration": 24, 55 | "id": "b8f64de1-e218-4091-9544-4cbf369fc238", 56 | "name": "showtime again", 57 | "partnerId": 123456, 58 | "reason": "", 59 | "sessionId": "SESSIONID", 60 | "size": 2227849, 61 | "status": "available", 62 | "url": "http://tokbox.com.archive2.s3.amazonaws.com/123456%2Fb8f64de1-e218-4091-9544-4cbf369fc238%2Farchive.mp4?Expires=1395188695&AWSAccessKeyId=AKIAI6LQCPIXYVWCQV6Q&Signature=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" 63 | }, 64 | { 65 | "createdAt": 1394321113000, 66 | "duration": 1294, 67 | "id": "832641bf-5dbf-41a1-ad94-fea213e59a92", 68 | "name": "showtime", 69 | "partnerId": 123456, 70 | "reason": "", 71 | "sessionId": "SESSIONID", 72 | "size": 42165242, 73 | "status": "available", 74 | "url": "http://tokbox.com.archive2.s3.amazonaws.com/123456%2F832641bf-5dbf-41a1-ad94-fea213e59a92%2Farchive.mp4?Expires=1395188695&AWSAccessKeyId=AKIAI6LQCPIXYVWCQV6Q&Signature=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" 75 | } 76 | ] 77 | } -------------------------------------------------------------------------------- /OpenTokTest/Data/ArchiveTests/ListArchivesAsyncWithValidSessionId-response.json: -------------------------------------------------------------------------------- 1 | { 2 | "count": 6, 3 | "items": [ 4 | { 5 | "createdAt": 1395187930000, 6 | "duration": 22, 7 | "id": "ef546c5a-4fd7-4e59-ab3d-f1cfb4148d1d", 8 | "name": "", 9 | "partnerId": 123456, 10 | "reason": "", 11 | "sessionId": "SESSIONID", 12 | "size": 2909274, 13 | "status": "available", 14 | "url": "http://tokbox.com.archive2.s3.amazonaws.com/123456%2Fef546c5a-4fd7-4e59-ab3d-f1cfb4148d1d%2Farchive.mp4?Expires=1395188695&AWSAccessKeyId=AKIAI6LQCPIXYVWCQV6Q&Signature=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" 15 | }, 16 | { 17 | "createdAt": 1395187910000, 18 | "duration": 14, 19 | "id": "5350f06f-0166-402e-bc27-09ba54948512", 20 | "name": "", 21 | "partnerId": 123456, 22 | "reason": "", 23 | "sessionId": "SESSIONID", 24 | "size": 1952651, 25 | "status": "available", 26 | "url": "http://tokbox.com.archive2.s3.amazonaws.com/123456%2F5350f06f-0166-402e-bc27-09ba54948512%2Farchive.mp4?Expires=1395188695&AWSAccessKeyId=AKIAI6LQCPIXYVWCQV6Q&Signature=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" 27 | }, 28 | { 29 | "createdAt": 1395187836000, 30 | "duration": 62, 31 | "id": "f6e7ee58-d6cf-4a59-896b-6d56b158ec71", 32 | "name": "", 33 | "partnerId": 123456, 34 | "reason": "", 35 | "sessionId": "SESSIONID", 36 | "size": 8347554, 37 | "status": "available", 38 | "url": "http://tokbox.com.archive2.s3.amazonaws.com/123456%2Ff6e7ee58-d6cf-4a59-896b-6d56b158ec71%2Farchive.mp4?Expires=1395188695&AWSAccessKeyId=AKIAI6LQCPIXYVWCQV6Q&Signature=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" 39 | }, 40 | { 41 | "createdAt": 1395183243000, 42 | "duration": 544, 43 | "id": "30b3ebf1-ba36-4f5b-8def-6f70d9986fe9", 44 | "name": "", 45 | "partnerId": 123456, 46 | "reason": "", 47 | "sessionId": "SESSIONID", 48 | "size": 78499758, 49 | "status": "available", 50 | "url": "http://tokbox.com.archive2.s3.amazonaws.com/123456%2F30b3ebf1-ba36-4f5b-8def-6f70d9986fe9%2Farchive.mp4?Expires=1395188695&AWSAccessKeyId=AKIAI6LQCPIXYVWCQV6Q&Signature=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" 51 | }, 52 | { 53 | "createdAt": 1394396753000, 54 | "duration": 24, 55 | "id": "b8f64de1-e218-4091-9544-4cbf369fc238", 56 | "name": "showtime again", 57 | "partnerId": 123456, 58 | "reason": "", 59 | "sessionId": "SESSIONID", 60 | "size": 2227849, 61 | "status": "available", 62 | "url": "http://tokbox.com.archive2.s3.amazonaws.com/123456%2Fb8f64de1-e218-4091-9544-4cbf369fc238%2Farchive.mp4?Expires=1395188695&AWSAccessKeyId=AKIAI6LQCPIXYVWCQV6Q&Signature=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" 63 | }, 64 | { 65 | "createdAt": 1394321113000, 66 | "duration": 1294, 67 | "id": "832641bf-5dbf-41a1-ad94-fea213e59a92", 68 | "name": "showtime", 69 | "partnerId": 123456, 70 | "reason": "", 71 | "sessionId": "SESSIONID", 72 | "size": 42165242, 73 | "status": "available", 74 | "url": "http://tokbox.com.archive2.s3.amazonaws.com/123456%2F832641bf-5dbf-41a1-ad94-fea213e59a92%2Farchive.mp4?Expires=1395188695&AWSAccessKeyId=AKIAI6LQCPIXYVWCQV6Q&Signature=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" 75 | } 76 | ] 77 | } -------------------------------------------------------------------------------- /OpenTokTest/Data/ArchiveTests/ListArchivesWithValidSessionId-response.json: -------------------------------------------------------------------------------- 1 | { 2 | "count": 6, 3 | "items": [ 4 | { 5 | "createdAt": 1395187930000, 6 | "duration": 22, 7 | "id": "ef546c5a-4fd7-4e59-ab3d-f1cfb4148d1d", 8 | "name": "", 9 | "partnerId": 123456, 10 | "reason": "", 11 | "sessionId": "SESSIONID", 12 | "size": 2909274, 13 | "status": "available", 14 | "url": "http://tokbox.com.archive2.s3.amazonaws.com/123456%2Fef546c5a-4fd7-4e59-ab3d-f1cfb4148d1d%2Farchive.mp4?Expires=1395188695&AWSAccessKeyId=AKIAI6LQCPIXYVWCQV6Q&Signature=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" 15 | }, 16 | { 17 | "createdAt": 1395187910000, 18 | "duration": 14, 19 | "id": "5350f06f-0166-402e-bc27-09ba54948512", 20 | "name": "", 21 | "partnerId": 123456, 22 | "reason": "", 23 | "sessionId": "SESSIONID", 24 | "size": 1952651, 25 | "status": "available", 26 | "url": "http://tokbox.com.archive2.s3.amazonaws.com/123456%2F5350f06f-0166-402e-bc27-09ba54948512%2Farchive.mp4?Expires=1395188695&AWSAccessKeyId=AKIAI6LQCPIXYVWCQV6Q&Signature=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" 27 | }, 28 | { 29 | "createdAt": 1395187836000, 30 | "duration": 62, 31 | "id": "f6e7ee58-d6cf-4a59-896b-6d56b158ec71", 32 | "name": "", 33 | "partnerId": 123456, 34 | "reason": "", 35 | "sessionId": "SESSIONID", 36 | "size": 8347554, 37 | "status": "available", 38 | "url": "http://tokbox.com.archive2.s3.amazonaws.com/123456%2Ff6e7ee58-d6cf-4a59-896b-6d56b158ec71%2Farchive.mp4?Expires=1395188695&AWSAccessKeyId=AKIAI6LQCPIXYVWCQV6Q&Signature=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" 39 | }, 40 | { 41 | "createdAt": 1395183243000, 42 | "duration": 544, 43 | "id": "30b3ebf1-ba36-4f5b-8def-6f70d9986fe9", 44 | "name": "", 45 | "partnerId": 123456, 46 | "reason": "", 47 | "sessionId": "SESSIONID", 48 | "size": 78499758, 49 | "status": "available", 50 | "url": "http://tokbox.com.archive2.s3.amazonaws.com/123456%2F30b3ebf1-ba36-4f5b-8def-6f70d9986fe9%2Farchive.mp4?Expires=1395188695&AWSAccessKeyId=AKIAI6LQCPIXYVWCQV6Q&Signature=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" 51 | }, 52 | { 53 | "createdAt": 1394396753000, 54 | "duration": 24, 55 | "id": "b8f64de1-e218-4091-9544-4cbf369fc238", 56 | "name": "showtime again", 57 | "partnerId": 123456, 58 | "reason": "", 59 | "sessionId": "SESSIONID", 60 | "size": 2227849, 61 | "status": "available", 62 | "url": "http://tokbox.com.archive2.s3.amazonaws.com/123456%2Fb8f64de1-e218-4091-9544-4cbf369fc238%2Farchive.mp4?Expires=1395188695&AWSAccessKeyId=AKIAI6LQCPIXYVWCQV6Q&Signature=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" 63 | }, 64 | { 65 | "createdAt": 1394321113000, 66 | "duration": 1294, 67 | "id": "832641bf-5dbf-41a1-ad94-fea213e59a92", 68 | "name": "showtime", 69 | "partnerId": 123456, 70 | "reason": "", 71 | "sessionId": "SESSIONID", 72 | "size": 42165242, 73 | "status": "available", 74 | "url": "http://tokbox.com.archive2.s3.amazonaws.com/123456%2F832641bf-5dbf-41a1-ad94-fea213e59a92%2Farchive.mp4?Expires=1395188695&AWSAccessKeyId=AKIAI6LQCPIXYVWCQV6Q&Signature=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" 75 | } 76 | ] 77 | } -------------------------------------------------------------------------------- /OpenTokTest/Data/ArchiveTests/StartArchive-response.json: -------------------------------------------------------------------------------- 1 | { 2 | "createdAt": 1395183243556, 3 | "duration": 0, 4 | "id": "30b3ebf1-ba36-4f5b-8def-6f70d9986fe9", 5 | "name": "", 6 | "partnerId": 123456, 7 | "reason": "", 8 | "sessionId": "1_MX4xMjM0NTZ-flNhdCBNYXIgMTUgMTQ6NDI6MjMgUERUIDIwMTR-MC40OTAxMzAyNX4", 9 | "size": 0, 10 | "status": "started", 11 | "url": null 12 | } -------------------------------------------------------------------------------- /OpenTokTest/Data/ArchiveTests/StartArchiveAsync-response.json: -------------------------------------------------------------------------------- 1 | { 2 | "createdAt": 1395183243556, 3 | "duration": 0, 4 | "id": "30b3ebf1-ba36-4f5b-8def-6f70d9986fe9", 5 | "name": "", 6 | "partnerId": 123456, 7 | "reason": "", 8 | "sessionId": "1_MX4xMjM0NTZ-flNhdCBNYXIgMTUgMTQ6NDI6MjMgUERUIDIwMTR-MC40OTAxMzAyNX4", 9 | "size": 0, 10 | "status": "started", 11 | "url": null 12 | } -------------------------------------------------------------------------------- /OpenTokTest/Data/ArchiveTests/StartArchiveAsyncAutoStreamMode-response.json: -------------------------------------------------------------------------------- 1 | { 2 | "createdAt": 1395183243556, 3 | "duration": 0, 4 | "id": "30b3ebf1-ba36-4f5b-8def-6f70d9986fe9", 5 | "name": "", 6 | "partnerId": 123456, 7 | "reason": "", 8 | "sessionId": "1_MX4xMjM0NTZ-flNhdCBNYXIgMTUgMTQ6NDI6MjMgUERUIDIwMTR-MC40OTAxMzAyNX4", 9 | "size": 0, 10 | "status": "started", 11 | "url": null, 12 | "streamMode": "auto" 13 | } -------------------------------------------------------------------------------- /OpenTokTest/Data/ArchiveTests/StartArchiveAsyncCreateInvalidIndividualModeArchivingWithResolution-response.json: -------------------------------------------------------------------------------- 1 | { 2 | "createdAt": 1395183243556, 3 | "duration": 0, 4 | "id": "30b3ebf1-ba36-4f5b-8def-6f70d9986fe9", 5 | "name": "", 6 | "outputMode": "individual", 7 | "resolution": "640x480", 8 | "partnerId": 123456, 9 | "reason": "", 10 | "sessionId": "1_MX4xMjM0NTZ-flNhdCBNYXIgMTUgMTQ6NDI6MjMgUERUIDIwMTR-MC40OTAxMzAyNX4", 11 | "size": 0, 12 | "status": "started", 13 | "url": null 14 | } -------------------------------------------------------------------------------- /OpenTokTest/Data/ArchiveTests/StartArchiveAsyncCustomLayout-response.json: -------------------------------------------------------------------------------- 1 | { 2 | "createdAt": 1395183243556, 3 | "duration": 0, 4 | "id": "30b3ebf1-ba36-4f5b-8def-6f70d9986fe9", 5 | "name": "", 6 | "outputMode": "composed", 7 | "resolution": "1280x720", 8 | "partnerId": 123456, 9 | "reason": "", 10 | "sessionId": "1_MX4xMjM0NTZ-flNhdCBNYXIgMTUgMTQ6NDI6MjMgUERUIDIwMTR-MC40OTAxMzAyNX4", 11 | "size": 0, 12 | "status": "started", 13 | "url": null 14 | } -------------------------------------------------------------------------------- /OpenTokTest/Data/ArchiveTests/StartArchiveAsyncCustomLayoutMissingStylesheet-response.json: -------------------------------------------------------------------------------- 1 | { 2 | "createdAt": 1395183243556, 3 | "duration": 0, 4 | "id": "30b3ebf1-ba36-4f5b-8def-6f70d9986fe9", 5 | "name": "", 6 | "outputMode": "composed", 7 | "resolution": "1280x720", 8 | "partnerId": 123456, 9 | "reason": "", 10 | "sessionId": "1_MX4xMjM0NTZ-flNhdCBNYXIgMTUgMTQ6NDI6MjMgUERUIDIwMTR-MC40OTAxMzAyNX4", 11 | "size": 0, 12 | "status": "started", 13 | "url": null 14 | } -------------------------------------------------------------------------------- /OpenTokTest/Data/ArchiveTests/StartArchiveAsyncIndividual-response.json: -------------------------------------------------------------------------------- 1 | { 2 | "createdAt": 1395183243556, 3 | "duration": 0, 4 | "id": "30b3ebf1-ba36-4f5b-8def-6f70d9986fe9", 5 | "name": "", 6 | "outputMode": "individual", 7 | "partnerId": 123456, 8 | "reason": "", 9 | "sessionId": "1_MX4xMjM0NTZ-flNhdCBNYXIgMTUgMTQ6NDI6MjMgUERUIDIwMTR-MC40OTAxMzAyNX4", 10 | "size": 0, 11 | "status": "started", 12 | "url": null 13 | } -------------------------------------------------------------------------------- /OpenTokTest/Data/ArchiveTests/StartArchiveAsyncManualStreamMode-response.json: -------------------------------------------------------------------------------- 1 | { 2 | "createdAt": 1395183243556, 3 | "duration": 0, 4 | "id": "30b3ebf1-ba36-4f5b-8def-6f70d9986fe9", 5 | "name": "", 6 | "partnerId": 123456, 7 | "reason": "", 8 | "sessionId": "1_MX4xMjM0NTZ-flNhdCBNYXIgMTUgMTQ6NDI6MjMgUERUIDIwMTR-MC40OTAxMzAyNX4", 9 | "size": 0, 10 | "status": "started", 11 | "url": null, 12 | "streamMode": "manual" 13 | } -------------------------------------------------------------------------------- /OpenTokTest/Data/ArchiveTests/StartArchiveAsyncNoResolution-response.json: -------------------------------------------------------------------------------- 1 | { 2 | "createdAt": 1395183243556, 3 | "duration": 0, 4 | "id": "30b3ebf1-ba36-4f5b-8def-6f70d9986fe9", 5 | "name": "", 6 | "partnerId": 123456, 7 | "reason": "", 8 | "sessionId": "1_MX4xMjM0NTZ-flNhdCBNYXIgMTUgMTQ6NDI6MjMgUERUIDIwMTR-MC40OTAxMzAyNX4", 9 | "resolution": "640x480", 10 | "size": 0, 11 | "status": "started", 12 | "url": null 13 | } -------------------------------------------------------------------------------- /OpenTokTest/Data/ArchiveTests/StartArchiveAsyncVerticalLayout-response.json: -------------------------------------------------------------------------------- 1 | { 2 | "createdAt": 1395183243556, 3 | "duration": 0, 4 | "id": "30b3ebf1-ba36-4f5b-8def-6f70d9986fe9", 5 | "name": "", 6 | "outputMode": "composed", 7 | "resolution": "1280x720", 8 | "partnerId": 123456, 9 | "reason": "", 10 | "sessionId": "1_MX4xMjM0NTZ-flNhdCBNYXIgMTUgMTQ6NDI6MjMgUERUIDIwMTR-MC40OTAxMzAyNX4", 11 | "size": 0, 12 | "status": "started", 13 | "url": null 14 | } -------------------------------------------------------------------------------- /OpenTokTest/Data/ArchiveTests/StartArchiveAsyncVerticalLayoutWithStyleSheet-response.json: -------------------------------------------------------------------------------- 1 | { 2 | "createdAt": 1395183243556, 3 | "duration": 0, 4 | "id": "30b3ebf1-ba36-4f5b-8def-6f70d9986fe9", 5 | "name": "", 6 | "outputMode": "composed", 7 | "resolution": "1280x720", 8 | "partnerId": 123456, 9 | "reason": "", 10 | "sessionId": "1_MX4xMjM0NTZ-flNhdCBNYXIgMTUgMTQ6NDI6MjMgUERUIDIwMTR-MC40OTAxMzAyNX4", 11 | "size": 0, 12 | "status": "started", 13 | "url": null 14 | } -------------------------------------------------------------------------------- /OpenTokTest/Data/ArchiveTests/StartArchiveAsyncVoiceOnly-response.json: -------------------------------------------------------------------------------- 1 | { 2 | "createdAt": 1395183243556, 3 | "duration": 0, 4 | "id": "30b3ebf1-ba36-4f5b-8def-6f70d9986fe9", 5 | "name": "", 6 | "partnerId": 123456, 7 | "reason": "", 8 | "sessionId": "1_MX4xMjM0NTZ-flNhdCBNYXIgMTUgMTQ6NDI6MjMgUERUIDIwMTR-MC40OTAxMzAyNX4", 9 | "size": 0, 10 | "status": "started", 11 | "url": null, 12 | "hasVideo": false, 13 | "hasAudio": true 14 | } -------------------------------------------------------------------------------- /OpenTokTest/Data/ArchiveTests/StartArchiveAsyncWithHDResolution-response.json: -------------------------------------------------------------------------------- 1 | { 2 | "createdAt": 1395183243556, 3 | "duration": 0, 4 | "id": "30b3ebf1-ba36-4f5b-8def-6f70d9986fe9", 5 | "name": "", 6 | "outputMode": "composed", 7 | "resolution": "1280x720", 8 | "partnerId": 123456, 9 | "reason": "", 10 | "sessionId": "1_MX4xMjM0NTZ-flNhdCBNYXIgMTUgMTQ6NDI6MjMgUERUIDIwMTR-MC40OTAxMzAyNX4", 11 | "size": 0, 12 | "status": "started", 13 | "url": null 14 | } -------------------------------------------------------------------------------- /OpenTokTest/Data/ArchiveTests/StartArchiveAsyncWithSDResolution-response.json: -------------------------------------------------------------------------------- 1 | { 2 | "createdAt": 1395183243556, 3 | "duration": 0, 4 | "id": "30b3ebf1-ba36-4f5b-8def-6f70d9986fe9", 5 | "name": "", 6 | "outputMode": "composed", 7 | "resolution": "640x480", 8 | "partnerId": 123456, 9 | "reason": "", 10 | "sessionId": "1_MX4xMjM0NTZ-flNhdCBNYXIgMTUgMTQ6NDI6MjMgUERUIDIwMTR-MC40OTAxMzAyNX4", 11 | "size": 0, 12 | "status": "started", 13 | "url": null 14 | } -------------------------------------------------------------------------------- /OpenTokTest/Data/ArchiveTests/StartArchiveAutoStreamMode-response.json: -------------------------------------------------------------------------------- 1 | { 2 | "createdAt": 1395183243556, 3 | "duration": 0, 4 | "id": "30b3ebf1-ba36-4f5b-8def-6f70d9986fe9", 5 | "name": "", 6 | "partnerId": 123456, 7 | "reason": "", 8 | "sessionId": "1_MX4xMjM0NTZ-flNhdCBNYXIgMTUgMTQ6NDI6MjMgUERUIDIwMTR-MC40OTAxMzAyNX4", 9 | "size": 0, 10 | "status": "started", 11 | "url": null, 12 | "streamMode": "auto" 13 | } -------------------------------------------------------------------------------- /OpenTokTest/Data/ArchiveTests/StartArchiveCreateInvalidIndividualModeArchivingWithResolution-response.json: -------------------------------------------------------------------------------- 1 | { 2 | "createdAt": 1395183243556, 3 | "duration": 0, 4 | "id": "30b3ebf1-ba36-4f5b-8def-6f70d9986fe9", 5 | "name": "", 6 | "outputMode": "individual", 7 | "resolution": "640x480", 8 | "partnerId": 123456, 9 | "reason": "", 10 | "sessionId": "1_MX4xMjM0NTZ-flNhdCBNYXIgMTUgMTQ6NDI6MjMgUERUIDIwMTR-MC40OTAxMzAyNX4", 11 | "size": 0, 12 | "status": "started", 13 | "url": null 14 | } -------------------------------------------------------------------------------- /OpenTokTest/Data/ArchiveTests/StartArchiveCustomLayout-response.json: -------------------------------------------------------------------------------- 1 | { 2 | "createdAt": 1395183243556, 3 | "duration": 0, 4 | "id": "30b3ebf1-ba36-4f5b-8def-6f70d9986fe9", 5 | "name": "", 6 | "outputMode": "composed", 7 | "resolution": "1280x720", 8 | "partnerId": 123456, 9 | "reason": "", 10 | "sessionId": "1_MX4xMjM0NTZ-flNhdCBNYXIgMTUgMTQ6NDI6MjMgUERUIDIwMTR-MC40OTAxMzAyNX4", 11 | "size": 0, 12 | "status": "started", 13 | "url": null 14 | } -------------------------------------------------------------------------------- /OpenTokTest/Data/ArchiveTests/StartArchiveCustomLayoutMissingStylesheet-response.json: -------------------------------------------------------------------------------- 1 | { 2 | "createdAt": 1395183243556, 3 | "duration": 0, 4 | "id": "30b3ebf1-ba36-4f5b-8def-6f70d9986fe9", 5 | "name": "", 6 | "outputMode": "composed", 7 | "resolution": "1280x720", 8 | "partnerId": 123456, 9 | "reason": "", 10 | "sessionId": "1_MX4xMjM0NTZ-flNhdCBNYXIgMTUgMTQ6NDI6MjMgUERUIDIwMTR-MC40OTAxMzAyNX4", 11 | "size": 0, 12 | "status": "started", 13 | "url": null 14 | } -------------------------------------------------------------------------------- /OpenTokTest/Data/ArchiveTests/StartArchiveIndividual-response.json: -------------------------------------------------------------------------------- 1 | { 2 | "createdAt": 1395183243556, 3 | "duration": 0, 4 | "id": "30b3ebf1-ba36-4f5b-8def-6f70d9986fe9", 5 | "name": "", 6 | "outputMode": "individual", 7 | "partnerId": 123456, 8 | "reason": "", 9 | "sessionId": "1_MX4xMjM0NTZ-flNhdCBNYXIgMTUgMTQ6NDI6MjMgUERUIDIwMTR-MC40OTAxMzAyNX4", 10 | "size": 0, 11 | "status": "started", 12 | "url": null 13 | } -------------------------------------------------------------------------------- /OpenTokTest/Data/ArchiveTests/StartArchiveManualStreamMode-response.json: -------------------------------------------------------------------------------- 1 | { 2 | "createdAt": 1395183243556, 3 | "duration": 0, 4 | "id": "30b3ebf1-ba36-4f5b-8def-6f70d9986fe9", 5 | "name": "", 6 | "partnerId": 123456, 7 | "reason": "", 8 | "sessionId": "1_MX4xMjM0NTZ-flNhdCBNYXIgMTUgMTQ6NDI6MjMgUERUIDIwMTR-MC40OTAxMzAyNX4", 9 | "size": 0, 10 | "status": "started", 11 | "url": null, 12 | "streamMode": "manual" 13 | } -------------------------------------------------------------------------------- /OpenTokTest/Data/ArchiveTests/StartArchiveNoResolution-response.json: -------------------------------------------------------------------------------- 1 | { 2 | "createdAt": 1395183243556, 3 | "duration": 0, 4 | "id": "30b3ebf1-ba36-4f5b-8def-6f70d9986fe9", 5 | "name": "", 6 | "partnerId": 123456, 7 | "reason": "", 8 | "sessionId": "1_MX4xMjM0NTZ-flNhdCBNYXIgMTUgMTQ6NDI6MjMgUERUIDIwMTR-MC40OTAxMzAyNX4", 9 | "resolution": "640x480", 10 | "size": 0, 11 | "status": "started", 12 | "url": null 13 | } -------------------------------------------------------------------------------- /OpenTokTest/Data/ArchiveTests/StartArchiveVerticalLayout-response.json: -------------------------------------------------------------------------------- 1 | { 2 | "createdAt": 1395183243556, 3 | "duration": 0, 4 | "id": "30b3ebf1-ba36-4f5b-8def-6f70d9986fe9", 5 | "name": "", 6 | "outputMode": "composed", 7 | "resolution": "1280x720", 8 | "partnerId": 123456, 9 | "reason": "", 10 | "sessionId": "1_MX4xMjM0NTZ-flNhdCBNYXIgMTUgMTQ6NDI6MjMgUERUIDIwMTR-MC40OTAxMzAyNX4", 11 | "size": 0, 12 | "status": "started", 13 | "url": null 14 | } -------------------------------------------------------------------------------- /OpenTokTest/Data/ArchiveTests/StartArchiveVerticalLayoutWithStyleSheet-response.json: -------------------------------------------------------------------------------- 1 | { 2 | "createdAt": 1395183243556, 3 | "duration": 0, 4 | "id": "30b3ebf1-ba36-4f5b-8def-6f70d9986fe9", 5 | "name": "", 6 | "outputMode": "composed", 7 | "resolution": "1280x720", 8 | "partnerId": 123456, 9 | "reason": "", 10 | "sessionId": "1_MX4xMjM0NTZ-flNhdCBNYXIgMTUgMTQ6NDI6MjMgUERUIDIwMTR-MC40OTAxMzAyNX4", 11 | "size": 0, 12 | "status": "started", 13 | "url": null 14 | } -------------------------------------------------------------------------------- /OpenTokTest/Data/ArchiveTests/StartArchiveVoiceOnly-response.json: -------------------------------------------------------------------------------- 1 | { 2 | "createdAt": 1395183243556, 3 | "duration": 0, 4 | "id": "30b3ebf1-ba36-4f5b-8def-6f70d9986fe9", 5 | "name": "", 6 | "partnerId": 123456, 7 | "reason": "", 8 | "sessionId": "1_MX4xMjM0NTZ-flNhdCBNYXIgMTUgMTQ6NDI6MjMgUERUIDIwMTR-MC40OTAxMzAyNX4", 9 | "size": 0, 10 | "status": "started", 11 | "url": null, 12 | "hasVideo": false, 13 | "hasAudio": true 14 | } -------------------------------------------------------------------------------- /OpenTokTest/Data/ArchiveTests/StartArchiveWithHDResolution-response.json: -------------------------------------------------------------------------------- 1 | { 2 | "createdAt": 1395183243556, 3 | "duration": 0, 4 | "id": "30b3ebf1-ba36-4f5b-8def-6f70d9986fe9", 5 | "name": "", 6 | "outputMode": "composed", 7 | "resolution": "1280x720", 8 | "partnerId": 123456, 9 | "reason": "", 10 | "sessionId": "1_MX4xMjM0NTZ-flNhdCBNYXIgMTUgMTQ6NDI6MjMgUERUIDIwMTR-MC40OTAxMzAyNX4", 11 | "size": 0, 12 | "status": "started", 13 | "url": null 14 | } -------------------------------------------------------------------------------- /OpenTokTest/Data/ArchiveTests/StartArchiveWithMultiArchiveTag-response.json: -------------------------------------------------------------------------------- 1 | { 2 | "createdAt": 1395183243556, 3 | "duration": 0, 4 | "id": "30b3ebf1-ba36-4f5b-8def-6f70d9986fe9", 5 | "name": "", 6 | "partnerId": 123456, 7 | "reason": "", 8 | "sessionId": "1_MX4xMjM0NTZ-flNhdCBNYXIgMTUgMTQ6NDI6MjMgUERUIDIwMTR-MC40OTAxMzAyNX4", 9 | "size": 0, 10 | "status": "started", 11 | "url": null, 12 | "multiArchiveTag": "TestArchiveTag" 13 | } -------------------------------------------------------------------------------- /OpenTokTest/Data/ArchiveTests/StartArchiveWithMultiArchiveTagAsync-response.json: -------------------------------------------------------------------------------- 1 | { 2 | "createdAt": 1395183243556, 3 | "duration": 0, 4 | "id": "30b3ebf1-ba36-4f5b-8def-6f70d9986fe9", 5 | "name": "", 6 | "partnerId": 123456, 7 | "reason": "", 8 | "sessionId": "1_MX4xMjM0NTZ-flNhdCBNYXIgMTUgMTQ6NDI6MjMgUERUIDIwMTR-MC40OTAxMzAyNX4", 9 | "size": 0, 10 | "status": "started", 11 | "url": null, 12 | "multiArchiveTag": "TestArchiveTag" 13 | } -------------------------------------------------------------------------------- /OpenTokTest/Data/ArchiveTests/StartArchiveWithSDResolution-response.json: -------------------------------------------------------------------------------- 1 | { 2 | "createdAt": 1395183243556, 3 | "duration": 0, 4 | "id": "30b3ebf1-ba36-4f5b-8def-6f70d9986fe9", 5 | "name": "", 6 | "outputMode": "composed", 7 | "resolution": "640x480", 8 | "partnerId": 123456, 9 | "reason": "", 10 | "sessionId": "1_MX4xMjM0NTZ-flNhdCBNYXIgMTUgMTQ6NDI6MjMgUERUIDIwMTR-MC40OTAxMzAyNX4", 11 | "size": 0, 12 | "status": "started", 13 | "url": null 14 | } -------------------------------------------------------------------------------- /OpenTokTest/Data/ArchiveTests/StopArchive-response.json: -------------------------------------------------------------------------------- 1 | { 2 | "createdAt": 1395183243556, 3 | "duration": 0, 4 | "id": "30b3ebf1-ba36-4f5b-8def-6f70d9986fe9", 5 | "name": "", 6 | "partnerId": 123456, 7 | "reason": "", 8 | "sessionId": "SESSIONID", 9 | "size": 0, 10 | "status": "stopped", 11 | "url": null 12 | } -------------------------------------------------------------------------------- /OpenTokTest/Data/ArchiveTests/StopArchiveAsync-response.json: -------------------------------------------------------------------------------- 1 | { 2 | "createdAt": 1395183243556, 3 | "duration": 0, 4 | "id": "30b3ebf1-ba36-4f5b-8def-6f70d9986fe9", 5 | "name": "", 6 | "partnerId": 123456, 7 | "reason": "", 8 | "sessionId": "SESSIONID", 9 | "size": 0, 10 | "status": "stopped", 11 | "url": null 12 | } -------------------------------------------------------------------------------- /OpenTokTest/Data/ArchiveTests/StopArchiveAsyncFromArchiveObject-response.json: -------------------------------------------------------------------------------- 1 | { 2 | "createdAt": 1395183243556, 3 | "duration": 0, 4 | "id": "30b3ebf1-ba36-4f5b-8def-6f70d9986fe9", 5 | "name": "", 6 | "partnerId": 123456, 7 | "reason": "", 8 | "sessionId": "SESSIONID", 9 | "size": 0, 10 | "status": "stopped", 11 | "url": null 12 | } -------------------------------------------------------------------------------- /OpenTokTest/Data/ArchiveTests/StopArchiveFromArchiveObject-response.json: -------------------------------------------------------------------------------- 1 | { 2 | "createdAt": 1395183243556, 3 | "duration": 0, 4 | "id": "30b3ebf1-ba36-4f5b-8def-6f70d9986fe9", 5 | "name": "", 6 | "partnerId": 123456, 7 | "reason": "", 8 | "sessionId": "SESSIONID", 9 | "size": 0, 10 | "status": "stopped", 11 | "url": null 12 | } -------------------------------------------------------------------------------- /OpenTokTest/Data/BroadcastTests/GetBroadcast-response.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "30b3ebf1-ba36-4f5b-8def-6f70d9986fe9", 3 | "sessionId": "SESSIONID", 4 | "projectId": 123456, 5 | "createdAt": 1395183243556, 6 | "updatedAt": 1395183243556, 7 | "resolution": "640x480", 8 | "status": "started", 9 | "broadcastUrls": { 10 | "hls": "http://server/fakepath/playlist.m3u8", 11 | "hlsStatus" : "ready" 12 | } 13 | } -------------------------------------------------------------------------------- /OpenTokTest/Data/BroadcastTests/GetBroadcastAsync-response.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "30b3ebf1-ba36-4f5b-8def-6f70d9986fe9", 3 | "sessionId": "SESSIONID", 4 | "projectId": 123456, 5 | "createdAt": 1395183243556, 6 | "updatedAt": 1395183243556, 7 | "resolution": "640x480", 8 | "status": "started", 9 | "broadcastUrls": { 10 | "hls": "http://server/fakepath/playlist.m3u8", 11 | "hlsStatus" : "ready" 12 | } 13 | } -------------------------------------------------------------------------------- /OpenTokTest/Data/BroadcastTests/StartBroadcast-response.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "30b3ebf1-ba36-4f5b-8def-6f70d9986fe9", 3 | "sessionId": "SESSIONID", 4 | "projectId": 123456, 5 | "createdAt": 1395183243556, 6 | "updatedAt": 1395183243556, 7 | "resolution": "640x480", 8 | "status": "started", 9 | "broadcastUrls": { 10 | "hls": "http://server/fakepath/playlist.m3u8" 11 | }, 12 | "settings": { "hls": { "lowLatency": false } }, 13 | "maxBitRate": 2000000 14 | } -------------------------------------------------------------------------------- /OpenTokTest/Data/BroadcastTests/StartBroadcastAsync-response.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "30b3ebf1-ba36-4f5b-8def-6f70d9986fe9", 3 | "sessionId": "SESSIONID", 4 | "projectId": 123456, 5 | "createdAt": 1395183243556, 6 | "updatedAt": 1395183243556, 7 | "resolution": "640x480", 8 | "status": "started", 9 | "broadcastUrls": { 10 | "hls": "http://server/fakepath/playlist.m3u8" 11 | }, 12 | "settings": { "hls": { "lowLatency": false } }, 13 | "maxBitRate": 1000000 14 | } -------------------------------------------------------------------------------- /OpenTokTest/Data/BroadcastTests/StartBroadcastOnlyWithRTMP-response.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "30b3ebf1-ba36-4f5b-8def-6f70d9986fe9", 3 | "sessionId": "SESSIONID", 4 | "projectId": 123456, 5 | "createdAt": 1395183243556, 6 | "updatedAt": 1395183243556, 7 | "resolution": "640x480", 8 | "status": "started", 9 | "broadcastUrls": { 10 | "rtmp": [ 11 | { 12 | "status": "connecting", 13 | "id": "foo", 14 | "serverUrl": "rtmp://myfooserver/myfooapp", 15 | "streamName": "myfoostream" 16 | }, 17 | { 18 | "status": "connecting", 19 | "id": "bar", 20 | "serverUrl": "rtmp://mybarserver/mybarapp", 21 | "streamName": "mybarstream" 22 | } 23 | ] 24 | } 25 | } -------------------------------------------------------------------------------- /OpenTokTest/Data/BroadcastTests/StartBroadcastOnlyWithRTMPAsync-response.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "30b3ebf1-ba36-4f5b-8def-6f70d9986fe9", 3 | "sessionId": "SESSIONID", 4 | "projectId": 123456, 5 | "createdAt": 1395183243556, 6 | "updatedAt": 1395183243556, 7 | "resolution": "640x480", 8 | "status": "started", 9 | "broadcastUrls": { 10 | "rtmp": [ 11 | { 12 | "status": "connecting", 13 | "id": "foo", 14 | "serverUrl": "rtmp://myfooserver/myfooapp", 15 | "streamName": "myfoostream" 16 | }, 17 | { 18 | "status": "connecting", 19 | "id": "bar", 20 | "serverUrl": "rtmp://mybarserver/mybarapp", 21 | "streamName": "mybarstream" 22 | } 23 | ] 24 | } 25 | } -------------------------------------------------------------------------------- /OpenTokTest/Data/BroadcastTests/StartBroadcastWithAutoStreamMode-response.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "30b3ebf1-ba36-4f5b-8def-6f70d9986fe9", 3 | "sessionId": "1_MX4xMjM0NTZ-flNhdCBNYXIgMTUgMTQ6NDI6MjMgUERUIDIwMTR-MC40OTAxMzAyNX4", 4 | "projectId": 123456, 5 | "createdAt": 1395183243556, 6 | "updatedAt": 1395183243556, 7 | "resolution": "640x480", 8 | "status": "started", 9 | "streamMode": "auto", 10 | "broadcastUrls": { 11 | "hls": "http://server/fakepath/playlist.m3u8" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /OpenTokTest/Data/BroadcastTests/StartBroadcastWithAutoStreamModeAsync-response.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "30b3ebf1-ba36-4f5b-8def-6f70d9986fe9", 3 | "sessionId": "1_MX4xMjM0NTZ-flNhdCBNYXIgMTUgMTQ6NDI6MjMgUERUIDIwMTR-MC40OTAxMzAyNX4", 4 | "projectId": 123456, 5 | "createdAt": 1395183243556, 6 | "updatedAt": 1395183243556, 7 | "resolution": "640x480", 8 | "status": "started", 9 | "streamMode": "auto", 10 | "broadcastUrls": { 11 | "hls": "http://server/fakepath/playlist.m3u8" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /OpenTokTest/Data/BroadcastTests/StartBroadcastWithDvr-response.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "30b3ebf1-ba36-4f5b-8def-6f70d9986fe9", 3 | "sessionId": "SESSIONID", 4 | "projectId": 123456, 5 | "createdAt": 1395183243556, 6 | "updatedAt": 1395183243556, 7 | "resolution": "640x480", 8 | "status": "started", 9 | "broadcastUrls": { 10 | "hls": "http://server/fakepath/playlist.m3u8" 11 | }, 12 | "settings": { "hls": { "lowLatency": false } } 13 | } -------------------------------------------------------------------------------- /OpenTokTest/Data/BroadcastTests/StartBroadcastWithDvrAsync-response.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "30b3ebf1-ba36-4f5b-8def-6f70d9986fe9", 3 | "sessionId": "SESSIONID", 4 | "projectId": 123456, 5 | "createdAt": 1395183243556, 6 | "updatedAt": 1395183243556, 7 | "resolution": "640x480", 8 | "status": "started", 9 | "broadcastUrls": { 10 | "hls": "http://server/fakepath/playlist.m3u8" 11 | }, 12 | "settings": { "hls": { "lowLatency": false } } 13 | } -------------------------------------------------------------------------------- /OpenTokTest/Data/BroadcastTests/StartBroadcastWithHDResolution-response.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "30b3ebf1-ba36-4f5b-8def-6f70d9986fe9", 3 | "sessionId": "SESSIONID", 4 | "projectId": 123456, 5 | "createdAt": 1395183243556, 6 | "updatedAt": 1395183243556, 7 | "resolution": "1280x720", 8 | "status": "started", 9 | "broadcastUrls": { 10 | "hls": "http://server/fakepath/playlist.m3u8" 11 | } 12 | } -------------------------------------------------------------------------------- /OpenTokTest/Data/BroadcastTests/StartBroadcastWithHDResolutionAsync-response.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "30b3ebf1-ba36-4f5b-8def-6f70d9986fe9", 3 | "sessionId": "SESSIONID", 4 | "projectId": 123456, 5 | "createdAt": 1395183243556, 6 | "updatedAt": 1395183243556, 7 | "resolution": "1280x720", 8 | "status": "started", 9 | "broadcastUrls": { 10 | "hls": "http://server/fakepath/playlist.m3u8" 11 | } 12 | } -------------------------------------------------------------------------------- /OpenTokTest/Data/BroadcastTests/StartBroadcastWithLowLatency-response.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "30b3ebf1-ba36-4f5b-8def-6f70d9986fe9", 3 | "sessionId": "SESSIONID", 4 | "projectId": 123456, 5 | "createdAt": 1395183243556, 6 | "updatedAt": 1395183243556, 7 | "resolution": "640x480", 8 | "status": "started", 9 | "broadcastUrls": { 10 | "hls": "http://server/fakepath/playlist.m3u8" 11 | }, 12 | "settings": { "hls": { "lowLatency": true } } 13 | } -------------------------------------------------------------------------------- /OpenTokTest/Data/BroadcastTests/StartBroadcastWithLowLatencyAsync-response.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "30b3ebf1-ba36-4f5b-8def-6f70d9986fe9", 3 | "sessionId": "SESSIONID", 4 | "projectId": 123456, 5 | "createdAt": 1395183243556, 6 | "updatedAt": 1395183243556, 7 | "resolution": "640x480", 8 | "status": "started", 9 | "broadcastUrls": { 10 | "hls": "http://server/fakepath/playlist.m3u8" 11 | }, 12 | "settings": { "hls": { "lowLatency": true } } 13 | } -------------------------------------------------------------------------------- /OpenTokTest/Data/BroadcastTests/StartBroadcastWithManualStreamMode-response.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "30b3ebf1-ba36-4f5b-8def-6f70d9986fe9", 3 | "sessionId": "1_MX4xMjM0NTZ-flNhdCBNYXIgMTUgMTQ6NDI6MjMgUERUIDIwMTR-MC40OTAxMzAyNX4", 4 | "projectId": 123456, 5 | "createdAt": 1395183243556, 6 | "updatedAt": 1395183243556, 7 | "resolution": "640x480", 8 | "status": "started", 9 | "streamMode": "manual", 10 | "broadcastUrls": { 11 | "hls": "http://server/fakepath/playlist.m3u8" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /OpenTokTest/Data/BroadcastTests/StartBroadcastWithManualStreamModeAsync-response.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "30b3ebf1-ba36-4f5b-8def-6f70d9986fe9", 3 | "sessionId": "1_MX4xMjM0NTZ-flNhdCBNYXIgMTUgMTQ6NDI6MjMgUERUIDIwMTR-MC40OTAxMzAyNX4", 4 | "projectId": 123456, 5 | "createdAt": 1395183243556, 6 | "updatedAt": 1395183243556, 7 | "resolution": "640x480", 8 | "status": "started", 9 | "streamMode": "manual", 10 | "broadcastUrls": { 11 | "hls": "http://server/fakepath/playlist.m3u8" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /OpenTokTest/Data/BroadcastTests/StartBroadcastWithMultiBroadcastTag-response.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "30b3ebf1-ba36-4f5b-8def-6f70d9986fe9", 3 | "sessionId": "SESSIONID", 4 | "projectId": 123456, 5 | "createdAt": 1395183243556, 6 | "updatedAt": 1395183243556, 7 | "resolution": "640x480", 8 | "status": "started", 9 | "broadcastUrls": { 10 | "hls": "http://server/fakepath/playlist.m3u8" 11 | }, 12 | "settings": { "hls": { "lowLatency": false } }, 13 | "multiBroadcastTag": "TestBroadcastTag" 14 | } -------------------------------------------------------------------------------- /OpenTokTest/Data/BroadcastTests/StartBroadcastWithRTMPandHLS-response.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "30b3ebf1-ba36-4f5b-8def-6f70d9986fe9", 3 | "sessionId": "SESSIONID", 4 | "projectId": 123456, 5 | "createdAt": 1395183243556, 6 | "updatedAt": 1395183243556, 7 | "resolution": "640x480", 8 | "status": "started", 9 | "broadcastUrls": { 10 | "hls": "http://server/fakepath/playlist.m3u8", 11 | "hlsStatus" : "ready", 12 | "rtmp": [ 13 | { 14 | "status": "connecting", 15 | "id": "foo", 16 | "serverUrl": "rtmp://myfooserver/myfooapp", 17 | "streamName": "myfoostream" 18 | }, 19 | { 20 | "status": "connecting", 21 | "id": "bar", 22 | "serverUrl": "rtmp://mybarserver/mybarapp", 23 | "streamName": "mybarstream" 24 | } 25 | ] 26 | } 27 | } -------------------------------------------------------------------------------- /OpenTokTest/Data/BroadcastTests/StartBroadcastWithRTMPandHLSAsync-response.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "30b3ebf1-ba36-4f5b-8def-6f70d9986fe9", 3 | "sessionId": "SESSIONID", 4 | "projectId": 123456, 5 | "createdAt": 1395183243556, 6 | "updatedAt": 1395183243556, 7 | "resolution": "640x480", 8 | "status": "started", 9 | "broadcastUrls": { 10 | "hls": "http://server/fakepath/playlist.m3u8", 11 | "hlsStatus" : "ready", 12 | "rtmp": [ 13 | { 14 | "status": "connecting", 15 | "id": "foo", 16 | "serverUrl": "rtmp://myfooserver/myfooapp", 17 | "streamName": "myfoostream" 18 | }, 19 | { 20 | "status": "connecting", 21 | "id": "bar", 22 | "serverUrl": "rtmp://mybarserver/mybarapp", 23 | "streamName": "mybarstream" 24 | } 25 | ] 26 | } 27 | } -------------------------------------------------------------------------------- /OpenTokTest/Data/BroadcastTests/StartBroadcastWithSDResolution-response.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "30b3ebf1-ba36-4f5b-8def-6f70d9986fe9", 3 | "sessionId": "SESSIONID", 4 | "projectId": 123456, 5 | "createdAt": 1395183243556, 6 | "updatedAt": 1395183243556, 7 | "resolution": "640x480", 8 | "status": "started", 9 | "broadcastUrls": { 10 | "hls": "http://server/fakepath/playlist.m3u8" 11 | } 12 | } -------------------------------------------------------------------------------- /OpenTokTest/Data/BroadcastTests/StartBroadcastWithSDResolutionAsync-response.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "30b3ebf1-ba36-4f5b-8def-6f70d9986fe9", 3 | "sessionId": "SESSIONID", 4 | "projectId": 123456, 5 | "createdAt": 1395183243556, 6 | "updatedAt": 1395183243556, 7 | "resolution": "640x480", 8 | "status": "started", 9 | "broadcastUrls": { 10 | "hls": "http://server/fakepath/playlist.m3u8" 11 | } 12 | } -------------------------------------------------------------------------------- /OpenTokTest/Data/BroadcastTests/StartBroadcastWithScreenShareType-response.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "30b3ebf1-ba36-4f5b-8def-6f70d9986fe9", 3 | "sessionId": "SESSIONID", 4 | "projectId": 123456, 5 | "createdAt": 1395183243556, 6 | "updatedAt": 1395183243556, 7 | "resolution": "640x480", 8 | "status": "started", 9 | "broadcastUrls": { 10 | "hls": "http://server/fakepath/playlist.m3u8" 11 | } 12 | } -------------------------------------------------------------------------------- /OpenTokTest/Data/BroadcastTests/StartBroadcastWithScreenShareTypeAsync-response.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "30b3ebf1-ba36-4f5b-8def-6f70d9986fe9", 3 | "sessionId": "SESSIONID", 4 | "projectId": 123456, 5 | "createdAt": 1395183243556, 6 | "updatedAt": 1395183243556, 7 | "resolution": "640x480", 8 | "status": "started", 9 | "broadcastUrls": { 10 | "hls": "http://server/fakepath/playlist.m3u8" 11 | } 12 | } -------------------------------------------------------------------------------- /OpenTokTest/Data/BroadcastTests/StopBroadcast-response.json: -------------------------------------------------------------------------------- 1 | { 2 | "id" : "30b3ebf1-ba36-4f5b-8def-6f70d9986fe9", 3 | "sessionId" : "SESSIONID", 4 | "projectId" : 123456, 5 | "createdAt" : 1395183243556, 6 | "updatedAt" : 1395183243556, 7 | "resolution" : "640x480", 8 | "broadcastUrls": null 9 | } -------------------------------------------------------------------------------- /OpenTokTest/Data/BroadcastTests/StopBroadcastAsync-response.json: -------------------------------------------------------------------------------- 1 | { 2 | "id" : "30b3ebf1-ba36-4f5b-8def-6f70d9986fe9", 3 | "sessionId" : "SESSIONID", 4 | "projectId" : 123456, 5 | "createdAt" : 1395183243556, 6 | "updatedAt" : 1395183243556, 7 | "resolution" : "640x480", 8 | "broadcastUrls": null 9 | } -------------------------------------------------------------------------------- /OpenTokTest/Data/DialTests/DialAsyncCorrectHeaders-response.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "a0a5a8c7-dc38-459f-a48d-a7f2008da853", 3 | "connectionId": "b9f8c166-6c67-440d-994a-04fb6dfed007", 4 | "streamId": "182bce73-f882-40fd-8ca5-cb74ff416036" 5 | } -------------------------------------------------------------------------------- /OpenTokTest/Data/DialTests/DialAsyncCorrectResponse-response.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "a0a5a8c7-dc38-459f-a48d-a7f2008da853", 3 | "connectionId": "b9f8c166-6c67-440d-994a-04fb6dfed007", 4 | "streamId": "182bce73-f882-40fd-8ca5-cb74ff416036" 5 | } -------------------------------------------------------------------------------- /OpenTokTest/Data/DialTests/DialCorrectData-response.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "b0a5a8c7-dc38-459f-a48d-a7f2008da853", 3 | "connectionId": "e9f8c166-6c67-440d-994a-04fb6dfed007", 4 | "streamId": "482bce73-f882-40fd-8ca5-cb74ff416036" 5 | } 6 | -------------------------------------------------------------------------------- /OpenTokTest/Data/DialTests/DialCorrectHeaders-response.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "b0a5a8c7-dc38-459f-a48d-a7f2008da853", 3 | "connectionId": "e9f8c166-6c67-440d-994a-04fb6dfed007", 4 | "streamId": "482bce73-f882-40fd-8ca5-cb74ff416036" 5 | } 6 | -------------------------------------------------------------------------------- /OpenTokTest/Data/DialTests/DialCorrectResponse-response.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "b0a5a8c7-dc38-459f-a48d-a7f2008da853", 3 | "connectionId": "e9f8c166-6c67-440d-994a-04fb6dfed007", 4 | "streamId": "482bce73-f882-40fd-8ca5-cb74ff416036" 5 | } 6 | -------------------------------------------------------------------------------- /OpenTokTest/Data/StreamTests/GetStream-response.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "$streamId$", 3 | "name": "johndoe", 4 | "layoutClassList": [ "asdf" ], 5 | "videoType": "screen" 6 | } -------------------------------------------------------------------------------- /OpenTokTest/Data/StreamTests/GetStreamAsync-response.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "$streamId$", 3 | "name": "johndoe", 4 | "layoutClassList": [ "asdf" ], 5 | "videoType": "screen" 6 | } -------------------------------------------------------------------------------- /OpenTokTest/Data/StreamTests/GetStreamAsyncEmpty-response.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "$streamId$", 3 | "name": "johndoe", 4 | "layoutClassList": [], 5 | "videoType": "screen" 6 | } -------------------------------------------------------------------------------- /OpenTokTest/Data/StreamTests/GetStreamEmpty-response.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "$streamId$", 3 | "name": "johndoe", 4 | "layoutClassList": [ ], 5 | "videoType": "screen" 6 | } -------------------------------------------------------------------------------- /OpenTokTest/Data/StreamTests/ListStreams-response.json: -------------------------------------------------------------------------------- 1 | { 2 | "count": 2, 3 | "items": [ 4 | { 5 | "id": "ef546c5a-4fd7-4e59-ab3d-f1cfb4148d1d", 6 | "name": "johndoe", 7 | "layoutClassList": [ "layout1" ], 8 | "videoType": "screen" 9 | }, 10 | { 11 | "createdAt": 1394321113000, 12 | "duration": 1294, 13 | "id": "1f546c5a-4fd7-4e59-ab3d-f1cfb4148d1d", 14 | "name": "janedoe", 15 | "layoutClassList": [ "layout2" ], 16 | "videoType": "camera" 17 | } 18 | ] 19 | } -------------------------------------------------------------------------------- /OpenTokTest/Data/StreamTests/ListStreamsAsync-response.json: -------------------------------------------------------------------------------- 1 | { 2 | "count": 2, 3 | "items": [ 4 | { 5 | "id": "ef546c5a-4fd7-4e59-ab3d-f1cfb4148d1d", 6 | "name": "johndoe", 7 | "layoutClassList": [ "layout1" ], 8 | "videoType": "screen" 9 | }, 10 | { 11 | "createdAt": 1394321113000, 12 | "duration": 1294, 13 | "id": "1f546c5a-4fd7-4e59-ab3d-f1cfb4148d1d", 14 | "name": "janedoe", 15 | "layoutClassList": [ "layout2" ], 16 | "videoType": "camera" 17 | } 18 | ] 19 | } -------------------------------------------------------------------------------- /OpenTokTest/OpenTok.AudioConnectorTests.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using System.Threading.Tasks; 4 | using AutoFixture; 5 | using Moq; 6 | using Newtonsoft.Json; 7 | using OpenTokSDK; 8 | using OpenTokSDK.Util; 9 | using Xunit; 10 | 11 | namespace OpenTokSDKTest 12 | { 13 | public class OpenTokAudioConnectorTests 14 | { 15 | private readonly int apiKey; 16 | private readonly Fixture fixture; 17 | private readonly Mock mockClient; 18 | private readonly OpenTok sut; 19 | 20 | public OpenTokAudioConnectorTests() 21 | { 22 | this.fixture = new Fixture(); 23 | this.fixture.Customize(new SupportMutableValueTypesCustomization()); 24 | this.apiKey = this.fixture.Create(); 25 | this.mockClient = new Mock(); 26 | this.sut = new OpenTok(this.apiKey, this.fixture.Create()) 27 | { 28 | Client = this.mockClient.Object, 29 | }; 30 | } 31 | 32 | [Fact] 33 | public async Task ConnectAsync_ShouldReturnResponse() 34 | { 35 | const string contentTypeKey = "Content-Type"; 36 | const string contentType = "application/json"; 37 | var expectedUrl = $"v2/project/{this.apiKey}/connect"; 38 | var expectedResponse = this.fixture.Create(); 39 | var serializedResponse = JsonConvert.SerializeObject(expectedResponse); 40 | var request = AudioConnectorStartRequestDataBuilder.Build().Create(); 41 | this.mockClient.Setup(httpClient => httpClient.PostAsync( 42 | expectedUrl, 43 | It.Is>(dictionary => 44 | dictionary.ContainsKey(contentTypeKey) && dictionary[contentTypeKey] == contentType), 45 | It.Is>(dictionary => 46 | dictionary.SequenceEqual(request.ToDataDictionary())))) 47 | .ReturnsAsync(serializedResponse); 48 | var response = await this.sut.StartAudioConnectorAsync(request); 49 | Assert.Equal(expectedResponse, response); 50 | } 51 | 52 | [Fact] 53 | public async Task StopAsync_ShouldStopConnection() 54 | { 55 | var connectionId = this.fixture.Create(); 56 | var expectedUrl = $"v2/project/{this.apiKey}/connect/{connectionId}/stop"; 57 | await this.sut.StopAudioConnectorAsync(connectionId); 58 | this.mockClient.Verify(httpClient => httpClient.PostAsync( 59 | expectedUrl, 60 | It.Is>(dictionary => !dictionary.Any()), 61 | It.Is>(dictionary => !dictionary.Any())), 62 | Times.Once); 63 | } 64 | } 65 | } -------------------------------------------------------------------------------- /OpenTokTest/OpenTok.CaptionsTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using AutoFixture; 6 | using Moq; 7 | using Newtonsoft.Json; 8 | using OpenTokSDK; 9 | using OpenTokSDK.Util; 10 | using Xunit; 11 | 12 | namespace OpenTokSDKTest 13 | { 14 | public class OpenTokCaptionsTests 15 | { 16 | private readonly int apiKey; 17 | private readonly Mock mockClient; 18 | private readonly OpenTok sut; 19 | 20 | public OpenTokCaptionsTests() 21 | { 22 | var fixture = new Fixture(); 23 | this.apiKey = fixture.Create(); 24 | this.mockClient = new Mock(); 25 | this.sut = new OpenTok(this.apiKey, fixture.Create()) 26 | { 27 | Client = this.mockClient.Object, 28 | }; 29 | } 30 | 31 | [Fact] 32 | public async Task StartLiveCaptionsAsync_ShouldReturnResponse() 33 | { 34 | const string contentTypeKey = "Content-Type"; 35 | const string contentType = "application/json"; 36 | var expectedUrl = $"v2/project/{this.apiKey}/captions"; 37 | var expectedResponse = new Caption {CaptionsId = Guid.NewGuid()}; 38 | var serializedResponse = JsonConvert.SerializeObject(expectedResponse); 39 | var request = CaptionOptions.Build("sessionId", "token"); 40 | this.mockClient.Setup(httpClient => httpClient.PostAsync( 41 | expectedUrl, 42 | It.Is>(dictionary => 43 | dictionary.ContainsKey(contentTypeKey) && dictionary[contentTypeKey] == contentType), 44 | It.Is>(dictionary => 45 | dictionary.SequenceEqual(request.ToDataDictionary())))) 46 | .ReturnsAsync(serializedResponse); 47 | var response = await this.sut.StartLiveCaptionsAsync(request); 48 | Assert.Equal(expectedResponse, response); 49 | } 50 | 51 | [Fact] 52 | public async Task StopLiveCaptionsAsync_ShouldReturnResponse() 53 | { 54 | const string contentTypeKey = "Content-Type"; 55 | const string contentType = "application/json"; 56 | var captionId = Guid.NewGuid(); 57 | var expectedUrl = $"v2/project/{this.apiKey}/captions/{captionId}/stop"; 58 | await this.sut.StopLiveCaptionsAsync(captionId); 59 | this.mockClient.Verify(httpClient => httpClient.PostAsync( 60 | expectedUrl, 61 | It.Is>(dictionary => 62 | dictionary.ContainsKey(contentTypeKey) && dictionary[contentTypeKey] == contentType), 63 | It.Is>(dictionary => !dictionary.Any())), Times.Once); 64 | } 65 | } 66 | } -------------------------------------------------------------------------------- /OpenTokTest/OpenTokTests.cs: -------------------------------------------------------------------------------- 1 | using AutoFixture; 2 | using OpenTokSDK; 3 | using Xunit; 4 | 5 | namespace OpenTokSDKTest 6 | { 7 | public class OpenTokTests 8 | { 9 | [Fact] 10 | public void SetCustomUserAgent_ShouldSetUserAgentOnClient() 11 | { 12 | var fixture = new Fixture(); 13 | var customUserAgent = fixture.Create(); 14 | var sut = new OpenTok(fixture.Create(), fixture.Create()); 15 | sut.SetCustomUserAgent(customUserAgent); 16 | Assert.Equal(customUserAgent, sut.Client.CustomUserAgent); 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /OpenTokTest/Render/ListRendersRequestTests.cs: -------------------------------------------------------------------------------- 1 | using OpenTokSDK.Exception; 2 | using OpenTokSDK.Render; 3 | using Xunit; 4 | 5 | namespace OpenTokSDKTest.Render 6 | { 7 | public class ListRendersRequestTests 8 | { 9 | [Fact] 10 | public void ListRendersRequest_ShouldThrowOpenTokException_GivenCountIsHigherThanThreshold() 11 | { 12 | void Act() => new ListRendersRequest(1001); 13 | var exception = Assert.Throws(Act); 14 | Assert.Equal(ListRendersRequest.CountExceeded, exception.Message); 15 | } 16 | 17 | [Fact] 18 | public void ListRendersRequest_ShouldThrowOpenTokException_GivenCountIsNegative() 19 | { 20 | void Act() => new ListRendersRequest(-1); 21 | var exception = Assert.Throws(Act); 22 | Assert.Equal(ListRendersRequest.NegativeCount, exception.Message); 23 | } 24 | 25 | [Fact] 26 | public void ListRendersRequest_ShouldThrowOpenTokException_GivenOffsetIsNegative() 27 | { 28 | void Act() => new ListRendersRequest(-1, 1); 29 | var exception = Assert.Throws(Act); 30 | Assert.Equal(ListRendersRequest.NegativeOffset, exception.Message); 31 | } 32 | 33 | [Theory] 34 | [InlineData(0, 0)] 35 | public void ListRendersRequest_ShouldReturnInstance(int offset, int count) 36 | { 37 | var request = new ListRendersRequest(offset, count); 38 | Assert.Equal(offset, request.Offset); 39 | Assert.Equal(count, request.Count); 40 | } 41 | 42 | [Theory] 43 | [InlineData(0)] 44 | [InlineData(1000)] 45 | public void ListRendersRequest_ShouldReturnInstance_GivenOnlyCountIsProvided(int count) 46 | { 47 | var request = new ListRendersRequest(count); 48 | Assert.Null(request.Offset); 49 | Assert.Equal(count, request.Count); 50 | } 51 | 52 | [Fact] 53 | public void ListRendersRequest_ShouldHaveDefaultCount() 54 | { 55 | var request = new ListRendersRequest(); 56 | Assert.Null(request.Offset); 57 | Assert.Equal(50, request.Count); 58 | } 59 | } 60 | } -------------------------------------------------------------------------------- /OpenTokTest/Render/StartRenderRequestDataBuilder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using AutoFixture; 3 | using OpenTokSDK.Render; 4 | 5 | namespace OpenTokSDKTest.Render 6 | { 7 | public class StartRenderRequestDataBuilder 8 | { 9 | private int? maxDuration; 10 | private RenderResolution? resolution; 11 | private string sessionId; 12 | private string streamName; 13 | private string token; 14 | private Uri url; 15 | private StartRenderRequest.PublisherProperties properties; 16 | 17 | private StartRenderRequestDataBuilder() 18 | { 19 | var fixture = new Fixture(); 20 | this.sessionId = fixture.Create(); 21 | this.token = fixture.Create(); 22 | this.url = fixture.Create(); 23 | this.maxDuration = default; 24 | this.resolution = default; 25 | this.streamName = fixture.Create(); 26 | this.properties = default; 27 | } 28 | 29 | public static StartRenderRequestDataBuilder Build() => new StartRenderRequestDataBuilder(); 30 | 31 | public StartRenderRequestDataBuilder WithSessionId(string value) 32 | { 33 | this.sessionId = value; 34 | return this; 35 | } 36 | 37 | public StartRenderRequestDataBuilder WithToken(string value) 38 | { 39 | this.token = value; 40 | return this; 41 | } 42 | 43 | public StartRenderRequestDataBuilder WithUrl(Uri value) 44 | { 45 | this.url = value; 46 | return this; 47 | } 48 | 49 | public StartRenderRequestDataBuilder WithResolution(RenderResolution? value) 50 | { 51 | this.resolution = value; 52 | return this; 53 | } 54 | 55 | public StartRenderRequest Create() => 56 | new StartRenderRequest( 57 | this.sessionId, 58 | this.token, 59 | this.url, 60 | this.maxDuration ?? default, 61 | this.resolution ?? default, 62 | this.properties); 63 | 64 | public StartRenderRequestDataBuilder WithMaxDuration(int? value) 65 | { 66 | this.maxDuration = value; 67 | return this; 68 | } 69 | 70 | public StartRenderRequestDataBuilder WithProperties(StartRenderRequest.PublisherProperties value) 71 | { 72 | this.properties = value; 73 | return this; 74 | } 75 | } 76 | } -------------------------------------------------------------------------------- /OpenTokTest/TestBase.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Reflection; 5 | using System.Runtime.CompilerServices; 6 | using System.Text.RegularExpressions; 7 | 8 | namespace OpenTokSDKTest 9 | { 10 | public abstract class TestBase 11 | { 12 | protected string ApiSecret = "1234567890abcdef1234567890abcdef1234567890"; 13 | protected int ApiKey = 123456; 14 | protected string SessionId = "1_MX4xMjM0NTZ-flNhdCBNYXIgMTUgMTQ6NDI6MjMgUERUIDIwMTR-MC40OTAxMzAyNX4"; 15 | protected string ApplicationId = "123"; 16 | protected string PrivateKey = "456"; 17 | 18 | #if NETCOREAPP2_0_OR_GREATER 19 | private static readonly Assembly ThisAssembly = typeof(TestBase).GetTypeInfo().Assembly; 20 | #else 21 | private static readonly Assembly ThisAssembly = typeof(TestBase).Assembly; 22 | #endif 23 | 24 | private static readonly string TestAssemblyName = ThisAssembly.GetName().Name; 25 | 26 | private static string AssemblyDirectory 27 | { 28 | get 29 | { 30 | string codeBase = ThisAssembly.CodeBase; 31 | UriBuilder uri = new UriBuilder(codeBase); 32 | string path = Uri.UnescapeDataString(uri.Path); 33 | return Path.GetDirectoryName(path); 34 | } 35 | } 36 | 37 | protected string GetResponseJson([CallerMemberName] string name = null) 38 | { 39 | return ReadDataFile(name, "json"); 40 | } 41 | 42 | static readonly Regex ResponseTokenRegex = new Regex(@"\$(\w+)\$", RegexOptions.Compiled); 43 | 44 | protected string GetResponseJson(Dictionary paramters, [CallerMemberName] string name = null) 45 | { 46 | var response = GetResponseJson(name); 47 | response = ResponseTokenRegex.Replace(response, match => paramters[match.Groups[1].Value]); 48 | return response; 49 | } 50 | 51 | protected string GetResponseXml([CallerMemberName] string name = null) 52 | { 53 | return ReadDataFile(name, "xml"); 54 | } 55 | 56 | private string ReadDataFile(string testName, string fileExtension) 57 | { 58 | testName = $"{testName}-response"; 59 | 60 | var type = GetType().Name; 61 | var ns = GetType().Namespace; 62 | if (ns != null) 63 | { 64 | var path = Path.Combine(AssemblyDirectory, "Data", type, $"{testName}.{fileExtension}"); 65 | 66 | if (!File.Exists(path)) 67 | { 68 | throw new FileNotFoundException($"File not found at {path}."); 69 | } 70 | 71 | var jsonContent = File.ReadAllText(path); 72 | jsonContent = Regex.Replace(jsonContent, "(\"(?:[^\"\\\\]|\\\\.)*\")|\\s+", "$1"); 73 | return jsonContent; 74 | } 75 | 76 | return string.Empty; 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /OpenTokTest/app.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /Samples/Archiving/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Samples/Archiving/App.config.sample: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /Samples/Archiving/Archiving.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Archiving 5 | 1.0.0 6 | net481 7 | Vonage 8 | Vonage 9 | Copyright © 2020 10 | Exe 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | Always 43 | 44 | 45 | Always 46 | 47 | 48 | Always 49 | 50 | 51 | Always 52 | 53 | 54 | Always 55 | 56 | 57 | Always 58 | 59 | 60 | Always 61 | 62 | 63 | Always 64 | 65 | 66 | Always 67 | 68 | 69 | Always 70 | 71 | 72 | Always 73 | 74 | 75 | Always 76 | 77 | 78 | Always 79 | 80 | 81 | 82 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /Samples/Archiving/Bootstrapper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | using Nancy; 7 | 8 | namespace Archiving 9 | { 10 | public class Bootstrapper : DefaultNancyBootstrapper 11 | { 12 | protected override void ConfigureApplicationContainer(Nancy.TinyIoc.TinyIoCContainer container) 13 | { 14 | base.ConfigureApplicationContainer(container); 15 | 16 | container.Register().AsSingleton(); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Samples/Archiving/Content/css/sample.css: -------------------------------------------------------------------------------- 1 | /* Move down content because we have a fixed navbar that is 50px tall */ 2 | body { 3 | padding-top: 50px; 4 | padding-bottom: 20px; 5 | background-color: #F2F2F2; 6 | } 7 | 8 | /* Responsive: Portrait tablets and up */ 9 | @media screen and (min-width: 768px) { 10 | /* Remove padding from wrapping element since we kick in the grid classes here */ 11 | .body-content { 12 | padding: 0; 13 | } 14 | } 15 | 16 | #subscribers div { 17 | float: left; 18 | } 19 | 20 | .bump-me { 21 | padding-top: 40px; 22 | } -------------------------------------------------------------------------------- /Samples/Archiving/Content/img/archiving-off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opentok/Opentok-.NET-SDK/25f7185a0aa34e561c14e3e4a5041a236813326d/Samples/Archiving/Content/img/archiving-off.png -------------------------------------------------------------------------------- /Samples/Archiving/Content/img/archiving-on-idle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opentok/Opentok-.NET-SDK/25f7185a0aa34e561c14e3e4a5041a236813326d/Samples/Archiving/Content/img/archiving-on-idle.png -------------------------------------------------------------------------------- /Samples/Archiving/Content/img/archiving-on-message.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opentok/Opentok-.NET-SDK/25f7185a0aa34e561c14e3e4a5041a236813326d/Samples/Archiving/Content/img/archiving-on-message.png -------------------------------------------------------------------------------- /Samples/Archiving/Content/js/host.js: -------------------------------------------------------------------------------- 1 | var session = OT.initSession(apiKey, sessionId), 2 | publisher = OT.initPublisher('publisher'), 3 | archiveID = null; 4 | 5 | session.connect(token, function(error) { 6 | if (error) { 7 | console.error('Failed to connect', error); 8 | } else { 9 | session.publish(publisher, function(error) { 10 | if (error) { 11 | console.error('Failed to publish', error); 12 | } 13 | }); 14 | } 15 | }); 16 | 17 | session.on('streamCreated', function(event) { 18 | session.subscribe(event.stream, 'subscribers', { 19 | insertMode: 'append' 20 | }, function(error) { 21 | if (error) { 22 | console.error('Failed to subscribe', error); 23 | } 24 | }); 25 | }); 26 | 27 | session.on('archiveStarted', function(event) { 28 | archiveID = event.id; 29 | console.log('ARCHIVE STARTED'); 30 | $('.start').hide(); 31 | $('.stop').show(); 32 | disableForm(); 33 | }); 34 | 35 | session.on('archiveStopped', function(event) { 36 | archiveID = null; 37 | console.log('ARCHIVE STOPPED'); 38 | $('.start').show(); 39 | $('.stop').hide(); 40 | enableForm(); 41 | }); 42 | 43 | $(document).ready(function() { 44 | $('.start').click(function(event) { 45 | var options = $('.archive-options').serialize(); 46 | disableForm(); 47 | $.post('/start', options).fail(enableForm); 48 | }).show(); 49 | $('.stop').click(function(event){ 50 | $.get('stop/' + archiveID); 51 | }).hide(); 52 | }); 53 | 54 | 55 | function disableForm() { 56 | $('.archive-options-fields').attr('disabled', 'disabled'); 57 | } 58 | 59 | function enableForm() { 60 | $('.archive-options-fields').removeAttr('disabled'); 61 | } 62 | -------------------------------------------------------------------------------- /Samples/Archiving/Content/js/participant.js: -------------------------------------------------------------------------------- 1 | var session = OT.initSession(apiKey, sessionId), 2 | publisher = OT.initPublisher('publisher'); 3 | 4 | session.connect(token, function(error) { 5 | if (error) { 6 | console.error('Failed to connect', error); 7 | } else { 8 | session.publish(publisher, function(error) { 9 | if (error) { 10 | console.error('Failed to publish', error); 11 | } 12 | }); 13 | } 14 | }); 15 | 16 | session.on('streamCreated', function(event) { 17 | session.subscribe(event.stream, 'subscribers', { 18 | insertMode : 'append' 19 | }, function(error) { 20 | if (error) { 21 | console.error('Failed to subscribe', error); 22 | } 23 | }); 24 | }); 25 | -------------------------------------------------------------------------------- /Samples/Archiving/MainModule.cs: -------------------------------------------------------------------------------- 1 | using System.Dynamic; 2 | using Nancy; 3 | using OpenTokSDK; 4 | 5 | namespace Archiving 6 | { 7 | public class MainModule : NancyModule 8 | { 9 | public MainModule(OpenTokService opentokService) 10 | { 11 | Get("/", _ => View["index"]); 12 | Get("/host", _ => 13 | { 14 | dynamic locals = new ExpandoObject(); 15 | locals.ApiKey = opentokService.OpenTok.ApiKey.ToString(); 16 | locals.SessionId = opentokService.Session.Id; 17 | locals.Token = opentokService.Session.GenerateToken(); 18 | return View["host", locals]; 19 | }); 20 | Get("/participant", _ => 21 | { 22 | dynamic locals = new ExpandoObject(); 23 | locals.ApiKey = opentokService.OpenTok.ApiKey.ToString(); 24 | locals.SessionId = opentokService.Session.Id; 25 | locals.Token = opentokService.Session.GenerateToken(); 26 | return View["participant", locals]; 27 | }); 28 | Get("/history", _ => 29 | { 30 | var page = Request.Query.page.HasValue ? (int) Request.Query.page : 1; 31 | var offset = (page - 1) * 5; 32 | var archives = opentokService.OpenTok.ListArchives(offset, 5); 33 | var showPrevious = page > 1 ? "/history?page=" + (page - 1) : null; 34 | var showNext = archives.TotalCount > offset + 5 ? "/history?page=" + (page + 1) : null; 35 | dynamic locals = new ExpandoObject(); 36 | locals.Archives = archives; 37 | locals.ShowPrevious = showPrevious; 38 | locals.ShowNext = showNext; 39 | return View["history", locals]; 40 | }); 41 | Get("/download/{id}", parameters => 42 | { 43 | Archive archive = opentokService.OpenTok.GetArchive(parameters.id); 44 | return Response.AsRedirect(archive.Url); 45 | }); 46 | Post("/start", _ => 47 | { 48 | var archive = opentokService.OpenTok.StartArchive( 49 | opentokService.Session.Id, 50 | ".NET Archiving Sample App", 51 | hasAudio: (bool) this.Request.Form.hasAudio, 52 | hasVideo: (bool) this.Request.Form.hasVideo, 53 | outputMode: this.Request.Form.outputMode == "composed" ? OutputMode.COMPOSED : OutputMode.INDIVIDUAL 54 | ); 55 | return archive; 56 | }); 57 | Get("/stop/{id}", parameters => 58 | { 59 | Archive archive = opentokService.OpenTok.StopArchive(parameters.id); 60 | return archive; 61 | }); 62 | Get("/delete/{id}", parameters => 63 | { 64 | opentokService.OpenTok.DeleteArchive(parameters.id); 65 | return Response.AsRedirect("/history"); 66 | }); 67 | } 68 | } 69 | } -------------------------------------------------------------------------------- /Samples/Archiving/OpenTokService.cs: -------------------------------------------------------------------------------- 1 | using OpenTokSDK; 2 | using System; 3 | using System.Configuration; 4 | using System.Net; 5 | 6 | namespace Archiving 7 | { 8 | public class OpenTokService 9 | { 10 | public Session Session { get; protected set; } 11 | public OpenTok OpenTok { get; protected set; } 12 | 13 | public OpenTokService() 14 | { 15 | int apiKey = 0; 16 | string apiSecret = null; 17 | try 18 | { 19 | string apiKeyString = ConfigurationManager.AppSettings["API_KEY"]; 20 | apiSecret = ConfigurationManager.AppSettings["API_SECRET"]; 21 | apiKey = Convert.ToInt32(apiKeyString); 22 | } 23 | 24 | catch (Exception ex) 25 | { 26 | if (!(ex is ConfigurationErrorsException || ex is FormatException || ex is OverflowException)) 27 | { 28 | throw ex; 29 | } 30 | } 31 | 32 | finally 33 | { 34 | if (apiKey == 0 || apiSecret == null) 35 | { 36 | Console.WriteLine( 37 | "The OpenTok API Key and API Secret were not set in the application configuration. " + 38 | "Set the values in App.config and try again. (apiKey = {0}, apiSecret = {1})", apiKey, apiSecret); 39 | Console.ReadLine(); 40 | Environment.Exit(-1); 41 | } 42 | } 43 | ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; 44 | 45 | this.OpenTok = new OpenTok(apiKey, apiSecret); 46 | 47 | this.Session = this.OpenTok.CreateSession(mediaMode: MediaMode.ROUTED); 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /Samples/Archiving/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Owin.Hosting; 2 | using System; 3 | 4 | namespace Archiving 5 | { 6 | 7 | class Program 8 | { 9 | static void Main(string[] args) 10 | { 11 | var url = "http://+:8080"; 12 | 13 | using (WebApp.Start(url)) 14 | { 15 | Console.WriteLine("Running on {0}", url); 16 | Console.WriteLine("Press enter to exit."); 17 | Console.ReadLine(); 18 | } 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Samples/Archiving/Startup.cs: -------------------------------------------------------------------------------- 1 | using Owin; 2 | 3 | namespace Archiving 4 | { 5 | class Startup 6 | { 7 | public void Configuration(IAppBuilder app) 8 | { 9 | app.UseNancy(); 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Samples/Archiving/views/History.cshtml: -------------------------------------------------------------------------------- 1 | 
2 | 3 |
4 | 5 |
6 |
7 |

Past Recordings

8 |
9 |
10 | @if (Model.Archives.Count > 0) 11 | { 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | @foreach (var archive in Model.Archives) 23 | { 24 | 25 | 26 | 43 | 49 | 50 | 51 | 59 | 60 | 61 | } 62 | 63 | 64 |
 CreatedDurationStatus
27 | @if ((archive.Status == OpenTokSDK.ArchiveStatus.AVAILABLE) && (archive.Url.Length > 0)) 28 | { 29 | @: 30 | } 31 | @if(!String.IsNullOrEmpty(archive.Name)) 32 | { 33 | @archive.Name 34 | } else 35 | { 36 | @: Untitled 37 | } 38 | @if ((archive.Status == OpenTokSDK.ArchiveStatus.AVAILABLE) && (archive.Url.Length > 0)) 39 | { 40 | @: 41 | } 42 | 44 | @{ 45 | var epoch = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); 46 | @epoch.AddMilliseconds(archive.CreatedAt).ToString() 47 | } 48 | @archive.Duration seconds@archive.Status 52 | @if (archive.Status == OpenTokSDK.ArchiveStatus.AVAILABLE) 53 | { 54 | Delete 55 | } else { 56 | @:   57 | } 58 |
65 | } else 66 | { 67 |

68 | There are no archives currently. Try making one in the host view. 69 |

70 | } 71 |
72 | 83 |
84 |
85 |
-------------------------------------------------------------------------------- /Samples/Archiving/views/Host.cshtml: -------------------------------------------------------------------------------- 1 |  2 | 3 |
4 | 5 |
6 | 7 |
8 |
9 |

Host

10 |
11 |
12 |
13 |
14 | 41 |
42 |
43 | 44 |
45 |
46 |

Instructions

47 |
48 |
49 |

50 | Click Start archiving to begin archiving this session. 51 | All publishers in the session will be included, and all publishers that 52 | join the session will be included as well. 53 |

54 |

55 | Click Stop archiving to end archiving this session. 56 | You can then go to past archives to 57 | view your archive (once its status changes to available). 58 |

59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 |
WhenYou will see
Archiving is started
Archiving remains on
Archiving is stopped
81 |
82 |
83 |
84 | 85 | 90 | -------------------------------------------------------------------------------- /Samples/Archiving/views/Index.cshtml: -------------------------------------------------------------------------------- 1 | 
2 | 3 | 4 |
5 | 6 | 7 |
8 |
9 | 10 |
11 |
Create an archive
12 |
13 |

14 | Everyone who joins either the Host View or Participant View 15 | joins a single OpenTok session. Anyone with the Host View 16 | open can click Start Archive or Stop Archive to control 17 | recording of the entire session. 18 |

19 |
20 | 24 |
25 | 26 |
27 |
28 | 29 |
30 |
Play an archive
31 |
32 |

33 | Click through to Past Archives to see examples of using the 34 | Archiving REST API to list archives showing status (started, 35 | stopped, available) and playback (for available archives). 36 |

37 |
38 | 41 |
42 | 43 |
44 |
45 | 46 |
47 | 48 |
49 | -------------------------------------------------------------------------------- /Samples/Archiving/views/Participant.cshtml: -------------------------------------------------------------------------------- 1 |  2 | 3 |
4 | 5 |
6 | 7 |
8 |
9 |

Participant

10 |
11 |
12 |
13 |
14 |
15 |
16 | 17 |
18 |
19 |

Instructions

20 |
21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 |
WhenYou will see
Archiving is started
Archiving remains on
Archiving is stopped
44 |
45 |
46 |
47 | 48 | 53 | 54 | -------------------------------------------------------------------------------- /Samples/Archiving/views/Shared/Layout.cshtml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | Archiving Sample 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 24 | 25 | @RenderBody() 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /Samples/Archiving/views/_ViewStart.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = "Shared/Layout.cshtml"; 3 | } -------------------------------------------------------------------------------- /Samples/Archiving/views/history.sshtml: -------------------------------------------------------------------------------- 1 | @Master['master.sshtml'] 2 | 3 | @Section['Content'] 4 |
5 | 6 |
7 | 8 |
9 |
10 |

Past Recordings

11 |
12 |
13 | <% if archives.count > 0 %> 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | @Each.Archives 25 | 26 | 27 | 36 | 37 | 38 | 39 | 46 | 47 | 48 | @EndEach 49 | 50 |
 CreatedDurationStatus
28 | <% if (item.status == "available") && item.url && (item.url.length > 0) %> 29 | 30 | <% end %> 31 | <%= item.name || "Untitled" %> 32 | <% if (item.status == "available") && item.url && (item.url.length > 0) %> 33 | 34 | <% end %> 35 | <%= Time.at(item.created_at/1000).strftime("%B %e, %Y at %I:%M %p") %><%= item.duration %> seconds<%= item.status %> 40 | <% if item.status == "available" %> 41 | Delete 42 | <% else %> 43 |   44 | <% end %> 45 |
51 | <% else %> 52 |

53 | There are no archives currently. Try making one in the host view. 54 |

55 | <% end %> 56 |
57 | 66 |
67 |
68 |
69 | @EndSection -------------------------------------------------------------------------------- /Samples/Broadcasting/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /Samples/Broadcasting/App.config.sample: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /Samples/Broadcasting/Bootstrapper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | using Nancy; 7 | 8 | namespace Broadcasting 9 | { 10 | public class Bootstrapper : DefaultNancyBootstrapper 11 | { 12 | protected override void ConfigureApplicationContainer(Nancy.TinyIoc.TinyIoCContainer container) 13 | { 14 | base.ConfigureApplicationContainer(container); 15 | 16 | container.Register().AsSingleton(); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Samples/Broadcasting/Broadcasting.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Broadcasting 5 | 1.0.0 6 | net481 7 | Vonage 8 | Vonage 9 | Copyright © 2020 10 | Exe 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | Always 32 | 33 | 34 | Always 35 | 36 | 37 | Always 38 | 39 | 40 | Always 41 | 42 | 43 | Always 44 | 45 | 46 | Always 47 | 48 | 49 | Always 50 | 51 | 52 | Always 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /Samples/Broadcasting/Content/css/sample.css: -------------------------------------------------------------------------------- 1 | /* Move down content because we have a fixed navbar that is 50px tall */ 2 | body { 3 | padding-top: 50px; 4 | padding-bottom: 20px; 5 | background-color: #F2F2F2; 6 | } 7 | 8 | /* Responsive: Portrait tablets and up */ 9 | @media screen and (min-width: 768px) { 10 | /* Remove padding from wrapping element since we kick in the grid classes here */ 11 | .body-content { 12 | padding: 0; 13 | } 14 | } 15 | 16 | #streams { 17 | background-color: gray; 18 | width: 320px; 19 | height: 180px; 20 | } 21 | 22 | #streams > div { 23 | width: 20%; 24 | height: 20%; 25 | float: left; 26 | position: relative; 27 | cursor: pointer; 28 | } 29 | 30 | #streams.vertical > div { 31 | left: 0px; 32 | clear: left; 33 | padding: 0px; 34 | } 35 | 36 | #streams .focus { 37 | position: relative; 38 | top: 0; 39 | left: 0; 40 | margin-top: 0; 41 | height: 100%; 42 | width: 100%; 43 | } 44 | 45 | #streams.vertical .focus { 46 | padding: 0; 47 | left: 0; 48 | margin: 0; 49 | left: 20%; 50 | height: 100%; 51 | width: 80%; 52 | } 53 | 54 | .stop { 55 | display: none; 56 | } 57 | 58 | .bump-me { 59 | padding-top: 40px; 60 | } 61 | 62 | .help-block { 63 | font-weight: bold; 64 | } 65 | -------------------------------------------------------------------------------- /Samples/Broadcasting/Content/js/participant.js: -------------------------------------------------------------------------------- 1 | /* global OT, apiKey, sessionId, token, $, layout, focusStreamId */ 2 | var session = OT.initSession(apiKey, sessionId); 3 | var publisher; 4 | 5 | var container = $('
'); 6 | 7 | if (layout === 'verticalPresentation') { 8 | $('#streams').addClass('vertical'); 9 | } 10 | 11 | container.addClass('focus'); 12 | $('#streams').append(container); 13 | 14 | publisher = OT.initPublisher('publisher', { 15 | insertMode: 'append', 16 | width: '100%', 17 | height: '100%', 18 | resolution: '1280x720' 19 | }); 20 | 21 | function positionStreams() { 22 | var $focusElement = $('.focus'); 23 | if ($('#streams').hasClass('vertical')) { 24 | $focusElement.appendTo('#streams'); 25 | $('#streams').children().css('top', '0'); 26 | $focusElement.css('top', (-20 * ($('#streams').children().size() - 1)) + '%'); 27 | } 28 | else { 29 | $focusElement.prependTo('#streams'); 30 | $focusElement.css('top', '0'); 31 | } 32 | } 33 | 34 | function focusStream(streamId) { 35 | var focusStreamId = streamId; 36 | var $focusElement = (publisher.stream && publisher.stream.id === focusStreamId) ? $('#publisher') 37 | : $('#' + focusStreamId); 38 | $('.focus').removeClass('focus'); 39 | $focusElement.addClass('focus'); 40 | positionStreams(); 41 | } 42 | 43 | session.connect(token, function (err) { 44 | if (err) { 45 | alert(err.message || err); // eslint-disable-line no-alert 46 | } 47 | session.publish(publisher); 48 | }); 49 | 50 | session.on('streamCreated', function (event) { 51 | var streamId = event.stream.id; 52 | container = document.createElement('div'); 53 | container.id = streamId; 54 | $('#streams').append(container); 55 | session.subscribe(event.stream, streamId, { 56 | insertMode: 'append', 57 | width: '100%', 58 | height: '100%' 59 | }); 60 | if (streamId === focusStreamId) { 61 | focusStream(streamId); 62 | } 63 | positionStreams(); 64 | }); 65 | 66 | session.on('streamDestroyed', function (event) { 67 | $('#' + event.stream.id).remove(); 68 | positionStreams(); 69 | }); 70 | 71 | session.on('signal:layoutClass', function (event) { 72 | if (event.data === 'horizontalPresentation') { 73 | $('#streams').removeClass('vertical'); 74 | $('.focus').prependTo('#streams'); 75 | } 76 | else { 77 | $('#streams').addClass('vertical'); 78 | $('.focus').appendTo('#streams'); 79 | } 80 | positionStreams(); 81 | }); 82 | 83 | session.on('signal:focusStream', function (event) { 84 | focusStream(event.data); 85 | }); 86 | -------------------------------------------------------------------------------- /Samples/Broadcasting/OpenTokService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Net; 3 | 4 | using System.Configuration; 5 | using OpenTokSDK; 6 | 7 | namespace Broadcasting 8 | { 9 | public class OpenTokService 10 | { 11 | public Session Session { get; protected set; } 12 | public OpenTok OpenTok { get; protected set; } 13 | public BroadcastLayout.LayoutType layout = BroadcastLayout.LayoutType.HorizontalPresentation; 14 | public string broadcastId = ""; 15 | public string focusStreamId = ""; 16 | 17 | public OpenTokService() 18 | { 19 | int apiKey = 0; 20 | string apiSecret = null; 21 | try 22 | { 23 | string apiKeyString = ConfigurationManager.AppSettings["API_KEY"]; 24 | apiSecret = ConfigurationManager.AppSettings["API_SECRET"]; 25 | apiKey = Convert.ToInt32(apiKeyString); 26 | } 27 | 28 | catch (Exception ex) 29 | { 30 | if (!(ex is ConfigurationErrorsException || ex is FormatException || ex is OverflowException)) 31 | { 32 | throw ex; 33 | } 34 | } 35 | 36 | finally 37 | { 38 | if (apiKey == 0 || apiSecret == null) 39 | { 40 | Console.WriteLine( 41 | "The OpenTok API Key and API Secret were not set in the application configuration. " + 42 | "Set the values in App.config and try again. (apiKey = {0}, apiSecret = {1})", apiKey, apiSecret); 43 | Console.ReadLine(); 44 | Environment.Exit(-1); 45 | } 46 | } 47 | 48 | ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; 49 | 50 | this.OpenTok = new OpenTok(apiKey, apiSecret); 51 | 52 | this.Session = this.OpenTok.CreateSession(mediaMode: MediaMode.ROUTED); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /Samples/Broadcasting/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Owin.Hosting; 2 | using System; 3 | 4 | namespace Broadcasting 5 | { 6 | 7 | class Program 8 | { 9 | static void Main(string[] args) 10 | { 11 | var url = "http://+:8080"; 12 | 13 | using (WebApp.Start(url)) 14 | { 15 | Console.WriteLine("Running on {0}", url); 16 | Console.WriteLine("Press enter to exit."); 17 | Console.ReadLine(); 18 | } 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Samples/Broadcasting/Startup.cs: -------------------------------------------------------------------------------- 1 | using Owin; 2 | 3 | namespace Broadcasting 4 | { 5 | class Startup 6 | { 7 | public void Configuration(IAppBuilder app) 8 | { 9 | app.UseNancy(); 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Samples/Broadcasting/views/Index.cshtml: -------------------------------------------------------------------------------- 1 | 
2 |
3 |
4 |
5 |
6 |
Start a Broadcast
7 |
8 |

9 | Everyone who joins either the Host View or Participant View joins a single OpenTok session. 10 | The Host can click Start Broadcast and Stop Broadcast to control the live streaming broadcast 11 | of the entire session. 12 |

13 |
14 | 19 |
20 |
21 |
22 |
23 |
24 | -------------------------------------------------------------------------------- /Samples/Broadcasting/views/Participant.cshtml: -------------------------------------------------------------------------------- 1 |  2 | 3 |
4 |
5 |
6 |
7 |

Participant

8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | 16 | 23 | 24 | -------------------------------------------------------------------------------- /Samples/Broadcasting/views/Shared/Layout.cshtml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | Broadcasting Sample 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 24 | 25 | @RenderBody() 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /Samples/Broadcasting/views/_ViewStart.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = "Shared/Layout.cshtml"; 3 | } -------------------------------------------------------------------------------- /Samples/HelloWorld/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /Samples/HelloWorld/App.config.sample: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /Samples/HelloWorld/Bootstrapper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | using Nancy; 7 | 8 | namespace HelloWorld 9 | { 10 | public class Bootstrapper : DefaultNancyBootstrapper 11 | { 12 | protected override void ConfigureApplicationContainer(Nancy.TinyIoc.TinyIoCContainer container) 13 | { 14 | base.ConfigureApplicationContainer(container); 15 | 16 | container.Register().AsSingleton(); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Samples/HelloWorld/Content/js/helloworld.js: -------------------------------------------------------------------------------- 1 | // Initialize an OpenTok Session object 2 | var session = OT.initSession(apiKey, sessionId); 3 | 4 | // Initialize a Publisher, and place it into the element with id="publisher" 5 | var publisher = OT.initPublisher('publisher', { 6 | insertMode: 'append', 7 | width: '100%', 8 | height: '100%', 9 | resolution: '1280x720' 10 | }, _ => { 11 | loadDevices(); 12 | }); 13 | 14 | 15 | // Attach event handlers 16 | session.on({ 17 | 18 | // This function runs when session.connect() asynchronously completes 19 | sessionConnected: function (event) { 20 | // Publish the publisher we initialzed earlier (this will trigger 'streamCreated' on other 21 | // clients) 22 | session.publish(publisher, function (error) { 23 | if (error) { 24 | console.error('Failed to publish', error); 25 | } 26 | }); 27 | }, 28 | 29 | // This function runs when another client publishes a stream (eg. session.publish()) 30 | streamCreated: function (event) { 31 | // Create a container for a new Subscriber, assign it an id using the streamId, put it inside 32 | // the element with id="subscribers" 33 | var subContainer = document.createElement('div'); 34 | subContainer.id = 'stream-' + event.stream.streamId; 35 | document.getElementById('subscribers').appendChild(subContainer); 36 | 37 | // Subscribe to the stream that caused this event, put it inside the container we just made 38 | session.subscribe(event.stream, subContainer, function (error) { 39 | if (error) { 40 | console.error('Failed to subscribe', error); 41 | } 42 | }); 43 | } 44 | 45 | }); 46 | 47 | // Connect to the Session using the 'apiKey' of the application and a 'token' for permission 48 | session.connect(token, function (error) { 49 | if (error) { 50 | console.error('Failed to connect', error); 51 | } 52 | }); 53 | 54 | function loadDevices() { 55 | 56 | var cameras = document.getElementById('cameras'); 57 | cameras.addEventListener('change', function (event) { 58 | publisher.setVideoSource(event.target.value); 59 | }); 60 | 61 | var mics = document.getElementById('mics'); 62 | mics.addEventListener('change', function (event) { 63 | publisher.setAudioSource(event.target.value); 64 | }); 65 | 66 | var videoSource = publisher.getVideoSource(); 67 | var audioSource = publisher.getAudioSource(); 68 | 69 | OT.getDevices((err, devices) => { 70 | 71 | if (err) { 72 | console.error(err); 73 | } 74 | 75 | var audioInputs = devices.filter((device) => device.kind === 'audioInput'); 76 | var videoInputs = devices.filter((device) => device.kind === 'videoInput'); 77 | 78 | videoInputs.forEach((device, idx) => { 79 | var option = document.createElement("option"); 80 | var txt = document.createTextNode(device.label); 81 | option.appendChild(txt); 82 | option.setAttribute("value", device.deviceId); 83 | 84 | if (videoSource != null && device.deviceId === videoSource.deviceId) { 85 | option.selected = true; 86 | } 87 | cameras.insertBefore(option, cameras.lastChild); 88 | }); 89 | 90 | audioInputs.forEach((device, idx) => { 91 | var option = document.createElement("option"); 92 | var txt = document.createTextNode(device.label); 93 | option.appendChild(txt); 94 | option.setAttribute("value", device.deviceId); 95 | 96 | if (audioSource != null && device.deviceId === audioSource.deviceId) { 97 | option.selected = true; 98 | } 99 | mics.insertBefore(option, mics.lastChild); 100 | }); 101 | }); 102 | } -------------------------------------------------------------------------------- /Samples/HelloWorld/HelloWorld.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | HelloWorld 5 | 1.0.0 6 | net481 7 | Vonage 8 | Vonage 9 | Copyright © 2020 10 | Exe 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | PreserveNewest 19 | 20 | 21 | Always 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /Samples/HelloWorld/MainModule.cs: -------------------------------------------------------------------------------- 1 | using System.Dynamic; 2 | using Nancy; 3 | 4 | namespace HelloWorld 5 | { 6 | public class MainModule : NancyModule 7 | { 8 | public MainModule(OpenTokService opentokService) 9 | { 10 | Get("/", _ => 11 | { 12 | dynamic locals = new ExpandoObject(); 13 | 14 | locals.ApiKey = opentokService.OpenTok.ApiKey.ToString(); 15 | locals.SessionId = opentokService.Session.Id; 16 | locals.Token = opentokService.Session.GenerateToken(); 17 | 18 | return View["index", locals]; 19 | }); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Samples/HelloWorld/OpenTokService.cs: -------------------------------------------------------------------------------- 1 | using OpenTokSDK; 2 | using System; 3 | using System.Configuration; 4 | using System.Net; 5 | 6 | namespace HelloWorld 7 | { 8 | public class OpenTokService 9 | { 10 | public Session Session { get; protected set; } 11 | public OpenTok OpenTok { get; protected set; } 12 | 13 | public OpenTokService() 14 | { 15 | int apiKey = 0; 16 | string apiSecret = null; 17 | try 18 | { 19 | string apiKeyString = ConfigurationManager.AppSettings["API_KEY"]; 20 | apiSecret = ConfigurationManager.AppSettings["API_SECRET"]; 21 | apiKey = Convert.ToInt32(apiKeyString); 22 | } 23 | 24 | catch (Exception ex) 25 | { 26 | if (!(ex is ConfigurationErrorsException || ex is FormatException || ex is OverflowException)) 27 | { 28 | throw ex; 29 | } 30 | } 31 | 32 | finally 33 | { 34 | if (apiKey == 0 || apiSecret == null) 35 | { 36 | Console.WriteLine( 37 | "The OpenTok API Key and API Secret were not set in the application configuration. " + 38 | "Set the values in App.config and try again. (apiKey = {0}, apiSecret = {1})", apiKey, apiSecret); 39 | Console.ReadLine(); 40 | Environment.Exit(-1); 41 | } 42 | } 43 | 44 | ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; 45 | 46 | this.OpenTok = new OpenTok(apiKey, apiSecret); 47 | 48 | this.Session = this.OpenTok.CreateSession(mediaMode:MediaMode.ROUTED); 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Samples/HelloWorld/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Owin.Hosting; 2 | using System; 3 | 4 | namespace HelloWorld 5 | { 6 | 7 | class Program 8 | { 9 | static void Main(string[] args) 10 | { 11 | var url = "http://+:8080"; 12 | 13 | using (WebApp.Start(url)) 14 | { 15 | Console.WriteLine("Running on {0}", url); 16 | Console.WriteLine("Press enter to exit."); 17 | Console.ReadLine(); 18 | } 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Samples/HelloWorld/Startup.cs: -------------------------------------------------------------------------------- 1 | using Owin; 2 | 3 | namespace HelloWorld 4 | { 5 | class Startup 6 | { 7 | public void Configuration(IAppBuilder app) 8 | { 9 | app.UseNancy(); 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Samples/HelloWorld/views/index.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | OpenTok Hello World 6 | 7 | 12 | 13 | 14 | 15 | 16 |

Hello, World!

17 |
18 |
19 | 20 |
21 |
22 | 23 |
24 | 25 |
26 | 27 |
28 | 29 | 30 | 31 | --------------------------------------------------------------------------------