From dc47a1d50f04cbf6aab23bc76bb6abf7f27afbd9 Mon Sep 17 00:00:00 2001 From: Simon Zeyer Date: Sun, 5 Dec 2021 13:41:26 +0100 Subject: [PATCH] init --- .gitignore | 3 ++ __main__.py | 72 +++++++++++++++++++++++++++++++++++++ __main__.spec | 44 +++++++++++++++++++++++ resources.py | 99 +++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 218 insertions(+) create mode 100644 .gitignore create mode 100644 __main__.py create mode 100644 __main__.spec create mode 100644 resources.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8b643e2 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +build +dist +__pycache__ \ No newline at end of file diff --git a/__main__.py b/__main__.py new file mode 100644 index 0000000..0e847d2 --- /dev/null +++ b/__main__.py @@ -0,0 +1,72 @@ +import asyncio +from winrt.windows.media.control import GlobalSystemMediaTransportControlsSessionManager as MediaManager +import win32com.client +import pythoncom +import time + +from resources import LineState, CLMgrMessage + +phone_mgr = "" +lines = [] +class PhoneLineEventHandler(): + + def OnDispOnLineMgrNotification(self, msg, param, returns=""): + if msg == 0: + print(CLMgrMessage.s[msg], LineState.s[param]) + for line in lines: + if line.DispState != LineState.Inactive: + asyncio.run(try_pause()) + return True + asyncio.run(try_play()) + return True + +# async def get_media_info(): +# sessions = await MediaManager.request_async() + +# # This source_app_user_model_id check and if statement is optional +# # Use it if you want to only get a certain player/program's media +# # (e.g. only chrome.exe's media not any other program's). + +# # To get the ID, use a breakpoint() to run sessions.get_current_session() +# # while the media you want to get is playing. +# # Then set TARGET_ID to the string this call returns. + +# current_session = sessions.get_current_session() +# if current_session: # there needs to be a media session running +# #if current_session.source_app_user_model_id == TARGET_ID: +# info = await current_session.try_get_media_properties_async() +# # song_attr[0] != '_' ignores system attributes +# info_dict = {song_attr: info.__getattribute__(song_attr) for song_attr in dir(info) if song_attr[0] != '_'} + +# # converts winrt vector to list +# info_dict['genres'] = list(info_dict['genres']) + +# return info_dict + +# # It could be possible to select a program from a list of current +# # available ones. I just haven't implemented this here for my use case. +# # See references for more information. +# raise Exception('TARGET_PROGRAM is not the current media session') + +async def try_play(): + print("try_play") + sessions = await MediaManager.request_async() + current_session = sessions.get_current_session() + if current_session: + await current_session.try_play_async() + +async def try_pause(): + print("try_pause") + sessions = await MediaManager.request_async() + current_session = sessions.get_current_session() + if current_session: + await current_session.try_pause_async() + +if __name__ == '__main__': + phone_mgr = win32com.client.Dispatch("CLMgr.ClientLineMgr") + phone_mgr_event = win32com.client.WithEvents("CLMgr.ClientLineMgr", PhoneLineEventHandler) + for i in range(3): + lines.append(phone_mgr.DispGetLine(i)) + while True: + #pythoncom.PumpWaitingMessages() + time.sleep(0.1) # Don't use up all our CPU checking constantly \ No newline at end of file diff --git a/__main__.spec b/__main__.spec new file mode 100644 index 0000000..91d0550 --- /dev/null +++ b/__main__.spec @@ -0,0 +1,44 @@ +# -*- mode: python ; coding: utf-8 -*- + + +block_cipher = None + + +a = Analysis(['__main__.py'], + pathex=['X:\\Documents\\Projekte\\Simon\\python media controll'], + binaries=[], + datas=[], + hiddenimports=[], + hookspath=[], + hooksconfig={}, + runtime_hooks=[], + excludes=[], + win_no_prefer_redirects=False, + win_private_assemblies=False, + cipher=block_cipher, + noarchive=False) +pyz = PYZ(a.pure, a.zipped_data, + cipher=block_cipher) + +exe = EXE(pyz, + a.scripts, + [], + exclude_binaries=True, + name='__main__', + debug=False, + bootloader_ignore_signals=False, + strip=False, + upx=True, + console=True, + disable_windowed_traceback=False, + target_arch=None, + codesign_identity=None, + entitlements_file=None ) +coll = COLLECT(exe, + a.binaries, + a.zipfiles, + a.datas, + strip=False, + upx=True, + upx_exclude=[], + name='__main__') diff --git a/resources.py b/resources.py new file mode 100644 index 0000000..441ddcf --- /dev/null +++ b/resources.py @@ -0,0 +1,99 @@ + +class CLMgrMessage(): + CLMgrLineStateChangedMessage = 0 # state of at least one line has changed + CLMgrLineSelectionChangedMessage = 1 # line in focus has changed + CLMgrLineDetailsChangedMessage = 2 # details of at least one line have changed + CLMgrCallDetailsMessage = 4 # details of last call are available, post mortem for logging purpose + CLMgrServerDownMessage = 5 # server goes down, keep line manager, wait for ServerUp message + CLMgrServerUpMessage = 6 # server is up again, keep interfaces to line manger + CLMgrWaveDeviceChanged = 7 # speaker / micro has been switched on / off + CLMgrGroupCallNotificationMessage = 8 # notification about group call + CLMgrNumberOfLinesChangedMessage = 10 # the number of lines has changed + CLMgrClientShutDownRequest = 11 # Client Line Manager requests client to shutdown and release all interfaces + CLMgrLineStateChangedMessageEx = 28 # state of certain line has changed, lParam: LOWORD: line index of line that changed its state (starting with 0) HIWORD: new state of this line + + s = [ + "CLMgrLineStateChangedMessage", + "CLMgrLineSelectionChangedMessage", + "CLMgrLineDetailsChangedMessage", + "", + "CLMgrCallDetailsMessage", + "CLMgrServerDownMessage", + "CLMgrServerUpMessage", + "CLMgrWaveDeviceChanged", + "CLMgrGroupCallNotificationMessage", + "", + "CLMgrNumberOfLinesChangedMessage", + "CLMgrClientShutDownRequest", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "CLMgrLineStateChangedMessageEx" + ] + +class LineState(): + Inactive = 0 # line is inactive + HookOffInternal = 1 # off hook, internal dialtone + HookOffExternal = 2 # off hook, external dialtone + Ringing = 3 # incoming call, ringing + Dialing = 4 # outgoing call, we are dialing, no sound + Alerting = 5 # outgoing call, alerting = ringing on destination + Knocking = 6 # outgoing call, knocking = second call ringing on destination + Busy = 7 # outgoing call, destination is busy + Active = 8 # incoming / outgoing call, logical and physical connection is established + OnHold = 9 # incoming / outgoing call, logical connection is established, destination gets music on hold + ConferenceActive = 10 # incoming / outgoing conference, logical and physical connection is established + ConferenceOnHold = 11 # incoming / outgoing conference, logical connection is established, not physcically connected + Terminated = 12 # incoming / outgoing connection / call has been disconnected + Transferring = 13 # special LSOnHold, call is awaiting to be transferred, peer gets special music on hold + Disabled = 14 # special LSInactive: wrap up time + + s = [ + "Inactive", + "HookOffInternal", + "HookOffExternal", + "Ringing", + "Dialing", + "Alerting", + "Knocking", + "Busy", + "Active", + "OnHold", + "ConferenceActive", + "ConferenceOnHold", + "Terminated", + "Transferring", + "Disabled" + ] + +class DisconnectReason(): + Normal = 0 + Busy = 1 + Rejected = 2 + Cancelled = 3 + Transferred = 4 + JoinedConference = 5 + NoAnswer = 6 + TooLate = 7 + DirectCallImpossible = 8 + WrongNumber = 9 + Unreachable = 10 + CallDiverted = 11 + CallRoutingFailed = 12 + PermissionDenied = 13 + NetworkCongestion = 14 + NoChannelAvailable = 15 + NumberChanged = 16 + IncompatibleDestination = 17 \ No newline at end of file