Media Player Built Entirely with PowerBuilder and Ultimate Suite for PowerBuilder
The next release of Ultimate Suite is going to include a new Circle Progress control. The best way to make sure that a new control covers all the needs of the developer is to use it in a real world application. Doing this allows you to identify deficiencies in the design or behavior. The best way I could think of to do this was to use the Circle Progress control within a media player. It can be used to start or pause playback and display the video's elapsed time. Using the Ultimate Suite caption-less window, some toolbars, the circle progress control and the Windows Media Player Active-X control, we get the following:
To create this, first inherit a new window from w_pbus_spa_captionless. Add a logo, static text for the application label, two toolbars for the play back options, and the circle progress control. Next, add an OLE control and select Windows Media Player.
In the open event of the window, add the following code:
//Use a custom color for the window background color
THIS.of_UseCustomColors(RGB(255,255,255), 0)
//Set the circle progress control to use the same color as the window
uo_play.BackColor = THIS.BackColor
//Set the URL for the video to play in the media player
ole_media.Object.URL = "<your video file>"
//We have two toolbars for play back options. Don't display borders
uo_toolbarleft.of_DisplayBorder(FALSE)
uo_toolbarright.of_DisplayBorder(FALSE)
//Set the icon size to large
uo_toolbarleft.of_SetSize(uo_toolbarleft.LARGE)
uo_toolbarright.of_SetSize(uo_toolbarleft.LARGE)
//Add buttons to the left toolbar
uo_toolbarleft.of_AddItem("Replay", "c:\dev\replay.png", uo_toolbarleft.RIGHT)
uo_toolbarleft.of_AddItem("Rewind", "c:\dev\rewind.png", uo_toolbarleft.RIGHT)
uo_toolbarleft.of_AddItem("Skip Backwards", "c:\dev\skipback.png", uo_toolbarleft.RIGHT)
//Add buttons to the right toolbar
uo_toolbarright.of_AddItem("Stop", "c:\dev\stop3.png")
uo_toolbarright.of_AddItem("Fast Forward", "c:\dev\fast_forward.png")
uo_toolbarright.of_AddItem("Skip Forwards", "c:\dev\skipforward.png")
In the resize event, we'll size the video play and snap the controls at the bottom of the screen:
SetRedraw(FALSE)
ole_media.Resize(NewWidth - (ole_media.X * 2), NewHeight - 316 - ole_media.Y)
uo_play.Move((NewWidth - uo_play.Width) / 2, ole_media.Y + ole_media.Height + 16)
uo_toolbarleft.Move(uo_play.X - 32 - uo_toolbarleft.Width,uo_play.Y + 52)
uo_toolbarright.Move(uo_play.X + uo_play.Width + 32,uo_play.Y + 52)
SetRedraw(TRUE)
There doesn't seem to be a working event in the Media Player control to track video progress so we'll setup a timer on the window. When the video plays, we'll trigger the windows timer event every half second by default.
In the timer event, we'll set progress:
Long ll_pos
//Get the current position of the video
ll_pos = Double(ole_media.Object.Controls.CurrentPosition)
//il_duration is set when the video starts and it contains the duration, in seconds, of the video
//We'll calculate a percentage complete and update the Circle Progress control with it
uo_play.of_SetProgress(ll_pos / il_duration * 100.00)
Lastly, in the close event of the window we'll make sure the media is not playing:
ole_media.Object.Controls.Stop( )
Now we can add some code to the Media Player control to change our UI depending on the Play State of the video.
Add the following code to the PlayStateChanged event of the media control:
CONSTANT INT Undefined = 0
CONSTANT INT Stopped = 1
CONSTANT INT Paused = 2
CONSTANT INT Playing = 3
CONSTANT INT ScanForward = 4
CONSTANT INT ScanReverse = 5
CONSTANT INT Buffering = 6
CONSTANT INT Waiting = 7
CONSTANT INT MediaEnded = 8
CONSTANT INT Transitioning = 9
CONSTANT INT Ready = 10
CONSTANT INT Reconnecting = 11
IF newstate = Playing THEN
//This is where we get the video duration, we'll later use this in the timer event to
//calculate the percentage complete
il_duration = Double(ole_media.Object.Controls.CurrentItem.Duration)
uo_play.of_SetImage("c:\dev\pause3.png")
//We will use the ii_advanceposition variable to indicate that the user has clicked on the
//Circle Progress control to change the video position
IF ii_advanceposition > 0 THEN
//Calculate a new position based on where the user clicked in the Circle Progress control
ole_media.Object.Controls.CurrentPosition = il_duration * (ii_advanceposition / 100)
ii_advanceposition = 0
END IF
//Start the timer
Timer(id_timer)
END IF
IF newstate = MediaEnded OR newstate = Stopped OR newstate = Paused THEN
//Video stopped so we can also stop the timer
Timer(0)
//We also need to re-display the play button. While playing, the button should be a pause button
uo_play.of_SetImage("c:\dev\play3.png")
END IF
//If we're fast forwarding or fast reversing, we need to display a play button to indicate
//to the user that they will use that button to play the video normally
IF newstate = ScanForward OR newstate = ScanReverse THEN
uo_play.of_SetImage("c:\dev\play3.png")
END IF
//Finally, if the video is stopped, we'll clear out the progress.
IF newstate = Stopped THEN
uo_play.of_SetProgress(0)
END IF
There are two events in the Circle Progress control that we'll use to control play back; CenterClicked and OutlineClicked. CenterClicked is triggered when the user clicks anywhere within the circle. The OutlineClicked event is triggered when the user clicked on the the actual circle outline.
In the CenterClicked event, add the following code to Play or Pause the video:
CHOOSE CASE ole_media.Object.PlayState
CASE 3 //Playing
ole_media.Object.Controls.Pause( )
CASE ELSE
ole_media.Object.Controls.Play( )
END CHOOSE
ole_media.Object.Controls.FastReverse( )
2) Give the ability to know when the center is clicked and when the outline is clicked.
3) I had to add way better precision. Progress use to be tracked as an Integer, now it's a Double.
Comments
Post a Comment