Setting since_tizen 3/4 on Tizen.NET API
[platform/core/csapi/tizenfx.git] / src / Tizen.Multimedia.AudioIO / TonePlayer / TonePlayer.cs
1 /*
2  * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the License);
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an AS IS BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 using System;
18 using System.Threading;
19 using System.Threading.Tasks;
20 using Native = Interop.TonePlayer;
21
22 namespace Tizen.Multimedia
23 {
24     /// <summary>
25     /// Provides the ability to play a tone.
26     /// </summary>
27     /// <since_tizen> 3 </since_tizen>
28     public static class TonePlayer
29     {
30         /// <summary>
31         /// Plays a tone, asynchronously.
32         /// </summary>
33         /// <param name="tone">A <see cref="ToneType"/> to play.</param>
34         /// <param name="streamPolicy">A <see cref="AudioStreamPolicy"/>.</param>
35         /// <param name="durationMilliseconds">The tone duration in milliseconds. -1 indicates an infinite duration.</param>
36         /// <returns>A task that represents the asynchronous operation.</returns>
37         /// <exception cref="ArgumentException"><paramref name="tone"/> is invalid.</exception>
38         /// <exception cref="ArgumentNullException"><paramref name="streamPolicy"/> is null.</exception>
39         /// <exception cref="ArgumentOutOfRangeException"><paramref name="durationMilliseconds"/> is less than -1.</exception>
40         /// <exception cref="InvalidOperationException">Any invalid operations occurred.</exception>
41         /// <exception cref="NotSupportedException"><paramref name="tone"/> is not a supported type.</exception>
42         /// <exception cref="ObjectDisposedException"><paramref name="streamPolicy"/> has already been disposed of.</exception>
43         /// <since_tizen> 3 </since_tizen>
44         public static Task StartAsync(ToneType tone, AudioStreamPolicy streamPolicy,
45             int durationMilliseconds)
46         {
47             return StartAsync(tone, streamPolicy, durationMilliseconds, CancellationToken.None);
48         }
49
50         /// <summary>
51         /// Plays a tone, asynchronously.
52         /// </summary>
53         /// <param name="tone">A <see cref="ToneType"/> to play.</param>
54         /// <param name="streamPolicy">A <see cref="AudioStreamPolicy"/>.</param>
55         /// <param name="durationMilliseconds">The tone duration in milliseconds. -1 indicates an infinite duration.</param>
56         /// <param name="cancellationToken">The cancellation token which can be used to stop playing the tone.</param>
57         /// <returns>A task that represents the asynchronous operation.</returns>
58         /// <exception cref="ArgumentException"><paramref name="tone"/> is invalid.</exception>
59         /// <exception cref="ArgumentNullException"><paramref name="streamPolicy"/> is null.</exception>
60         /// <exception cref="ArgumentOutOfRangeException"><paramref name="durationMilliseconds"/> is less than -1.</exception>
61         /// <exception cref="InvalidOperationException">Any invalid operations occurred.</exception>
62         /// <exception cref="NotSupportedException"><paramref name="tone"/> is not a supported type.</exception>
63         /// <exception cref="ObjectDisposedException"><paramref name="streamPolicy"/> has already been disposed of.</exception>
64         /// <since_tizen> 3 </since_tizen>
65         public static Task StartAsync(ToneType tone, AudioStreamPolicy streamPolicy,
66             int durationMilliseconds, CancellationToken cancellationToken)
67         {
68             if (durationMilliseconds < -1)
69             {
70                 throw new ArgumentOutOfRangeException(nameof(durationMilliseconds), durationMilliseconds,
71                     $"{nameof(durationMilliseconds)} can't be less than -1.");
72             }
73
74             if (streamPolicy == null)
75             {
76                 throw new ArgumentNullException(nameof(streamPolicy));
77             }
78
79             ValidationUtil.ValidateEnum(typeof(ToneType), tone, nameof(tone));
80
81             if (cancellationToken.IsCancellationRequested)
82             {
83                 return Task.FromCanceled(cancellationToken);
84             }
85
86             return StartAsyncCore(tone, streamPolicy, durationMilliseconds, cancellationToken);
87         }
88
89         private static async Task StartAsyncCore(ToneType tone, AudioStreamPolicy streamPolicy,
90             int durationMilliseconds, CancellationToken cancellationToken)
91         {
92
93             var tcs = new TaskCompletionSource<bool>();
94
95             Native.Start(tone, streamPolicy.Handle, durationMilliseconds, out var id).
96                 Validate("Failed to play tone.");
97
98             using (RegisterCancellationAction(tcs, cancellationToken, id))
99             {
100                 await WaitForDuration(tcs, cancellationToken, durationMilliseconds);
101
102                 await tcs.Task;
103             }
104         }
105
106         private static async Task WaitForDuration(TaskCompletionSource<bool> tcs,
107             CancellationToken cancellationToken, int durationMilliseconds)
108         {
109             if (durationMilliseconds == -1)
110             {
111                 return;
112             }
113
114             try
115             {
116                 await Task.Delay(durationMilliseconds, cancellationToken);
117                 tcs.TrySetResult(true);
118             }
119             catch (TaskCanceledException)
120             {
121             }
122         }
123
124         private static IDisposable RegisterCancellationAction(TaskCompletionSource<bool> tcs,
125             CancellationToken cancellationToken, int id)
126         {
127             if (cancellationToken.CanBeCanceled == false)
128             {
129                 return null;
130             }
131
132             return cancellationToken.Register(() =>
133             {
134                 Native.Stop(id).Validate("Failed to cancel");
135                 tcs.TrySetCanceled();
136             });
137         }
138     }
139 }
140