matrixbirds 5 лет назад
Родитель
Сommit
bb0fa6f200

+ 74
- 0
android/src/main/java/com/syan/agora/AgoraConst.java Просмотреть файл

@@ -0,0 +1,74 @@
1
+package com.syan.agora;
2
+
3
+public class AgoraConst {
4
+
5
+    public final static String AG_PREFIX = "ag_rtc";
6
+    public final static String AGWarning = "warning";
7
+    public final static String AGError = "error";
8
+    public final static String AGApiCallExecute = "apiCallExecute";
9
+    public final static String AGJoinChannelSuccess = "joinChannelSuccess";
10
+    public final static String AGRejoinChannelSuccess = "rejoinChannelSuccess";
11
+    public final static String AGLeaveChannel = "leaveChannel";
12
+    public final static String AGClientRoleChanged = "clientRoleChanged";
13
+    public final static String AGUserJoined = "userJoined";
14
+    public final static String AGUserOffline = "userOffline";
15
+    public final static String AGConnectionStateChanged = "connectionStateChanged";
16
+    public final static String AGConnectionLost = "connectionLost";
17
+    public final static String AGTokenPrivilegeWillExpire = "tokenPrivilegeWillExpire";
18
+    public final static String AGRequestToken = "requestToken";
19
+
20
+    public final static String AGMicrophoneEnabled = "microphoneEnabled";
21
+    public final static String AGAudioVolumeIndication = "audioVolumeIndication";
22
+    public final static String AGActiveSpeaker = "activeSpeaker";
23
+    public final static String AGFirstLocalAudioFrame = "firstLocalAudioFrame";
24
+    public final static String AGFirstRemoteAudioFrame = "firstRemoteAudioFrame";
25
+    public final static String AGVideoStopped = "videoStopped";
26
+    public final static String AGFirstLocalVideoFrame = "firstLocalVideoFrame";
27
+    public final static String AGFirstRemoteVideoDecoded = "firstRemoteVideoDecoded";
28
+    public final static String AGFirstRemoteVideoFrame = "firstRemoteVideoFrame";
29
+    public final static String AGUserMuteAudio = "userMuteAudio";
30
+    public final static String AGUserMuteVideo = "userMuteVideo";
31
+    public final static String AGUserEnableVideo = "userEnableVideo";
32
+    public final static String AGUserEnableLocalVideo = "userEnableLocalVideo";
33
+    public final static String AGVideoSizeChanged = "videoSizeChanged";
34
+    public final static String AGRtmpStreamingStateChanged = "rtmpStreamingStateChanged";
35
+    public final static String AGNetworkTypeChanged = "networkTypeChanged";
36
+    public final static String AGFirstRemoteAudioDecoded = "firstRemoteAudioDecoded";
37
+    public final static String AGMediaMetaDataReceived = "mediaMetaDataReceived";
38
+    public final static String AGLocalVideoChanged = "localVideoChanged";
39
+    public final static String AGRemoteVideoStateChanged = "remoteVideoStateChanged";
40
+    public final static String AGLocalPublishFallbackToAudioOnly = "localPublishFallbackToAudioOnly";
41
+    public final static String AGRemoteSubscribeFallbackToAudioOnly = "remoteSubscribeFallbackToAudioOnly";
42
+
43
+    public final static String AGAudioRouteChanged = "audioRouteChanged";
44
+    public final static String AGCameraReady = "cameraReady";
45
+    public final static String AGCameraFocusAreaChanged = "cameraFocusAreaChanged";
46
+    public final static String AGCameraExposureAreaChanged = "cameraExposureAreaChanged";
47
+
48
+    public final static String AGRtcStats = "rtcStats";
49
+    public final static String AGLastmileQuality = "lastmileQuality";
50
+    public final static String AGNetworkQuality = "networkQuality";
51
+    public final static String AGLocalVideoStats = "localVideoStats";
52
+    public final static String AGRemoteVideoStats = "remoteVideoStats";
53
+    public final static String AGRemoteAudioStats = "remoteAudioStats";
54
+    public final static String AGAudioTransportStatsOfUid = "audioTransportStatsOfUid";
55
+    public final static String AGVideoTransportStatsOfUid = "videoTransportStatsOfUid";
56
+
57
+    public final static String AGRemoteAudioMixingStart = "remoteAudioMixingStart";
58
+    public final static String AGRemoteAudioMixingFinish = "remoteAudioMixingFinish";
59
+    public final static String AGAudioEffectFinish = "audioEffectFinish";
60
+    public final static String AGAudioMixingStateChanged = "audioMixingStateChanged";
61
+
62
+    public final static String AGStreamPublished = "streamPublished";
63
+    public final static String AGStreamUnpublish = "streamUnpublish";
64
+    public final static String AGTranscodingUpdate = "transcodingUpdate";
65
+
66
+    public final static String AGStreamInjectedStatus = "streamInjectedStatus";
67
+
68
+    public final static String AGReceiveStreamMessage = "receiveStreamMessage";
69
+    public final static String AGOccurStreamMessageError = "occurStreamMessageError";
70
+
71
+    public final static String AGMediaEngineLoaded = "mediaEngineLoaded";
72
+    public final static String AGMediaEngineStartCall = "mediaEngineStartCall";
73
+    public final static String AGLastmileProbeResult = "lastmileProbeTestResult";
74
+}

