McBasic™Get McBasic™ ↗
Build 881
Hands-on tutorial · Media & graphics

Control audio playback

Handle loading, playback, completion and failure as separate states.

1 Form / control designs1 complete BASIC filesGuided sample project

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
project.mcproj
{
  "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 propertyValue
Caption"AudioPlayer — McBasic"
Width520
Height330
MinWidth460
MinHeight300
TypeNameParent
AudioPlayeraudToneForm
CommandButtoncmdPlayForm
CommandButtoncmdPauseForm
CommandButtoncmdStopForm
CommandButtoncmdReloadForm
LabellblStatusForm
LabellblPositionForm
audTone · exact Inspector values
PropertyValue
Left24
Top24
Width472
Height86
Source"Tone"
AutoPlayFalse
LoopFalse
Volume0.35
Anchor edgesLeft, Top, Right
cmdPlay · exact Inspector values
PropertyValue
Left24
Top130
Width110
Height36
Caption"Play"
Anchor edgesLeft, Top
cmdPause · exact Inspector values
PropertyValue
Left146
Top130
Width110
Height36
Caption"Pause"
Anchor edgesLeft, Top
cmdStop · exact Inspector values
PropertyValue
Left268
Top130
Width110
Height36
Caption"Stop"
Anchor edgesLeft, Top
cmdReload · exact Inspector values
PropertyValue
Left390
Top130
Width106
Height36
Caption"Reload"
Anchor edgesRight, Top
lblStatus · exact Inspector values
PropertyValue
Left24
Top184
Width472
Height32
Caption"Ready"
Anchor edgesLeft, Top, Right
lblPosition · exact Inspector values
PropertyValue
Left24
Top224
Width472
Height32
Caption"Position 0 / 0 seconds"
Anchor edgesLeft, Top, Right

Step 3Connect the events explicitly#

frmMain

ObjectEventProcedureParameters
audToneLoadedaudTone_LoadedLoaded()
audToneCompletedaudTone_CompletedCompleted()
audToneFailedaudTone_FailedFailed()
audToneStateChangedaudTone_StateChangedStateChanged()
cmdPlayClickcmdPlay_ClickClick()
cmdPauseClickcmdPause_ClickClick()
cmdStopClickcmdStop_ClickClick()
cmdReloadClickcmdReload_ClickClick()
FormLoadForm_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.

Forms/frmMain.bas · declarations
Option Explicit
Private Sub Form_Load()

Initialize state before enabling dependent actions. Keep the shared declarations and startup dependencies with this procedure.

Forms/frmMain.bas · Form_Load
Private Sub Form_Load()
    lblStatus.Caption = "Audio state: " + audTone.State
    lblPosition.Caption = "Duration: " + CStr(audTone.Duration) + " seconds"
End Sub
Private Sub cmdPlay_Click()

Enter the complete action, including its input checks and calls to helper procedures.

Forms/frmMain.bas · cmdPlay_Click
Private Sub cmdPlay_Click()
    audTone.Position = 0
    audTone.Play
End Sub
Private Sub cmdPause_Click()

Enter the complete action, including its input checks and calls to helper procedures.

Forms/frmMain.bas · cmdPause_Click
Private Sub cmdPause_Click()
    audTone.Pause
End Sub
Private Sub cmdStop_Click()

Enter the complete action, including its input checks and calls to helper procedures.

Forms/frmMain.bas · cmdStop_Click
Private Sub cmdStop_Click()
    audTone.Stop
End Sub
Private Sub cmdReload_Click()

Enter the complete action, including its input checks and calls to helper procedures.

Forms/frmMain.bas · cmdReload_Click
Private Sub cmdReload_Click()
    audTone.Load
End Sub
Private Sub audTone_Loaded()

Enter this helper in the named source file, outside every other procedure. Its callers are included in the same project.

Forms/frmMain.bas · audTone_Loaded
Private Sub audTone_Loaded()
    lblStatus.Caption = "Loaded " + audTone.Source
    lblPosition.Caption = "Duration: " + CStr(audTone.Duration) + " seconds"
End Sub
Private Sub audTone_Completed()

Enter this helper in the named source file, outside every other procedure. Its callers are included in the same project.

Forms/frmMain.bas · audTone_Completed
Private Sub audTone_Completed()
    lblStatus.Caption = "Playback completed"
End Sub
Private Sub audTone_Failed()

Enter this helper in the named source file, outside every other procedure. Its callers are included in the same project.

Forms/frmMain.bas · audTone_Failed
Private Sub audTone_Failed()
    lblStatus.Caption = audTone.Error
End Sub
Private Sub audTone_StateChanged()

Enter this helper in the named source file, outside every other procedure. Its callers are included in the same project.

Forms/frmMain.bas · audTone_StateChanged
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 Sub
Copy the complete Forms/frmMain.bas file

Replace the file once; do not append duplicate procedures.

Forms/frmMain.bas
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 Sub

Step 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.

FilePurpose
Resources/tone.wavBundled 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:

Developer CLI
mcbasic check AudioPlayer.mcbproj
mcbasic run AudioPlayer.mcbproj

Acceptance 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.

Source baseline 20f4bfed6b · Build manifest