Control audio playback
Handle loading, playback, completion and failure as separate states.
The media source must be available to the running app. Loaded does not mean playback has completed; StateChanged is not a substitute for Failed. Keep the error visible and avoid automatically retrying a bad source in a tight loop.
Step 1Prepare a safe practice project#
Extract the archive into a new writable folder, separate from your own application. Open AudioPlayer.mcbproj in McBasic™. Keep every declared source, layout, resource and migration file together.
To reconstruct it yourself, create a DesktopApp project and add the files declared below. In the complete project, follow these steps as a guided rebuild: replace each named source file once and Check after all its procedures are present.
Exact project configuration
{
"schemaVersion": 1,
"projectId": "645592a9-13e6-49ef-af46-231cb8603bb0",
"name": "AudioPlayerSample",
"kind": "DesktopApp",
"ai": {
"storeChatsInProject": false
},
"language": {
"dialect": "McBasic1",
"requireExplicit": true,
"compare": "Binary",
"defaultArrayBase": 0
},
"application": {
"bundleIdentifier": "com.mcbasic.samples.audioplayer",
"version": "0.1.0",
"buildNumber": "1",
"startupFormId": "form-main",
"shutdownMode": "OnStartupFormClosed"
},
"forms": [
{
"id": "form-main",
"typeName": "frmMain",
"layout": "Forms/frmMain.form.json",
"code": "Forms/frmMain.bas"
}
],
"modules": [],
"classes": [],
"tests": [],
"references": [],
"resources": [
{
"name": "Tone",
"path": "Resources/tone.wav"
}
],
"targets": [
"osx-arm64"
],
"capabilities": []
}Step 2Build the Form and set its properties#
frmMain
Select the Form first and set its properties. Add containers before their children. These are initial Designer values, not statements to paste into a procedure.
| Form property | Value |
|---|---|
Caption | "AudioPlayer — McBasic" |
Width | 520 |
Height | 330 |
MinWidth | 460 |
MinHeight | 300 |
| Type | Name | Parent |
|---|---|---|
| AudioPlayer | audTone | Form |
| CommandButton | cmdPlay | Form |
| CommandButton | cmdPause | Form |
| CommandButton | cmdStop | Form |
| CommandButton | cmdReload | Form |
| Label | lblStatus | Form |
| Label | lblPosition | Form |
audTone · exact Inspector values
| Property | Value |
|---|---|
Left | 24 |
Top | 24 |
Width | 472 |
Height | 86 |
Source | "Tone" |
AutoPlay | False |
Loop | False |
Volume | 0.35 |
| Anchor edges | Left, Top, Right |
cmdPlay · exact Inspector values
| Property | Value |
|---|---|
Left | 24 |
Top | 130 |
Width | 110 |
Height | 36 |
Caption | "Play" |
| Anchor edges | Left, Top |
cmdPause · exact Inspector values
| Property | Value |
|---|---|
Left | 146 |
Top | 130 |
Width | 110 |
Height | 36 |
Caption | "Pause" |
| Anchor edges | Left, Top |
cmdStop · exact Inspector values
| Property | Value |
|---|---|
Left | 268 |
Top | 130 |
Width | 110 |
Height | 36 |
Caption | "Stop" |
| Anchor edges | Left, Top |
cmdReload · exact Inspector values
| Property | Value |
|---|---|
Left | 390 |
Top | 130 |
Width | 106 |
Height | 36 |
Caption | "Reload" |
| Anchor edges | Right, Top |
lblStatus · exact Inspector values
| Property | Value |
|---|---|
Left | 24 |
Top | 184 |
Width | 472 |
Height | 32 |
Caption | "Ready" |
| Anchor edges | Left, Top, Right |
lblPosition · exact Inspector values
| Property | Value |
|---|---|
Left | 24 |
Top | 224 |
Width | 472 |
Height | 32 |
Caption | "Position 0 / 0 seconds" |
| Anchor edges | Left, Top, Right |
Step 3Connect the events explicitly#
frmMain
| Object | Event | Procedure | Parameters |
|---|---|---|---|
audTone | Loaded | audTone_Loaded | Loaded() |
audTone | Completed | audTone_Completed | Completed() |
audTone | Failed | audTone_Failed | Failed() |
audTone | StateChanged | audTone_StateChanged | StateChanged() |
cmdPlay | Click | cmdPlay_Click | Click() |
cmdPause | Click | cmdPause_Click | Click() |
cmdStop | Click | cmdStop_Click | Click() |
cmdReload | Click | cmdReload_Click | Click() |
| Form | Load | Form_Load | () |
Step 4Enter the complete behavior#
Open the named source file. Enter declarations first, then every procedure. Expand a procedure for its full body, or copy the complete file. Helpers are required: do not stop after entering the first Click handler.
Forms/frmMain.bas
Enter these declarations at file scope, before the procedures.
Option ExplicitPrivate Sub Form_Load()
Initialize state before enabling dependent actions. Keep the shared declarations and startup dependencies with this procedure.
Private Sub Form_Load()
lblStatus.Caption = "Audio state: " + audTone.State
lblPosition.Caption = "Duration: " + CStr(audTone.Duration) + " seconds"
End SubPrivate Sub cmdPlay_Click()
Enter the complete action, including its input checks and calls to helper procedures.
Private Sub cmdPlay_Click()
audTone.Position = 0
audTone.Play
End SubPrivate Sub cmdPause_Click()
Enter the complete action, including its input checks and calls to helper procedures.
Private Sub cmdPause_Click()
audTone.Pause
End SubPrivate Sub cmdStop_Click()
Enter the complete action, including its input checks and calls to helper procedures.
Private Sub cmdStop_Click()
audTone.Stop
End SubPrivate Sub cmdReload_Click()
Enter the complete action, including its input checks and calls to helper procedures.
Private Sub cmdReload_Click()
audTone.Load
End SubPrivate Sub audTone_Loaded()
Enter this helper in the named source file, outside every other procedure. Its callers are included in the same project.
Private Sub audTone_Loaded()
lblStatus.Caption = "Loaded " + audTone.Source
lblPosition.Caption = "Duration: " + CStr(audTone.Duration) + " seconds"
End SubPrivate Sub audTone_Completed()
Enter this helper in the named source file, outside every other procedure. Its callers are included in the same project.
Private Sub audTone_Completed()
lblStatus.Caption = "Playback completed"
End SubPrivate Sub audTone_Failed()
Enter this helper in the named source file, outside every other procedure. Its callers are included in the same project.
Private Sub audTone_Failed()
lblStatus.Caption = audTone.Error
End SubPrivate Sub audTone_StateChanged()
Enter this helper in the named source file, outside every other procedure. Its callers are included in the same project.
Private Sub audTone_StateChanged()
lblStatus.Caption = "Audio state: " + audTone.State
If audTone.Playing Then
lblPosition.Caption = "Playing from " + CStr(audTone.Position) + " seconds"
ElseIf audTone.Paused Then
lblPosition.Caption = "Paused at " + CStr(audTone.Position) + " seconds"
End If
End SubCopy the complete Forms/frmMain.bas file
Replace the file once; do not append duplicate procedures.
Option Explicit
Private Sub Form_Load()
lblStatus.Caption = "Audio state: " + audTone.State
lblPosition.Caption = "Duration: " + CStr(audTone.Duration) + " seconds"
End Sub
Private Sub cmdPlay_Click()
audTone.Position = 0
audTone.Play
End Sub
Private Sub cmdPause_Click()
audTone.Pause
End Sub
Private Sub cmdStop_Click()
audTone.Stop
End Sub
Private Sub cmdReload_Click()
audTone.Load
End Sub
Private Sub audTone_Loaded()
lblStatus.Caption = "Loaded " + audTone.Source
lblPosition.Caption = "Duration: " + CStr(audTone.Duration) + " seconds"
End Sub
Private Sub audTone_Completed()
lblStatus.Caption = "Playback completed"
End Sub
Private Sub audTone_Failed()
lblStatus.Caption = audTone.Error
End Sub
Private Sub audTone_StateChanged()
lblStatus.Caption = "Audio state: " + audTone.State
If audTone.Playing Then
lblPosition.Caption = "Playing from " + CStr(audTone.Position) + " seconds"
ElseIf audTone.Paused Then
lblPosition.Caption = "Paused at " + CStr(audTone.Position) + " seconds"
End If
End SubStep 5Keep resources and storage reproducible#
Keep the following files at their declared relative paths. Apply migrations before the first query. Media and report resources must travel with the build.
| File | Purpose |
|---|---|
Resources/tone.wav | Bundled asset / license |
Step 6Check, run and test the result#
Save all files and run Check. Resolve diagnostics before Run. Developer CLI users can work from the extracted folder:
mcbasic check AudioPlayer.mcbproj
mcbasic run AudioPlayer.mcbprojAcceptance checklist
- Load the bundled sample asset and start playback.
- Pause, resume and stop.
- Reload and play again.
- Test a missing source in a disposable copy and inspect the Failed event.
Step 7Make one change and repeat the tests#
Disable Play until the source has loaded successfully.
Save a working Git checkpoint first. Change one behavior, Check again and repeat the acceptance checklist. Compare with the downloaded solution if a regression appears.
20f4bfed6b · Build manifest