+ 0
- 0
android/src/main/java/com/syan/agora/AgoraManager.java Просмотреть файл


+ 5
- 69
android/src/main/java/com/syan/agora/AgoraModule.java Просмотреть файл

@@ -36,6 +36,7 @@ import io.agora.rtc.video.CameraCapturerConfiguration;
36 36
 import io.agora.rtc.video.VideoEncoderConfiguration;
37 37
 
38 38
 import static com.facebook.react.bridge.UiThreadUtil.runOnUiThread;
39
+import static com.syan.agora.AgoraConst.*;
39 40
 
40 41
 public class AgoraModule extends ReactContextBaseJavaModule {
41 42
 
@@ -259,74 +260,7 @@ public class AgoraModule extends ReactContextBaseJavaModule {
259 260
         return constants;
260 261
     }
261 262
 
262
-    private final static String AGWarning = "warning";
263
-    private final static String AGError = "error";
264
-    private final static String AGApiCallExecute = "apiCallExecute";
265
-    private final static String AGJoinChannelSuccess = "joinChannelSuccess";
266
-    private final static String AGRejoinChannelSuccess = "rejoinChannelSuccess";
267
-    private final static String AGLeaveChannel = "leaveChannel";
268
-    private final static String AGClientRoleChanged = "clientRoleChanged";
269
-    private final static String AGUserJoined = "userJoined";
270
-    private final static String AGUserOffline = "userOffline";
271
-    private final static String AGConnectionStateChanged = "connectionStateChanged";
272
-    private final static String AGConnectionLost = "connectionLost";
273
-    private final static String AGTokenPrivilegeWillExpire = "tokenPrivilegeWillExpire";
274
-    private final static String AGRequestToken = "requestToken";
275
-
276
-    private final static String AGMicrophoneEnabled = "microphoneEnabled";
277
-    private final static String AGAudioVolumeIndication = "audioVolumeIndication";
278
-    private final static String AGActiveSpeaker = "activeSpeaker";
279
-    private final static String AGFirstLocalAudioFrame = "firstLocalAudioFrame";
280
-    private final static String AGFirstRemoteAudioFrame = "firstRemoteAudioFrame";
281
-    private final static String AGVideoStopped = "videoStopped";
282
-    private final static String AGFirstLocalVideoFrame = "firstLocalVideoFrame";
283
-    private final static String AGFirstRemoteVideoDecoded = "firstRemoteVideoDecoded";
284
-    private final static String AGFirstRemoteVideoFrame = "firstRemoteVideoFrame";
285
-    private final static String AGUserMuteAudio = "userMuteAudio";
286
-    private final static String AGUserMuteVideo = "userMuteVideo";
287
-    private final static String AGUserEnableVideo = "userEnableVideo";
288
-    private final static String AGUserEnableLocalVideo = "userEnableLocalVideo";
289
-    private final static String AGVideoSizeChanged = "videoSizeChanged";
290
-    private final static String AGRtmpStreamingStateChanged = "rtmpStreamingStateChanged";
291
-    private final static String AGNetworkTypeChanged = "networkTypeChanged";
292
-    private final static String AGFirstRemoteAudioDecoded = "firstRemoteAudioDecoded";
293
-    private final static String AGMediaMetaDataReceived = "mediaMetaDataReceived";
294
-    private final static String AGLocalVideoChanged = "localVideoChanged";
295
-    private final static String AGRemoteVideoStateChanged = "remoteVideoStateChanged";
296
-    private final static String AGLocalPublishFallbackToAudioOnly = "localPublishFallbackToAudioOnly";
297
-    private final static String AGRemoteSubscribeFallbackToAudioOnly = "remoteSubscribeFallbackToAudioOnly";
298
-
299
-    private final static String AGAudioRouteChanged = "audioRouteChanged";
300
-    private final static String AGCameraReady = "cameraReady";
301
-    private final static String AGCameraFocusAreaChanged = "cameraFocusAreaChanged";
302
-    private final static String AGCameraExposureAreaChanged = "cameraExposureAreaChanged";
303
-
304
-    private final static String AGRtcStats = "rtcStats";
305
-    private final static String AGLastmileQuality = "lastmileQuality";
306
-    private final static String AGNetworkQuality = "networkQuality";
307
-    private final static String AGLocalVideoStats = "localVideoStats";
308
-    private final static String AGRemoteVideoStats = "remoteVideoStats";
309
-    private final static String AGRemoteAudioStats = "remoteAudioStats";
310
-    private final static String AGAudioTransportStatsOfUid = "audioTransportStatsOfUid";
311
-    private final static String AGVideoTransportStatsOfUid = "videoTransportStatsOfUid";
312
-
313
-    private final static String AGRemoteAudioMixingStart = "remoteAudioMixingStart";
314
-    private final static String AGRemoteAudioMixingFinish = "remoteAudioMixingFinish";
315
-    private final static String AGAudioEffectFinish = "audioEffectFinish";
316
-    private final static String AGAudioMixingStateChanged = "audioMixingStateChanged";
317
-
318
-    private final static String AGStreamPublished = "streamPublished";
319
-    private final static String AGStreamUnpublish = "streamUnpublish";
320
-    private final static String AGTranscodingUpdate = "transcodingUpdate";
321
-
322
-    private final static String AGStreamInjectedStatus = "streamInjectedStatus";
323
-
324
-    private final static String AGReceiveStreamMessage = "receiveStreamMessage";
325
-    private final static String AGOccurStreamMessageError = "occurStreamMessageError";
326
-
327
-    private final static String AGMediaEngineLoaded = "mediaEngineLoaded";
328
-    private final static String AGMediaEngineStartCall = "mediaEngineStartCall";
329
-    private final static String AGLastmileProbeResult = "lastmileProbeTestResult";
263
+
330 264
 //    private final static String AGIntervalTest = "startEchoTestWithInterval";
331 265
 
332 266
     private MediaObserver mediaObserver = null;
@@ -2742,8 +2676,10 @@ public class AgoraModule extends ReactContextBaseJavaModule {
2742 2676
     private void sendEvent(ReactContext reactContext,
2743 2677
                            String eventName,
2744 2678
                            @Nullable WritableMap params) {
2679
+        StringBuffer agoraEvtName = new StringBuffer(AG_PREFIX);
2680
+        agoraEvtName.append(eventName);
2745 2681
         reactContext
2746 2682
                 .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
2747
-                .emit(eventName, params);
2683
+                .emit(agoraEvtName.toString(), params);
2748 2684
     }
2749 2685
 }

+ 3
- 0
ios/RCTAgora/AgoraConst.h Просмотреть файл

@@ -8,6 +8,8 @@
8 8
 
9 9
 #import <AgoraRtcEngineKit/AgoraRtcEngineKit.h>
10 10
 
11
+static NSString *AG_PREFIX = @"ag_rtc";
12
+
11 13
 static NSString *RCTAgoraErrorDomain = @"RCTAgoraErrorDomain";
12 14
 
13 15
 static NSString *AGWarning = @"warning";
@@ -97,4 +99,5 @@ typedef NS_ENUM(NSInteger, AgoraModeType) {
97 99
 
98 100
 + (instancetype)share;
99 101
 
102
++ (NSArray<NSString*> *) supportEvents;
100 103
 @end

+ 80
- 0
ios/RCTAgora/AgoraConst.m Просмотреть файл

@@ -27,6 +27,86 @@ static AgoraConst *_person;
27 27
   return _person;
28 28
 }
29 29
 
30
++ (NSArray<NSString*>*) supportEvents {
31
+    NSArray<NSString*>* array = @[AGWarning,
32
+                                  AGError,
33
+                                  AGApiCallExecute,
34
+                                  AGJoinChannelSuccess,
35
+                                  AGRejoinChannelSuccess,
36
+                                  AGLeaveChannel,
37
+                                  AGClientRoleChanged,
38
+                                  AGUserJoined,
39
+                                  AGUserOffline,
40
+                                  AGConnectionStateChanged,
41
+                                  AGConnectionLost,
42
+                                  AGTokenPrivilegeWillExpire,
43
+                                  AGRequestToken,
44
+                                  
45
+                                  AGMicrophoneEnabled,
46
+                                  AGAudioVolumeIndication,
47
+                                  AGActiveSpeaker,
48
+                                  AGFirstLocalAudioFrame,
49
+                                  AGFirstRemoteAudioFrame,
50
+                                  AGFirstRemoteAudioDecoded,
51
+                                  AGVideoStopped,
52
+                                  AGFirstLocalVideoFrame,
53
+                                  AGFirstRemoteVideoDecoded,
54
+                                  AGFirstRemoteVideoFrame,
55
+                                  AGUserMuteAudio,
56
+                                  AGUserMuteVideo,
57
+                                  AGUserEnableVideo,
58
+                                  AGUserEnableLocalVideo,
59
+                                  AGVideoSizeChanged,
60
+                                  AGRemoteVideoStateChanged,
61
+                                  AGLocalPublishFallbackToAudioOnly,
62
+                                  AGRemoteSubscribeFallbackToAudioOnly,
63
+                                  
64
+                                  AGAudioRouteChanged,
65
+                                  AGCameraReady,
66
+                                  AGCameraFocusAreaChanged,
67
+                                  AGCameraExposureAreaChanged,
68
+                                  
69
+                                  AGRtcStats,
70
+                                  AGLastmileQuality,
71
+                                  AGNetworkQuality,
72
+                                  AGLocalVideoStats,
73
+                                  AGRemoteVideoStats,
74
+                                  AGRemoteAudioStats,
75
+                                  AGAudioTransportStatsOfUid,
76
+                                  AGVideoTransportStatsOfUid,
77
+                                  
78
+                                  AGAudioMixingStateChanged,
79
+                                  AGRemoteAudioMixingStart,
80
+                                  AGRemoteAudioMixingFinish,
81
+                                  AGAudioEffectFinish,
82
+                                  
83
+                                  AGStreamPublished,
84
+                                  AGStreamUnpublish,
85
+                                  AGTranscodingUpdate,
86
+                                  
87
+                                  AGStreamInjectedStatus,
88
+                                  
89
+                                  AGReceiveStreamMessage,
90
+                                  AGOccurStreamMessageError,
91
+                                  
92
+                                  AGMediaEngineLoaded,
93
+                                  AGMediaEngineStartCall,
94
+                                  AGIntervalTest,
95
+                                  AGLastmileProbeTestResult,
96
+                                  AGRtmpStreamingStateChanged,
97
+                                  AGLocalVideoChanged,
98
+                                  AGNetworkTypeChanged,
99
+                                  AGFirstRemoteAudioFrame,
100
+                                  AGMediaMetaDataReceived];
101
+  
102
+  NSMutableArray<NSString *> *eventList = [NSMutableArray arrayWithCapacity:[array count]];
103
+  [eventList enumerateObjectsUsingBlock:^(NSString * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
104
+    id mapObj = [NSString stringWithFormat:@"%@%@", AG_PREFIX, obj];
105
+    [eventList addObject:mapObj];
106
+  }];
107
+  return eventList;
108
+}
109
+
30 110
 - (id)copyWithZone:(NSZone *)zone {
31 111
   return _person;
32 112
 }

+ 4
- 73
ios/RCTAgora/RCTAgora.m Просмотреть файл

@@ -1998,84 +1998,15 @@ RCT_EXPORT_METHOD(registerMediaMetadataObserver
1998 1998
   }
1999 1999
 }
