Problem Set #99: Music Player

Ciele

  • Precvičiť si prácu so štruktúrovanými údajovými typmi

  • Precvičiť si prácu s dynamickou alokáciou pamäti

  • Precvičiť si prácu so spojkovými zoznamami

About

Akú aplikáciu používate na prehrávanie vašej hudobnej zbierky? WinAmp? Banshee? Rhythmbox? Alebo si vystačíte s Majkrosoft Media Player-om? Alebo ste už presedlali na YouTube alebo podobnú online službu? Každopádne táto úloha bude mať k prehrávaniu hudobných súborov veľmi blízko.

Štruktúra struct playlist

V rámci tejto úlohy vytvoríte jednoduchú implementáciu zoznamu skladieb (z angl. playlist) v jazyku C. Zoznam skladieb je reprezentovaný pomocou štruktúrovaného typu struct playlist, ktorý sa skladá z týchto prvkov:

  • name - názov zoznamu skladieb, napr. “Heavy Metal Classic”
  • duration - celková dlžka trvania zoznamu skladieb v sekundách
  • size - počet skladieb nachádzajúcich sa v zozname skladieb
  • mode - režim prehrávania, ktorý je definovaný pomocou enumeračného typu enum play_mode
  • current - referencia na aktuálnu položku zoznamu typu struct entry
  • first - referencia na prvú položku zo zoznamu skladieb typu struct entry

Definícia spolu s dokumentáciou sa nachádza v súbore playlist.h.

Štruktúra struct track

Každá skladba je reprezentovaná ako štruktúra struct track. Každá skladba má tieto povinné položky:

  • title - názov skladby
  • duration - dlžka trvania v sekundách

Jedna skladba sa samozrejme môže nachádzať vo viacerých zoznamoch skladieb. Prepojenie skladby s príslušným zoznamom skladieb, sa nachádza v inštanciách štruktúrovaného typu struct entry.

Definícia spolu s dokumentáciou sa nachádza v súbore track.h.

Štruktúra struct entry

Táto štruktúra reprezentuje jeden prvok obojsmerného spájaného zoznamu, z ktorého je vytvorený zoznam skladieb. Skladá sa z týchto položiek:

  • prev - referencia na predchádzajúcu položku v zozname
  • next - referencia na nasledujúcu položku v zozname
  • track - referencia na skladbu

Definícia spolu s dokumentáciou sa nachádza v súbore playlist.h.

Modul Track

Tento modul obsahuje všetko potrebné na prácu so skladbami. Obsahuje štruktúru struct track ako aj funkcie s ňou pracujúce.

Úloha #1: Funkcia create_track()

Na vytvorenie skladby sú potrebné dva parametre:

  • title - názov skladby, max. dĺžka je 100 znakov
  • duration - dĺžka trvania v sekundách

Skladbu je možné vytvoriť iba vtedy, ak je názov skladby platný (neprázdny reťazec o max. dĺžke 100 znakov) a dĺžka jej trvania je celé kladné číslo. V opačnom prípade vráti funkcia NULL.

Názov skladby je potrebné vytvoriť kópiou.

Príklad použitia:

struct track* track = create_track("Za rana za rosy", 240);
// struct track track = { .name = "Za rana za rosy", .duration = 240 };

Úloha #2: Funkcia free_track()

Funkcia uvoľní všetky zdroje vyhradené pre skladbu z pamäte.

Modul Playlist

Tento modul obsahuje všetko potrebné na prácu so zoznamami skladieb. Obsahuje štruktúru definujúcu zoznam skladieb struct playlist, štruktúru struct entry definujúcu jednu položku zoznamu skladieb a enumeračný typ enum play_mode, ktorý opisuje režim prehrávania skladieb.

Úloha #3: Funkcia create_playlist()

Na vytvorenie skladby je potrebný len jeden parameter:

  • name - názov skladby, max. dĺžka je 100 znakov

Zoznam skladieb je možné vytvoriť iba vtedy, ak je jeho názov platný (neprázdny reťazec o max. dĺžke 100 znakov). V opačnom prípade vráti funkcia NULL.

Názov zoznamu skladieb je potrebné vytvoriť kópiou.

Príklad použitia:

struct playlist* playlist = create_playlist("Soundtracks");
// struct playlist playlist = {
//    .name = "Soundtracks",
//    .duration = 0,
//    .size = 0,
//    .mode = REPEAT,
//    .current = NULL,
//    .first = NULL
// };

Úloha #4: Funkcia append_track_to_playlist()

Pomocou funkcie pripojíte do existujúceho zoznamu skladieb novú skladbu. To však len vtedy, ak zoznam skladieb aj skladba samotná existujú.

Príklad použitia:

struct track* track = create_track("Don't Let Me Be Misunderstood", 629);
struct playlist* playlist = create_playlist("Vypekacky");
append_track_to_playlist(playlist, track);
// struct playlist playlist = {
//    .name = "Vypekacky",
//    .duration = 629,
//    .size = 1,
//    .mode = REPEAT,
//    .current = { .name = "Don't Let Me Be Misunderstood", .duration = 629 },
//    .first = { .name = "Don't Let Me Be Misunderstood", .duration = 629 }
// };

Úloha #5: Funkcia play()

