No Description
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

main.c 8.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  1. /* Author: Bradlee Speice
  2. * Program: XMMS2 playlist creator
  3. * Purpose: Given a playlist name (current playlist if none is given)
  4. output a file playlist with the URL's of all media in the
  5. XMMS2 playlist.
  6. Filetypes supported: M3U, PLS
  7. */
  8. #include "main.h"
  9. int main(int argc, char **argv)
  10. {
  11. /* Let's get everything set up.
  12. * Parse the command line, and find out
  13. * what exactly it is that we're doing.
  14. */
  15. int opt = 0;
  16. int long_index = 0;
  17. xplaylist_args.playlist_name = NULL;
  18. xplaylist_args.output_type = NULL;
  19. xplaylist_args.output_filename = NULL;
  20. xplaylist_args.out_file = NULL;
  21. struct medialib_info_node *head_node, *current_node;
  22. current_node = head_node = NULL;
  23. int playlist_length = 0;
  24. while(opt != -1)
  25. {
  26. opt = getopt_long(argc, argv, xplaylist_opt_string, xplaylist_long_opts, &long_index);
  27. switch(opt)
  28. {
  29. case 0:
  30. fprintf(stdout, "Unknown option %s: %s\n", xplaylist_long_opts[long_index].name, optarg); break;
  31. case 'p':
  32. xplaylist_args.playlist_name = optarg;
  33. break;
  34. case 't':
  35. xplaylist_args.output_type = optarg;
  36. break;
  37. case 'h':
  38. usage();
  39. exit(EXIT_SUCCESS);
  40. case '?':
  41. usage();
  42. return(EXIT_FAILURE);
  43. }
  44. }
  45. /* And then we need the output file_name */
  46. xplaylist_args.output_filename = argv[optind];
  47. if ((argc - optind) > 1){
  48. optind++;
  49. fprintf(stdout, "Extra input: ");
  50. for (optind; optind < argc; optind++){
  51. fprintf(stdout, "%s", argv[optind]);
  52. }
  53. fprintf(stdout, "\n");
  54. }
  55. if (xplaylist_args.output_type == NULL)
  56. xplaylist_args.output_type = "pls";
  57. /* End argument parsing */
  58. /* Connection and basic I/O variables */
  59. xmmsc_connection_t *connection;
  60. xmmsc_result_t *result;
  61. xmmsv_t *return_value;
  62. const char *err_buf;
  63. /* Other variables */
  64. xmmsv_list_iter_t *iterator;
  65. /* Now we start the fun stuff */
  66. /* Set up the connection */
  67. connection = xmmsc_init("xplaylist_creator");
  68. if (!connection) {
  69. fprintf(stderr, "Connection failed: %s\n",
  70. xmmsc_get_last_error(connection));
  71. exit (EXIT_FAILURE);
  72. }
  73. if (!xmmsc_connect (connection, getenv("XMMS_PATH"))) {
  74. fprintf(stderr, "Connection failed: %s\n",
  75. xmmsc_get_last_error(connection));
  76. exit (EXIT_FAILURE);
  77. }
  78. /* Get the playlist */
  79. result = xmmsc_playlist_list_entries(connection, xplaylist_args.playlist_name);
  80. xmmsc_result_wait(result);
  81. return_value = xmmsc_result_get_value(result);
  82. if (xmmsv_get_error(return_value, &err_buf)){
  83. fprintf(stderr, "Couldn't get the playlist. Are you that playlist \"%s\" exists?\nError: %s\n",
  84. xplaylist_args.playlist_name, err_buf);
  85. exit(EXIT_FAILURE);
  86. }
  87. if (!xmmsv_get_list_iter (return_value, &iterator)){
  88. fprintf(stderr, "Couldn't get the list of elements in the playlist.\n");
  89. exit(EXIT_FAILURE);
  90. }
  91. /* For every element in the playlist, add it to the list, and
  92. keep a count of how many items we have */
  93. int playlist_size = 0;
  94. char* media_result;
  95. for (; xmmsv_list_iter_valid (iterator); xmmsv_list_iter_next(iterator)){
  96. /* Get the id of the entry */
  97. int entry_id;
  98. xmmsv_t *list_entry;
  99. xmmsv_list_iter_entry(iterator, &list_entry);
  100. xmmsv_get_int(list_entry, &entry_id);
  101. if (head_node == NULL){
  102. /* Start our list */
  103. head_node = malloc(sizeof(struct medialib_info_node));
  104. current_node = head_node;
  105. media_result = get_media_string(connection, entry_id, "url");
  106. current_node->url = malloc(sizeof(char) * strlen(media_result) + 1);
  107. strcpy(current_node->url, media_result);
  108. media_result = get_media_string(connection, entry_id, "title");
  109. current_node->title = malloc(sizeof(char) * strlen(media_result) + 1);
  110. strcpy(current_node->title, media_result);
  111. media_result = get_media_string(connection, entry_id, "artist");
  112. current_node->artist = malloc(strlen(media_result) + 1);
  113. strcpy(current_node->artist, media_result);
  114. current_node->length = get_media_int(connection, entry_id, "duration");
  115. current_node->length = current_node->length / 1000;
  116. current_node->next = NULL;
  117. playlist_size++;
  118. } else {
  119. current_node->next = malloc(sizeof(struct medialib_info_node));
  120. current_node = current_node->next;
  121. media_result = get_media_string(connection, entry_id, "url");
  122. current_node->url = malloc(strlen(media_result) + 1);
  123. strcpy(current_node->url, media_result);
  124. media_result = get_media_string(connection, entry_id, "title");
  125. current_node->title = malloc(strlen(media_result) + 1);
  126. strcpy(current_node->title, media_result);
  127. media_result = get_media_string(connection, entry_id, "artist");
  128. current_node->artist = malloc(strlen(media_result) + 1);
  129. strcpy(current_node->artist, media_result);
  130. current_node->length = get_media_int(connection, entry_id, "duration");
  131. current_node->length = current_node->length / 1000;
  132. current_node->next = NULL;
  133. playlist_size++;
  134. }
  135. }
  136. bool use_pls = !strcmp(xplaylist_args.output_type, "pls");
  137. current_node = head_node;
  138. struct medialib_info_node *temp_node;
  139. int i = 0;
  140. for (i; i < playlist_size; i++){
  141. if (current_node == head_node){
  142. if (use_pls)
  143. start_playlist_pls(playlist_size);
  144. else
  145. start_playlist_m3u();
  146. }
  147. if (use_pls)
  148. add_playlist_pls(current_node->length, current_node->title, current_node->url);
  149. else
  150. add_playlist_m3u(current_node->length, current_node->title, current_node->url, current_node->artist);
  151. temp_node = current_node;
  152. current_node = current_node->next;
  153. free(temp_node->url);
  154. free(temp_node->title);
  155. free(temp_node->artist);
  156. free(temp_node);
  157. }
  158. if (use_pls)
  159. end_playlist_pls();
  160. else
  161. end_playlist_m3u();
  162. xmmsc_result_unref(result);
  163. return 0;
  164. //return EXIT_SUCCESS;
  165. }
  166. void usage(){
  167. fprintf(stdout, "Welcome to the XMMS2 playlist creator!\n");
  168. fprintf(stdout, "This program will output the content of an\n");
  169. fprintf(stdout, "XMMS2 playlist into something usable by other programs.\n");
  170. fprintf(stdout, "\nNot that you'd want to use other programs.");
  171. fprintf(stdout, "\nUsage:\n");
  172. fprintf(stdout, "\txplaylist_creator [-t <output type>] [-p <playlist_name>] <output_file_name>\n");
  173. fprintf(stdout, "Options:\n");
  174. fprintf(stdout, "\t[-p, --playlist]: Playlist name inside XMMS2. Current playlist is used if not specified.\n");
  175. fprintf(stdout, "\t[-t, --type]: Type of playlist to output. Acceptable values are:\n");
  176. fprintf(stdout, "\t\tm3u, pls\n");
  177. fprintf(stdout, "\nAnd that should be it. If there are any issues, feel free to let the XMMS2 team know.\n");
  178. }
  179. char* get_media_string(xmmsc_connection_t *connection, int entry_id, const char* information)
  180. {
  181. xmmsc_result_t *result;
  182. xmmsv_t *return_value;
  183. const char *err_buf;
  184. xmmsv_t *dict_entry;
  185. xmmsv_t *infos;
  186. const char* val;
  187. char *return_val;
  188. result = xmmsc_medialib_get_info(connection, entry_id);
  189. xmmsc_result_wait(result);
  190. return_value = xmmsc_result_get_value(result);
  191. if (xmmsv_get_error(return_value, &err_buf)) {
  192. fprintf(stderr, "Couldn't get %s information for song id %i\n", information, entry_id);
  193. fprintf(stderr, "Error: %s\n", err_buf);
  194. }
  195. infos = xmmsv_propdict_to_dict(return_value, NULL);
  196. if (!xmmsv_dict_get(infos, information, &dict_entry) ||
  197. !xmmsv_get_string(dict_entry, &val)) {
  198. val = "#INVALID ENTRY";
  199. }
  200. int string_length = strlen(val);
  201. return_val = malloc(string_length + 1);
  202. strncpy(return_val, val, string_length + 1);
  203. xmmsv_unref(infos);
  204. xmmsc_result_unref(result);
  205. /* free(return_val); */
  206. return return_val;
  207. }
  208. int get_media_int(xmmsc_connection_t* connection, int entry_id, const char* information)
  209. {
  210. xmmsc_result_t *result;
  211. xmmsv_t *return_value;
  212. const char *err_buf;
  213. xmmsv_t *dict_entry;
  214. xmmsv_t *infos;
  215. int val;
  216. result = xmmsc_medialib_get_info(connection, entry_id);
  217. xmmsc_result_wait(result);
  218. return_value = xmmsc_result_get_value(result);
  219. if (xmmsv_get_error(return_value, &err_buf)) {
  220. fprintf(stderr, "Couldn't get %s information for song id %i\n", information, entry_id);
  221. fprintf(stderr, "Error: %s\n", err_buf);
  222. }
  223. infos = xmmsv_propdict_to_dict(return_value, NULL);
  224. if (!xmmsv_dict_get(infos, information, &dict_entry) ||
  225. !xmmsv_get_int(dict_entry, &val)) {
  226. val = -2; /* Note that -2 is used since a value of -1 represents a stream - indefinite length */
  227. }
  228. xmmsv_unref(infos);
  229. xmmsc_result_unref(result);
  230. return val;
  231. }
  232. bool start_playlist_m3u(){
  233. printf("#EXTM3U\n");
  234. return true;
  235. }
  236. bool add_playlist_m3u(int length, const char* title, const char *url, const char *artist){
  237. printf("#EXTINF: %i,%s - %s\n%s\n", length, artist, title, url);
  238. return true;
  239. }
  240. bool end_playlist_m3u(int playlist_size){
  241. return true;
  242. }
  243. bool start_playlist_pls(int size){
  244. printf("[playlist]\nNumberOfEntries=%i\n", size);
  245. return true;
  246. }
  247. bool add_playlist_pls(int length, const char* title, const char *url){
  248. static int entry_no;
  249. entry_no++;
  250. printf("File%i=%s\n", entry_no, url);
  251. printf("Title%i=%s\n", entry_no, title);
  252. printf("Length%i=%i\n", entry_no, length);
  253. return true;
  254. }
  255. bool end_playlist_pls(){
  256. printf("Version=2\n");
  257. return true;
  258. }