[AudioManager] Add new class for audio ducking (#979)
[platform/core/csapi/tizenfx.git] / src / Tizen.Multimedia / AudioManager / AudioDucking.cs
1 /*
2  * Copyright (c) 2019 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.Diagnostics;
19
20 namespace Tizen.Multimedia
21 {
22     /// <summary>
23     /// Provides the ability to control audio ducking.
24     /// </summary>
25     /// <seealso cref="AudioManager"/>
26     /// <since_tizen> 6 </since_tizen>
27     public sealed class AudioDucking : IDisposable
28     {
29         private AudioDuckingHandle _handle;
30         private bool _disposed = false;
31         private Interop.AudioDucking.DuckingStateChangedCallback _duckingStateChangedCallback;
32
33         /// <summary>
34         /// Initializes a new instance of the <see cref="AudioDucking"/> class with <see cref="AudioStreamType"/>.
35         /// </summary>
36         /// <param name="targetType">The type of sound stream to be affected by this new instance.</param>
37         /// <exception cref="ArgumentException"><paramref name="targetType"/> is invalid.</exception>
38         /// <exception cref="InvalidOperationException">Operation failed; internal error.</exception>
39         /// <since_tizen> 6 </since_tizen>
40         public AudioDucking(AudioStreamType targetType)
41         {
42             ValidationUtil.ValidateEnum(typeof(AudioStreamType), targetType, nameof(targetType));
43
44             _duckingStateChangedCallback = (AudioDuckingHandle ducking, bool isDucked, IntPtr _) =>
45             {
46                 DuckingStateChanged?.Invoke(this,
47                     new AudioDuckingStateChangedEventArgs(IsDucked));
48             };
49
50             Interop.AudioDucking.Create(targetType, _duckingStateChangedCallback,
51                 IntPtr.Zero, out _handle).ThrowIfError("Unable to create stream ducking");
52
53             Debug.Assert(_handle != null);
54         }
55
56         /// <summary>
57         /// Occurs when the ducking state is changed.
58         /// </summary>
59         /// <since_tizen> 6 </since_tizen>
60         public event EventHandler<AudioDuckingStateChangedEventArgs> DuckingStateChanged;
61
62         /// <summary>
63         /// Gets the ducking state of the stream.
64         /// </summary>
65         /// <value>true if the audio stream is ducked; otherwise, false.</value>
66         /// <exception cref="InvalidOperationException">Operation failed; internal error.</exception>
67         /// <exception cref="ObjectDisposedException">The <see cref="AudioDucking"/> has already been disposed of.</exception>
68         /// <since_tizen> 6 </since_tizen>
69         public bool IsDucked
70         {
71             get
72             {
73                 if (_disposed)
74                 {
75                     throw new ObjectDisposedException(nameof(AudioDucking));
76                 }
77
78                 Interop.AudioDucking.IsDucked(Handle, out bool isDucked).
79                     ThrowIfError("Failed to get the running state of the device");
80
81                 return isDucked;
82             }
83         }
84
85         /// <summary>
86         /// Activate audio ducking
87         /// </summary>
88         /// <param name="duration">The duration(milisecond) for ducking.</param>
89         /// <param name="ratio">The volume ratio when ducked.</param>
90         /// <remarks>To activate ducking, the specified privilege is required.</remarks>
91         /// <privilege>http://tizen.org/privilege/volume.set</privilege>
92         /// <exception cref="ArgumentOutOfRangeException">
93         ///     <paramref name="duration"/> is less than 0 or greater than 3000.<br/>
94         ///     -or-<br/>
95         ///     <paramref name="ratio"/> is less than 0.0 or greater than or equal to 1.0.<br/>
96         /// </exception>
97         /// <exception cref="InvalidOperationException">
98         ///     Operation failed; internal error.<br/>
99         ///     -or-<br/>
100         ///     The target stream is already ducked.
101         /// </exception>
102         /// <exception cref="UnauthorizedAccessException">The caller does not have required privilege to set volume.</exception>
103         /// <exception cref="ObjectDisposedException">The <see cref="AudioDucking"/> has already been disposed of.</exception>
104         /// <since_tizen> 6 </since_tizen>
105         public void Activate(uint duration, double ratio)
106         {
107             if (_disposed)
108             {
109                 throw new ObjectDisposedException(nameof(AudioDucking));
110             }
111
112             if (duration < 0 || duration > 3000)
113             {
114                 throw new ArgumentOutOfRangeException(nameof(duration), duration, "Valid range : 0 <= duration <= 3000");
115             }
116
117             if (ratio < 0.0 || ratio >= 1.0)
118             {
119                 throw new ArgumentOutOfRangeException(nameof(ratio), ratio, "Valid range : 0 <= ratio < 1.0");
120             }
121
122             Interop.AudioDucking.Activate(Handle, duration, ratio).
123                 ThrowIfError("Failed to activate ducking");
124         }
125
126         /// <summary>
127         /// Deactivate audio ducking
128         /// </summary>
129         /// <remarks>To deactivate ducking, the specified privilege is required.</remarks>
130         /// <privilege>http://tizen.org/privilege/volume.set</privilege>
131         /// <exception cref="InvalidOperationException">
132         ///     Operation failed; internal error.<br/>
133         ///     -or-<br/>
134         ///     The target stream is already unducked.
135         /// </exception>
136         /// <exception cref="UnauthorizedAccessException">The caller does not have required privilege to set volume.</exception>
137         /// <exception cref="ObjectDisposedException">The <see cref="AudioDucking"/> has already been disposed of.</exception>
138         /// <since_tizen> 6 </since_tizen>
139         public void Deactivate()
140         {
141             if (_disposed)
142             {
143                 throw new ObjectDisposedException(nameof(AudioDucking));
144             }
145
146             Interop.AudioDucking.Deactivate(Handle).
147                 ThrowIfError("Failed to deactivate ducking");
148         }
149
150         /// <summary>
151         /// Releases all resources used by the <see cref="AudioDucking"/>.
152         /// </summary>
153         /// <since_tizen> 6 </since_tizen>
154         public void Dispose()
155         {
156             if (_disposed)
157             {
158                 return;
159             }
160
161             if (_handle != null)
162             {
163                 _handle.Dispose();
164             }
165
166             _disposed = true;
167             GC.SuppressFinalize(this);
168         }
169
170         internal AudioDuckingHandle Handle
171         {
172             get
173             {
174                 if (_disposed)
175                 {
176                     throw new ObjectDisposedException(nameof(AudioDucking));
177                 }
178                 return _handle;
179             }
180         }
181     }
182 }