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