Files
mediadevices/examples/device_observer_darwin/main.go
T
sean yu 03900dcb1b Add darwin runtime device observer support (#670)
* wip

* wip

* Organize

* Remove unnecessary change in camera_darwin.go filtering

* wip

* Make observer stop safe during startup

* wip IsAvailable impl

* Fix non-darwin builds

* Lock bg loop to main thread and add comment

* Remove fmt prints

* Simplify isAvailable; Add timeout for Read darwin

* Match comment with code

* Change to singleton pattern; Add clearer safer state machine states; Change language from Stop to Destroy; Add new error for when observer is unavailable;

* Add stubs for linux

* Move cancel() up so its not dead code sometimes

* Add stubs for Windows too

* Remove StopObserver usage

* Add camera tests

* Add device observer tests

* Fix multiple destroy calls bug; Call setup in start

* Improve isAvailable

* Improve string handling in device observer c

* Add error handling in example

* Add comment about setup vs start

* Rename and organize device observer darwin

* Explicitly case initial state for setup

* Fix potential destroy goroutine leak; Use only modern build tag; Return err not nil for stubs; Improve comments

* Close startDone channel on device observer stop not wait
2025-12-28 13:33:36 -08:00

71 lines
1.6 KiB
Go

package main
import (
"bufio"
"fmt"
"os"
"strings"
"github.com/pion/mediadevices/pkg/driver"
"github.com/pion/mediadevices/pkg/driver/camera"
)
func main() {
fmt.Println("This example demonstrates query-based camera device discovery on Darwin.")
fmt.Println("The background observer automatically updates the manager's device list")
fmt.Println("when cameras are connected or disconnected.")
// Calling StartObserver without calling SetupObserver prior implicitly calls SetupObserver
// due to state machine internals. We make SetupObserver and StartObserver distinct because
// not all downstream programs will want to start pumping the NSRunLoop to handle events immediately.
err := camera.StartObserver()
if err != nil {
fmt.Printf("failed to start observer: %v\n", err)
}
defer func() {
err := camera.DestroyObserver()
if err != nil {
fmt.Printf("failed to destroy observer: %v\n", err)
}
}()
scanner := bufio.NewScanner(os.Stdin)
queryCount := 0
queryDevices(0)
for {
fmt.Print("\nPress Enter to query (or 'q' to exit): ")
if !scanner.Scan() {
break
}
input := strings.TrimSpace(scanner.Text())
if strings.ToLower(input) == "q" {
break
}
queryCount++
queryDevices(queryCount)
}
}
func queryDevices(count int) {
if count > 0 {
fmt.Printf("Query #%d\n", count)
}
devices := driver.GetManager().Query(driver.FilterVideoRecorder())
if len(devices) == 0 {
fmt.Println("No video devices found.")
} else {
fmt.Printf("Found %d video device(s):\n", len(devices))
for i, d := range devices {
info := d.Info()
fmt.Printf(" %d. %s [%s]\n", i+1, info.Name, info.Label)
}
}
}