summaryrefslogtreecommitdiff
path: root/src/ui/documentwidget.c
diff options
context:
space:
mode:
authorJaakko Keränen <jaakko.keranen@iki.fi>2020-10-18 08:01:08 +0300
committerJaakko Keränen <jaakko.keranen@iki.fi>2020-10-18 08:01:08 +0300
commitb31764ed2a12d27053dba8ec7a6780f730d426e5 (patch)
tree2db1e94cde259c7fb42ea34d21b010ffa37b9872 /src/ui/documentwidget.c
parent6329646833a719097ef2e7eec42665ab0437d91f (diff)
DocumentWidget: Improved audio player UI refresh
There is no need to prioritize animation smoothness when it comes to audio players. Just post timer events at a relaxed 15 Hz when active players are visible. Fixes an issue on macOS (and possibly other platforms) where moving the window was very glitchy if a player was active.
Diffstat (limited to 'src/ui/documentwidget.c')
-rw-r--r--src/ui/documentwidget.c70
1 files changed, 58 insertions, 12 deletions
diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c
index 85c17a5b..827e2810 100644
--- a/src/ui/documentwidget.c
+++ b/src/ui/documentwidget.c
@@ -143,7 +143,7 @@ struct Impl_OutlineItem {
143 143
144/*----------------------------------------------------------------------------------------------*/ 144/*----------------------------------------------------------------------------------------------*/
145 145
146static void animatePlayingAudio_DocumentWidget_(void *); 146static void animatePlayingAudio_DocumentWidget_(iDocumentWidget *d);
147 147
148static const int smoothSpeed_DocumentWidget_ = 120; /* unit: gap_Text per second */ 148static const int smoothSpeed_DocumentWidget_ = 120; /* unit: gap_Text per second */
149static const int outlineMinWidth_DocumentWdiget_ = 45; /* times gap_UI */ 149static const int outlineMinWidth_DocumentWdiget_ = 45; /* times gap_UI */
@@ -181,6 +181,7 @@ struct Impl_DocumentWidget {
181 iPtrArray visiblePlayers; /* currently playing audio */ 181 iPtrArray visiblePlayers; /* currently playing audio */
182 const iGmRun * grabbedPlayer; /* currently adjusting volume in a player */ 182 const iGmRun * grabbedPlayer; /* currently adjusting volume in a player */
183 float grabbedStartVolume; 183 float grabbedStartVolume;
184 int playerTimer;
184 const iGmRun * hoverLink; 185 const iGmRun * hoverLink;
185 const iGmRun * contextLink; 186 const iGmRun * contextLink;
186 iBool noHoverWhileScrolling; 187 iBool noHoverWhileScrolling;
@@ -248,6 +249,7 @@ void init_DocumentWidget(iDocumentWidget *d) {
248 init_PtrArray(&d->visibleLinks); 249 init_PtrArray(&d->visibleLinks);
249 init_PtrArray(&d->visiblePlayers); 250 init_PtrArray(&d->visiblePlayers);
250 d->grabbedPlayer = NULL; 251 d->grabbedPlayer = NULL;
252 d->playerTimer = 0;
251 init_Click(&d->click, d, SDL_BUTTON_LEFT); 253 init_Click(&d->click, d, SDL_BUTTON_LEFT);
252 addChild_Widget(w, iClob(d->scroll = new_ScrollWidget())); 254 addChild_Widget(w, iClob(d->scroll = new_ScrollWidget()));
253 d->menu = NULL; /* created when clicking */ 255 d->menu = NULL; /* created when clicking */
@@ -261,7 +263,6 @@ void init_DocumentWidget(iDocumentWidget *d) {
261} 263}
262 264
263void deinit_DocumentWidget(iDocumentWidget *d) { 265void deinit_DocumentWidget(iDocumentWidget *d) {
264 removeTicker_App(animatePlayingAudio_DocumentWidget_, d);
265 delete_VisBuf(d->visBuf); 266 delete_VisBuf(d->visBuf);
266 delete_PtrSet(d->invalidRuns); 267 delete_PtrSet(d->invalidRuns);
267 deinit_Array(&d->outline); 268 deinit_Array(&d->outline);
@@ -270,6 +271,9 @@ void deinit_DocumentWidget(iDocumentWidget *d) {
270 deinit_Block(&d->sourceContent); 271 deinit_Block(&d->sourceContent);
271 deinit_String(&d->sourceMime); 272 deinit_String(&d->sourceMime);
272 iRelease(d->doc); 273 iRelease(d->doc);
274 if (d->playerTimer) {
275 SDL_RemoveTimer(d->playerTimer);
276 }
273 deinit_PtrArray(&d->visiblePlayers); 277 deinit_PtrArray(&d->visiblePlayers);
274 deinit_PtrArray(&d->visibleLinks); 278 deinit_PtrArray(&d->visibleLinks);
275 delete_String(d->certSubject); 279 delete_String(d->certSubject);
@@ -455,21 +459,58 @@ static void updateOutlineOpacity_DocumentWidget_(iDocumentWidget *d) {
455 animate_DocumentWidget_(d); 459 animate_DocumentWidget_(d);
456} 460}
457 461
458static void animatePlayingAudio_DocumentWidget_(void *widget) { 462static uint32_t playerUpdateInterval_DocumentWidget_(const iDocumentWidget *d) {
459 iDocumentWidget *d = widget; 463 if (document_App() != d) {
460 if (document_App() != d) return; 464 return 0;
465 }
466 uint32_t interval = 0;
461 iConstForEach(PtrArray, i, &d->visiblePlayers) { 467 iConstForEach(PtrArray, i, &d->visiblePlayers) {
462 const iGmRun *run = i.ptr; 468 const iGmRun *run = i.ptr;
463 iPlayer * plr = audioPlayer_Media(media_GmDocument(d->doc), run->audioId); 469 iPlayer * plr = audioPlayer_Media(media_GmDocument(d->doc), run->audioId);
464 if (idleTimeMs_Player(plr) > 3000 && ~flags_Player(plr) & volumeGrabbed_PlayerFlag && 470 if (flags_Player(plr) & adjustingVolume_PlayerFlag ||
465 flags_Player(plr) & adjustingVolume_PlayerFlag) { 471 (isStarted_Player(plr) && !isPaused_Player(plr))) {
466 setFlags_Player(plr, adjustingVolume_PlayerFlag, iFalse); 472 interval = 1000 / 15;
467 refresh_Widget(d); 473 }
474 }
475 return interval;
476}
477
478static uint32_t postPlayerUpdate_DocumentWidget_(uint32_t interval, void *context) {
479 /* Called in timer thread; don't access the widget. */
480 iUnused(context);
481 postCommand_App("media.player.update");
482 return interval;
483}
484
485static void updateAudioPlayers_DocumentWidget_(iDocumentWidget *d) {
486 if (document_App() == d) {
487 refresh_Widget(d);
488 iConstForEach(PtrArray, i, &d->visiblePlayers) {
489 const iGmRun *run = i.ptr;
490 iPlayer * plr = audioPlayer_Media(media_GmDocument(d->doc), run->audioId);
491 if (idleTimeMs_Player(plr) > 3000 && ~flags_Player(plr) & volumeGrabbed_PlayerFlag &&
492 flags_Player(plr) & adjustingVolume_PlayerFlag) {
493 setFlags_Player(plr, adjustingVolume_PlayerFlag, iFalse);
494 }
468 } 495 }
469 if (isStarted_Player(plr) && !isPaused_Player(plr)) { 496 }
470 refresh_Widget(d); 497 if (d->playerTimer && playerUpdateInterval_DocumentWidget_(d) == 0) {
471 addTicker_App(animatePlayingAudio_DocumentWidget_, d); 498 SDL_RemoveTimer(d->playerTimer);
499 d->playerTimer = 0;
500 }
501}
502
503static void animatePlayingAudio_DocumentWidget_(iDocumentWidget *d) {
504 if (document_App() != d) {
505 if (d->playerTimer) {
506 SDL_RemoveTimer(d->playerTimer);
507 d->playerTimer = 0;
472 } 508 }
509 return;
510 }
511 uint32_t interval = playerUpdateInterval_DocumentWidget_(d);
512 if (interval && !d->playerTimer) {
513 d->playerTimer = SDL_AddTimer(interval, postPlayerUpdate_DocumentWidget_, d);
473 } 514 }
474} 515}
475 516
@@ -1349,6 +1390,10 @@ static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd)
1349 } 1390 }
1350 } 1391 }
1351 } 1392 }
1393 else if (equal_Command(cmd, "media.player.update")) {
1394 updateAudioPlayers_DocumentWidget_(d);
1395 return iFalse;
1396 }
1352 else if (equal_Command(cmd, "document.stop") && document_App() == d) { 1397 else if (equal_Command(cmd, "document.stop") && document_App() == d) {
1353 if (d->request) { 1398 if (d->request) {
1354 postCommandf_App( 1399 postCommandf_App(
@@ -1622,6 +1667,7 @@ static iBool processAudioPlayerEvents_DocumentWidget_(iDocumentWidget *d, const
1622 setFlags_Player(plr, 1667 setFlags_Player(plr,
1623 adjustingVolume_PlayerFlag, 1668 adjustingVolume_PlayerFlag,
1624 !(flags_Player(plr) & adjustingVolume_PlayerFlag)); 1669 !(flags_Player(plr) & adjustingVolume_PlayerFlag));
1670 animatePlayingAudio_DocumentWidget_(d);
1625 refresh_Widget(d); 1671 refresh_Widget(d);
1626 return iTrue; 1672 return iTrue;
1627 } 1673 }