2000 2000
 
2001
+
2001 2002
 - (NSArray<NSString *> *)supportedEvents {
2002
-  return @[
2003
-           AGWarning,
2004
-           AGError,
2005
-           AGApiCallExecute,
2006
-           AGJoinChannelSuccess,
2007
-           AGRejoinChannelSuccess,
2008
-           AGLeaveChannel,
2009
-           AGClientRoleChanged,
2010
-           AGUserJoined,
2011
-           AGUserOffline,
2012
-           AGConnectionStateChanged,
2013
-           AGConnectionLost,
2014
-           AGTokenPrivilegeWillExpire,
2015
-           AGRequestToken,
2016
-           
2017
-           AGMicrophoneEnabled,
2018
-           AGAudioVolumeIndication,
2019
-           AGActiveSpeaker,
2020
-           AGFirstLocalAudioFrame,
2021
-           AGFirstRemoteAudioFrame,
2022
-           AGFirstRemoteAudioDecoded,
2023
-           AGVideoStopped,
2024
-           AGFirstLocalVideoFrame,
2025
-           AGFirstRemoteVideoDecoded,
2026
-           AGFirstRemoteVideoFrame,
2027
-           AGUserMuteAudio,
2028
-           AGUserMuteVideo,
2029
-           AGUserEnableVideo,
2030
-           AGUserEnableLocalVideo,
2031
-           AGVideoSizeChanged,
2032
-           AGRemoteVideoStateChanged,
2033
-           AGLocalPublishFallbackToAudioOnly,
2034
-           AGRemoteSubscribeFallbackToAudioOnly,
2035
-           
2036
-           AGAudioRouteChanged,
2037
-           AGCameraReady,
2038
-           AGCameraFocusAreaChanged,
2039
-           AGCameraExposureAreaChanged,
2040
-           
2041
-           AGRtcStats,
2042
-           AGLastmileQuality,
2043
-           AGNetworkQuality,
2044
-           AGLocalVideoStats,
2045
-           AGRemoteVideoStats,
2046
-           AGRemoteAudioStats,
2047
-           AGAudioTransportStatsOfUid,
2048
-           AGVideoTransportStatsOfUid,
2049
-           
2050
-           AGAudioMixingStateChanged,
2051
-           AGRemoteAudioMixingStart,
2052
-           AGRemoteAudioMixingFinish,
2053
-           AGAudioEffectFinish,
2054
-           
2055
-           AGStreamPublished,
2056
-           AGStreamUnpublish,
2057
-           AGTranscodingUpdate,
2058
-           
2059
-           AGStreamInjectedStatus,
2060
-           
2061
-           AGReceiveStreamMessage,
2062
-           AGOccurStreamMessageError,
2063
-           
2064
-           AGMediaEngineLoaded,
2065
-           AGMediaEngineStartCall,
2066
-           AGIntervalTest,
2067
-           AGLastmileProbeTestResult,
2068
-           AGRtmpStreamingStateChanged,
2069
-           AGLocalVideoChanged,
2070
-           AGNetworkTypeChanged,
2071
-           AGFirstRemoteAudioFrame,
2072
-           AGMediaMetaDataReceived
2073
-           ];
2003
+  return [AgoraConst supportEvents];
2074 2004
 }
