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