CS 312 - Week 7 Class 1
CS 312 Audio Programming Winter 2020

Table of Contents

7.1 Class

Project 1 class presentations.

Homework 7.1


Qt crash course (no pun intended)

Qt folder path
WCC /Users/labuser/Qt
CMC /Applications/Qt
Qt IDE application used to design, build, and run applications
"Qt Creator"

Execute in Mac terminal.

cd $HOME312/cs312/
mkdir hw71
mkdir hw71/build-hw711
mkdir hw71/build-hw712
mkdir hw71/build-hw713
# for WCC double quotes required because of space in filename
open "/Users/labuser/Qt/Qt Creator.app"

# for CMC double
# open "/Applications/Qt/Qt Creator.app"

Open the QtCreator application.

The above script should have opened Qt Creator for you. If not, navigate to the Qt folder and double click Qt Creator.

Choose New Project


When the New Project window appears use these settings and click the Choose button.


Name the project and set the project location.


Define the build system as qmake.


Class Information can be left unchanged.


Translation File can be left as <none>


Kit Selection - Desktop Qt … clang 64bit


No version control


Click Done and the project explorer opens. At first it appears there are errors while QtCreator is checking the project. In a few seconds the errors should disappear.

Set the build folder

Project tool

Click the Project tool in the left toobar


Make these settings.

  • Shadow build checked
  • Click the Choose button and navigate to the build-hw71 folder.


Build and Run

Click the green arrow on the left toolbar to build and run the application.


The icon directly below Run is the "Debug Run" button. Qt comes with an excellent debugger based on llvm and clang.

A blank window will appear with the title "MainWindow".

  • You can move it around and resize it.
  • The red, yellow, and green buttons in the window title bar buttons work as expected.
  • There is an hw711_cmidiin_gui menu that you can use to Quit the app.
  • You can also quit by clicking the red close button in the window title bar.


Edit tool

The Edit tool gives you access to all your project files. The main.cpp file has been selected. You'll notice how few lines of code it uses. The mainwindow.cpp file is where you code responses to GUI actions like mouse clicks, key presses, and menu choices. The mainwindow.ui file contians the GUI design you've create.


Design tool

Double click the mainwindow.ui file. The .ui extension is used for User Interface files that are built using the Design tool. A blank window representing the MainWindow will open. A list of widgets you can drag into the form are shown on the left.


Select the MainWindow form and name the window MIDI Monitor in the windowTitle field on the right. You'll have to scroll to find it.


Set the minimumSize and maximumSize to give the window a fixed dimension.


Drag a single Push Button widget into the ui window. Then create the other three by selecting the button you just placed and Option-dragging to create copies.


Add a plainTextEdit widget.


Arrange them like this.


Double click the push button text to change the button names as shown.


Or type the name in the object properties list.


Assign the the variable name pushButton_record to Record button. That name will be used to reference the Record button in your code.


Assign these variable names to the other three buttons.

  • pushButton_play
  • pushButton_stop
  • pushButton_clear

The variable names and types of the UI objects appear in the upper right panel. This panel can also be used to select objects on the main form.


Select the plainTextEdit widget. We'll accept the default name, plainTextEdit, because it's the only on on the form.


Add the ScrollBar policies.


Build and Run
Click the green arrow on the left toolbar to build and run the application.


The window will appear with the title "MIDI Monitor".

  • You can move it around but you cannot resize it.
  • You can type into the text area.
  • If you fill the text area a scroll bar will appear and you can scroll through the text.
  • Copy and paste works.
  • Undo works.
  • Select all works.
  • Text cursor movement using arrow keys works.
  • Command-UpArrow takes you to the top of the text.
  • Command-DownArrow takes you to the bottom of the text.
  • You can click the buttons and they highlight as long as the mouse is held down.
  • You can close the window using the red close button.
  • You can close the window using the Quit command in the hw711_Qt_cmidiin_gui menu.
  • All this comes for free.


Close the project from the Qt Creator File menu.


hw712 and hw713 requirements

  • See class 6.2 for detailed instructions.
  • IAC Driver must be enabled in Audio MIDI Setup app.
  • Au Lab must be open with the DLSMusicDevice setup correctly.
  • VMPK must be open.
  • You must have a working midiprobe command line tool in your courses bin folder