2075 2005
 
2076 2006
 - (void) sendEvent:(NSString *)msg params:(NSDictionary *)params {
2077 2007
   if (hasListeners) {
2078
-    [self sendEventWithName:msg body:params];
2008
+    NSString *evtName = [NSString stringWithFormat:@"%@%@", AG_PREFIX, msg];
2009
+    [self sendEventWithName:evtName body:params];
2079 2010
   }
2080 2011
 }
2081 2012
 

+ 1
- 16
lib/RtcEngine.native.d.ts Просмотреть файл

@@ -7,7 +7,7 @@ import { Option, Callback, AudioMixingOption, DataStreamOption, PlayEffectOption
7 7
  * Other methods of the RtcEngine object serve for agora native sdk and set up error logging.
8 8
  */
9 9
 declare class RtcEngine {
10
-    private static eventTypes;
10
+    private static readonly AG_PREFIX;
11 11
     /**
12 12
      * Creates a RtcEngine Object internal.
13 13
      *
@@ -35,21 +35,6 @@ declare class RtcEngine {
35 35
      * @param listener
36 36
      */
37 37
     static on(eventType: string, listener: (...args: any[]) => any): void;
38
-    /**
39
-     * remove event listeners
40
-     *
41
-     * This method unsubscribes specified eventType related all listeners. You should call this method when you want to unsubscribe some eventType.
42
-     * @param eventType
43
-     */
44
-    static off(eventType: string): void;
45
-    /**
46
-     * remove all events listeners
47
-     *
48
-     * This method unsubscribes all eventTypes related listeners.
49
-     *
50
-     * @param token
51
-     */
52
-    static removeAllListeners(): void;
53 38
     /**
54 39
      * renew token
55 40
      *

+ 2
- 26
lib/RtcEngine.native.js Просмотреть файл

@@ -43,31 +43,7 @@ class RtcEngine {
43 43
      * @param listener
44 44
      */
45 45
     static on(eventType, listener) {
46
-        this.eventTypes.add(eventType);
47
-        AgoraEventEmitter.addListener(eventType, listener);
48
-    }
49
-    /**
50
-     * remove event listeners
51
-     *
52
-     * This method unsubscribes specified eventType related all listeners. You should call this method when you want to unsubscribe some eventType.
53
-     * @param eventType
54
-     */
55
-    static off(eventType) {
56
-        AgoraEventEmitter.removeListener(eventType, () => { });
57
-        this.eventTypes.delete(eventType);
58
-    }
59
-    /**
60
-     * remove all events listeners
61
-     *
62
-     * This method unsubscribes all eventTypes related listeners.
63
-     *
64
-     * @param token
65
-     */
66
-    static removeAllListeners() {
67
-        for (let eventType of this.eventTypes) {
68
-            AgoraEventEmitter.removeListener(eventType, () => { });
69
-        }
70
-        this.eventTypes.clear();
46
+        AgoraEventEmitter.addListener(`${RtcEngine.AG_PREFIX}${eventType}`, listener);
71 47
     }
72 48
     /**
73 49
      * renew token
@@ -1269,6 +1245,6 @@ class RtcEngine {
1269 1245
         });
1270 1246
     }
1271 1247
 }
1272
-RtcEngine.eventTypes = new Set();
1248
+RtcEngine.AG_PREFIX = 'ag_rtc';
1273 1249
 exports.default = RtcEngine;
1274 1250
 //# sourceMappingURL=RtcEngine.native.js.map

+ 1
- 1
lib/RtcEngine.native.js.map
Разница между файлами не показана из-за своего большого размера
Просмотреть файл


+ 2
- 28
src/RtcEngine.native.ts Просмотреть файл

@@ -40,7 +40,7 @@ const AgoraEventEmitter = new NativeEventEmitter(Agora);
40 40
  */
41 41
 class RtcEngine {
42 42
 
43
-    private static eventTypes: Set<string> = new Set<string>();
43
+    private static readonly AG_PREFIX: string = 'ag_rtc';
44 44
 
45 45
     /**
46 46
      * Creates a RtcEngine Object internal.
@@ -75,33 +75,7 @@ class RtcEngine {
75 75
      * @param listener
76 76
      */
77 77
     public static on(eventType: string, listener: (...args: any[]) => any) {
78
-        this.eventTypes.add(eventType);
79
-        AgoraEventEmitter.addListener(eventType, listener);
80
-    }
81
-
82
-    /**
83
-     * remove event listeners
84
-     *
85
-     * This method unsubscribes specified eventType related all listeners. You should call this method when you want to unsubscribe some eventType.
86
-     * @param eventType
87
-     */
88
-    public static off(eventType: string) {
89
-        AgoraEventEmitter.removeListener(eventType, () => {});
90
-        this.eventTypes.delete(eventType);
91
-    }
92
-
93
-    /**
94
-     * remove all events listeners
95
-     *
96
-     * This method unsubscribes all eventTypes related listeners.
97
-     *
98
-     * @param token
99
-     */
100
-    public static removeAllListeners() {
101
-        for (let eventType of this.eventTypes) {
102
-            AgoraEventEmitter.removeListener(eventType, () => {});
103
-        }
104
-        this.eventTypes.clear();
78
+        AgoraEventEmitter.addListener(`${RtcEngine.AG_PREFIX}${eventType}`, listener);
105 79
     }
106 80
 
107 81
     /**