teams-call icon indicating copy to clipboard operation
teams-call copied to clipboard

Support for New Teams

Open adnet-solutions opened this issue 1 year ago • 20 comments
trafficstars

Its looks like that the Script not work with the new teams. I checked the logfile wich you like to parse but it is not updated by the new teams version. And i still not find that new teams in a logfile. Any Idea?

adnet-solutions avatar Jun 28 '24 11:06 adnet-solutions

Hey, I can't test this at the moment, but I'd be curious if someone found a workaround. If so, we can add support.

mre avatar Jun 28 '24 14:06 mre

Same, it doesn't work for me =(

matheusft avatar Mar 29 '25 19:03 matheusft

Looks like it's not possible at the moment. See here.

mre avatar Mar 31 '25 12:03 mre

I was able to hack something together with an applescript:

tell application "System Events"
    repeat with TeamsWindow in (every window of process "MSTeams")
        -- entire contents of TeamsWindow
        -- Examples:
        -- group "Elapsed time 02:55" of toolbar 1 of group 1 of group 1 of group 1 of group 1 of group 1 of UI element "Meeting compact view | Fooobar | Microsoft Teams" of group 2 of group 1 of group 1 of group "Meeting compact view | Fooobar | Microsoft Teams - Web content - Profile 2" of window "Meeting compact view | Fooobar | Microsoft Teams" of application process "MSTeams"
        -- group "Elapsed time 03:31" of toolbar 1 of group 1 of group 1 of group 3 of group 1 of group 1 of group 1 of UI element "Foobar | Microsoft Teams" of group 2 of group 1 of group 1 of group "Foobar | Microsoft Teams - Web content - Profile 2" of window "Foobar | Microsoft Teams" of application process "MSTeams"

        -- Best way I can find to determine a meeting it this nested group item which shows the elapsed time of the meeting
        repeat with CurGroup in group of toolbar of group of group of group of group of group of group of UI element of group of UI element of group of group of TeamsWindow
            if (name of CurGroup contains "Elapsed time") then
                return true
            end if
        end repeat
    end repeat
end tell

And run is osascript:

$ osascript get–teams-call.applescript
true

There's probably a better way to loop through these nested objects, but this works for now.

jessejoe avatar Apr 01 '25 14:04 jessejoe

Oh, that's clever. Would you like to send a pull request? https://stackoverflow.com/a/65016330 Can be behind a check for macOS.

mre avatar Apr 01 '25 14:04 mre

The group stuff would break if Teams changed their UI elements. Have you tried something like this?

tell application "System Events"
    -- Check if MSTeams is running
    if not (exists process "MSTeams") then
        return false
    end if
    
    -- Simple approach: look for "Elapsed time" text in any Teams window
    tell process "MSTeams"
        try
            -- Search for any UI element containing "Elapsed time" regardless of hierarchy
            set elapsedTimeElements to (get UI elements whose name contains "Elapsed time")
            if (count of elapsedTimeElements) > 0 then
                return true
            end if
        end try
    end tell
    
    return false
end tell

mre avatar Apr 01 '25 14:04 mre

@mre That doesn't work since the "Elapsed time" is the name of a group, not a UI element itself. I'm not sure if there's a way to get every nested group like this.

jessejoe avatar Apr 01 '25 15:04 jessejoe

I was also able to detect whether I'm in a call based on the the number of Microsoft Teams UDP connections.

Very hacky but it seems to work for me on Microsoft Teams macOS Desktop App macOS Sequoia 15.3.2

matheusft avatar Apr 01 '25 15:04 matheusft

@jessejoe, this works for me:

tell application "System Events"
	-- Early exit if Teams isn't running
	if not (exists process "MSTeams") then
		return false
	end if
	
	with timeout of 3 seconds
		tell process "MSTeams"
			try
				repeat with w in windows
					set winName to name of w
					if winName contains "Meeting" or winName contains "Call" then
						-- Found a meeting window title 
						return true
					end if
				end repeat
				
			on error
				return false
			end try
		end tell
	end timeout
	return false
end tell

mre avatar Apr 01 '25 17:04 mre

@mre that actually won't always work because a meeting can be named anything and may not have "Meeting" or "Call" in the title. Debugging your script:

tell application "System Events"
	exists process "MSTeams"
		--> true
	count every window of process "MSTeams"
		--> 2
	get name of item 1 of every window of process "MSTeams"
		--> "I named this Foobar | Microsoft Teams"
	get name of item 2 of every window of process "MSTeams"
		--> "Meet App | Microsoft Teams"
end tell
Result:
false

You're actually going through the same process I went through before I ended up on my first comment, haha. That will probably work most of the time though.

jessejoe avatar Apr 01 '25 17:04 jessejoe

Okay, thanks. 😅 Then I'd accept a PR for your version. We could also port the script to a different language like Rust or Go tbh. A static binary makes the most sense here. But perhaps for now an addition to either the Python or Bash version in the is fine as well. Completely up to you.

mre avatar Apr 01 '25 18:04 mre

I was also able to detect whether I'm in a call based on the the number of Microsoft Teams UDP connections.

