Hello all.  I am having a problem with displaying the position of a cd track.  Code is as follows (this only displays seconds so far):
      ;get current position
mov mciStatusParms.dwItem, MCI_STATUS_POSITION
mov eax, cur_track
mov mciStatusParms.dwTrack, eax
invoke mciSendCommand, hDeviceID, MCI_STATUS, MCI_STATUS_ITEM, addr mciStatusParms
mov eax, mciStatusParms.dwReturn ;al = minutes ah = seconds
xor ebx, ebx
mov bl, ah
mov position, ebx
invoke dwtoa, ebx, addr temp
invoke SetDlgItemText, g_hDlg, 1005, addr temp

My problem is that when the track starts, it displays 2 as the first second instead of displaying 0 and then 1.  I have checked the code in olly and the seconds byte (ah) always starts on 2 as soon as I hit play.  Am I doing this wrong?
Posted on 2006-01-15 14:24:14 by Desp
Audio tracks are usually prepended
 with 2 seconds of silence. You can write an audio track without this silence by setting an option (for example in NERO). It has something to do with old CD drives which weren't able to read one track immediately after the previous one.

Write yourself a CD without the silence (for example with NERO), so it will start at 0.

Or maybe you DO have a CD without the silence, and your code is wrong  :mrgreen:
Posted on 2006-01-15 14:37:33 by ti_mo_n
Very interesting.  I hadn't thought of the 2 second silence.  The thing is that when I play the cd in say windows media player or media player classic it always starts on zero (Then again that may be because they might not use the MCI method).  Any suggestions on how to get around this sillyness? 
Posted on 2006-01-15 14:45:06 by Desp
The real question is: Does your code skip 2 seconds of audio, or 2 seconds of silence? IF the latter one, then everything is fine - just display a timer starting at 0 and that's all to it. If it's skipping 2 seconds of the audio itself, then there is a problem somewhere.
Posted on 2006-01-15 19:29:46 by ti_mo_n
Track 1 starts at position: 2 seconds.  This is why I am getting the result "2" in the display.  I thought maybe that I could subtract the start of the track (2 secs) from the current position and maybe fix the problem.  It will start on zero but it messes up seconds 58 and 59.  Is there no way to display the current position in Mins:Secs without creating your own timer that ticks off every second?
Posted on 2006-01-15 19:49:49 by Desp
Why not just substract 2 before displaying the value? I'll start at 2, but you'll display 0.

1) start a track
2) get track pos
3) from now on: display (current_time - start_time)
Posted on 2006-01-15 23:08:33 by ti_mo_n
That's what I have tried except when you get to 58 and 59 seconds it messes up because it is (0-2) and (1-2).  I have gotten it to work for the first track but when you go to another track it messes up again.  I am really looking for a solution that will work in every situation and not just a specific fix.  I have tried to look at some other source code but have come up empty.  Thanks for the replies though I am a lot closer to getting this.  :D
Posted on 2006-01-15 23:14:19 by Desp
What do you mean by "it messes up" ? Make sure you convert actual track position to seconds (seconds + minutes*60 + hours*3600), then substract the start_time, then convert back to HH:MM:SS format, or whatever.
Posted on 2006-01-15 23:20:04 by ti_mo_n
The format is in MM:SS:FF Minutes, Seconds, Frames.  The position of the track is reported as follows: a word is returned that looks like this MM:SS.  I realize now from what you said that I need to convert MM:SS to seconds before I subtract.  I will try this out and post back.  Thanks.
Posted on 2006-01-15 23:49:32 by Desp
OK. I can display the correct time now.  :)  My other problem is that I can't get the MCI_SEEK command to work...  I want to be able to go to the next track but something isn't working right.  Code is as follows:

;set time format
mov mciSetParms.dwTimeFormat, MCI_FORMAT_TMSF
invoke mciSendCommand, hDeviceID, MCI_SET, MCI_SET_TIME_FORMAT, addr mciSetParms

;pause playback
invoke mciSendCommand, hDeviceID, MCI_PAUSE, MCI_NOTIFY, addr mciGenericParms

;get current track and add 1
mov mciStatusParms.dwItem, MCI_STATUS_CURRENT_TRACK
invoke mciSendCommand, hDeviceID, MCI_STATUS, MCI_STATUS_ITEM, addr mciStatusParms
mov eax, mciStatusParms.dwReturn
add eax, 1 ;add 1 to current track

;get start of next track
mov mciStatusParms.dwTrack, eax ;next track
mov mciStatusParms.dwItem, MCI_STATUS_POSITION
invoke mciSendCommand, hDeviceID, MCI_STATUS, MCI_STATUS_ITEM + MCI_TRACK, addr mciStatusParms
mov eax, mciStatusParms.dwReturn

;seek to next track and play
mov mciSeekParms.dwTo, eax
invoke mciSendCommand, hDeviceID, MCI_SEEK, MCI_SEEK_TO_START, addr mciSeekParms
invoke mciSendCommand, hDeviceID, MCI_PLAY, MCI_NOTIFY, addr mciPlayParms

I have looked around for sources or examples but I can't find any in SendCommand form.  Hope someone can help.  Thanks.
Posted on 2006-01-16 12:58:24 by Desp
The attached file is CD player sample by Ron Thomas. Maybe it will help you.
Posted on 2006-01-16 18:56:32 by ti_mo_n
Thanks a lot for the source.  I got the seek working.  Now I have another problem.  How should I go about updating the display?  Currently, everything works ok but when I switch to the next track it shows a different time then quickly goes to 0:00 or 0:01.  I am using SetTimer with a callback that updates the edit boxes.  I looked at the source by Ron Thomas and tried to do the same thing he does with WM_TIMER but failed. 
Posted on 2006-01-16 21:35:07 by Desp
I am coming along nicely with the code so far.  TMSF time format is SO much easier to work with.  I still have the updating problem though.  Whats the best way to update correctly?  Currently I am using a SetTimer function with a callback to the update proc when you hit "Play".  The timer interval is 1 second.  Sometimes this works and sometimes it doesn't.  It could go from 1 second then delay and display 3 seconds and so on.  I would like to add a repeat track and general repeat so it will keep playing the cd over and over.  Right now when it gets to the end of the last track on the cd it stops playing (sets last track position to zero) and causes all kinds of problems.  How can I determine when the last track has ended so I can really stop the cd?  I hope these aren't too much trouble to answer.
Posted on 2006-01-18 14:43:06 by Desp
Timers are not precise. You should use a more precise notification method. Windows Multimedia has a way of precise notifying an app, but unfortunately I never played with it. Try searching the forum for a precise notification method.
Posted on 2006-01-18 16:43:29 by ti_mo_n
Ok, I have looked all over for stuff on timers but I am still not sure of what to do.  I have looked at multimedia timers, waitable timers, queue timers, and so on.  For the multimedia timer you can only call certain things in the callback I think so I read that I would have to make an invisible window and use subclassing which I really don't want to do... Isn't there a less painful way to do this?  Maybe the waitable timer would work? 
Posted on 2006-01-19 16:02:22 by Desp