Funkcia prehrá (vypíše na obrazovku) aktuálnu skladbu a po jej prehratí presunie ukaozvateľ .current na ďalšiu skladbu na základe režimu prehrávania:

  • ak je režim ONE_SONG, tak aktuálna skladba sa nezmení
  • ak je režim REPEAT, tak sa aktuálna skladba zmení na nasledujúcu v poradí; ak sa jedná o poslednú skladbu zoznamu, nastaví sa na jeho prvú skladbu
  • ak je režim DONT_REPEAT, zmena funguje ako v režime REPEAT; ak sa však jedná o poslednú skladbu, k žiadnej ďalšej zmene už nedôjde

Príklad použitia:

struct playlist* playlist = create_playlist("M83");
append_track_to_playlist(playlist, create_track("Wait", 355));
append_track_to_playlist(playlist, create_track("Outro", 247));
append_track_to_playlist(playlist, create_track("Midnight City", 242));
// struct playlist playlist = {
//    .name = "M83",
//    .duration = 844,
//    .size = 3,
//    .mode = REPEAT,
//    .current = { .name = "Wait", .duration = 355 },
//    .first = { .name = "Wait", .duration = 355 }
// };
play(playlist);
// Playing track: 'Wait' from playlist 'M83'
// struct playlist playlist = {
//    .name = "M83",
//    .duration = 844,
//    .size = 3,
//    .mode = REPEAT,
//    .current = { .name = "Outro", .duration = 247 },
//    .first = { .name = "Wait", .duration = 355 }
// };

Úloha #6: Funkcie next() a prev()

Funkcie vzhľadom na režim prehrávania zoznamu skladieb zmenia aktuálnu skladbu (položku .current), ktorej referenciu aj následne vrátia. V prípade, že referencia na zoznam skladieb neexistuje, vrátia hodnotu NULL.

Úloha #8: Funkcia change_mode()

Funkcia zmení aktuálny režim prehrávania na nový vzhľadom na parameter. V prípade, že parametre funkcie sú neplatné, funkcia nič nezmení.

Príklad použitia:

struct playlist* playlist = create_playlist("Best Off");
// struct playlist playlist = {
//    .name = "Best Off",
//    .duration = 0,
//    .size = 0,
//    .mode = REPEAT,
//    .current = NULL,
//    .first = NULL
// };

change_mode(playlist, DONT_REPEAT);
// struct playlist playlist = {
//    .name = "Best Off",
//    .duration = 0,
//    .size = 0,
//    .mode = DONT_REPEAT,
//    .current = NULL,
//    .first = NULL
// };

Úloha #9: Funkcia free_playlist()

Funkcia uvoľní všetky zdroje vyhradené pre zoznam skladieb z pamäte vrátane skladieb.

Odovzdávanie projektu

Zadanie sa odovzdáva prostredníctvom systému na správu verzií Git na serveri git.kpi.fei.tuke.sk. Riešenie tejto úlohy odovzdáte ako súčasť vášho projektu s názvom prog-2021.

Štruktúra vášho projektu bude vyzerať nasledovne:

.
├── ps99
│   ├── main.c
│   ├── Makefile
│   ├── playlist.c
│   ├── playlist.h
│   ├── track.c
│   └── track.h
└── README

kde význam súborov v priečinku ps99/ je nasledovný:

  • playlist.c, playlist.h - Zdrojový kód a hlavičkový súbor modulu pre prácu so zoznamom skladieb.

  • track.c, track.h - Zdrojový kód a hlavičkový súbor modulu pre prácu so skladbou.

  • main.c - Zdrojový kód obsahujúci hlavnú funkciu main(). Tento súbor nebude súčasťou testov, ale musí byť samozrejme valídny.

  • Makefile - Makefile súbor obsahujúci ciele na vygenerovanie samostatných modulov a cieľ all a clean.

  • README - Súbor, v ktorom bude uvedené označenie vašej skupiny, ktorú navštevujete na cvičeniach v tvare:

    GROUP : A1

Ak ste opakujúci študent, uveďte v README skupinu v tvare:

GROUP : O<P>

kde <P> nahradíte písmenom paralelky, ktorá podľa rozvrhu zodpovedá vášmu študijnému programu (napr. A pre informatikov).

Kostra projektu

Tentokrát je kostra projektu reprezentovaná len jedným hlavičkovým súborom, ktorý si môžete stiahnuť z tohto odkazu.

Hodnotenie a testovanie

Vaše hodnotenie sa bude odvíjať od výsledku automatických testov (ak sa ich podarí pripraviť) a od osobného hodnotenia vášho cvičiaceho. Overovať sa bude:

  • Štruktúra vášho projektu (či sa v ňom nachádzajú všetky potrebné súbory).
  • Statická analýza vášho kódu pomocou nástroja cppcheck.
  • Prítomnosť globálnych premenných vo vašom kóde.
  • Funkčnosť vašej implementácie.

Testovanie vašich riešení sa bude vykonávať automaticky každú hodinu.

Vaše riešenia opäť prejdú kontrolou originality. Preto sa pri práci na vašom zadaní správajte podľa pravidiel etického kódexu! V prípade, že odovzdáte zadanie, ktoré nie je vaše, budete vylúčení z predmetu!