aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.Api
diff options
context:
space:
mode:
Diffstat (limited to 'MediaBrowser.Api')
-rw-r--r--MediaBrowser.Api/LiveTv/LiveTvService.cs6
-rw-r--r--MediaBrowser.Api/LocalizationService.cs15
-rw-r--r--MediaBrowser.Api/MediaBrowser.Api.csproj1
-rw-r--r--MediaBrowser.Api/Music/InstantMixService.cs75
-rw-r--r--MediaBrowser.Api/Playback/BaseStreamingService.cs96
-rw-r--r--MediaBrowser.Api/Playback/Hls/BaseHlsService.cs2
-rw-r--r--MediaBrowser.Api/Playback/ProgressiveStreamService.cs73
-rw-r--r--MediaBrowser.Api/Playback/StreamRequest.cs5
-rw-r--r--MediaBrowser.Api/Playback/StreamState.cs2
-rw-r--r--MediaBrowser.Api/SessionsService.cs74
10 files changed, 205 insertions, 144 deletions
diff --git a/MediaBrowser.Api/LiveTv/LiveTvService.cs b/MediaBrowser.Api/LiveTv/LiveTvService.cs
index 96fe01ab3..abeaba910 100644
--- a/MediaBrowser.Api/LiveTv/LiveTvService.cs
+++ b/MediaBrowser.Api/LiveTv/LiveTvService.cs
@@ -39,6 +39,9 @@ namespace MediaBrowser.Api.LiveTv
/// <value>The limit.</value>
[ApiMember(Name = "Limit", Description = "Optional. The maximum number of records to return", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
public int? Limit { get; set; }
+
+ [ApiMember(Name = "IsFavorite", Description = "Filter by channels that are favorites, or not.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
+ public bool? IsFavorite { get; set; }
}
[Route("/LiveTv/Channels/{Id}", "GET", Summary = "Gets a live tv channel")]
@@ -290,7 +293,8 @@ namespace MediaBrowser.Api.LiveTv
ChannelType = request.Type,
UserId = request.UserId,
StartIndex = request.StartIndex,
- Limit = request.Limit
+ Limit = request.Limit,
+ IsFavorite = request.IsFavorite
}, CancellationToken.None).Result;
diff --git a/MediaBrowser.Api/LocalizationService.cs b/MediaBrowser.Api/LocalizationService.cs
index 60270a389..be86090ac 100644
--- a/MediaBrowser.Api/LocalizationService.cs
+++ b/MediaBrowser.Api/LocalizationService.cs
@@ -32,6 +32,14 @@ namespace MediaBrowser.Api
}
/// <summary>
+ /// Class ParentalRatings
+ /// </summary>
+ [Route("/Localization/Options", "GET", Summary = "Gets localization options")]
+ public class GetLocalizationOptions : IReturn<List<LocalizatonOption>>
+ {
+ }
+
+ /// <summary>
/// Class CulturesService
/// </summary>
public class LocalizationService : BaseApiService
@@ -62,6 +70,13 @@ namespace MediaBrowser.Api
return ToOptimizedSerializedResultUsingCache(result);
}
+ public object Get(GetLocalizationOptions request)
+ {
+ var result = _localization.GetLocalizationOptions().ToList();
+
+ return ToOptimizedSerializedResultUsingCache(result);
+ }
+
/// <summary>
/// Gets the specified request.
/// </summary>
diff --git a/MediaBrowser.Api/MediaBrowser.Api.csproj b/MediaBrowser.Api/MediaBrowser.Api.csproj
index 18559a68d..c03eddf99 100644
--- a/MediaBrowser.Api/MediaBrowser.Api.csproj
+++ b/MediaBrowser.Api/MediaBrowser.Api.csproj
@@ -103,6 +103,7 @@
<Compile Include="Playback\Hls\DynamicHlsService.cs" />
<Compile Include="Playback\Hls\HlsSegmentService.cs" />
<Compile Include="Playback\Hls\VideoHlsService.cs" />
+ <Compile Include="Playback\ProgressiveStreamService.cs" />
<Compile Include="Playback\Progressive\AudioService.cs" />
<Compile Include="Playback\Progressive\BaseProgressiveStreamingService.cs" />
<Compile Include="Playback\BaseStreamingService.cs" />
diff --git a/MediaBrowser.Api/Music/InstantMixService.cs b/MediaBrowser.Api/Music/InstantMixService.cs
index 9b9df3a92..c39811bb6 100644
--- a/MediaBrowser.Api/Music/InstantMixService.cs
+++ b/MediaBrowser.Api/Music/InstantMixService.cs
@@ -1,9 +1,9 @@
using MediaBrowser.Controller.Dto;
+using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Querying;
using ServiceStack;
-using System;
using System.Collections.Generic;
using System.Linq;
@@ -36,103 +36,74 @@ namespace MediaBrowser.Api.Music
public class InstantMixService : BaseApiService
{
private readonly IUserManager _userManager;
- private readonly ILibraryManager _libraryManager;
private readonly IDtoService _dtoService;
+ private readonly IMusicManager _musicManager;
- public InstantMixService(IUserManager userManager, ILibraryManager libraryManager, IDtoService dtoService)
+ public InstantMixService(IUserManager userManager, IDtoService dtoService, IMusicManager musicManager)
{
_userManager = userManager;
- _libraryManager = libraryManager;
_dtoService = dtoService;
+ _musicManager = musicManager;
}
public object Get(GetInstantMixFromSong request)
{
- var item = _dtoService.GetItemByDtoId(request.Id);
+ var item = (Audio)_dtoService.GetItemByDtoId(request.Id);
- var result = GetInstantMixResult(request, item.Genres);
+ var user = _userManager.GetUserById(request.UserId.Value);
- return ToOptimizedSerializedResultUsingCache(result);
+ var items = _musicManager.GetInstantMixFromSong(item, user);
+
+ return GetResult(items, user, request);
}
public object Get(GetInstantMixFromAlbum request)
{
var album = (MusicAlbum)_dtoService.GetItemByDtoId(request.Id);
- var genres = album
- .RecursiveChildren
- .OfType<Audio>()
- .SelectMany(i => i.Genres)
- .Concat(album.Genres)
- .Distinct(StringComparer.OrdinalIgnoreCase);
+ var user = _userManager.GetUserById(request.UserId.Value);
- var result = GetInstantMixResult(request, genres);
+ var items = _musicManager.GetInstantMixFromAlbum(album, user);
- return ToOptimizedSerializedResultUsingCache(result);
+ return GetResult(items, user, request);
}
public object Get(GetInstantMixFromMusicGenre request)
{
- var genre = GetMusicGenre(request.Name, _libraryManager);
+ var user = _userManager.GetUserById(request.UserId.Value);
- var result = GetInstantMixResult(request, new[] { genre.Name });
+ var items = _musicManager.GetInstantMixFromGenres(new[] { request.Name }, user);
- return ToOptimizedSerializedResultUsingCache(result);
+ return GetResult(items, user, request);
}
public object Get(GetInstantMixFromArtist request)
{
- var artist = GetArtist(request.Name, _libraryManager);
-
- var genres = _libraryManager.RootFolder
- .RecursiveChildren
- .OfType<Audio>()
- .Where(i => i.HasArtist(artist.Name))
- .SelectMany(i => i.Genres)
- .Concat(artist.Genres)
- .Distinct(StringComparer.OrdinalIgnoreCase);
+ var user = _userManager.GetUserById(request.UserId.Value);
- var result = GetInstantMixResult(request, genres);
+ var items = _musicManager.GetInstantMixFromArtist(request.Name, user);
- return ToOptimizedSerializedResultUsingCache(result);
+ return GetResult(items, user, request);
}
- private ItemsResult GetInstantMixResult(BaseGetSimilarItems request, IEnumerable<string> genres)
+ private object GetResult(IEnumerable<Audio> items, User user, BaseGetSimilarItems request)
{
- var user = request.UserId.HasValue ? _userManager.GetUserById(request.UserId.Value) : null;
-
var fields = request.GetItemFields().ToList();
- var inputItems = user == null
- ? _libraryManager.RootFolder.RecursiveChildren
- : user.RootFolder.GetRecursiveChildren(user);
-
- var genresDictionary = genres.ToDictionary(i => i, StringComparer.OrdinalIgnoreCase);
-
- var limit = request.Limit.HasValue ? request.Limit.Value * 2 : 100;
-
- var items = inputItems
- .OfType<Audio>()
- .Select(i => new Tuple<Audio, int>(i, i.Genres.Count(genresDictionary.ContainsKey)))
- .OrderByDescending(i => i.Item2)
- .ThenBy(i => Guid.NewGuid())
- .Select(i => i.Item1)
- .Take(limit)
- .OrderBy(i => Guid.NewGuid())
- .ToList();
+ var list = items.ToList();
var result = new ItemsResult
{
- TotalRecordCount = items.Count
+ TotalRecordCount = list.Count
};
- var dtos = items.Take(request.Limit ?? items.Count)
+ var dtos = list.Take(request.Limit ?? list.Count)
.Select(i => _dtoService.GetBaseItemDto(i, fields, user));
result.Items = dtos.ToArray();
- return result;
+ return ToOptimizedResult(result);
}
}
diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs
index 519ff7947..6c406a11c 100644
--- a/MediaBrowser.Api/Playback/BaseStreamingService.cs
+++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs
@@ -734,7 +734,9 @@ namespace MediaBrowser.Api.Playback
{
if (audioStream != null)
{
- if (audioStream.Channels > 2 && string.Equals(request.AudioCodec, "wma", StringComparison.OrdinalIgnoreCase))
+ var codec = request.AudioCodec ?? string.Empty;
+
+ if (audioStream.Channels > 2 && codec.IndexOf("wma", StringComparison.OrdinalIgnoreCase) != -1)
{
// wmav2 currently only supports two channel output
return 2;
@@ -835,11 +837,6 @@ namespace MediaBrowser.Api.Playback
/// <returns>System.String.</returns>
protected string GetInputArgument(StreamState state)
{
- if (state.SendInputOverStandardInput)
- {
- return "-";
- }
-
var type = InputType.File;
var inputPath = new[] { state.MediaPath };
@@ -898,9 +895,7 @@ namespace MediaBrowser.Api.Playback
Arguments = commandLineArgs,
WindowStyle = ProcessWindowStyle.Hidden,
- ErrorDialog = false,
-
- RedirectStandardInput = state.SendInputOverStandardInput
+ ErrorDialog = false
},
EnableRaisingEvents = true
@@ -933,11 +928,6 @@ namespace MediaBrowser.Api.Playback
throw;
}
- if (state.SendInputOverStandardInput)
- {
- StreamToStandardInput(process, state);
- }
-
// MUST read both stdout and stderr asynchronously or a deadlock may occurr
process.BeginOutputReadLine();
@@ -965,32 +955,6 @@ namespace MediaBrowser.Api.Playback
}
}
- private async void StreamToStandardInput(Process process, StreamState state)
- {
- try
- {
- await StreamToStandardInputInternal(process, state).ConfigureAwait(false);
- }
- catch (OperationCanceledException)
- {
- Logger.Debug("Stream to standard input closed normally.");
- }
- catch (Exception ex)
- {
- Logger.ErrorException("Error writing to standard input", ex);
- }
- }
-
- private async Task StreamToStandardInputInternal(Process process, StreamState state)
- {
- state.StandardInputCancellationTokenSource = new CancellationTokenSource();
-
- using (var fileStream = FileSystem.GetFileStream(state.MediaPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, true))
- {
- await new EndlessStreamCopy().CopyStream(fileStream, process.StandardInput.BaseStream, state.StandardInputCancellationTokenSource.Token).ConfigureAwait(false);
- }
- }
-
protected int? GetVideoBitrateParamValue(StreamState state)
{
var bitrate = state.VideoRequest.VideoBitRate;
@@ -1280,22 +1244,12 @@ namespace MediaBrowser.Api.Playback
}
else if (i == 14)
{
- if (videoRequest != null)
- {
- videoRequest.Framerate = int.Parse(val, UsCulture);
- }
+ request.StartTimeTicks = long.Parse(val, UsCulture);
}
else if (i == 15)
{
if (videoRequest != null)
{
- request.StartTimeTicks = long.Parse(val, UsCulture);
- }
- }
- else if (i == 16)
- {
- if (videoRequest != null)
- {
videoRequest.Level = val;
}
}
@@ -1315,11 +1269,6 @@ namespace MediaBrowser.Api.Playback
ParseParams(request);
}
- if (request.ThrowDebugError)
- {
- throw new InvalidOperationException("You asked for a debug error, you got one.");
- }
-
var user = AuthorizationRequestFilterAttribute.GetCurrentUser(Request, UserManager);
var url = Request.PathInfo;
@@ -1369,8 +1318,6 @@ namespace MediaBrowser.Api.Playback
{
state.MediaPath = path;
state.IsRemote = false;
-
- state.SendInputOverStandardInput = recording.RecordingInfo.Status == RecordingStatus.InProgress;
}
else if (!string.IsNullOrEmpty(mediaUrl))
{
@@ -1378,7 +1325,8 @@ namespace MediaBrowser.Api.Playback
state.IsRemote = true;
}
- //state.RunTimeTicks = recording.RunTimeTicks;
+ state.RunTimeTicks = recording.RunTimeTicks;
+
if (recording.RecordingInfo.Status == RecordingStatus.InProgress && !state.IsRemote)
{
await Task.Delay(1000, cancellationToken).ConfigureAwait(false);
@@ -1544,21 +1492,9 @@ namespace MediaBrowser.Api.Playback
state.EnableMpegtsM2TsMode = transcodingProfile.EnableMpegtsM2TsMode;
state.TranscodeSeekInfo = transcodingProfile.TranscodeSeekInfo;
- foreach (var setting in transcodingProfile.Settings)
+ if (state.VideoRequest != null && string.IsNullOrWhiteSpace(state.VideoRequest.Profile))
{
- switch (setting.Name)
- {
- case TranscodingSettingType.VideoProfile:
- {
- if (state.VideoRequest != null && string.IsNullOrWhiteSpace(state.VideoRequest.Profile))
- {
- state.VideoRequest.Profile = setting.Value;
- }
- break;
- }
- default:
- throw new ArgumentException("Unrecognized TranscodingSettingType");
- }
+ state.VideoRequest.Profile = transcodingProfile.VideoProfile;
}
}
}
@@ -1575,12 +1511,6 @@ namespace MediaBrowser.Api.Playback
{
var timeSeek = GetHeader("TimeSeekRange.dlna.org");
- if (!string.IsNullOrEmpty(timeSeek))
- {
- ResultFactory.ThrowError(406, "Time seek not supported during encoding.", responseHeaders);
- return;
- }
-
var transferMode = GetHeader("transferMode.dlna.org");
responseHeaders["transferMode.dlna.org"] = string.IsNullOrEmpty(transferMode) ? "Streaming" : transferMode;
responseHeaders["realTimeInfo.dlna.org"] = "DLNA.ORG_TLAG=*";
@@ -1589,7 +1519,13 @@ namespace MediaBrowser.Api.Playback
var extension = GetOutputFileExtension(state);
// first bit means Time based seek supported, second byte range seek supported (not sure about the order now), so 01 = only byte seek, 10 = time based, 11 = both, 00 = none
- var orgOp = isStaticallyStreamed || state.TranscodeSeekInfo == TranscodeSeekInfo.Bytes ? ";DLNA.ORG_OP=01" : ";DLNA.ORG_OP=00";
+ var orgOp = ";DLNA.ORG_OP=";
+
+ // Time-based seeking currently only possible when transcoding
+ orgOp += isStaticallyStreamed ? "0" : "1";
+
+ // Byte-based seeking only possible when not transcoding
+ orgOp += isStaticallyStreamed || state.TranscodeSeekInfo == TranscodeSeekInfo.Bytes ? "1" : "0";
// 0 = native, 1 = transcoded
var orgCi = isStaticallyStreamed ? ";DLNA.ORG_CI=0" : ";DLNA.ORG_CI=1";
diff --git a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs
index 96b36ac7f..1a190b75e 100644
--- a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs
+++ b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs
@@ -276,7 +276,7 @@ namespace MediaBrowser.Api.Playback.Hls
? 0
: ((GetHlsVideoStream)state.VideoRequest).TimeStampOffsetMs;
- var itsOffset = itsOffsetMs == 0 ? string.Empty : string.Format("-itsoffset {0} ", TimeSpan.FromMilliseconds(itsOffsetMs).TotalSeconds);
+ var itsOffset = itsOffsetMs == 0 ? string.Empty : string.Format("-itsoffset {0} ", TimeSpan.FromMilliseconds(itsOffsetMs).TotalSeconds.ToString(UsCulture));
var threads = GetNumberOfThreads(state, false);
diff --git a/MediaBrowser.Api/Playback/ProgressiveStreamService.cs b/MediaBrowser.Api/Playback/ProgressiveStreamService.cs
new file mode 100644
index 000000000..531f79a22
--- /dev/null
+++ b/MediaBrowser.Api/Playback/ProgressiveStreamService.cs
@@ -0,0 +1,73 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using MediaBrowser.Api.Playback.Progressive;
+
+namespace MediaBrowser.Api.Playback
+{
+ //public class GetProgressiveAudioStream : StreamRequest
+ //{
+
+ //}
+
+ //public class ProgressiveStreamService : BaseApiService
+ //{
+ // public object Get(GetProgressiveAudioStream request)
+ // {
+ // return ProcessRequest(request, false);
+ // }
+
+ // /// <summary>
+ // /// Gets the specified request.
+ // /// </summary>
+ // /// <param name="request">The request.</param>
+ // /// <returns>System.Object.</returns>
+ // public object Head(GetProgressiveAudioStream request)
+ // {
+ // return ProcessRequest(request, true);
+ // }
+
+ // protected object ProcessRequest(StreamRequest request, bool isHeadRequest)
+ // {
+ // var state = GetState(request, CancellationToken.None).Result;
+
+ // var responseHeaders = new Dictionary<string, string>();
+
+ // if (request.Static && state.IsRemote)
+ // {
+ // AddDlnaHeaders(state, responseHeaders, true);
+
+ // return GetStaticRemoteStreamResult(state.MediaPath, responseHeaders, isHeadRequest).Result;
+ // }
+
+ // var outputPath = GetOutputFilePath(state);
+ // var outputPathExists = File.Exists(outputPath);
+
+ // var isStatic = request.Static ||
+ // (outputPathExists && !ApiEntryPoint.Instance.HasActiveTranscodingJob(outputPath, TranscodingJobType.Progressive));
+
+ // AddDlnaHeaders(state, responseHeaders, isStatic);
+
+ // if (request.Static)
+ // {
+ // var contentType = state.GetMimeType(state.MediaPath);
+
+ // return ResultFactory.GetStaticFileResult(Request, state.MediaPath, contentType, FileShare.Read, responseHeaders, isHeadRequest);
+ // }
+
+ // if (outputPathExists && !ApiEntryPoint.Instance.HasActiveTranscodingJob(outputPath, TranscodingJobType.Progressive))
+ // {
+ // var contentType = state.GetMimeType(outputPath);
+
+ // return ResultFactory.GetStaticFileResult(Request, outputPath, contentType, FileShare.Read, responseHeaders, isHeadRequest);
+ // }
+
+ // return GetStreamResult(state, responseHeaders, isHeadRequest).Result;
+ // }
+
+ //}
+}
diff --git a/MediaBrowser.Api/Playback/StreamRequest.cs b/MediaBrowser.Api/Playback/StreamRequest.cs
index 0eb2984fb..add517b5d 100644
--- a/MediaBrowser.Api/Playback/StreamRequest.cs
+++ b/MediaBrowser.Api/Playback/StreamRequest.cs
@@ -67,11 +67,6 @@ namespace MediaBrowser.Api.Playback
[ApiMember(Name = "DeviceProfileId", Description = "Optional. The dlna device profile id to utilize.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
public string DeviceProfileId { get; set; }
-
- /// <summary>
- /// For testing purposes
- /// </summary>
- public bool ThrowDebugError { get; set; }
public string Params { get; set; }
}
diff --git a/MediaBrowser.Api/Playback/StreamState.cs b/MediaBrowser.Api/Playback/StreamState.cs
index 504d7d921..48285a4b1 100644
--- a/MediaBrowser.Api/Playback/StreamState.cs
+++ b/MediaBrowser.Api/Playback/StreamState.cs
@@ -51,8 +51,6 @@ namespace MediaBrowser.Api.Playback
public bool HasMediaStreams { get; set; }
- public bool SendInputOverStandardInput { get; set; }
-
public CancellationTokenSource StandardInputCancellationTokenSource { get; set; }
public string LiveTvStreamId { get; set; }
diff --git a/MediaBrowser.Api/SessionsService.cs b/MediaBrowser.Api/SessionsService.cs
index a509c876c..1f3bcf75b 100644
--- a/MediaBrowser.Api/SessionsService.cs
+++ b/MediaBrowser.Api/SessionsService.cs
@@ -146,7 +146,36 @@ namespace MediaBrowser.Api
/// </summary>
/// <value>The play command.</value>
[ApiMember(Name = "Command", Description = "The command to send.", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
- public SystemCommand Command { get; set; }
+ public string Command { get; set; }
+ }
+
+ [Route("/Sessions/{Id}/Command/{Command}", "POST", Summary = "Issues a system command to a client")]
+ public class SendGeneralCommand : IReturnVoid
+ {
+ /// <summary>
+ /// Gets or sets the id.
+ /// </summary>
+ /// <value>The id.</value>
+ [ApiMember(Name = "Id", Description = "Session Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
+ public Guid Id { get; set; }
+
+ /// <summary>
+ /// Gets or sets the command.
+ /// </summary>
+ /// <value>The play command.</value>
+ [ApiMember(Name = "Command", Description = "The command to send.", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
+ public string Command { get; set; }
+ }
+
+ [Route("/Sessions/{Id}/Command", "POST", Summary = "Issues a system command to a client")]
+ public class SendFullGeneralCommand : GeneralCommand, IReturnVoid
+ {
+ /// <summary>
+ /// Gets or sets the id.
+ /// </summary>
+ /// <value>The id.</value>
+ [ApiMember(Name = "Id", Description = "Session Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
+ public Guid Id { get; set; }
}
[Route("/Sessions/{Id}/Message", "POST", Summary = "Issues a command to a client to display a message to the user")]
@@ -301,9 +330,22 @@ namespace MediaBrowser.Api
/// <param name="request">The request.</param>
public void Post(SendSystemCommand request)
{
- var task = _sessionManager.SendSystemCommand(GetSession().Id, request.Id, request.Command, CancellationToken.None);
+ GeneralCommandType commandType;
- Task.WaitAll(task);
+ if (Enum.TryParse(request.Command, true, out commandType))
+ {
+ var currentSession = GetSession();
+
+ var command = new GeneralCommand
+ {
+ Name = commandType.ToString(),
+ ControllingUserId = currentSession.UserId.HasValue ? currentSession.UserId.Value.ToString("N") : null
+ };
+
+ var task = _sessionManager.SendGeneralCommand(currentSession.Id, request.Id, command, CancellationToken.None);
+
+ Task.WaitAll(task);
+ }
}
/// <summary>
@@ -343,6 +385,32 @@ namespace MediaBrowser.Api
Task.WaitAll(task);
}
+ public void Post(SendGeneralCommand request)
+ {
+ var currentSession = GetSession();
+
+ var command = new GeneralCommand
+ {
+ Name = request.Command,
+ ControllingUserId = currentSession.UserId.HasValue ? currentSession.UserId.Value.ToString("N") : null
+ };
+
+ var task = _sessionManager.SendGeneralCommand(currentSession.Id, request.Id, command, CancellationToken.None);
+
+ Task.WaitAll(task);
+ }
+
+ public void Post(SendFullGeneralCommand request)
+ {
+ var currentSession = GetSession();
+
+ request.ControllingUserId = currentSession.UserId.HasValue ? currentSession.UserId.Value.ToString("N") : null;
+
+ var task = _sessionManager.SendGeneralCommand(currentSession.Id, request.Id, request, CancellationToken.None);
+
+ Task.WaitAll(task);
+ }
+
public void Post(AddUserToSession request)
{
_sessionManager.AddAdditionalUser(request.Id, request.UserId);