In this assignment we'll display rtmidiin messages in CMidiPacket format inside the QEditPlainText widget.


cd $HOME312/Cs312/hw71
cp -R $HOME312/cs312/hw71/hw711_Qt_cmidiin_gui $HOME312/cs312/hw71/hw712_Qt_rtmidiin
cd $HOME312/cs312/hw71/hw712_Qt_rtmidiin
mv hw711_Qt_cmidiin_gui.pro hw712_Qt_rtmidiin.pro
mv hw711_Qt_cmidiin_gui.pro.user hw712_Qt_rtmidiin.pro.user
sed -i '' s/hw711_Qt_cmidiin_gui/hw712_Qt_rtmidiin/g hw711_Qt_cmidiin_gui.pro.user
cp $HOME312/common/RtMidi.h .
cp $HOME312/common/RtMidi.cpp .
cp $HOME312/common/hw332_CMidiPacket.h .
cp $HOME312/common/hw332_CMidiPacket.cpp .

Double click hw712_Qt_rtmidiin.pro to open it in QtCreator



Qt uses a build system called qmake and the .pro files are counterparts to cmake's CMakeLists.txt file. Qt is working towards importing and using a CMakeLists.txt file but it was not accurate enough for use in this class.

You can add files to your project by adding them to the qmake project file, hw711_Qt_cmidiin.pro.

Task 1 - Add RtMidi and hw331_CMidiPacket files

Open the hw712_Qt_cmidiin.pro file. You should see this.


Make these changes. Copy/paste snippets are shown below the screenshot.


You can copy/paste sections from here. Be sure to match up with the picture above.

#CONFIG += c++11
CONFIG += c++17

