[Bluetooth][Non-ACR] Add the exception handling logic (#2021)
[platform/core/csapi/tizenfx.git] / src / Tizen.Network.Bluetooth / Tizen.Network.Bluetooth / BluetoothAudioImpl.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
19 namespace Tizen.Network.Bluetooth
20 {
21     internal class BluetoothAudioImpl : IDisposable
22     {
23         private event EventHandler<AudioConnectionStateChangedEventArgs> _audioConnectionChanged;
24         private Interop.Bluetooth.AudioConnectionStateChangedCallback _audioConnectionChangedCallback;
25
26         private event EventHandler<AgScoStateChangedEventArgs> _agScoStateChanged;
27         private Interop.Bluetooth.AgScoStateChangedCallback _agScoStateChangedCallback;
28
29         private static readonly Lazy<BluetoothAudioImpl> _instance = new Lazy<BluetoothAudioImpl>(() =>
30         {
31             return new BluetoothAudioImpl();
32         });
33         private bool disposed = false;
34
35         internal event EventHandler<AudioConnectionStateChangedEventArgs> AudioConnectionStateChanged
36         {
37             add
38             {
39                 if (_audioConnectionChanged == null)
40                 {
41                     RegisterAudioConnectionChangedEvent();
42                 }
43                 _audioConnectionChanged += value;
44             }
45             remove
46             {
47                 _audioConnectionChanged -= value;
48                 if (_audioConnectionChanged == null)
49                 {
50                     UnregisterAudioConnectionChangedEvent();
51                 }
52             }
53         }
54
55         private void RegisterAudioConnectionChangedEvent()
56         {
57             _audioConnectionChangedCallback = (int result, bool connected, string deviceAddress, int profileType, IntPtr userData) =>
58             {
59                 _audioConnectionChanged?.Invoke(this, new AudioConnectionStateChangedEventArgs(result, connected, deviceAddress, (BluetoothAudioProfileType)profileType));
60             };
61             int ret = Interop.Bluetooth.SetAudioConnectionStateChangedCallback(_audioConnectionChangedCallback, IntPtr.Zero);
62             if (ret != (int)BluetoothError.None)
63             {
64                 Log.Error(Globals.LogTag, "Failed to set audio connection changed callback, Error - " + (BluetoothError)ret);
65             }
66         }
67
68         private void UnregisterAudioConnectionChangedEvent()
69         {
70             int ret = Interop.Bluetooth.UnsetAudioConnectionStateChangedCallback();
71             if (ret != (int)BluetoothError.None)
72             {
73                 Log.Error(Globals.LogTag, "Failed to unset audio connection changed callback, Error - " + (BluetoothError)ret);
74             }
75         }
76
77         internal int Connect(string deviceAddress, BluetoothAudioProfileType type)
78         {
79             int ret = Interop.Bluetooth.Connect(deviceAddress, (int)type);
80             if (ret != (int)BluetoothError.None)
81             {
82                 Log.Error(Globals.LogTag, "Failed to connect device with the given profile type, Error - " + (BluetoothError)ret);
83             }
84             return ret;
85         }
86
87         internal int Disconnect(string deviceAddress, BluetoothAudioProfileType type)
88         {
89             int ret = Interop.Bluetooth.Disconnect(deviceAddress, (int)type);
90             if (ret != (int)BluetoothError.None)
91             {
92                 Log.Error(Globals.LogTag, "Failed to disconnect device with the given profile type, Error - " + (BluetoothError)ret);
93             }
94             return ret;
95         }
96
97         internal void OpenAgSco()
98         {
99             if (Globals.IsAudioInitialize)
100             {
101                 int ret = Interop.Bluetooth.OpenAgSco();
102                 if (ret != (int)BluetoothError.None)
103                 {
104                     Log.Error(Globals.LogTag, "Failed to open ag sco to remote device, Error - " + (BluetoothError)ret);
105                     BluetoothErrorFactory.ThrowBluetoothException(ret);
106                 }
107             }
108             else
109             {
110                 BluetoothErrorFactory.ThrowBluetoothException((int)BluetoothError.NotInitialized);
111             }   
112         }
113
114         internal void CloseAgSco()
115         {
116             if (Globals.IsAudioInitialize)
117             {
118                 int ret = Interop.Bluetooth.CloseAgSco();
119                 if (ret != (int)BluetoothError.None)
120                 {
121                     Log.Error(Globals.LogTag, "Failed to close ag sco to remote device, Error - " + (BluetoothError)ret);
122                     BluetoothErrorFactory.ThrowBluetoothException(ret);
123                 }
124             }
125             else
126             {
127                 BluetoothErrorFactory.ThrowBluetoothException((int)BluetoothError.NotInitialized);
128             }
129         }
130
131         internal bool IsAgScoOpened
132         {
133             get
134             {
135                 bool isOpened;
136                 int ret = Interop.Bluetooth.IsAgScoOpened(out isOpened);
137                 if (ret != (int)BluetoothError.None)
138                 {
139                     Log.Error(Globals.LogTag, "Failed to check whether an opened SCO exists or not., Error - " + (BluetoothError)ret);
140                 }
141                 return isOpened;
142             }
143         }
144
145         internal event EventHandler<AgScoStateChangedEventArgs> AgScoStateChanged
146         {
147             add
148             {
149                 if (_agScoStateChanged == null)
150                 {
151                     RegisterAgScoStateChangedEvent();
152                 }
153                 _agScoStateChanged += value;
154             }
155             remove
156             {
157                 _agScoStateChanged -= value;
158                 if (_agScoStateChanged == null)
159                 {
160                     UnregisterAgScoStateChangedEvent();
161                 }
162             }
163         }
164
165         private void RegisterAgScoStateChangedEvent()
166         {
167             _agScoStateChangedCallback = (int result, bool opened, IntPtr userData) =>
168             {
169                 _agScoStateChanged?.Invoke(null, new AgScoStateChangedEventArgs(opened));
170             };
171
172             int ret = Interop.Bluetooth.SetAgScoStateChangedCallback(_agScoStateChangedCallback, IntPtr.Zero);
173             if (ret != (int)BluetoothError.None)
174             {
175                 Log.Error(Globals.LogTag, "Failed to set ag sco state changed callback, Error - " + (BluetoothError)ret);
176             }
177         }
178
179         private void UnregisterAgScoStateChangedEvent()
180         {
181             int ret = Interop.Bluetooth.UnsetAgScoStateChangedCallback();
182             if (ret != (int)BluetoothError.None)
183             {
184                 Log.Error(Globals.LogTag, "Failed to unset ag sco state changed callback, Error - " + (BluetoothError)ret);
185             }
186         }
187
188         internal void NotifyAgVoiceRecognitionState(bool enable)
189         {
190             if (Globals.IsAudioInitialize)
191             {
192                 int ret = Interop.Bluetooth.NotifyAgVoiceRecognitionState(enable);
193                 if (ret != (int)BluetoothError.None)
194                 {
195                     Log.Error(Globals.LogTag, "Failed to notify sco voice recognition state, Error - " + (BluetoothError)ret);
196                     BluetoothErrorFactory.ThrowBluetoothException(ret);
197                 }
198             }
199             else
200             {
201                 BluetoothErrorFactory.ThrowBluetoothException((int)BluetoothError.NotInitialized);
202             }
203         }
204
205         internal static BluetoothAudioImpl Instance
206         {
207             get
208             {
209                 return _instance.Value;
210             }
211         }
212
213         private BluetoothAudioImpl ()
214         {
215             Log.Info(Globals.LogTag, "Initializing audio");
216             initialize();
217         }
218
219         ~BluetoothAudioImpl()
220         {
221             Dispose(false);
222         }
223
224         public void Dispose()
225         {
226             Dispose(true);
227             GC.SuppressFinalize(this);
228         }
229
230         private void Dispose(bool disposing)
231         {
232             if (disposed)
233                 return;
234
235             if (disposing)
236             {
237                 // Free managed objects.
238             }
239             //Free unmanaged objects
240             deinitialize();
241             RemoveAllRegisteredEvent();
242             disposed = true;
243         }
244
245         private void initialize()
246         {
247             if (Globals.IsInitialize)
248             {
249                 int ret = Interop.Bluetooth.InitializeAudio ();
250                 if (ret != (int)BluetoothError.None)
251                 {
252                     Log.Error(Globals.LogTag, "Failed to initialize bluetoothaudio, Error - " + (BluetoothError)ret);
253                     Globals.IsAudioInitialize = false;
254                     BluetoothErrorFactory.ThrowBluetoothException (ret);
255                 }
256                 else
257                 {
258                     Globals.IsAudioInitialize = true;
259                 }
260             }
261             else
262             {
263                 BluetoothErrorFactory.ThrowBluetoothException((int)BluetoothError.NotInitialized);
264             }
265         }
266
267         private void deinitialize()
268         {
269             if (Globals.IsAudioInitialize) {
270                 int ret = Interop.Bluetooth.DeinitializeAudio ();
271                 if (ret != (int)BluetoothError.None) {
272                     Log.Error (Globals.LogTag, "Failed to deinitialize bluetoothaudio, Error - " + (BluetoothError)ret);
273                 }
274             }
275         }
276
277         private void RemoveAllRegisteredEvent()
278         {
279             if (_audioConnectionChanged != null)
280             {
281                 UnregisterAudioConnectionChangedEvent();
282             }
283         }
284     }
285 }