SyncPlayService.cs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. using System.Threading;
  2. using System;
  3. using System.Collections.Generic;
  4. using MediaBrowser.Controller.Configuration;
  5. using MediaBrowser.Controller.Net;
  6. using MediaBrowser.Controller.Session;
  7. using MediaBrowser.Controller.SyncPlay;
  8. using MediaBrowser.Model.Services;
  9. using MediaBrowser.Model.SyncPlay;
  10. using Microsoft.Extensions.Logging;
  11. namespace MediaBrowser.Api.SyncPlay
  12. {
  13. [Route("/SyncPlay/New", "POST", Summary = "Create a new SyncPlay group")]
  14. [Authenticated]
  15. public class SyncPlayNew : IReturnVoid
  16. {
  17. }
  18. [Route("/SyncPlay/Join", "POST", Summary = "Join an existing SyncPlay group")]
  19. [Authenticated]
  20. public class SyncPlayJoin : IReturnVoid
  21. {
  22. /// <summary>
  23. /// Gets or sets the Group id.
  24. /// </summary>
  25. /// <value>The Group id to join.</value>
  26. [ApiMember(Name = "GroupId", Description = "Group Id", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")]
  27. public string GroupId { get; set; }
  28. /// <summary>
  29. /// Gets or sets the playing item id.
  30. /// </summary>
  31. /// <value>The client's currently playing item id.</value>
  32. [ApiMember(Name = "PlayingItemId", Description = "Client's playing item id", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
  33. public string PlayingItemId { get; set; }
  34. }
  35. [Route("/SyncPlay/Leave", "POST", Summary = "Leave joined SyncPlay group")]
  36. [Authenticated]
  37. public class SyncPlayLeave : IReturnVoid
  38. {
  39. }
  40. [Route("/SyncPlay/List", "GET", Summary = "List SyncPlay groups")]
  41. [Authenticated]
  42. public class SyncPlayList : IReturnVoid
  43. {
  44. /// <summary>
  45. /// Gets or sets the filter item id.
  46. /// </summary>
  47. /// <value>The filter item id.</value>
  48. [ApiMember(Name = "FilterItemId", Description = "Filter by item id", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")]
  49. public string FilterItemId { get; set; }
  50. }
  51. [Route("/SyncPlay/Play", "POST", Summary = "Request play in SyncPlay group")]
  52. [Authenticated]
  53. public class SyncPlayPlay : IReturnVoid
  54. {
  55. }
  56. [Route("/SyncPlay/Pause", "POST", Summary = "Request pause in SyncPlay group")]
  57. [Authenticated]
  58. public class SyncPlayPause : IReturnVoid
  59. {
  60. }
  61. [Route("/SyncPlay/Seek", "POST", Summary = "Request seek in SyncPlay group")]
  62. [Authenticated]
  63. public class SyncPlaySeek : IReturnVoid
  64. {
  65. [ApiMember(Name = "PositionTicks", IsRequired = true, DataType = "long", ParameterType = "query", Verb = "POST")]
  66. public long PositionTicks { get; set; }
  67. }
  68. [Route("/SyncPlay/Buffering", "POST", Summary = "Request group wait in SyncPlay group while buffering")]
  69. [Authenticated]
  70. public class SyncPlayBuffering : IReturnVoid
  71. {
  72. /// <summary>
  73. /// Gets or sets the date used to pin PositionTicks in time.
  74. /// </summary>
  75. /// <value>The date related to PositionTicks.</value>
  76. [ApiMember(Name = "When", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")]
  77. public string When { get; set; }
  78. [ApiMember(Name = "PositionTicks", IsRequired = true, DataType = "long", ParameterType = "query", Verb = "POST")]
  79. public long PositionTicks { get; set; }
  80. /// <summary>
  81. /// Gets or sets whether this is a buffering or a buffering-done request.
  82. /// </summary>
  83. /// <value><c>true</c> if buffering is complete; <c>false</c> otherwise.</value>
  84. [ApiMember(Name = "BufferingDone", IsRequired = true, DataType = "bool", ParameterType = "query", Verb = "POST")]
  85. public bool BufferingDone { get; set; }
  86. }
  87. [Route("/SyncPlay/Ping", "POST", Summary = "Update session ping")]
  88. [Authenticated]
  89. public class SyncPlayPing : IReturnVoid
  90. {
  91. [ApiMember(Name = "Ping", IsRequired = true, DataType = "double", ParameterType = "query", Verb = "POST")]
  92. public double Ping { get; set; }
  93. }
  94. /// <summary>
  95. /// Class SyncPlayService.
  96. /// </summary>
  97. public class SyncPlayService : BaseApiService
  98. {
  99. /// <summary>
  100. /// The session context.
  101. /// </summary>
  102. private readonly ISessionContext _sessionContext;
  103. /// <summary>
  104. /// The SyncPlay manager.
  105. /// </summary>
  106. private readonly ISyncPlayManager _syncPlayManager;
  107. public SyncPlayService(
  108. ILogger<SyncPlayService> logger,
  109. IServerConfigurationManager serverConfigurationManager,
  110. IHttpResultFactory httpResultFactory,
  111. ISessionContext sessionContext,
  112. ISyncPlayManager syncPlayManager)
  113. : base(logger, serverConfigurationManager, httpResultFactory)
  114. {
  115. _sessionContext = sessionContext;
  116. _syncPlayManager = syncPlayManager;
  117. }
  118. /// <summary>
  119. /// Handles the specified request.
  120. /// </summary>
  121. /// <param name="request">The request.</param>
  122. public void Post(SyncPlayNew request)
  123. {
  124. var currentSession = GetSession(_sessionContext);
  125. _syncPlayManager.NewGroup(currentSession, CancellationToken.None);
  126. }
  127. /// <summary>
  128. /// Handles the specified request.
  129. /// </summary>
  130. /// <param name="request">The request.</param>
  131. public void Post(SyncPlayJoin request)
  132. {
  133. var currentSession = GetSession(_sessionContext);
  134. Guid groupId;
  135. Guid playingItemId = Guid.Empty;
  136. if (!Guid.TryParse(request.GroupId, out groupId))
  137. {
  138. Logger.LogError("JoinGroup: {0} is not a valid format for GroupId. Ignoring request.", request.GroupId);
  139. return;
  140. }
  141. // Both null and empty strings mean that client isn't playing anything
  142. if (!string.IsNullOrEmpty(request.PlayingItemId) && !Guid.TryParse(request.PlayingItemId, out playingItemId))
  143. {
  144. Logger.LogError("JoinGroup: {0} is not a valid format for PlayingItemId. Ignoring request.", request.PlayingItemId);
  145. return;
  146. }
  147. var joinRequest = new JoinGroupRequest()
  148. {
  149. GroupId = groupId,
  150. PlayingItemId = playingItemId
  151. };
  152. _syncPlayManager.JoinGroup(currentSession, groupId, joinRequest, CancellationToken.None);
  153. }
  154. /// <summary>
  155. /// Handles the specified request.
  156. /// </summary>
  157. /// <param name="request">The request.</param>
  158. public void Post(SyncPlayLeave request)
  159. {
  160. var currentSession = GetSession(_sessionContext);
  161. _syncPlayManager.LeaveGroup(currentSession, CancellationToken.None);
  162. }
  163. /// <summary>
  164. /// Handles the specified request.
  165. /// </summary>
  166. /// <param name="request">The request.</param>
  167. /// <value>The requested list of groups.</value>
  168. public List<GroupInfoView> Get(SyncPlayList request)
  169. {
  170. var currentSession = GetSession(_sessionContext);
  171. var filterItemId = Guid.Empty;
  172. if (!string.IsNullOrEmpty(request.FilterItemId) && !Guid.TryParse(request.FilterItemId, out filterItemId))
  173. {
  174. Logger.LogWarning("ListGroups: {0} is not a valid format for FilterItemId. Ignoring filter.", request.FilterItemId);
  175. }
  176. return _syncPlayManager.ListGroups(currentSession, filterItemId);
  177. }
  178. /// <summary>
  179. /// Handles the specified request.
  180. /// </summary>
  181. /// <param name="request">The request.</param>
  182. public void Post(SyncPlayPlay request)
  183. {
  184. var currentSession = GetSession(_sessionContext);
  185. var syncPlayRequest = new PlaybackRequest()
  186. {
  187. Type = PlaybackRequestType.Play
  188. };
  189. _syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None);
  190. }
  191. /// <summary>
  192. /// Handles the specified request.
  193. /// </summary>
  194. /// <param name="request">The request.</param>
  195. public void Post(SyncPlayPause request)
  196. {
  197. var currentSession = GetSession(_sessionContext);
  198. var syncPlayRequest = new PlaybackRequest()
  199. {
  200. Type = PlaybackRequestType.Pause
  201. };
  202. _syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None);
  203. }
  204. /// <summary>
  205. /// Handles the specified request.
  206. /// </summary>
  207. /// <param name="request">The request.</param>
  208. public void Post(SyncPlaySeek request)
  209. {
  210. var currentSession = GetSession(_sessionContext);
  211. var syncPlayRequest = new PlaybackRequest()
  212. {
  213. Type = PlaybackRequestType.Seek,
  214. PositionTicks = request.PositionTicks
  215. };
  216. _syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None);
  217. }
  218. /// <summary>
  219. /// Handles the specified request.
  220. /// </summary>
  221. /// <param name="request">The request.</param>
  222. public void Post(SyncPlayBuffering request)
  223. {
  224. var currentSession = GetSession(_sessionContext);
  225. var syncPlayRequest = new PlaybackRequest()
  226. {
  227. Type = request.BufferingDone ? PlaybackRequestType.BufferingDone : PlaybackRequestType.Buffering,
  228. When = DateTime.Parse(request.When),
  229. PositionTicks = request.PositionTicks
  230. };
  231. _syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None);
  232. }
  233. /// <summary>
  234. /// Handles the specified request.
  235. /// </summary>
  236. /// <param name="request">The request.</param>
  237. public void Post(SyncPlayPing request)
  238. {
  239. var currentSession = GetSession(_sessionContext);
  240. var syncPlayRequest = new PlaybackRequest()
  241. {
  242. Type = PlaybackRequestType.UpdatePing,
  243. Ping = Convert.ToInt64(request.Ping)
  244. };
  245. _syncPlayManager.HandleRequest(currentSession, syncPlayRequest, CancellationToken.None);
  246. }
  247. }
  248. }