Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions Src/Music_Player_Application/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Makefile for Lecture 18 C++ Music Player System

CXX = g++
CXXFLAGS = -std=c++11 -Wall -Wextra
TARGET = music_player
SOURCE = main.cpp

# Default target
all: $(TARGET)

# Build the executable
$(TARGET): $(SOURCE)
$(CXX) $(CXXFLAGS) -I. -o $(TARGET) $(SOURCE)

# Run the application
run: $(TARGET)
./$(TARGET)

# Clean up compiled files
clean:
rm -f $(TARGET) $(TARGET).exe

# Help target
help:
@echo "Available targets:"
@echo " all - Build the application (default)"
@echo " run - Build and run the application"
@echo " clean - Remove compiled files"
@echo " help - Show this help message"

.PHONY: all run clean help
94 changes: 94 additions & 0 deletions Src/Music_Player_Application/MusicPlayerApplication.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
#pragma once
#include "managers/PlaylistManager.hpp"
#include "MusicPlayerFacade.hpp"

using namespace std;

class MusicPlayerApplication {
private:
static MusicPlayerApplication* instance;
vector<Song*> songLibrary;
MusicPlayerApplication() {}

public:
static MusicPlayerApplication* getInstance() {
if (!instance) {
instance = new MusicPlayerApplication();
}
return instance;
}

void createSongInLibrary(const string& title, const string& artist,
const string& path) {
Song* newSong = new Song(title, artist, path);
songLibrary.push_back(newSong);
}

Song* findSongByTitle(const string& title) {
for (Song* s : songLibrary) {
if (s->getTitle() == title) {
return s;
}
}
return nullptr;
}
void createPlaylist(const string& playlistName) {
PlaylistManager::getInstance()->createPlaylist(playlistName);
}

void addSongToPlaylist(const string& playlistName,
const string& songTitle) {
Song* song = findSongByTitle(songTitle);
if (!song) {
throw runtime_error("Song \"" + songTitle + "\" not found in library.");
}
PlaylistManager::getInstance()
->addSongToPlaylist(playlistName, song);
}

void connectAudioDevice(DeviceType deviceType) {
MusicPlayerFacade::getInstance()->connectDevice(deviceType);
}

void selectPlayStrategy(PlayStrategyType strategyType) {
MusicPlayerFacade::getInstance()->setPlayStrategy(strategyType);
}

void loadPlaylist(const string& playlistName) {
MusicPlayerFacade::getInstance()->loadPlaylist(playlistName);
}

void playSingleSong(const string& songTitle) {
Song* song = findSongByTitle(songTitle);
if (!song) {
throw runtime_error("Song \"" + songTitle + "\" not found.");
}
MusicPlayerFacade::getInstance()->playSong(song);
}

void pauseCurrentSong(const string& songTitle) {
Song* song = findSongByTitle(songTitle);
if (!song) {
throw runtime_error("Song \"" + songTitle + "\" not found.");
}
MusicPlayerFacade::getInstance()->pauseSong(song);
}

void playAllTracksInPlaylist() {
MusicPlayerFacade::getInstance()->playAllTracks();
}

void playPreviousTrackInPlaylist() {
MusicPlayerFacade::getInstance()->playPreviousTrack();
}

void queueSongNext(const string& songTitle) {
Song* song = findSongByTitle(songTitle);
if (!song) {
throw runtime_error("Song \"" + songTitle + "\" not found.");
}
MusicPlayerFacade::getInstance()->enqueueNext(song);
}
};

MusicPlayerApplication* MusicPlayerApplication::instance = nullptr;
112 changes: 112 additions & 0 deletions Src/Music_Player_Application/MusicPlayerFacade.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
#pragma once
#include "core/AudioEngine.hpp"
#include "models/Playlist.hpp"
#include "models/Song.hpp"
#include "strategies/PlayStrategy.hpp"
#include "enums/DeviceType.hpp"
#include "enums/PlayStrategyType.hpp"
#include "managers/DeviceManager.hpp"
#include "managers/PlaylistManager.hpp"
#include "managers/StrategyManager.hpp"

using namespace std;