Very hacky but it seems to work for me on Microsoft Teams macOS Desktop App macOS Sequoia 15.3.2


#!/bin/bash

# teams_call_detector.sh
# Script to detect if a Teams call is active
# Prints 1 if in a call, 0 if not

# Function to check if in Teams call
function check_teams_call() {
    # Count the number of Teams UDP connections
    connection_count=$(lsof -nP -iUDP | grep -c "MSTeams")
    
    # If more than 1 connection, likely in a call
    if [ "$connection_count" -gt 1 ]; then
        echo "1"  # In call
    else
        echo "0"  # Not in call
    fi
}

# Make script more robust by handling interruptions
trap "echo -e '\nExiting Teams call detector'; exit" INT TERM

# Print header
echo "Teams Call Status Monitor"
echo "1 = In call, 0 = Not in call"
echo "Press Ctrl+C to exit"
echo "------------------------"

# Main loop - check every second
while true; do
    status=$(check_teams_call)
    echo -n -e "\r$(date +"%H:%M:%S") - Call status: $status     "
    sleep 1
done


This worked for me

matheusft avatar Apr 01 '25 19:04 matheusft

New and much simpler and faster approach to use the menu status icon:

tell application "System Events"
	-- Check if MSTeams is running
	if not (exists process "MSTeams") then
		return false
	end if
	
	tell process "MSTeams"
		-- There's multiple menu bar elements, but only one with the description
		set menuBar to (first UI element whose description is equal to "menu bar")
		set menuStatus to name of first menu item of first menu of first menu bar item of menuBar
		-- This can also be "Do not disturb", "Be right back", etc.
		-- Could also change to `not equal to "Available"` if preferred
		if menuStatus is equal to "Busy" then
			return true
		end if
	end tell
	
	return false
end tell

Does pretty much no extra looping or work:

tell application "System Events"
	exists process "MSTeams"
		--> true
	get UI element 1 of process "MSTeams" whose description = "menu bar"
		--> menu bar 2 of application process "MSTeams"
	get name of menu item 1 of menu 1 of menu bar item 1 of menu bar 2 of application process "MSTeams"
		--> "Busy"
end tell
Result:
true

jessejoe avatar Apr 01 '25 20:04 jessejoe

That's great. Nice find; let's go with that. Would you be able to create a pull request? 😃

mre avatar Apr 02 '25 08:04 mre

I actually don't even use this tool, it was just the first result when searching for a solution, but I can probably throw something together!

jessejoe avatar Apr 02 '25 13:04 jessejoe

Thanks, that would be nice. But no pressure if not. Just let me know and I can also whip something up. In the long run, I kinda would like to rewrite it to Go or so. ¯\_(ツ)_/¯

mre avatar Apr 03 '25 15:04 mre

I'm actually debating the approach because it turns out Teams also marks you as busy for the entire duration of your calendar event, even if you aren't in a call or the call has ended. I don't see any way to turn that off, so I'm not sure if I'm going to stick with method. I'll keep digging.

jessejoe avatar Apr 03 '25 15:04 jessejoe

Yet another approach which will work for all apps by checking the Control Center menu bar for the Microphone in use (could also check for "Camera" or "Camera and Microphone"):

tell application "System Events"
	tell process "ControlCenter"
		-- There's also the "Audio and Video Controls" menu item which is less descriptive 
		-- and may not exist, "Control Center" should always be there
		set CCMenu to (first menu bar item of menu bar 1 whose description contains "Control Center")
		-- Possible values: "Control Center", "Control Center, Microphone is in use"
		-- or "Control Center, Camera and Microphone are in use"
		if "Microphone" is in description of CCMenu then
			return true
		end if
	end tell
	
	return false
end tell

I like this better for my personal requirements, but probably not a fit for this repo.

jessejoe avatar Apr 03 '25 20:04 jessejoe

Hey @mre, I can put this in as a PR but not sure if you wanna continue supporting old teams, have support for both etc which is more of an architecture question.

Following your current approach of checking logs, I've found this works for me. I've only tested it on Windows and on Teams client build 25212.2204.3869.2204

Also tagging @jessejoe and @adnet-solutions as they might be interested in this approach.

Hope this helps!

import os
from pathlib import Path

def isInCall():

    start_call_token = "HfpVoipCallCoordinatorImpl: requestStartCall completed"
    end_call_token = "HfpVoipCallCoordinatorImpl: Notifying voipCallCoordinator about ended call callId"

    log_paths = Path(os.getenv('LOCALAPPDATA')).glob("Packages/MSTeams_*/LocalCache/Microsoft/MSTeams/Logs/MSTeams_*.log")

    with open(max(log_paths)) as latest_log_file:
        latest_log = latest_log_file.read()
        return latest_log.count(start_call_token) > latest_log.count(end_call_token)

TheMariday avatar Sep 30 '25 11:09 TheMariday

Hey @TheMariday, you're right, the old teams support is probably overkill at this point. Happy to accept a PR which will make it work for the new teams. We can phase out the old version. Alternatively, we keep the logic in there but just on a best-effort basis. No hard feelings either way. 😆

mre avatar Sep 30 '25 12:09 mre