sarker306

Simple Music Player using SDL as music loader

Aug 25th, 2025
65
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 7.83 KB | Music | 0 0
  1. // Compile: cc -o musicplayer sdl2-musicplayer.c -lSDL2 -lSDL2_mixer -lSDL2_ttf
  2. #include <stdio.h>
  3. #include <dirent.h> // for opendir(), readdir(), closedir(), struct dirent
  4. #include <libgen.h> // for basename()
  5. #include <sys/stat.h> // for stat() and S_ISDIR() macro
  6. #include <limits.h> // for PATH_MAX
  7.  
  8. #ifndef PATH_MAX
  9. #define PATH_MAX 4096
  10. #endif
  11.  
  12. #include <SDL2/SDL.h>
  13. #include <SDL2/SDL_ttf.h>
  14. #include <SDL2/SDL_image.h>
  15. #include <SDL2/SDL_mixer.h>
  16.  
  17. #define TRUE 1
  18. #define FALSE 0
  19.  
  20. SDL_Window *pWindow;
  21. SDL_Renderer *pRenderer;
  22. SDL_Event event;
  23. int playerIsRunning;
  24. static int playMusic(const char *file);
  25. static int init(const char *title, int xpos, int ypos, int height, int width, int flags);
  26. static void render(const char *text);
  27. static void close();
  28. static SDL_Texture *loadText(const char *text);
  29. static SDL_Texture *loadImage(const char *imgPath);
  30.  
  31. int main(int argc, char **argv) {
  32.     int path_exists(const char*);
  33.     int path_is_directory(const char*);
  34.  
  35.     if ( init ("Hello SDL Player",
  36.                 SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
  37.                 640, 480,
  38.                 SDL_WINDOW_SHOWN | SDL_WINDOW_BORDERLESS ) == FALSE )
  39.         return EXIT_FAILURE;
  40.  
  41.     for ( int i = 1 ; i < argc && playerIsRunning ; i++ ) {
  42.         const char *target_path = argv[i];
  43.         // --- 1. Check if path exists ---
  44.         if ( !path_exists(target_path) ) {
  45.             fprintf(stderr, "SDL Player Error: %s not found.\n", target_path);
  46.             continue;
  47.         }
  48.  
  49.         // --- 2. Check if the path is a directory ---
  50.         // --- If not, it is probably an audio file. Play it. ---
  51.  
  52.         if ( !path_is_directory(target_path) ) {
  53.             playMusic(target_path);
  54.             continue;
  55.         }
  56.  
  57.         // --- 3. The path is a directory. Iterate through it. ---
  58.         DIR *p_dir_stream;           // Pointer to a directory stream
  59.         struct dirent *p_dir_entry;  // Pointer to a directory entry structure
  60.         p_dir_stream = opendir(target_path);
  61.         if ( p_dir_stream == NULL ) {
  62.             fprintf(stderr, "opendir Error: %s not opened\n", target_path);
  63.             perror(NULL);
  64.             continue;
  65.         }
  66.  
  67.         // readdir() reads the next entry in the directory stream
  68.         // It returns NULL when there are no more entries or an error occurs.
  69.  
  70.         while ((p_dir_entry = readdir(p_dir_stream)) != NULL && playerIsRunning ) {
  71.             // In POSIX systems, directories always contain "." (current directory)
  72.             // and ".." (parent directory). We usually skip these.
  73.             if ( strcmp(p_dir_entry->d_name, ".") == 0 || strcmp(p_dir_entry->d_name, "..") == 0 ) {
  74.                 continue;
  75.             }
  76.  
  77.             char full_entry_path[PATH_MAX];
  78.             snprintf(full_entry_path, sizeof(full_entry_path),
  79.                     "%s/%s", target_path, p_dir_entry->d_name);
  80.             printf("%s\n", full_entry_path);
  81.             playMusic(full_entry_path);
  82.         }
  83.  
  84.         closedir(p_dir_stream);
  85.     }
  86.  
  87.     close();
  88.     return EXIT_SUCCESS;
  89. }
  90.  
  91. static int init(const char *title, int xpos, int ypos, int height, int width, int flags) {
  92.     if ( SDL_Init(SDL_INIT_EVERYTHING) < 0 ) {
  93.         fprintf(stderr, "SDL_Init error: %s\n", SDL_GetError());
  94.         return FALSE;
  95.     }
  96.    
  97.     pWindow = SDL_CreateWindow(title, xpos, ypos, height, width, flags);
  98.     if ( pWindow == NULL ) {
  99.         fprintf(stderr, "SDL_CreateWindow error: %s\n", SDL_GetError());
  100.         SDL_Quit();
  101.         return FALSE;
  102.     }
  103.  
  104.     pRenderer = SDL_CreateRenderer(pWindow, -1, 0);
  105.     if ( pRenderer == NULL ) {
  106.         fprintf(stderr, "SDL_CreateRenderer error: %s\n", SDL_GetError());
  107.         SDL_DestroyWindow(pWindow);
  108.         SDL_Quit();
  109.         return FALSE;
  110.     }
  111.  
  112.     SDL_SetRenderDrawColor(pRenderer, 255, 0, 0, 255);
  113.  
  114.     SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "2");
  115.    
  116.     if ( Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 4096) < 0 ) {
  117.         fprintf(stderr, "Mix_OpenAudio error: %s\n", SDL_GetError());
  118.         SDL_DestroyRenderer(pRenderer);
  119.         SDL_DestroyWindow(pWindow);
  120.         SDL_Quit();
  121.         return FALSE;
  122.     }
  123.  
  124.     playerIsRunning = TRUE;
  125.     return TRUE;
  126. }
  127.  
  128. static void close() {
  129.     Mix_CloseAudio();
  130.     SDL_DestroyRenderer(pRenderer);
  131.     SDL_DestroyWindow(pWindow);
  132.     SDL_Quit();
  133. }
  134.  
  135. static int playMusic(const char *file) {
  136.     Mix_Music *pMusic;
  137.  
  138.     fprintf(stdout, "Playing music: %s\n", file);
  139.     render(basename(file));
  140.     pMusic = Mix_LoadMUS(file);
  141.  
  142.     if ( pMusic == NULL ) {
  143.         fprintf(stderr, "Mix_LoadMUS error: %s\n", Mix_GetError());
  144.         return FALSE;
  145.     }
  146.  
  147.     if ( Mix_PlayMusic(pMusic, 1) < 0 ) {
  148.         fprintf(stderr, "Mix_PlayMusic error: %s\n", Mix_GetError());
  149.         Mix_FreeMusic(pMusic);
  150.         return FALSE;
  151.     }
  152.  
  153.     while ( Mix_PlayingMusic() ) {
  154.         while ( SDL_PollEvent(&event) ) {
  155.             switch (event.type) {
  156.                 case SDL_QUIT:
  157.                     playerIsRunning = FALSE;
  158.                     Mix_FadeOutMusic(1000);
  159.                     break;
  160.             }
  161.         }
  162.     }
  163.  
  164.     Mix_FreeMusic(pMusic);
  165.  
  166.     return TRUE;
  167. }
  168.  
  169. static SDL_Texture* loadText(const char *text) {
  170.     if ( TTF_Init() < 0 ) {
  171.         fprintf(stderr, "TTF_Init error: %s\n", TTF_GetError());
  172.         return NULL;
  173.     }
  174.  
  175.     TTF_Font *pFont = TTF_OpenFont("/usr/share/fonts/truetype/msttcorefonts/Courier_New_Bold.ttf", 256);
  176.     if ( pFont == NULL ) {
  177.         fprintf(stderr, "TTF_OpenFont error: %s\n", TTF_GetError());
  178.         return NULL;
  179.     }
  180.  
  181.     SDL_Color color = {000, 255, 255};
  182.  
  183.     SDL_Surface *pSurface = TTF_RenderText_Solid(pFont, text, color);
  184.  
  185.     SDL_Texture *pTexture = SDL_CreateTextureFromSurface(pRenderer, pSurface);
  186.  
  187.     SDL_FreeSurface(pSurface);
  188.  
  189.     if ( pTexture == NULL ) {
  190.         fprintf(stderr, "SDL_CreateTextureFromSurface error: %s\n", SDL_GetError());
  191.         return NULL;
  192.     }
  193.  
  194.     return pTexture;
  195. }
  196.  
  197. static SDL_Texture *loadImage(const char *imgPath) {
  198.     SDL_Surface *pImage = IMG_Load(imgPath);
  199.     if ( pImage == NULL ) {
  200.         fprintf(stderr, "IMG_Load error: %s\n", IMG_GetError());
  201.         return NULL;
  202.     }
  203.  
  204.     SDL_Texture *pTexture = SDL_CreateTextureFromSurface(pRenderer, pImage);
  205.  
  206.     SDL_FreeSurface(pImage);
  207.  
  208.     if ( pTexture == NULL ) {
  209.         fprintf(stderr, "SDL_CreateTextureFromSurface error: %s\n", SDL_GetError());
  210.         return NULL;
  211.     }
  212.  
  213.     return pTexture;
  214. }
  215.  
  216. static void render(const char *text) {
  217.     int tw, th;
  218.     int w, h;
  219.     SDL_Rect dest;
  220.  
  221.     SDL_RenderClear(pRenderer);
  222.     SDL_GetRendererOutputSize(pRenderer, &w, &h);
  223. /*
  224.     // Image rendering
  225.     SDL_Texture *pImageTexture = loadImage("/home/zuko/Pictures/life-universe-physics-martin-gardner.png");
  226.  
  227.     SDL_QueryTexture(pImageTexture, NULL, NULL, &tw, &th);
  228.    
  229.     dest.x = 0;
  230.     dest.w = w;
  231.     dest.h = th * w / tw;
  232.     dest.y = (h - dest.h) / 2;
  233.  
  234.     SDL_RenderCopy(pRenderer, pImageTexture, NULL, &dest);
  235. */
  236.     // Text rendering
  237.     SDL_Texture *pTextTexture = loadText(text);
  238.  
  239.     SDL_QueryTexture(pTextTexture, NULL, NULL, &tw, &th);
  240.  
  241.     // Texts always have width much bigger than height
  242.     dest.x = 0;
  243.     dest.w = w;
  244.     dest.h = th * w / tw;
  245.     dest.y = (h - dest.h) / 2;
  246.  
  247.     SDL_RenderCopy(pRenderer, pTextTexture, NULL, &dest);
  248.  
  249.     SDL_RenderPresent(pRenderer);
  250.  
  251.     SDL_DestroyTexture(pTextTexture);
  252.     /*SDL_DestroyTexture(pImageTexture);*/
  253. }
  254.  
  255. int path_exists(const char *path) {
  256.     struct stat st;
  257.     // stat() attempts to get file status. Returns 0 on success, -1 on failure.
  258.     return stat(path, &st) == 0;
  259. }
  260.  
  261. int path_is_directory(const char *path) {
  262.     struct stat st;
  263.     if ( stat(path, &st) != 0 ) return FALSE;
  264.     // S_ISDIR() is a POSIX macro to check if st_mode indicates a directory.
  265.     return S_ISDIR(st.st_mode);
  266. }
Advertisement
Add Comment
Please, Sign In to add comment