class MusicPlayerFacade {
private:
static MusicPlayerFacade* instance;
AudioEngine* audioEngine;
Playlist* loadedPlaylist;
PlayStrategy* playStrategy;

MusicPlayerFacade() {
loadedPlaylist = nullptr;
playStrategy = nullptr;
audioEngine = new AudioEngine();
}

public:
static MusicPlayerFacade* getInstance() {
if (!instance) {
instance = new MusicPlayerFacade();
}
return instance;
}

void connectDevice(DeviceType deviceType) {
DeviceManager::getInstance()->connect(deviceType);
}

void setPlayStrategy(PlayStrategyType strategyType) {
playStrategy = StrategyManager::getInstance()->getStrategy(strategyType);
}

void loadPlaylist(const string& name) {
loadedPlaylist = PlaylistManager::getInstance()->getPlaylist(name);
if (!playStrategy) {
throw runtime_error("Play strategy not set before loading.");
}
playStrategy->setPlaylist(loadedPlaylist);
}

void playSong(Song* song) {
if (!DeviceManager::getInstance()->hasOutputDevice()) {
throw runtime_error("No audio device connected.");
}
IAudioOutputDevice* device = DeviceManager::getInstance()->getOutputDevice();
audioEngine->play(device, song);
}

void pauseSong(Song* song) {
if (audioEngine->getCurrentSongTitle() != song->getTitle()) {
throw runtime_error("Cannot pause \"" + song->getTitle() + "\"; not currently playing.");
}
audioEngine->pause();
}

void playAllTracks() {
if (!loadedPlaylist) {
throw runtime_error("No playlist loaded.");
}
while (playStrategy->hasNext()) {
Song* nextSong = playStrategy->next();
IAudioOutputDevice* device = DeviceManager::getInstance()->getOutputDevice();
audioEngine->play(device, nextSong);
}
cout << "Completed playlist: " << loadedPlaylist->getPlaylistName() << "\n";
}

void playNextTrack() {
if (!loadedPlaylist) {
throw runtime_error("No playlist loaded.");
}
if(playStrategy->hasNext()) {
Song* nextSong = playStrategy->next();
IAudioOutputDevice* device = DeviceManager::getInstance()->getOutputDevice();
audioEngine->play(device, nextSong);
}
else {
cout << "Completed playlist: " << loadedPlaylist->getPlaylistName() << "\n";
}
}

void playPreviousTrack() {
if (!loadedPlaylist) {
throw runtime_error("No playlist loaded.");
}
if(playStrategy->hasPrevious()) {
Song* prevSong = playStrategy->previous();
IAudioOutputDevice* device = DeviceManager::getInstance()->getOutputDevice();
audioEngine->play(device, prevSong);
}
else {
cout << "Completed playlist: " << loadedPlaylist->getPlaylistName() << "\n";
}
}

void enqueueNext(Song* song) {
playStrategy->addToNext(song);
}
};

MusicPlayerFacade* MusicPlayerFacade::instance = nullptr;

17 changes: 17 additions & 0 deletions Src/Music_Player_Application/compile.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
@echo off
echo Compiling C++ Music Player System...

REM Compile the main program
g++ -std=c++11 -I. -o music_player main.cpp

if %errorlevel% equ 0 (
echo Compilation successful!
echo Running the Music Player application...
echo.
music_player.exe
) else (
echo Compilation failed!
echo Please check for any syntax errors.
)

pause
15 changes: 15 additions & 0 deletions Src/Music_Player_Application/compile.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/bin/bash
echo "Compiling Lecture 18 C++ Music Player System..."

# Compile the main program
g++ -std=c++11 -I. -o music_player main.cpp

if [ $? -eq 0 ]; then
echo "Compilation successful!"
echo "Running the Music Player application..."
echo
./music_player
else
echo "Compilation failed!"
echo "Please check for any syntax errors."
fi
55 changes: 55 additions & 0 deletions Src/Music_Player_Application/core/AudioEngine.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#pragma once
#include "../models/Song.hpp"
#include "../device/IAudioOutputDevice.hpp"
#include<string>
#include<iostream>

using namespace std;

class AudioEngine {
private:
Song* currentSong;
bool songIsPaused;
public:
AudioEngine() {
currentSong = nullptr;
songIsPaused = false;
}
string getCurrentSongTitle() const {
if (currentSong) {
return currentSong->getTitle();
}
return "";
}
bool isPaused() const {
return songIsPaused;
}
void play(IAudioOutputDevice* aod, Song* song) {
if (song == nullptr) {
throw runtime_error("Cannot play a null song.");
}
// Resume if same song was paused
if (songIsPaused && song == currentSong) {
songIsPaused = false;
cout << "Resuming song: " << song->getTitle() << "\n";
aod->playAudio(song);
return;
}

currentSong = song;
songIsPaused = false;
cout << "Playing song: " << song->getTitle() << "\n";
aod->playAudio(song);
}

void pause() {
if (currentSong == nullptr) {
throw runtime_error("No song is currently playing to pause.");
}
if (songIsPaused) {
throw runtime_error("Song is already paused.");
}
songIsPaused = true;
cout << "Pausing song: " << currentSong->getTitle() << "\n";
}
};
20 changes: 20 additions & 0 deletions Src/Music_Player_Application/device/BluetoothSpeakerAdapter.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#pragma once
#include "../models/Song.hpp"
#include "IAudioOutputDevice.hpp"
#include "../external/BluetoothSpeakerAPI.hpp"

using namespace std;

class BluetoothSpeakerAdapter : public IAudioOutputDevice {
private:
BluetoothSpeakerAPI* bluetoothApi;
public:
BluetoothSpeakerAdapter(BluetoothSpeakerAPI* api) {
bluetoothApi = api;
}

void playAudio(Song* song) override {
string payload = song->getTitle() + " by " + song->getArtist();
bluetoothApi->playSoundViaBluetooth(payload);
}
};
21 changes: 21 additions & 0 deletions Src/Music_Player_Application/device/HeadphonesAdapter.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#pragma once
#include "../models/Song.hpp"
#include "IAudioOutputDevice.hpp"
#include "../external/HeadphonesAPI.hpp"

using namespace std;

class HeadphonesAdapter : public IAudioOutputDevice {
private:
HeadphonesAPI* headphonesApi;
public:
HeadphonesAdapter(HeadphonesAPI* api) {
headphonesApi = api;
}

void playAudio(Song* song) override {
string payload = song->getTitle() + " by " + song->getArtist();
headphonesApi->playSoundViaJack(payload);
}
};

8 changes: 8 additions & 0 deletions Src/Music_Player_Application/device/IAudioOutputDevice.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#pragma once
#include "../models/Song.hpp"

class IAudioOutputDevice {
public:
virtual ~IAudioOutputDevice() {}
virtual void playAudio(Song* song) = 0;
};
Loading
Loading