Skip to content

Commit 82266bf

Browse files
authored
Merge pull request #40 from adityacosmos24/main
feat: added music player aplication
2 parents 0085118 + 10b6fc6 commit 82266bf

28 files changed

+1015
-0
lines changed
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# Makefile for Lecture 18 C++ Music Player System
2+
3+
CXX = g++
4+
CXXFLAGS = -std=c++11 -Wall -Wextra
5+
TARGET = music_player
6+
SOURCE = main.cpp
7+
8+
# Default target
9+
all: $(TARGET)
10+
11+
# Build the executable
12+
$(TARGET): $(SOURCE)
13+
$(CXX) $(CXXFLAGS) -I. -o $(TARGET) $(SOURCE)
14+
15+
# Run the application
16+
run: $(TARGET)
17+
./$(TARGET)
18+
19+
# Clean up compiled files
20+
clean:
21+
rm -f $(TARGET) $(TARGET).exe
22+
23+
# Help target
24+
help:
25+
@echo "Available targets:"
26+
@echo " all - Build the application (default)"
27+
@echo " run - Build and run the application"
28+
@echo " clean - Remove compiled files"
29+
@echo " help - Show this help message"
30+
31+
.PHONY: all run clean help
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
#pragma once
2+
#include "managers/PlaylistManager.hpp"
3+
#include "MusicPlayerFacade.hpp"
4+
5+
using namespace std;
6+
7+
class MusicPlayerApplication {
8+
private:
9+
static MusicPlayerApplication* instance;
10+
vector<Song*> songLibrary;
11+
MusicPlayerApplication() {}
12+
13+
public:
14+
static MusicPlayerApplication* getInstance() {
15+
if (!instance) {
16+
instance = new MusicPlayerApplication();
17+
}
18+
return instance;
19+
}
20+
21+
void createSongInLibrary(const string& title, const string& artist,
22+
const string& path) {
23+
Song* newSong = new Song(title, artist, path);
24+
songLibrary.push_back(newSong);
25+
}
26+
27+
Song* findSongByTitle(const string& title) {
28+
for (Song* s : songLibrary) {
29+
if (s->getTitle() == title) {
30+
return s;
31+
}
32+
}
33+
return nullptr;
34+
}
35+
void createPlaylist(const string& playlistName) {
36+
PlaylistManager::getInstance()->createPlaylist(playlistName);
37+
}
38+
39+
void addSongToPlaylist(const string& playlistName,
40+
const string& songTitle) {
41+
Song* song = findSongByTitle(songTitle);
42+
if (!song) {
43+
throw runtime_error("Song \"" + songTitle + "\" not found in library.");
44+
}
45+
PlaylistManager::getInstance()
46+
->addSongToPlaylist(playlistName, song);
47+
}
48+
49+
void connectAudioDevice(DeviceType deviceType) {
50+
MusicPlayerFacade::getInstance()->connectDevice(deviceType);
51+
}
52+
53+
void selectPlayStrategy(PlayStrategyType strategyType) {
54+
MusicPlayerFacade::getInstance()->setPlayStrategy(strategyType);
55+
}
56+
57+
void loadPlaylist(const string& playlistName) {
58+
MusicPlayerFacade::getInstance()->loadPlaylist(playlistName);
59+
}
60+
61+
void playSingleSong(const string& songTitle) {
62+
Song* song = findSongByTitle(songTitle);
63+
if (!song) {
64+
throw runtime_error("Song \"" + songTitle + "\" not found.");
65+
}
66+
MusicPlayerFacade::getInstance()->playSong(song);
67+
}
68+
69+
void pauseCurrentSong(const string& songTitle) {
70+
Song* song = findSongByTitle(songTitle);
71+
if (!song) {
72+
throw runtime_error("Song \"" + songTitle + "\" not found.");
73+
}
74+
MusicPlayerFacade::getInstance()->pauseSong(song);
75+
}
76+
77+
void playAllTracksInPlaylist() {
78+
MusicPlayerFacade::getInstance()->playAllTracks();
79+
}
80+
81+
void playPreviousTrackInPlaylist() {
82+
MusicPlayerFacade::getInstance()->playPreviousTrack();
83+
}
84+
85+
void queueSongNext(const string& songTitle) {
86+
Song* song = findSongByTitle(songTitle);
87+
if (!song) {
88+
throw runtime_error("Song \"" + songTitle + "\" not found.");
89+
}
90+
MusicPlayerFacade::getInstance()->enqueueNext(song);
91+
}
92+
};
93+
94+
MusicPlayerApplication* MusicPlayerApplication::instance = nullptr;
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
#pragma once
2+
#include "core/AudioEngine.hpp"
3+
#include "models/Playlist.hpp"
4+
#include "models/Song.hpp"
5+
#include "strategies/PlayStrategy.hpp"
6+
#include "enums/DeviceType.hpp"
7+
#include "enums/PlayStrategyType.hpp"
8+
#include "managers/DeviceManager.hpp"
9+
#include "managers/PlaylistManager.hpp"
10+
#include "managers/StrategyManager.hpp"
11+
12+
using namespace std;
13+
14+
class MusicPlayerFacade {
15+
private:
16+
static MusicPlayerFacade* instance;
17+
AudioEngine* audioEngine;
18+
Playlist* loadedPlaylist;
19+
PlayStrategy* playStrategy;
20+
21+
MusicPlayerFacade() {
22+
loadedPlaylist = nullptr;
23+
playStrategy = nullptr;
24+
audioEngine = new AudioEngine();
25+
}
26+
27+
public:
28+
static MusicPlayerFacade* getInstance() {
29+
if (!instance) {
30+
instance = new MusicPlayerFacade();
31+
}
32+
return instance;
33+
}
34+
35+
void connectDevice(DeviceType deviceType) {
36+
DeviceManager::getInstance()->connect(deviceType);
37+
}
38+
39+
void setPlayStrategy(PlayStrategyType strategyType) {
40+
playStrategy = StrategyManager::getInstance()->getStrategy(strategyType);
41+
}
42+
43+
void loadPlaylist(const string& name) {
44+
loadedPlaylist = PlaylistManager::getInstance()->getPlaylist(name);
45+
if (!playStrategy) {
46+
throw runtime_error("Play strategy not set before loading.");
47+
}
48+
playStrategy->setPlaylist(loadedPlaylist);
49+
}
50+
51+
void playSong(Song* song) {
52+
if (!DeviceManager::getInstance()->hasOutputDevice()) {
53+
throw runtime_error("No audio device connected.");
54+
}
55+
IAudioOutputDevice* device = DeviceManager::getInstance()->getOutputDevice();
56+
audioEngine->play(device, song);
57+
}
58+
59+
void pauseSong(Song* song) {
60+
if (audioEngine->getCurrentSongTitle() != song->getTitle()) {
61+
throw runtime_error("Cannot pause \"" + song->getTitle() + "\"; not currently playing.");
62+
}
63+
audioEngine->pause();
64+
}
65+
66+
void playAllTracks() {
67+
if (!loadedPlaylist) {
68+
throw runtime_error("No playlist loaded.");
69+
}
70+
while (playStrategy->hasNext()) {
71+
Song* nextSong = playStrategy->next();
72+
IAudioOutputDevice* device = DeviceManager::getInstance()->getOutputDevice();
73+
audioEngine->play(device, nextSong);
74+
}
75+
cout << "Completed playlist: " << loadedPlaylist->getPlaylistName() << "\n";
76+
}
77+
78+
void playNextTrack() {
79+
if (!loadedPlaylist) {
80+
throw runtime_error("No playlist loaded.");
81+
}
82+
if(playStrategy->hasNext()) {
83+
Song* nextSong = playStrategy->next();
84+
IAudioOutputDevice* device = DeviceManager::getInstance()->getOutputDevice();
85+
audioEngine->play(device, nextSong);
86+
}
87+
else {
88+
cout << "Completed playlist: " << loadedPlaylist->getPlaylistName() << "\n";
89+
}
90+
}
91+
92+
void playPreviousTrack() {
93+
if (!loadedPlaylist) {
94+
throw runtime_error("No playlist loaded.");
95+
}
96+
if(playStrategy->hasPrevious()) {
97+
Song* prevSong = playStrategy->previous();
98+
IAudioOutputDevice* device = DeviceManager::getInstance()->getOutputDevice();
99+
audioEngine->play(device, prevSong);
100+
}
101+
else {
102+
cout << "Completed playlist: " << loadedPlaylist->getPlaylistName() << "\n";
103+
}
104+
}
105+
106+
void enqueueNext(Song* song) {
107+
playStrategy->addToNext(song);
108+
}
109+
};
110+
111+
MusicPlayerFacade* MusicPlayerFacade::instance = nullptr;
112+
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
@echo off
2+
echo Compiling C++ Music Player System...
3+
4+
REM Compile the main program
5+
g++ -std=c++11 -I. -o music_player main.cpp
6+
7+
if %errorlevel% equ 0 (
8+
echo Compilation successful!
9+
echo Running the Music Player application...
10+
echo.
11+
music_player.exe
12+
) else (
13+
echo Compilation failed!
14+
echo Please check for any syntax errors.
15+
)
16+
17+
pause
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#!/bin/bash
2+
echo "Compiling Lecture 18 C++ Music Player System..."
3+
4+
# Compile the main program
5+
g++ -std=c++11 -I. -o music_player main.cpp
6+
7+
if [ $? -eq 0 ]; then
8+
echo "Compilation successful!"
9+
echo "Running the Music Player application..."
10+
echo
11+
./music_player
12+
else
13+
echo "Compilation failed!"
14+
echo "Please check for any syntax errors."
15+
fi
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
#pragma once
2+
#include "../models/Song.hpp"
3+
#include "../device/IAudioOutputDevice.hpp"
4+
#include<string>
5+
#include<iostream>
6+
7+
using namespace std;
8+
9+
class AudioEngine {
10+
private:
11+
Song* currentSong;
12+
bool songIsPaused;
13+
public:
14+
AudioEngine() {
15+
currentSong = nullptr;
16+
songIsPaused = false;
17+
}
18+
string getCurrentSongTitle() const {
19+
if (currentSong) {
20+
return currentSong->getTitle();
21+
}
22+
return "";
23+
}
24+
bool isPaused() const {
25+
return songIsPaused;
26+
}
27+
void play(IAudioOutputDevice* aod, Song* song) {
28+
if (song == nullptr) {
29+
throw runtime_error("Cannot play a null song.");
30+
}
31+
// Resume if same song was paused
32+
if (songIsPaused && song == currentSong) {
33+
songIsPaused = false;
34+
cout << "Resuming song: " << song->getTitle() << "\n";
35+
aod->playAudio(song);
36+
return;
37+
}
38+
39+
currentSong = song;
40+
songIsPaused = false;
41+
cout << "Playing song: " << song->getTitle() << "\n";
42+
aod->playAudio(song);
43+
}
44+
45+
void pause() {
46+
if (currentSong == nullptr) {
47+
throw runtime_error("No song is currently playing to pause.");
48+
}
49+
if (songIsPaused) {
50+
throw runtime_error("Song is already paused.");
51+
}
52+
songIsPaused = true;
53+
cout << "Pausing song: " << currentSong->getTitle() << "\n";
54+
}
55+
};
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#pragma once
2+
#include "../models/Song.hpp"
3+
#include "IAudioOutputDevice.hpp"
4+
#include "../external/BluetoothSpeakerAPI.hpp"
5+
6+
using namespace std;
7+
8+
class BluetoothSpeakerAdapter : public IAudioOutputDevice {
9+
private:
10+
BluetoothSpeakerAPI* bluetoothApi;
11+
public:
12+
BluetoothSpeakerAdapter(BluetoothSpeakerAPI* api) {
13+
bluetoothApi = api;
14+
}
15+
16+
void playAudio(Song* song) override {
17+
string payload = song->getTitle() + " by " + song->getArtist();
18+
bluetoothApi->playSoundViaBluetooth(payload);
19+
}
20+
};
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#pragma once
2+
#include "../models/Song.hpp"
3+
#include "IAudioOutputDevice.hpp"
4+
#include "../external/HeadphonesAPI.hpp"
5+
6+
using namespace std;
7+
8+
class HeadphonesAdapter : public IAudioOutputDevice {
9+
private:
10+
HeadphonesAPI* headphonesApi;
11+
public:
12+
HeadphonesAdapter(HeadphonesAPI* api) {
13+
headphonesApi = api;
14+
}
15+
16+
void playAudio(Song* song) override {
17+
string payload = song->getTitle() + " by " + song->getArtist();
18+
headphonesApi->playSoundViaJack(payload);
19+
}
20+
};
21+
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#pragma once
2+
#include "../models/Song.hpp"
3+
4+
class IAudioOutputDevice {
5+
public:
6+
virtual ~IAudioOutputDevice() {}
7+
virtual void playAudio(Song* song) = 0;
8+
};

0 commit comments

Comments
 (0)