0

I have a simple C or Objective-C program that prints all connected video devices on MacOS using AVFoundation framework. When I disconnect or connect new video capture device list doesn't get refreshed until I stop program and run it again.

My code looks as follows:

#import <AVFoundation/AVFoundation.h>
#include <stdio.h>

void print_devices() {
  NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
  for (AVCaptureDevice *device in devices) {
    const char *name = [[device localizedName] UTF8String];
    fprintf(stderr, "Device: %s\n", name);
  }
}

int main() {
  print_devices();

  sleep(10);
  // I connect or disconnect new capture device here via USB

  print_devices();
  // second print_devices(); displays exact same devices
  // as first call to this function.

  return 0;
}

My actual program looks a bit different and I call code from Go program but this is minimal reproduction code to see where is the problem. I always get printed same devices until I stop program and start it again then new devices are detected correctly.

Where is the catch or what am I missing here?

Jan Kuri
  • 927
  • 12
  • 17

1 Answers1

1

You need to run an event loop.

Most likely, AVFoundation only updates its devices list in response to events. You call sleep() in this app. While sleeping, the app receives no notifications. So the devices array is going to be the same before and after the sleep().

If you're using Apple's Foundation/AppKit/UIKit frameworks, you need to write the program in an Apple kind of way. That means using a run loop and timers, instead of sleep();

TyR
  • 718
  • 4
  • 9
  • thanks for the quick reply. I do not call sleep() in code of my actual program, I just added sleep() here for an example to have time to connect/disconnect USB device. – Jan Kuri Apr 13 '18 at 21:44
  • 1
    Are you observing the notifications AVCaptureDeviceWasConnectedNotification and AVCaptureDeviceWasDisconnectedNotification ? – TyR Apr 13 '18 at 21:47
  • no. actually now I got it what are you saying. do you think it is possible to return "fresh" devices list without implementing code in the Apple kind of way and subscribe to above stated observers? I only have/need single function that returns me device name and device index so I can display it on web application and then later use with ffmpeg. If it is possible I would really avoid making this function more complex. Thanks for helping. – Jan Kuri Apr 13 '18 at 21:54
  • You need a run loop for this one, I'm pretty sure. It won't be too painful to implement, and so much architecturally cleaner than polling. Here is a good starting point: https://stackoverflow.com/questions/2154600/run-nsrunloop-in-a-cocoa-command-line-program – TyR Apr 13 '18 at 21:57
  • I am a total noob in macos dev or apple frameworks, also wanted to stay like that but looks like it won't go :) I see, this is a nice starting point and could get me to final result pretty fast. Thank you! Marking your answer as accepted. – Jan Kuri Apr 13 '18 at 22:03