PageRenderTime 48ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

/src/wp/Media.cs

https://gitlab.com/dannywillems/cordova-plugin-media
C# | 678 lines | 507 code | 72 blank | 99 comment | 16 complexity | cae1c557c018ae7d8fb688c512d167af MD5 | raw file
  1. /*
  2. Licensed under the Apache License, Version 2.0 (the "License");
  3. you may not use this file except in compliance with the License.
  4. You may obtain a copy of the License at
  5. http://www.apache.org/licenses/LICENSE-2.0
  6. Unless required by applicable law or agreed to in writing, software
  7. distributed under the License is distributed on an "AS IS" BASIS,
  8. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  9. See the License for the specific language governing permissions and
  10. limitations under the License.
  11. */
  12. using System;
  13. using System.Collections.Generic;
  14. using System.Runtime.Serialization;
  15. using System.Windows;
  16. using System.Diagnostics;
  17. namespace WPCordovaClassLib.Cordova.Commands
  18. {
  19. /// <summary>
  20. /// Provides the ability to record and play back audio files on a device.
  21. /// </summary>
  22. public class Media : BaseCommand
  23. {
  24. /// <summary>
  25. /// Audio player objects
  26. /// </summary>
  27. private static Dictionary<string, AudioPlayer> players = new Dictionary<string, AudioPlayer>();
  28. /// <summary>
  29. /// Callback id for Media events channel
  30. /// </summary>
  31. private static string messageChannelCallbackId;
  32. /// <summary>
  33. /// Represents Media action options.
  34. /// </summary>
  35. [DataContract]
  36. public class MediaOptions
  37. {
  38. /// <summary>
  39. /// Audio id
  40. /// </summary>
  41. [DataMember(Name = "id", IsRequired = true)]
  42. public string Id { get; set; }
  43. /// <summary>
  44. /// Path to audio file
  45. /// </summary>
  46. [DataMember(Name = "src")]
  47. public string Src { get; set; }
  48. /// <summary>
  49. /// New track position
  50. /// </summary>
  51. [DataMember(Name = "milliseconds")]
  52. public int Milliseconds { get; set; }
  53. public string CallbackId { get; set; }
  54. }
  55. /// <summary>
  56. /// Reperesent media channel status changed action
  57. /// </summary>
  58. [DataContract]
  59. public class MediaChannelStatusAction
  60. {
  61. /// <summary>
  62. /// Action type
  63. /// </summary>
  64. [DataMember(Name = "action", IsRequired = true)]
  65. public string Action { get; set; }
  66. /// <summary>
  67. /// Status data
  68. /// </summary>
  69. [DataMember(Name = "status", IsRequired = true)]
  70. public MediaStatus Status { get; set; }
  71. /// <summary>
  72. /// Initialize a new instance
  73. /// </summary>
  74. public MediaChannelStatusAction()
  75. {
  76. this.Action = "status";
  77. }
  78. }
  79. /// <summary>
  80. /// Represents Media error
  81. /// </summary>
  82. [DataContract]
  83. public class MediaError
  84. {
  85. [DataMember(Name = "code", IsRequired = true)]
  86. public int Code { get; set; }
  87. }
  88. /// <summary>
  89. /// Represents Media status
  90. /// </summary>
  91. [DataContract]
  92. [KnownType(typeof(MediaError))]
  93. public class MediaStatus
  94. {
  95. /// <summary>
  96. /// Audio player Id
  97. /// </summary>
  98. [DataMember(Name = "id", IsRequired = true)]
  99. public string Id { get; set; }
  100. /// <summary>
  101. /// Status message type
  102. /// </summary>
  103. [DataMember(Name = "msgType", IsRequired = true)]
  104. public int MsgType { get; set; }
  105. /// <summary>
  106. /// Status message value
  107. /// </summary>
  108. [DataMember(Name = "value")]
  109. public dynamic Value { get; set; }
  110. }
  111. /// <summary>
  112. /// Establish channel for Media events
  113. /// </summary>
  114. public void messageChannel(string options)
  115. {
  116. string[] optionsString = JSON.JsonHelper.Deserialize<string[]>(options);
  117. messageChannelCallbackId = optionsString[0];
  118. }
  119. /// <summary>
  120. /// Report Media status to JS
  121. /// </summary>
  122. public void ReportStatus(MediaStatus status)
  123. {
  124. PluginResult result = new PluginResult(PluginResult.Status.OK, new MediaChannelStatusAction() { Status = status });
  125. result.KeepCallback = true;
  126. DispatchCommandResult(result, messageChannelCallbackId);
  127. }
  128. /// <summary>
  129. /// Releases the audio player instance to save memory.
  130. /// </summary>
  131. public void release(string options)
  132. {
  133. string callbackId = this.CurrentCommandCallbackId;
  134. try
  135. {
  136. MediaOptions mediaOptions = new MediaOptions();
  137. try
  138. {
  139. string[] optionsString = JSON.JsonHelper.Deserialize<string[]>(options);
  140. mediaOptions.Id = optionsString[0];
  141. callbackId = mediaOptions.CallbackId = optionsString[1];
  142. }
  143. catch (Exception)
  144. {
  145. DispatchCommandResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION), callbackId);
  146. return;
  147. }
  148. if (!Media.players.ContainsKey(mediaOptions.Id))
  149. {
  150. DispatchCommandResult(new PluginResult(PluginResult.Status.OK, false), callbackId);
  151. return;
  152. }
  153. Deployment.Current.Dispatcher.BeginInvoke(() =>
  154. {
  155. try
  156. {
  157. AudioPlayer audio = Media.players[mediaOptions.Id];
  158. Media.players.Remove(mediaOptions.Id);
  159. audio.Dispose();
  160. DispatchCommandResult(new PluginResult(PluginResult.Status.OK, true), mediaOptions.CallbackId);
  161. }
  162. catch (Exception e)
  163. {
  164. DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, e.Message), mediaOptions.CallbackId);
  165. }
  166. });
  167. }
  168. catch (Exception e)
  169. {
  170. DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, e.Message), callbackId);
  171. }
  172. }
  173. private AudioPlayer GetOrCreatePlayerById(string id)
  174. {
  175. AudioPlayer audio = null;
  176. lock (Media.players)
  177. {
  178. if (!Media.players.TryGetValue(id, out audio))
  179. {
  180. audio = new AudioPlayer(this, id);
  181. Media.players.Add(id, audio);
  182. Debug.WriteLine("Media Created in GetOrCreatePlayerById");
  183. }
  184. }
  185. return audio;
  186. }
  187. /// <summary>
  188. /// Starts recording and save the specified file
  189. /// </summary>
  190. public void startRecordingAudio(string options)
  191. {
  192. string callbackId = this.CurrentCommandCallbackId;
  193. try
  194. {
  195. MediaOptions mediaOptions = new MediaOptions();
  196. try
  197. {
  198. string[] optionsString = JSON.JsonHelper.Deserialize<string[]>(options);
  199. mediaOptions.Id = optionsString[0];
  200. mediaOptions.Src = optionsString[1];
  201. callbackId = mediaOptions.CallbackId = optionsString[2];
  202. }
  203. catch (Exception)
  204. {
  205. DispatchCommandResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION), mediaOptions.CallbackId);
  206. return;
  207. }
  208. if (mediaOptions != null)
  209. {
  210. Deployment.Current.Dispatcher.BeginInvoke(() =>
  211. {
  212. try
  213. {
  214. AudioPlayer audio;
  215. if (!Media.players.ContainsKey(mediaOptions.Id))
  216. {
  217. audio = new AudioPlayer(this, mediaOptions.Id);
  218. Media.players.Add(mediaOptions.Id, audio);
  219. }
  220. else
  221. {
  222. audio = Media.players[mediaOptions.Id];
  223. }
  224. if (audio != null)
  225. {
  226. audio.startRecording(mediaOptions.Src);
  227. DispatchCommandResult(new PluginResult(PluginResult.Status.OK), mediaOptions.CallbackId);
  228. }
  229. else
  230. {
  231. DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR,
  232. "Error accessing AudioPlayer for key " + mediaOptions.Id), mediaOptions.CallbackId);
  233. }
  234. }
  235. catch (Exception e)
  236. {
  237. DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, e.Message), mediaOptions.CallbackId);
  238. }
  239. });
  240. }
  241. else
  242. {
  243. DispatchCommandResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION), mediaOptions.CallbackId);
  244. }
  245. }
  246. catch (Exception e)
  247. {
  248. DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, e.Message), callbackId);
  249. }
  250. }
  251. /// <summary>
  252. /// Stops recording and save to the file specified when recording started
  253. /// </summary>
  254. public void stopRecordingAudio(string options)
  255. {
  256. string callbackId = this.CurrentCommandCallbackId;
  257. try
  258. {
  259. string[] optStrings = JSON.JsonHelper.Deserialize<string[]>(options);
  260. string mediaId = optStrings[0];
  261. callbackId = optStrings[1];
  262. Deployment.Current.Dispatcher.BeginInvoke(() =>
  263. {
  264. try
  265. {
  266. if (Media.players.ContainsKey(mediaId))
  267. {
  268. AudioPlayer audio = Media.players[mediaId];
  269. audio.stopRecording();
  270. Media.players.Remove(mediaId);
  271. }
  272. DispatchCommandResult(new PluginResult(PluginResult.Status.OK), callbackId);
  273. }
  274. catch (Exception e)
  275. {
  276. DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, e.Message), callbackId);
  277. }
  278. });
  279. }
  280. catch (Exception)
  281. {
  282. DispatchCommandResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION), callbackId);
  283. }
  284. }
  285. public void setVolume(string options) // id,volume
  286. {
  287. string callbackId = this.CurrentCommandCallbackId;
  288. try
  289. {
  290. string[] optionsString = JSON.JsonHelper.Deserialize<string[]>(options);
  291. string id = optionsString[0];
  292. double volume = 0.0d;
  293. double.TryParse(optionsString[1], out volume);
  294. callbackId = optionsString[2];
  295. if (Media.players.ContainsKey(id))
  296. {
  297. Deployment.Current.Dispatcher.BeginInvoke(() =>
  298. {
  299. try
  300. {
  301. AudioPlayer player = Media.players[id];
  302. player.setVolume(volume);
  303. }
  304. catch (Exception e)
  305. {
  306. DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, e.Message), callbackId);
  307. }
  308. });
  309. }
  310. }
  311. catch (Exception)
  312. {
  313. DispatchCommandResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION,
  314. "Error parsing options into setVolume method"), callbackId);
  315. }
  316. }
  317. // Some Audio Notes:
  318. // In the Windows Phone Emulator, playback of video or audio content using the MediaElement control is not supported.
  319. // While playing, a MediaElement stops all other media playback on the phone.
  320. // Multiple MediaElement controls are NOT supported
  321. // Called when you create a new Media('blah.wav') object in JS.
  322. public void create(string options)
  323. {
  324. string callbackId = this.CurrentCommandCallbackId;
  325. try
  326. {
  327. MediaOptions mediaOptions;
  328. try
  329. {
  330. string[] optionsString = JSON.JsonHelper.Deserialize<string[]>(options);
  331. mediaOptions = new MediaOptions();
  332. mediaOptions.Id = optionsString[0];
  333. mediaOptions.Src = optionsString[1];
  334. callbackId = mediaOptions.CallbackId = optionsString[2];
  335. }
  336. catch (Exception)
  337. {
  338. DispatchCommandResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION,
  339. "Error parsing options into create method"), callbackId);
  340. return;
  341. }
  342. GetOrCreatePlayerById(mediaOptions.Id);
  343. DispatchCommandResult(new PluginResult(PluginResult.Status.OK), callbackId);
  344. }
  345. catch (Exception e)
  346. {
  347. DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, e.Message), callbackId);
  348. }
  349. }
  350. /// <summary>
  351. /// Starts or resume playing audio file
  352. /// </summary>
  353. public void startPlayingAudio(string options)
  354. {
  355. string callbackId = this.CurrentCommandCallbackId;
  356. try
  357. {
  358. MediaOptions mediaOptions;
  359. try
  360. {
  361. string[] optionsString = JSON.JsonHelper.Deserialize<string[]>(options);
  362. mediaOptions = new MediaOptions();
  363. mediaOptions.Id = optionsString[0];
  364. mediaOptions.Src = optionsString[1];
  365. int msec = 0;
  366. if (int.TryParse(optionsString[2], out msec))
  367. {
  368. mediaOptions.Milliseconds = msec;
  369. }
  370. callbackId = mediaOptions.CallbackId = optionsString[3];
  371. }
  372. catch (Exception)
  373. {
  374. DispatchCommandResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION), callbackId);
  375. return;
  376. }
  377. AudioPlayer audio = GetOrCreatePlayerById(mediaOptions.Id);
  378. Deployment.Current.Dispatcher.BeginInvoke(() =>
  379. {
  380. try
  381. {
  382. audio.startPlaying(mediaOptions.Src);
  383. DispatchCommandResult(new PluginResult(PluginResult.Status.OK), callbackId);
  384. }
  385. catch (Exception e)
  386. {
  387. DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, e.Message), callbackId);
  388. }
  389. });
  390. }
  391. catch (Exception e)
  392. {
  393. DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, e.Message), callbackId);
  394. }
  395. }
  396. /// <summary>
  397. /// Seeks to a location
  398. /// </summary>
  399. public void seekToAudio(string options)
  400. {
  401. string callbackId = this.CurrentCommandCallbackId;
  402. try
  403. {
  404. MediaOptions mediaOptions;
  405. try
  406. {
  407. string[] optionsString = JSON.JsonHelper.Deserialize<string[]>(options);
  408. mediaOptions = new MediaOptions();
  409. mediaOptions.Id = optionsString[0];
  410. int msec = 0;
  411. if (int.TryParse(optionsString[1], out msec))
  412. {
  413. mediaOptions.Milliseconds = msec;
  414. }
  415. callbackId = mediaOptions.CallbackId = optionsString[2];
  416. }
  417. catch (Exception)
  418. {
  419. DispatchCommandResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION), callbackId);
  420. return;
  421. }
  422. Deployment.Current.Dispatcher.BeginInvoke(() =>
  423. {
  424. try
  425. {
  426. if (Media.players.ContainsKey(mediaOptions.Id))
  427. {
  428. AudioPlayer audio = Media.players[mediaOptions.Id];
  429. audio.seekToPlaying(mediaOptions.Milliseconds);
  430. }
  431. else
  432. {
  433. Debug.WriteLine("ERROR: seekToAudio could not find mediaPlayer for " + mediaOptions.Id);
  434. }
  435. DispatchCommandResult(new PluginResult(PluginResult.Status.OK), callbackId);
  436. }
  437. catch (Exception e)
  438. {
  439. DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, e.Message), callbackId);
  440. }
  441. });
  442. }
  443. catch (Exception e)
  444. {
  445. DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, e.Message), callbackId);
  446. }
  447. }
  448. /// <summary>
  449. /// Pauses playing
  450. /// </summary>
  451. public void pausePlayingAudio(string options)
  452. {
  453. string callbackId = this.CurrentCommandCallbackId;
  454. try
  455. {
  456. string[] optionsString = JSON.JsonHelper.Deserialize<string[]>(options);
  457. string mediaId = optionsString[0];
  458. callbackId = optionsString[1];
  459. Deployment.Current.Dispatcher.BeginInvoke(() =>
  460. {
  461. try
  462. {
  463. if (Media.players.ContainsKey(mediaId))
  464. {
  465. AudioPlayer audio = Media.players[mediaId];
  466. audio.pausePlaying();
  467. }
  468. else
  469. {
  470. Debug.WriteLine("ERROR: pausePlayingAudio could not find mediaPlayer for " + mediaId);
  471. }
  472. DispatchCommandResult(new PluginResult(PluginResult.Status.OK), callbackId);
  473. }
  474. catch (Exception e)
  475. {
  476. DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, e.Message),callbackId);
  477. }
  478. });
  479. }
  480. catch (Exception)
  481. {
  482. DispatchCommandResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION),callbackId);
  483. }
  484. }
  485. /// <summary>
  486. /// Stops playing the audio file
  487. /// </summary>
  488. public void stopPlayingAudio(String options)
  489. {
  490. string callbackId = this.CurrentCommandCallbackId;
  491. try
  492. {
  493. string[] optionsStrings = JSON.JsonHelper.Deserialize<string[]>(options);
  494. string mediaId = optionsStrings[0];
  495. callbackId = optionsStrings[1];
  496. Deployment.Current.Dispatcher.BeginInvoke(() =>
  497. {
  498. try
  499. {
  500. if (Media.players.ContainsKey(mediaId))
  501. {
  502. AudioPlayer audio = Media.players[mediaId];
  503. audio.stopPlaying();
  504. }
  505. else
  506. {
  507. Debug.WriteLine("stopPlaying could not find mediaPlayer for " + mediaId);
  508. }
  509. DispatchCommandResult(new PluginResult(PluginResult.Status.OK), callbackId);
  510. }
  511. catch (Exception e)
  512. {
  513. DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, e.Message), callbackId);
  514. }
  515. });
  516. }
  517. catch (Exception)
  518. {
  519. DispatchCommandResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION), callbackId);
  520. }
  521. }
  522. /// <summary>
  523. /// Gets current position of playback
  524. /// </summary>
  525. public void getCurrentPositionAudio(string options)
  526. {
  527. string callbackId = this.CurrentCommandCallbackId;
  528. try
  529. {
  530. string[] optionsStrings = JSON.JsonHelper.Deserialize<string[]>(options);
  531. string mediaId = optionsStrings[0];
  532. callbackId = optionsStrings[1];
  533. Deployment.Current.Dispatcher.BeginInvoke(() =>
  534. {
  535. try
  536. {
  537. if (Media.players.ContainsKey(mediaId))
  538. {
  539. AudioPlayer audio = Media.players[mediaId];
  540. DispatchCommandResult(new PluginResult(PluginResult.Status.OK, audio.getCurrentPosition()), callbackId);
  541. }
  542. else
  543. {
  544. DispatchCommandResult(new PluginResult(PluginResult.Status.OK, -1), callbackId);
  545. }
  546. }
  547. catch (Exception e)
  548. {
  549. DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, e.Message), callbackId);
  550. }
  551. });
  552. }
  553. catch (Exception)
  554. {
  555. DispatchCommandResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION), callbackId);
  556. return;
  557. }
  558. }
  559. /// <summary>
  560. /// Gets the duration of the audio file
  561. /// </summary>
  562. [Obsolete("This method will be removed shortly")]
  563. public void getDurationAudio(string options)
  564. {
  565. string callbackId = this.CurrentCommandCallbackId;
  566. try
  567. {
  568. MediaOptions mediaOptions;
  569. try
  570. {
  571. string[] optionsString = JSON.JsonHelper.Deserialize<string[]>(options);
  572. mediaOptions = new MediaOptions();
  573. mediaOptions.Id = optionsString[0];
  574. mediaOptions.Src = optionsString[1];
  575. callbackId = mediaOptions.CallbackId = optionsString[2];
  576. }
  577. catch (Exception)
  578. {
  579. DispatchCommandResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION), callbackId);
  580. return;
  581. }
  582. AudioPlayer audio;
  583. if (Media.players.ContainsKey(mediaOptions.Id))
  584. {
  585. audio = Media.players[mediaOptions.Id];
  586. }
  587. else
  588. {
  589. Debug.WriteLine("ERROR: getDurationAudio could not find mediaPlayer for " + mediaOptions.Id);
  590. audio = new AudioPlayer(this, mediaOptions.Id);
  591. Media.players.Add(mediaOptions.Id, audio);
  592. }
  593. Deployment.Current.Dispatcher.BeginInvoke(() =>
  594. {
  595. DispatchCommandResult(new PluginResult(PluginResult.Status.OK, audio.getDuration(mediaOptions.Src)), callbackId);
  596. });
  597. }
  598. catch (Exception e)
  599. {
  600. DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, e.Message), callbackId);
  601. }
  602. }
  603. }
  604. }