소스 검색

Add connect/disconnect handling for mac-avcapture

Palana 11 년 전
부모
커밋
1df433e7cc
1개의 변경된 파일80개의 추가작업 그리고 5개의 파일을 삭제
  1. 80 5
      plugins/mac-avcapture/av-capture.m

+ 80 - 5
plugins/mac-avcapture/av-capture.m

@@ -49,6 +49,10 @@ struct av_capture {
 	dispatch_queue_t queue;
 	bool has_clock;
 
+	NSString *uid;
+	id connect_observer;
+	id disconnect_observer;
+
 	unsigned fourcc;
 	enum video_format video_format;
 
@@ -149,6 +153,9 @@ static void av_capture_destroy(void *data)
 	if (!capture)
 		return;
 
+	NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
+	[nc removeObserver:capture->connect_observer];
+	[nc removeObserver:capture->disconnect_observer];
 
 	remove_device(capture);
 	AVFREE(capture->out);
@@ -159,6 +166,8 @@ static void av_capture_destroy(void *data)
 	AVFREE(capture->delegate);
 	AVFREE(capture->session);
 
+	AVFREE(capture->uid);
+
 	bfree(capture);
 }
 
@@ -367,27 +376,90 @@ error_input:
 	AVFREE(capture->device);
 }
 
+static inline void handle_disconnect(struct av_capture* capture,
+		AVCaptureDevice *dev)
+{
+	if (!dev)
+		return;
+
+	if (![dev.uniqueID isEqualTo:capture->uid])
+		return;
+
+	if (!capture->device) {
+		AVLOG(LOG_ERROR, "Received disconnect for unused device '%s'",
+				capture->uid.UTF8String);
+		return;
+	}
+
+	AVLOG(LOG_ERROR, "Device with unique ID '%s' disconnected",
+			dev.uniqueID.UTF8String);
+
+	remove_device(capture);
+}
+
+static inline void handle_connect(struct av_capture *capture,
+		AVCaptureDevice *dev, obs_data_t settings)
+{
+	if (!dev)
+		return;
+
+	if (![dev.uniqueID isEqualTo:capture->uid])
+		return;
+
+	if (capture->device) {
+		AVLOG(LOG_ERROR, "Received connect for in-use device '%s'",
+				capture->uid.UTF8String);
+		return;
+	}
+
+	AVLOG(LOG_INFO, "Device with unique ID '%s' connected, "
+			"resuming capture", dev.uniqueID.UTF8String);
+
+	capture_device(capture, [dev retain], settings);
+}
+
 static void av_capture_init(struct av_capture *capture, obs_data_t settings)
 {
 	if (!init_session(capture))
 		return;
 
-	NSString *uid = get_string(settings, "device");
+	capture->uid = [get_string(settings, "device") retain];
+
+	NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
+	capture->disconnect_observer = [nc
+		addObserverForName:AVCaptureDeviceWasDisconnectedNotification
+			    object:nil
+			     queue:[NSOperationQueue mainQueue]
+			usingBlock:^(NSNotification *note)
+			{
+				handle_disconnect(capture, note.object);
+			}
+	];
+
+	capture->connect_observer = [nc
+		addObserverForName:AVCaptureDeviceWasConnectedNotification
+			    object:nil
+			     queue:[NSOperationQueue mainQueue]
+			usingBlock:^(NSNotification *note)
+			{
+				handle_connect(capture, note.object, settings);
+			}
+	];
 
 	AVCaptureDevice *dev =
-		[[AVCaptureDevice deviceWithUniqueID:uid] retain];
+		[[AVCaptureDevice deviceWithUniqueID:capture->uid] retain];
 
 	if (!dev) {
-		if (uid.length < 1)
+		if (capture->uid.length < 1)
 			AVLOG(LOG_ERROR, "No device selected");
 		else
 			AVLOG(LOG_ERROR, "Could not initialize device " \
 					"with unique ID '%s'",
-					uid.UTF8String);
+					capture->uid.UTF8String);
 		return;
 	}
 
-	init_with_device(capture, dev, settings);
+	capture_device(capture, dev, settings);
 }
 
 static void *av_capture_create(obs_data_t settings, obs_source_t source)
@@ -549,6 +621,9 @@ static void switch_device(struct av_capture *capture, NSString *uid,
 	if (capture->device)
 		remove_device(capture);
 
+	AVFREE(capture->uid);
+	capture->uid = [uid retain];
+
 	AVCaptureDevice *dev = [AVCaptureDevice deviceWithUniqueID:uid];
 	if (!dev) {
 		AVLOG(LOG_ERROR, "Device with unique id '%s' not found",