## Mac OS specific qmake options
macx {
TARGET = hw711_Qt_cmidiin
    CONFIG += app_bundle
    INCLUDEPATH += /Users/je/cs312/common
    INCLUDEPATH += /Library/Frameworks/
    QMAKE_LFLAGS += -F/Library/Frameworks
    LIBS += -framework CoreFoundation \
        -framework CoreMIDI \
        -framework CoreAudio
    QMAKE_CXXFLAGS_WARN_ON += -Wno-unknown-pragmas
#    ICON = MIDIDisplay.icns

    main.cpp \
    mainwindow.cpp \
    RtMidi.cpp \

    mainwindow.h \
    RtMidi.h \
FORMS += \

After a short pause you should see the files appear in the Edit panel.


Change the project build folder to build-hw722
Click the Project tool and make these changes.


Build and run
You should have no errors at this point.

Task 2 - Add code to open RtMidiIn and RtMidiOut

Make these changes.


VMPK and midiprobe

  • If VMPK is not open, open it.
  • Run /midiprobe.
  • Make note of the VMPK Input and the DLSMusicDevice Output port numbers.
je$ midiprobe

Compiled APIs:

Current input API: OS-X CoreMIDI

There are 2 MIDI input sources available.
  Input Port #0: IAC Driver Bus 1
  Input Port #1: VMPK Output

Current output API: OS-X CoreMIDI

There are 3 MIDI output ports available.
  Output Port #0: IAC Driver Bus 1
  Output Port #1: DLSMusicDevice
  Output Port #2: VMPK Input

It's slightly confusing the way MIDI is connected. This is true for both hardware and software.

  • The device Output (VMPK Output) connects to the computer input (RtMidiIn).
  • The computer output (DLSMusicDevice) connects to the device input (IAC Driver Bus 1).

Make these changes


Then copy and implement this code below the MIDI Utilities comment.

void mycallback( double deltatime, std::vector<unsigned char>* message, void* /*userData*/ )
    // This is the same callback you wrote for hw621_cmidiin_cmp33
    // to convert message into CMidiPacket data
    // up until you got to std::cout

      This is new
      You cannot use std::cout
      You have to use the QPlainTextEdit function insertPlainText.
      Click the Help icon in QtCreator and read about
      Remember the variable pte is a pointer to a QPlainTextEdit widget
      You have to use this
      pte->insertPlainText(const QString &text)
      You've already got a CMidiPacket and you can use mp.to_string();
      Use Qt Help or google to find out how to convert a std::string into a QString.

    // I did it in two lines of code

void MainWindow::init_midi_in( uint32_t num )
    // copy from c622_rt_cmidiin
       // gmidiin varaiable is in .h class
       // create gmidiin

    catch ( RtMidiError& error )
        exit( EXIT_FAILURE );

//    open midiin port( num ); // num is from result of midiprobe.
//    set midiin callback
//    maybe call ignoreTypes

void MainWindow::init_midi_out( uint32_t num )
    // copy from c623_rt_cmidiout
       // gmidiout varaiable is in .h class
       // create gmidiout

    catch ( RtMidiError& error )
        exit( EXIT_FAILURE );
//    open midiout port( num ); // num is from result of midiprobe.

Task 3 - Capture MIDI input data and display it

You can use most of the same code you used the hw621_cmidiin_cmp33 callback function.

Eliminate any warnings displayed in the code
Type conversion warning can be fixed using static_cast.

Build and Run the project
If there are no errors the MIDI Monitor window will appear.

Play notes and move controls on the VMPK software keyboard. You should see CMidiPacket messages appear with timestamps in the QPlainTextEdit widget.



In this assignment we'll hook up the pushButton widgets.


cd $HOME312/Cs312/hw71
cp -R $HOME312/cs312/hw71/hw712_Qt_rtmidiin $HOME312/cs312/hw71/hw713_Qt_rtmidiin_buttons
cd $HOME312/cs312/hw71/hw713_Qt_rtmidiin_buttons
mv hw712_Qt_rtmidiin.pro hw713_Qt_rtmidiin_buttons.pro
mv hw712_Qt_rtmidiin.pro.user hw713_Qt_rtmidiin_buttons.pro.user
sed -i '' s/hw712_Qt_rtmidiin/hw713_Qt_rtmidiin_buttons/g hw713_Qt_rtmidiin_buttons.pro.user

Change the project build folder to build-hw723
Click the Project tool and make these changes.


Build and run
You should have no errors at this point.

Variables needed

Add at bottom of the file outside of the mainwindow class. Use extern.

// hw711 variables
extern QPlainTextEdit* pte;
// hw713 variables
extern bool isRecording;
extern bool isFirstTimestampCaptured;
extern uint32_t firstRecordTimestamp;
extern std::vector<CMidiPacket> vplay;

#endif // MAINWINDOW_H

Add after the include section. Remove extern and initialize the variables.

#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <QString>

#ifndef HW332_CMIDIPACKET_H_
#include "hw332_CMidiPacket.h"

using namespace CMP33;

// hw711 variables
QPlainTextEdit* pte = nullptr;
// hw713 variables
bool isRecording = false;
bool isFirstTimestampCaptured = false;
uint32_t firstRecordTimestamp = 0;
std::vector<CMidiPacket> vplay;

Functions needed

Qt responds user actions in the GUI through a signal-slot mechanism. For the most part this is transparent to your code. We won't get into advanced uses of this mechanism here.

In the mainwindow.ui form right click the Record button and choose Go to slot.


The available signals are displayed. Choose clicked() and click OK.


You'll go the the implementation of the button click in mainwindow.cpp.


A new private slots: section has also been added to the /MainWindow class in mainwindow.h.


Repeat these steps for the Stop, Play, and Clear buttons

Record button
  • No MIDI messages are recorded or displayed if isRecording == false.
  • On click sets isRecording to true.
  • Messages received from rtmidiin are displayed in CMidiPacket format.
  • On each Record button click convert the first rtmidiin timestamp to CMidiPacket format and set firstRecordTimestamp to that value.
  • Set isFirstTimestampCaptured to true.
  • On future clicks the rtmidiin timestamp will not be zero but the CMidiPacket timestamp needs be reset to zero.
  • Use the firstRecordTimestamp to adjust the CMidiPacket timestamp back to zero
  • Clear std::vector<CMidiPacket> vplay.

Add this code to on_pushButton_record_clicked()

void MainWindow::on_pushButton_record_clicked()
    isRecording = true;
    isFirstTimestampCaptured = false;
Stop button
  • Stop recording and displaying MIDI messages.
  • The RtMidi timestamp clock keeps running.

Add this code to on_pushButton_stop_clicked()

void MainWindow::on_pushButton_stop_clicked()
    isRecording = false;
    isFirstTimestampCaptured = true;
Play button
  • This is left as an exercise for the reader.

Add this code to on_pushButton_play_clicked().

void MainWindow::on_pushButton_play_clicked()
    isRecording = false;
    isFirstTimestampCaptured = true;
    // now make it play
Clear button
  • Clear the contents of QPlainTextEdit.
  • Turn off the isRecording flag.

Add this code to on_pushButton_stop_clicked()

void MainWindow::on_pushButton_clear_clicked()
    isRecording = false;
    isFirstTimestampCaptured = true;
Button highlighting

We'll make each button remain highlighted until another button is clicked. Buttons act like toggles.

In Design view hold down the command key and select all 4 push buttons.


Then add the checkable property.


Add the allButtonsOff() function.


Add this code for void MainWindow::allButtonsOff()

void MainWindow::allButtonsOff()
    ui->pushButton_record->setChecked( false );
    ui->pushButton_stop->setChecked( false );
    ui->pushButton_play->setChecked( false );
    ui->pushButton_clear->setChecked( false );

Then turn on each pushButton in its on_pushButton_name_clicked() implementation. For example.

void MainWindow::on_pushButton_record_clicked()
    // highlighting
    ui->pushButton_record->setChecked( true );

    isRecording = true;
    isFirstTimestampCaptured = false;

Repeat these steps for each button.

Enable MIDI Output
Make these connections in VMPK.
Choose MIDI connections from the Edit menu.


Choose these settings.


Build and run
You should hear the notes you play in VMPK and see the messages appear in the MIDI Monitor window.

Submission Format

Feel free to email jellinge@carleton.edu on any part of the homework that is unclear to you. Chances are if you have questions other students do too. I will answer those questions by email to everyone in the class. The original sender will remain anonymous. I have tried to provide clues to the homework in the web pages, reading assignments, and labs. Sometimes what seems obvious to me is not obvious to students just learning C++.

Create a folder named hwNN_LastnameFirstname_LastnameFirstname.
Substitute your name and your partner's name for LastnameFirstname_LastnameFirstname.


  • Boilerplate header at top of every file.
  • Make sure your program compiles before submitting.
  • Programs that compile and produce partially correct output will be graded.
  • You can send notes to me in your homework files by enclosing them in block comments.
  • Programs that do not compile get an automatic F (59%).
  • Submit the homework in only one of the partner's folders.
  • Empty your build or build-debug folders using the command emptyBuildFolder.sh
  • Only include .h, .cpp, Makefiles, CMakeLists.txt
  • Do not include these folders/files
  • Double check for the above two folders using this command

    ls -a hwNN_LastnameFirstname1_LastnameFirstname2
    # if either .git or .vscode exist in the folder you're submitting remove them with
    # rm -fR .git
    # rm -fR .vscode

Hand-in folder contents

├── hw332_CMidiPacket.cpp
├── hw332_CMidiPacket.h
├── hw411_rand_int.cpp
├── hw411_rand_int.h
├── hw421_CDelayMs.cpp
├── hw421_CDelayMs.h
├── hw422_CAppleMidiSynth.cpp
├── hw422_CAppleMidiSynth.h
├── hw423_CMidiTrack.cpp
├── hw423_CMidiTrack.h
├── hw511_CInstrument.cpp
├── hw511_CInstrument.h
└── hw511_CInstrument.h

├── hw711_Qt_cmidiin_gui
│   ├── hw711_Qt_cmidiin_gui.pro
│   ├── hw711_Qt_cmidiin_gui.pro.user
│   ├── main.cpp
│   ├── mainwindow.cpp
│   ├── mainwindow.h
│   └── mainwindow.ui
├── hw712_Qt_rtmidiin
│   ├── hw332_CMidiPacket.cpp
│   ├── hw332_CMidiPacket.h
│   ├── hw712_Qt_rtmidiin.pro
│   ├── hw712_Qt_rtmidiin.pro.user
│   ├── main.cpp
│   ├── mainwindow.cpp
│   ├── mainwindow.h
│   └── mainwindow.ui
└── hw713_Qt_rtmidiin_buttons
    ├── hw332_CMidiPacket.cpp
    ├── hw332_CMidiPacket.h
    ├── hw713_Qt_rtmidiin_buttons.pro
    ├── hw713_Qt_rtmidiin_buttons.pro.user
    ├── main.cpp
    ├── mainwindow.cpp
    ├── mainwindow.h
    └── mainwindow.ui

Author: John Ellinger

Created: 2020-02-16 Sun 20:26