import Foundation import CoreVideo /// Microsoft Teams adapter (native app: com.microsoft.teams2 / .teams). /// /// Teams' active-speaker cue is a **coloured ring/border** (Teams violet) around /// the speaking participant's tile; the **name sits in the tile's bottom-left**. /// Not a launch priority — included so the four detected platforms all have a /// visual adapter and degrade no worse than colored-border detection. /// /// Detection *logic* is validated on synthetic frames; geometry constants are a /// first pass pending real Teams screenshots. struct TeamsAdapter: AppAdapter { static let bundleIDs = ["com.microsoft.teams2", "com.microsoft.teams"] let adapterVersion = "teams-0.1.0" let preferredFPS = 3 private let analyzer: GridCallAnalyzer init() { var config = GridCallAnalyzer.Config() config.nameAnchor = .bottomLeft config.detectColoredBorder = true // Teams-violet speaking ring config.detectWhiteBorder = false config.tileExpandX = 3.0 config.tileExpandY = 5.0 self.analyzer = GridCallAnalyzer(config: config) } func analyze(frame: CVPixelBuffer, at t: TimeInterval) -> [SpeakerObservation] { analyzer.analyze(pixelBuffer: frame, at: t) } // Exposed for fixture/synthetic tests. func analyze(cgImage: CGImage, at t: TimeInterval) -> [SpeakerObservation] { analyzer.analyze(cgImage: cgImage, at: t) } }