Page 1 of 1

Best Way To Display Timer Without Flicker

Posted: Tue Nov 11, 2003 1:00 am
by bcgreen
So...I'm practicing my skills by writing an mp3 player. My question is: how can I display the elapsed time of a track without flicker? (Either in the status bar or a stringgadget)

I have the display constantly updating when a track is playing, and the only way I've found to somewhat reduce flicker is throwing a Sleep_(20) in there after the update....still get some flicker though. How can I produce a rock solid time display?

Thanks as always,
Bryan

Posted: Tue Nov 11, 2003 1:32 am
by Kale
Can you post some code?

Posted: Tue Nov 11, 2003 2:01 am
by Codemonger
I use Delay(10) sometimes, works good. But yeah, some code would really help out. I imagine Delay() is the same command as sleep_() .

Posted: Tue Nov 11, 2003 2:33 am
by freak
You should use the delay only if no other events occured
(WindowEvent() = 0) Otherwise, there will be a delay between each
event like drawing and such, and that causes the flickering.

Timo

Posted: Tue Nov 11, 2003 3:00 am
by bcgreen
Well, here's my main loop:

Code: Select all

Repeat
 
  event = WindowEvent()
  
  Select event
    Case #PB_EventGadget
      Select EventGadgetID()
        Case #mp3list
          SelectElement(tracks(), GetGadgetState(#mp3list))
          filename$ = tracks()
              Mci("Close thesound")
              Mci("Open " + Chr(34) + filename$ + Chr(34) + " alias thesound")
              Mci("Play thesound from 1 notify")
        Case #browseButton
            filedir$ = PathRequester("Select mp3 Directory:", "")
            If filedir$
              ExamineDirectory(1, filedir$, "*.mp3")
              ClearList(tracks())
              While NextDirectoryEntry()
                AddElement(tracks())
                fullname$ = filedir$ + DirectoryEntryName()
                tracks() = fullname$: OnErrorResume()
                parsemp3(fullname$)
                mpi.MP3Info
                GetMP3Info(fullname$, @mpi)
                mpisec$ = Str(mpi\filelength/1000)
                theminutes$ = Str(Val(mpisec$)/60)
                theseconds$ = Str(Val(mpisec$) - Val(theminutes$)*60):If Val(theseconds$) < 10: theseconds$ = "0" + theseconds$:EndIf
                AddGadgetItem(#mp3list, -1, artist$ + Chr(10) + song$ + Chr(10) + album$ + Chr(10) + theminutes$ + ":" + theseconds$)
              Wend
            EndIf
        Case #playButton
          If playtoggle = 1
            Mci("Resume thesound")
            playtoggle = 0
          Else
            Mci("Pause thesound")
            playtoggle = 1
          EndIf
      EndSelect
  Case 0
      Mci("status thesound position")
      seconds$ = Str(Val(MciResponse$)/1000)
      min$ = Str(Val(seconds$)/60)
      If Val(min$) < 10
        min$ = "0" + min$
      EndIf
      sec$ = Str(Val(seconds$) - (Val(min$) * 60))
      If Val(sec$) < 10
        sec$ = "0" + sec$
      EndIf
      StatusBarText(99, 0, "Current Track: " + min$ + ":" + sec$):Sleep_(20)    
  EndSelect
  
Until event = #PB_EventCloseWindow
GlobalFree_(*buffer)
End
So basically, I'm writing the current position of the file to the statusbar whenever there is idle time (When WindowEvent() = 0) and slapping in a slight delay to cut down the flicker, although there still is some annoying flicker....

Thanks!
Bryan

Posted: Tue Nov 11, 2003 4:20 am
by fsw
Don't have time to look at your code deeply but had you time to look at this:

viewtopic.php?t=8261

there is a TextGadget which does not flicker... at least on my machine

Posted: Tue Nov 11, 2003 11:36 am
by Froggerprogger
It is just too often updated.
When WindowEvent is 0, the statusbar is updated and then immediately the loop restarts. So (without an delay) it is updated hundreds of times per second. But a delay won't help here, either.
You could put an elapsed time check around your case 0 - code.
Something like this:

Code: Select all

Case 0
  If GetTickCount_() - act_time >= 500
    act_time = GetTickCount_()
    ;... your statusbarupdatecode
  Endif

Posted: Tue Nov 11, 2003 11:40 pm
by bcgreen
Cool! Thanks for the snippet. I'll give it a try....

Bryan

Posted: Wed Nov 12, 2003 7:51 am
by AngelSoul
There is also another method to avoid flickering without having to put delays in your code.

Here's an example:

Code: Select all

OpenWindow(0,50,50,200,30,#PB_Window_ScreenCentered + #PB_Window_MinimizeGadget,"A Window...")
CreateStatusBar(0,WindowID())

Repeat
ww=WindowEvent()
If Date()<>lastdate
   a$=Str(Date())
   StatusBarText(0,0,a$)
   lastdate=Date()
EndIf   


Delay(1)
Until ww=#PB_Event_CloseWindow
Instead of displaying hundreds of times in a second, it'll only display once every second. You can do the same with your sec$ and min$ variables.

Each time you'll display the elapsed time, store those sec and min variables to other temporary values.

Now when the time comes to display the time, put a condition such as:

If min$<>lastmin$ or sec$<>lastsec$
;put what you want to display
lastmin$=min
lastsec$=sec$
EndIf

That way you'll avoid putting unnecessary delays.
Hope this helps.

Posted: Wed Nov 12, 2003 7:59 am
by Codemonger
That is definately a more accurate way, only update when needed.

Posted: Wed Nov 12, 2003 10:31 am
by Fred
The correct way to handle an WindowEvent() loop is something like that:

Code: Select all


Repeat
  Event = WindowEvent()

  If Event  ; An event was in the queue so process it
    ....
  Else  
    Delay(1) ; No Event, let the others apps get some CPU time too !
  EndIf
Until Event = #PB_Event_CloseWindow
Why the Delay shouldn't be put after each events ? because when lot of events will come (like refresh, gadgets updates etc..) the apps will wait 20 ms (on windows at least) between each events. So the delay need to be put when no events are recieved. Another (API) way is to use a timer and stick which WaitWindowEvent().

Ok, I will put it in the docs :wink:

Posted: Wed Nov 12, 2003 10:50 am
by AngelSoul
Cool! A great way to properly optimize your loop.

Haven't thought of that :>

Posted: Thu Nov 13, 2003 3:35 am
by bcgreen
Thanks AngelSoul! That's a great solution...

Bryan