Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitf93dda8

Browse files
committed
feat(media): add session switching functionality
1 parente3e3fdd commitf93dda8

File tree

2 files changed

+75
-28
lines changed

2 files changed

+75
-28
lines changed

‎src/core/utils/win32/media.py

Lines changed: 60 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -98,12 +98,19 @@ def _run_setup(self):
9898
# Manually trigger the callback on startup
9999
self._on_current_session_changed(self._session_manager,None,is_setup=True)
100100

101-
def_on_current_session_changed(self,manager:SessionManager,args:SessionsChangedEventArgs,is_setup=False):
101+
def_on_current_session_changed(
102+
self,
103+
manager:SessionManager,
104+
args:SessionsChangedEventArgs,
105+
is_setup=False,
106+
is_overridden=False,
107+
):
102108
ifDEBUG:
103109
self._log.debug('MediaCallback: _on_current_session_changed')
104110

105111
withself._current_session_lock:
106-
self._current_session=manager.get_current_session()
112+
ifnotis_overridden:
113+
self._current_session=manager.get_current_session()
107114

108115
ifself._current_sessionisnotNone:
109116

@@ -121,7 +128,19 @@ def _on_current_session_changed(self, manager: SessionManager, args: SessionsCha
121128

122129
forcallbackincallbacks:
123130
callback(self._current_sessionisnotNone)
131+
132+
def_current_session_only(fn):
133+
"""
134+
Decorator to ensure that the function is only called if the session is the same as the current session
135+
"""
136+
137+
defwrapper(self:"WindowsMedia",session:Session,*args,**kwargs):
138+
withself._current_session_lock:
139+
ifself._are_same_sessions(session,self._current_session):
140+
returnfn(self,session,*args,**kwargs)
141+
returnwrapper
124142

143+
@_current_session_only
125144
def_on_playback_info_changed(self,session:Session,args:PlaybackInfoChangedEventArgs):
126145
ifDEBUG:
127146
self._log.info('MediaCallback: _on_playback_info_changed')
@@ -136,6 +155,7 @@ def _on_playback_info_changed(self, session: Session, args: PlaybackInfoChangedE
136155
forcallbackincallbacks:
137156
callback(self._playback_info)
138157

158+
@_current_session_only
139159
def_on_timeline_properties_changed(self,session:Session,args:TimelinePropertiesChangedEventArgs):
140160
ifDEBUG:
141161
self._log.info('MediaCallback: _on_timeline_properties_changed')
@@ -150,6 +170,7 @@ def _on_timeline_properties_changed(self, session: Session, args: TimelineProper
150170
forcallbackincallbacks:
151171
callback(self._timeline_info)
152172

173+
@_current_session_only
153174
def_on_media_properties_changed(self,session:Session,args:MediaPropertiesChangedEventArgs):
154175
ifDEBUG:
155176
self._log.debug('MediaCallback: _on_media_properties_changed')
@@ -162,6 +183,7 @@ def _on_media_properties_changed(self, session: Session, args: MediaPropertiesCh
162183
# Only for the initial timer based update, because it is called from an event loop
163184
asyncio.create_task(self._update_media_properties(session))
164185

186+
@_current_session_only
165187
asyncdef_update_media_properties(self,session:Session):
166188
ifDEBUG:
167189
self._log.debug('MediaCallback: Attempting media info update')
@@ -171,14 +193,9 @@ async def _update_media_properties(self, session: Session):
171193

172194
media_info=self._properties_2_dict(media_info)
173195

174-
# Skip initial change calls where the thumbnail is None. This prevents processing multiple updates.
175-
# Might prevent showing info for no-thumbnail media
176-
ifmedia_info['thumbnail']isNone:
177-
ifDEBUG:
178-
self._log.debug('MediaCallback: Skipping media info update: no thumbnail')
179-
return
196+
ifmedia_info['thumbnail']isnotNone:
197+
media_info['thumbnail']=awaitself.get_thumbnail(media_info['thumbnail'])
180198

181-
media_info['thumbnail']=awaitself.get_thumbnail(media_info['thumbnail'])
182199
exceptExceptionase:
183200
self._log.error(f'MediaCallback: Error occurred whilst fetching media properties and thumbnail:{e}')
184201
return
@@ -228,21 +245,40 @@ async def get_thumbnail(thumbnail_stream_reference: IRandomAccessStreamReference
228245
finally:
229246
# Close the stream
230247
readable_stream.close()
248+
249+
def_are_same_sessions(self,session1:Session,session2:Session)->bool:
250+
returnsession1.source_app_user_model_id==session2.source_app_user_model_id
251+
252+
defswitch_session(self,direction:int):
253+
sessions=self._session_manager.get_sessions()
254+
iflen(sessions)==0:
255+
return
231256

232-
@staticmethod
233-
defplay_pause():
234-
user32=ctypes.windll.user32
235-
user32.keybd_event(VK_MEDIA_PLAY_PAUSE,0,KEYEVENTF_EXTENDEDKEY,0)
236-
user32.keybd_event(VK_MEDIA_PLAY_PAUSE,0,KEYEVENTF_KEYUP,0)
257+
withself._current_session_lock:
258+
current_session_idx=-1
259+
fori,sessioninenumerate(sessions):
260+
ifself._current_sessionisNoneorself._are_same_sessions(session,self._current_session):
261+
current_session_idx=i
262+
break
263+
264+
idx= (current_session_idx+direction)%len(sessions)
265+
ifself._are_same_sessions(sessions[idx],self._current_session):
266+
return
267+
self._log.info(f"Switching to session{idx} ({sessions[idx].source_app_user_model_id})")
268+
self._current_session=sessions[idx]
269+
self._on_current_session_changed(self._session_manager,None,is_overridden=True)
237270

238-
@staticmethod
239-
defprev():
240-
user32=ctypes.windll.user32
241-
user32.keybd_event(VK_MEDIA_PREV_TRACK,0,KEYEVENTF_EXTENDEDKEY,0)
242-
user32.keybd_event(VK_MEDIA_PREV_TRACK,0,KEYEVENTF_KEYUP,0)
271+
defplay_pause(self):
272+
withself._current_session_lock:
273+
ifself._current_sessionisnotNone:
274+
self._current_session.try_toggle_play_pause_async()
243275

244-
@staticmethod
245-
defnext():
246-
user32=ctypes.windll.user32
247-
user32.keybd_event(VK_MEDIA_NEXT_TRACK,0,KEYEVENTF_EXTENDEDKEY,0)
248-
user32.keybd_event(VK_MEDIA_NEXT_TRACK,0,KEYEVENTF_KEYUP,0)
276+
defprev(self):
277+
withself._current_session_lock:
278+
ifself._current_sessionisnotNone:
279+
self._current_session.try_skip_previous_async()
280+
281+
defnext(self):
282+
withself._current_session_lock:
283+
ifself._current_sessionisnotNone:
284+
self._current_session.try_skip_next_async()

‎src/core/widgets/yasb/media.py

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
fromPIL.ImageQtimportQPixmap
77
fromPyQt6importQtCore
88
fromPyQt6.QtCoreimportQt
9+
fromPyQt6.QtGuiimportQWheelEvent
910
fromPIL.ImageQtimportImageQt
1011
fromwinsdk.windows.media.controlimportGlobalSystemMediaTransportControlsSessionPlaybackInfo
1112

@@ -193,6 +194,11 @@ def _on_media_properties_changed(self, media_info: Optional[dict[str, Any]]):
193194
ifnotself._show_thumbnail:
194195
return
195196

197+
# If no media in session, hide thumbnail and stop here
198+
ifmedia_info['thumbnail']isNoneandnotmedia_info['title']:
199+
self._thumbnail_label.hide()
200+
return
201+
196202
# Only update the thumbnail if the title/artist changes or if we did a toggle (resize)
197203
try:
198204
ifmedia_info['thumbnail']isnotNone:
@@ -248,16 +254,21 @@ def _create_media_button(self, icon, action):
248254
returnlabel
249255

250256
def_create_media_buttons(self):
251-
return (self._create_media_button(self._media_button_icons['prev_track'],WindowsMedia.prev),
252-
self._create_media_button(
253-
self._media_button_icons['play'],WindowsMedia.play_pause),self._create_media_button(
254-
self._media_button_icons['next_track'],WindowsMedia.next))
257+
return (self._create_media_button(self._media_button_icons['prev_track'],WindowsMedia().prev),
258+
self._create_media_button(self._media_button_icons['play'],WindowsMedia().play_pause),
259+
self._create_media_button(self._media_button_icons['next_track'],WindowsMedia().next))
255260

256261
defexecute_code(self,func):
257262
try:
258263
func()
259264
exceptExceptionase:
260265
logging.error(f"Error executing code:{e}")
266+
267+
defwheelEvent(self,event:QWheelEvent):
268+
ifevent.angleDelta().y()>0:
269+
self.media.switch_session(+1)# Next
270+
elifevent.angleDelta().y()<0:
271+
self.media.switch_session(-1)# Prev
261272

262273
classClickableLabel(QLabel):
263274
def__init__(self,parent=None):

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp