Skip to content

Commit

Permalink
Debounce scrubbing
Browse files Browse the repository at this point in the history
- 1 seconds debounce
- avoids spamming cast device
- use play (without volume set) instead of unstable cast seek
- no need to set volume in play if from seek because seek itself would not set the volume. In other words, the volume already set is assumed to be the correct one
  • Loading branch information
elibroftw committed Apr 18, 2024
1 parent 919d0c1 commit 66b1526
Show file tree
Hide file tree
Showing 5 changed files with 33 additions and 28 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
Music Caster by Elijah Lopez Changelog

5.18.8
- [Fix] Improve track scrubbing performance

5.18.7
- [Fix] logging

Expand Down
8 changes: 4 additions & 4 deletions build_files/mc_version_info.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
# For more details about fixed file info 'ffi' see: http://msdn.microsoft.com/en-us/library/ms646997.aspx
VSVersionInfo(
ffi=FixedFileInfo(
prodvers=(5, 18, 7, 0),
filevers=(5, 18, 7, 0),
prodvers=(5, 18, 8, 0),
filevers=(5, 18, 8, 0),
# Contains a bitmask that specifies the valid bits 'flags'r
mask=0x17,
# Contains a bitmask that specifies the Boolean attributes of the file.
Expand All @@ -27,12 +27,12 @@ VSVersionInfo(
'000004b0',
[StringStruct('CompanyName', 'Elijah Lopez'),
StringStruct('FileDescription', 'Music Caster'),
StringStruct('FileVersion', '5.18.7.0'),
StringStruct('FileVersion', '5.18.8.0'),
StringStruct('InternalName', 'Music Caster'),
StringStruct('LegalCopyright', 'Copyright (c) 2019 - 2024, Elijah Lopez'),
StringStruct('OriginalFilename', 'Music Caster.exe'),
StringStruct('ProductName', 'Music Caster'),
StringStruct('ProductVersion', '5.18.7.0')])
StringStruct('ProductVersion', '5.18.8.0')])
]),
VarFileInfo([VarStruct('Translation', [0, 1200])])
]
Expand Down
2 changes: 1 addition & 1 deletion build_files/setup_script.iss
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#define MyAppName "Music Caster"
#define MyAppVersion "5.18.7"
#define MyAppVersion "5.18.8"
#define MyAppPublisher "Elijah Lopez"
#define MyAppURL "https://elijahlopez.ca/software#music-caster"
#define MyAppExeName "Music Caster.exe"
Expand Down
2 changes: 1 addition & 1 deletion src/meta.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
VERSION = latest_version = '5.18.7'
VERSION = latest_version = '5.18.8'
UPDATE_MESSAGE = """
[NEW] Better Error Capturing
[MSG] Language translators wanted
Expand Down
46 changes: 24 additions & 22 deletions src/music_caster.py
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,8 @@ def activate_instance(port=2001, default_timeout=0.5, to_port=2004):
CHECK_MARK = '✓'
music_folders, device_names = [], [(f'{CHECK_MARK} ' + t('Local device'), 'device:0')]
music_queue, done_queue, next_queue = deque(), deque(), deque()
# usage: background_thread sleep(1) if seek_queue, seek_queue.pop(), seek_queue.clear(), call set_pos
seek_queue = []
playing_url = deezer_opened = attribute_error_reported = False
recent_api_plays = {'play': 0, 'queue': 0, 'play_next': 0}
# seconds but using time()
Expand Down Expand Up @@ -1849,7 +1851,7 @@ def play_url(position=0, autoplay=True, switching_device=False, show_error=False

# up to 4 seconds!
@timing
def play(position=0, autoplay=True, switching_device=False, show_error=False):
def play(position=0, autoplay=True, switching_device=False, show_error=False, from_set_pos=False):
global cast, track_start, track_end, track_length, track_position, music_queue, playing_url, cast_browser, zconf
uri = music_queue[0]
while not os.path.exists(uri):
Expand Down Expand Up @@ -1887,22 +1889,16 @@ def play(position=0, autoplay=True, switching_device=False, show_error=False):
url = f'http://{get_ipv4()}:{State.PORT}/file?{url_args}'
cast.wait(timeout=WAIT_TIMEOUT)
app_log.info('cast.set_volume')
t1 = time.time()
with suppress(RequestTimeout):
cast.set_volume(volume)
app_log.info(f'cast.set_volume took {time.time() - t1:.2f} seconds')
if not from_set_pos:
with suppress(RequestTimeout):
cast.set_volume(volume)
mc = cast.media_controller
metadata = {'title': str(metadata['title']), 'artist': str(metadata['artist']),
'albumName': str(metadata['album']), 'metadataType': 3}
ext = uri.split('.')[-1]
app_log.info('try playing media on media controller')
t1 = time.time()
mc.play_media(url, f'audio/{ext}', current_time=position,
metadata=metadata, thumb=f'{url}&thumbnail_only=true', autoplay=autoplay)
t2 = time.time()
app_log.info(f'play media took {t2 - t1:.2f} seconds')
mc.block_until_active(WAIT_TIMEOUT)
app_log.info(f'mc.block_until_active took {time.time() - t2:.2f} seconds')
app_log.info(f'mc.status.player_state={mc.status.player_state}')
except (NotConnected, AttributeError) as e:
app_log.error('Cast device is not connected')
Expand Down Expand Up @@ -2281,14 +2277,14 @@ def set_pos(new_position):
app_log.info(f'cast.wait took {time.time() - t1:.2f} seconds')
if cast.media_controller.status.player_is_idle and music_queue:
app_log.info('called play instead')
SYNC_WITH_CHROMECAST = time.time() + 5
return play(position=new_position, autoplay=playing_status.playing())
return play(position=new_position, autoplay=playing_status.playing(), from_set_pos=True)
else:
for _ in range(2):
t1 = time.time()
try:
app_log.info('trying call seek')
cast.media_controller.seek(new_position, timeout=WAIT_TIMEOUT)
# seek is unstable. use play instead
app_log.info('call play with new position')
return play(position=new_position, autoplay=playing_status.playing(), from_set_pos=True)
# cast.media_controller.seek(new_position)
if playing_status.paused():
cast.media_controller.pause()
break
Expand All @@ -2297,7 +2293,7 @@ def set_pos(new_position):
if not IS_FROZEN or is_debug():
print(f'encountered error while seeking: {type(e)} {e}')
# seeking is broken, prefer play instead
SYNC_WITH_CHROMECAST = time.time() + 5
return play(position=new_position, autoplay=playing_status.playing(), from_set_pos=True)
break
except (NotConnected):
app_log.exception('seek failed')
Expand Down Expand Up @@ -2421,15 +2417,14 @@ def background_thread():
While True tasks:
- scans files
"""
global auto_updating
global auto_updating, SYNC_WITH_CHROMECAST
# check for update and update if no must-run arguments were provided or if the update flag was used
limited_args = len(sys.argv) == 1 or ['-m'] == sys.argv[1:]
if (limited_args and settings['auto_update'] or args.update) and not args.nupdate: auto_update()
auto_updating = False

