playlist.c 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include "kill.h"
  5. #include "exit_status.h"
  6. #define strdup _strdup
  7. /* Up to 128 songs, for now */
  8. static char *songs[128];
  9. static int should_shuffle = 0;
  10. static int song_count = 0;
  11. static char read_buf[1024];
  12. static void callback_playlist() {
  13. for (size_t i = 0; i < 128; ++i) {
  14. if (songs[i]) free(songs[i]);
  15. }
  16. }
  17. void playlist_init() {
  18. for (size_t i = 0; i < 128; ++i) songs[i] = NULL;
  19. kill_push(callback_playlist);
  20. }
  21. void playlist_load(const char *path) {
  22. FILE *f = fopen(path, "r");
  23. if (!f) {
  24. printf("Could not open playlist '%s'\n", path);
  25. kill(EX_ERR_BAD_PLAYLIST);
  26. }
  27. int write = 0;
  28. int song_write = 0;
  29. for (;;) {
  30. int c = fgetc(f);
  31. if (c == EOF) break;
  32. if (c == '\n') {
  33. if (read_buf[0] == '+') {
  34. read_buf[write] = '\0';
  35. if (!strcmp(read_buf, "+shuffle")) {
  36. should_shuffle = 1;
  37. }
  38. }
  39. else {
  40. read_buf[write] = '\0';
  41. songs[song_write++] = strdup(read_buf);
  42. if (song_write >= 128) break;
  43. }
  44. write = 0;
  45. }
  46. else read_buf[write++] = (char)c;
  47. if (write >= 1024) {
  48. break;
  49. }
  50. }
  51. fclose(f);
  52. song_count = song_write;
  53. if (song_count == 0) {
  54. printf("Playlist '%s' contains no songs!", path);
  55. kill(EX_ERR_NO_SONGS);
  56. }
  57. }
  58. static const char *next_normal() {
  59. static int index = 0;
  60. char *result = songs[index];
  61. index = (index + 1) % song_count;
  62. return result;
  63. }
  64. static const char *next_shuffle() {
  65. static int has_played[128] = { 0 };
  66. size_t choices[128];
  67. size_t choice_count = 0;
  68. for (size_t i = 0; i < song_count; ++i) {
  69. if (!has_played[i]) {
  70. choices[choice_count++] = i;
  71. }
  72. }
  73. if (choice_count == 0) {
  74. for (size_t i = 0; i < song_count; ++i) {
  75. has_played[i] = 0;
  76. choices[i] = i;
  77. }
  78. choice_count = song_count;
  79. }
  80. size_t index = ((rand() / (float)RAND_MAX) * (choice_count - 1));
  81. char *result = songs[choices[index]];
  82. has_played[choices[index]] = 1;
  83. return result;
  84. }
  85. const char *playlist_next() {
  86. if (should_shuffle) return next_shuffle();
  87. return next_normal();
  88. }