import pynput.keyboard
global track_position, track_start, track_end
app_log.info(f'entered background_thread')
app_log.info(f'system: {platform.system()}')
start_on_login_modifications()
UpdateChecker()
Expand All @@ -2452,6 +2447,13 @@ def background_thread():
gui_window.metadata['update_listboxes'] = True
if scanned:
gui_window.metadata['update_listboxes'] = True

if seek_queue and time.time() > SYNC_WITH_CHROMECAST:
time_to_seek = seek_queue.pop()
seek_queue.clear()
set_pos_thread = Thread(target=set_pos, args=(time_to_seek,), name='SetPos', daemon=False)
set_pos_thread.start()
SYNC_WITH_CHROMECAST = time.time() + 1
time.sleep(0.1)


Expand Down Expand Up @@ -3216,11 +3218,11 @@ def read_main_window():
gui_window['progress_bar'].update(disabled=True, value=0)
return
else:
# debounce setting the track position
# background_thread will call set_pos
track_position = main_values['progress_bar']
# set pos is slow and broken so just run it in a thread for now
set_pos_thread = Thread(target=set_pos, args=(track_position,), name='SetPos', daemon=True)
set_pos_thread.start()
SYNC_WITH_CHROMECAST = time.time() + 5
seek_queue.append(track_position)
SYNC_WITH_CHROMECAST = time.time() + 1
# main window settings tab
elif main_event == 'open_email':
open_in_browser(create_email_url())
Expand Down

0 comments on commit 66b1526

Please sign in to comment.