multimedia_paradise 1.1.314

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of multimedia_paradise might be problematic. Click here for more details.

Files changed (417) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +2340 -0
  3. data/bin/audio_player +12 -0
  4. data/bin/auto_title +7 -0
  5. data/bin/convert_audio_to_mp4video_with_image +7 -0
  6. data/bin/cut_audio +7 -0
  7. data/bin/cut_multimedia +7 -0
  8. data/bin/extract_audio +7 -0
  9. data/bin/ffmpeg_merge +7 -0
  10. data/bin/file_duration +7 -0
  11. data/bin/gtk_radio +7 -0
  12. data/bin/loop_this_video +7 -0
  13. data/bin/merge_avi_files +7 -0
  14. data/bin/merge_mp3 +7 -0
  15. data/bin/missing_video_files +7 -0
  16. data/bin/movie_searcher +7 -0
  17. data/bin/mp3_to_opus +7 -0
  18. data/bin/mplayer_wrapper +7 -0
  19. data/bin/multimedia_information +11 -0
  20. data/bin/multimedia_paradise +9 -0
  21. data/bin/multimedia_paradise_sinatra +7 -0
  22. data/bin/play_random_simpsons_video +7 -0
  23. data/bin/playlist +7 -0
  24. data/bin/random_video +7 -0
  25. data/bin/remove_audio +9 -0
  26. data/bin/remove_last_second +7 -0
  27. data/bin/remove_subtitles +7 -0
  28. data/bin/tag_mp3_files +7 -0
  29. data/bin/to_aiff +10 -0
  30. data/bin/to_mp4 +7 -0
  31. data/bin/verbose_analyse_this_mp3_file_for_id3_tags +9 -0
  32. data/bin/video_codec +7 -0
  33. data/bin/video_information +8 -0
  34. data/bin/video_player +11 -0
  35. data/bin/video_to_images +7 -0
  36. data/bin/vp9 +9 -0
  37. data/bin/waveform +73 -0
  38. data/doc/CHANGELOG.md +44 -0
  39. data/doc/LINKS.md +6 -0
  40. data/doc/MOTIVATION_FOR_THIS_PROJECT.md +22 -0
  41. data/doc/MergingVideoLectures.md +12 -0
  42. data/doc/README.gen +2300 -0
  43. data/doc/Readme_for_the_cut_audio_component.md +168 -0
  44. data/doc/todo/todo_for_the_GUIs.md +0 -0
  45. data/doc/todo/todo_for_the_multimedia_paradise_project.md +111 -0
  46. data/lib/multimedia_paradise/audio/audio_player/audio_player.rb +83 -0
  47. data/lib/multimedia_paradise/audio/audio_player/constants.rb +136 -0
  48. data/lib/multimedia_paradise/audio/audio_player/menu.rb +164 -0
  49. data/lib/multimedia_paradise/audio/audio_player/misc.rb +718 -0
  50. data/lib/multimedia_paradise/audio/audio_player/reset.rb +77 -0
  51. data/lib/multimedia_paradise/audio/audio_player/tab.rb +35 -0
  52. data/lib/multimedia_paradise/audio/audio_tag_reader/README.md +7 -0
  53. data/lib/multimedia_paradise/audio/audio_tag_reader/audio_tag_reader.rb +503 -0
  54. data/lib/multimedia_paradise/audio/base.rb +67 -0
  55. data/lib/multimedia_paradise/audio/compress.rb +97 -0
  56. data/lib/multimedia_paradise/audio/create_m3u_playlist.rb +245 -0
  57. data/lib/multimedia_paradise/audio/extract_audio/constants.rb +37 -0
  58. data/lib/multimedia_paradise/audio/extract_audio/extract_audio.rb +417 -0
  59. data/lib/multimedia_paradise/audio/file_duration/constants.rb +53 -0
  60. data/lib/multimedia_paradise/audio/file_duration/file_duration.rb +602 -0
  61. data/lib/multimedia_paradise/audio/genres/boogie.rb +35 -0
  62. data/lib/multimedia_paradise/audio/genres/concerts.rb +35 -0
  63. data/lib/multimedia_paradise/audio/genres/constants.rb +53 -0
  64. data/lib/multimedia_paradise/audio/genres/eurodance.rb +35 -0
  65. data/lib/multimedia_paradise/audio/genres/genre.rb +696 -0
  66. data/lib/multimedia_paradise/audio/genres/hip_hop.rb +35 -0
  67. data/lib/multimedia_paradise/audio/genres/italian_songs.rb +35 -0
  68. data/lib/multimedia_paradise/audio/genres/the_1980s.rb +35 -0
  69. data/lib/multimedia_paradise/audio/genres/trance.rb +35 -0
  70. data/lib/multimedia_paradise/audio/lyrics_fetcher.rb +238 -0
  71. data/lib/multimedia_paradise/audio/merge_audio_files.rb +136 -0
  72. data/lib/multimedia_paradise/audio/modify_year_of_audio_file.rb +151 -0
  73. data/lib/multimedia_paradise/audio/n_audio_songs.rb +216 -0
  74. data/lib/multimedia_paradise/audio/play_all_audio_files.rb +122 -0
  75. data/lib/multimedia_paradise/audio/playlist/playlist.rb +1559 -0
  76. data/lib/multimedia_paradise/audio/remove_audio.rb +98 -0
  77. data/lib/multimedia_paradise/audio/remove_last_second.rb +83 -0
  78. data/lib/multimedia_paradise/audio/report_missing_id.rb +139 -0
  79. data/lib/multimedia_paradise/audio/streamripper/constants.rb +51 -0
  80. data/lib/multimedia_paradise/audio/streamripper/streamripper_wrapper.rb +279 -0
  81. data/lib/multimedia_paradise/audio/to_mp3.rb +138 -0
  82. data/lib/multimedia_paradise/audio/to_ogg.rb +104 -0
  83. data/lib/multimedia_paradise/audio/wav_to_mp3.rb +87 -0
  84. data/lib/multimedia_paradise/audio/waveform/class.rb +341 -0
  85. data/lib/multimedia_paradise/audio/waveform/constants.rb +38 -0
  86. data/lib/multimedia_paradise/audio/waveform/log.rb +101 -0
  87. data/lib/multimedia_paradise/autoinclude.rb +3 -0
  88. data/lib/multimedia_paradise/autoinclude_remove_audio.rb +6 -0
  89. data/lib/multimedia_paradise/base/base.rb +34 -0
  90. data/lib/multimedia_paradise/base/colours.rb +354 -0
  91. data/lib/multimedia_paradise/base/commandline_arguments.rb +52 -0
  92. data/lib/multimedia_paradise/base/constants.rb +19 -0
  93. data/lib/multimedia_paradise/base/encoding.rb +31 -0
  94. data/lib/multimedia_paradise/base/misc.rb +618 -0
  95. data/lib/multimedia_paradise/base/namespace.rb +36 -0
  96. data/lib/multimedia_paradise/base/time.rb +25 -0
  97. data/lib/multimedia_paradise/colours/colours.rb +82 -0
  98. data/lib/multimedia_paradise/commandline/menu.rb +498 -0
  99. data/lib/multimedia_paradise/configuration/play_zoomed.yml +1 -0
  100. data/lib/multimedia_paradise/constants/constants.rb +23 -0
  101. data/lib/multimedia_paradise/constants/conversions.rb +62 -0
  102. data/lib/multimedia_paradise/constants/directory_constants.rb +133 -0
  103. data/lib/multimedia_paradise/constants/encodings.rb +26 -0
  104. data/lib/multimedia_paradise/constants/file_constants.rb +171 -0
  105. data/lib/multimedia_paradise/constants/misc.rb +80 -0
  106. data/lib/multimedia_paradise/constants/my_video_directory.rb +30 -0
  107. data/lib/multimedia_paradise/constants/namespace.rb +14 -0
  108. data/lib/multimedia_paradise/constants/newline.rb +14 -0
  109. data/lib/multimedia_paradise/constants/video_filetypes.rb +27 -0
  110. data/lib/multimedia_paradise/constants/web_constants.rb +150 -0
  111. data/lib/multimedia_paradise/conversions/README.md +2 -0
  112. data/lib/multimedia_paradise/conversions/conversions.rb +930 -0
  113. data/lib/multimedia_paradise/css/project.css +15 -0
  114. data/lib/multimedia_paradise/data/asoundrc +12 -0
  115. data/lib/multimedia_paradise/ffmpeg/README.md +2 -0
  116. data/lib/multimedia_paradise/ffmpeg/ffmpeg.rb +620 -0
  117. data/lib/multimedia_paradise/gui/fox/play_from_radio_station.rb +75 -0
  118. data/lib/multimedia_paradise/gui/gosu/video_player/video_player.rb +109 -0
  119. data/lib/multimedia_paradise/gui/gtk2/lyrics/lyrics.rb +33 -0
  120. data/lib/multimedia_paradise/gui/gtk2/multimedia_converter/multimedia_converter.rb +33 -0
  121. data/lib/multimedia_paradise/gui/gtk2/notebook.rb +144 -0
  122. data/lib/multimedia_paradise/gui/gtk2/play_video_from_my_collection/play_video_from_my_collection.rb +43 -0
  123. data/lib/multimedia_paradise/gui/gtk2/simple_play_widget/README.md +12 -0
  124. data/lib/multimedia_paradise/gui/gtk2/simple_play_widget/simple_play_widget.rb +40 -0
  125. data/lib/multimedia_paradise/gui/gtk2/video_collection/video_collection.rb +56 -0
  126. data/lib/multimedia_paradise/gui/gtk2/widget_increase_or_decrease_audio/widget_increase_or_decrease_audio.rb +42 -0
  127. data/lib/multimedia_paradise/gui/gtk2/youtube_downloader/youtube_downloader.rb +32 -0
  128. data/lib/multimedia_paradise/gui/gtk3/change_metadata_widget/README.md +3 -0
  129. data/lib/multimedia_paradise/gui/gtk3/change_metadata_widget/change_metadata_widget.rb +150 -0
  130. data/lib/multimedia_paradise/gui/gtk3/cut_multimedia/cut_multimedia.rb +321 -0
  131. data/lib/multimedia_paradise/gui/gtk3/information_about_a_mp3_file/information_about_a_mp3_file.rb +421 -0
  132. data/lib/multimedia_paradise/gui/gtk3/lyrics/lyrics.rb +33 -0
  133. data/lib/multimedia_paradise/gui/gtk3/multimedia_converter/multimedia_converter.rb +34 -0
  134. data/lib/multimedia_paradise/gui/gtk3/multimedia_notebook/multimedia_notebook.rb +34 -0
  135. data/lib/multimedia_paradise/gui/gtk3/play_video_from_my_collection/play_video_from_my_collection.rb +34 -0
  136. data/lib/multimedia_paradise/gui/gtk3/playlist/playlist.rb +34 -0
  137. data/lib/multimedia_paradise/gui/gtk3/radio/misc.rb +487 -0
  138. data/lib/multimedia_paradise/gui/gtk3/radio/radio.rb +698 -0
  139. data/lib/multimedia_paradise/gui/gtk3/simple_play_widget/simple_play_widget.rb +38 -0
  140. data/lib/multimedia_paradise/gui/gtk3/sound_effect_widget/sound_effect_widget.rb +34 -0
  141. data/lib/multimedia_paradise/gui/gtk3/tag_mp3_files/connect_skeleton.rb +61 -0
  142. data/lib/multimedia_paradise/gui/gtk3/tag_mp3_files/create.rb +405 -0
  143. data/lib/multimedia_paradise/gui/gtk3/tag_mp3_files/misc.rb +1820 -0
  144. data/lib/multimedia_paradise/gui/gtk3/tag_mp3_files/tag_mp3_files.config +6 -0
  145. data/lib/multimedia_paradise/gui/gtk3/tag_mp3_files/tag_mp3_files.rb +66 -0
  146. data/lib/multimedia_paradise/gui/gtk3/video_collection/video_collection.rb +43 -0
  147. data/lib/multimedia_paradise/gui/gtk3/video_editor/video_editor.rb +34 -0
  148. data/lib/multimedia_paradise/gui/gtk3/video_player/video_player.rb +34 -0
  149. data/lib/multimedia_paradise/gui/gtk3/webcam_widget/webcam_widget.rb +425 -0
  150. data/lib/multimedia_paradise/gui/gtk3/widget_increase_or_decrease_audio/widget_increase_or_decrease_audio.rb +36 -0
  151. data/lib/multimedia_paradise/gui/gtk3/youtube_channels/youtube_channels.rb +210 -0
  152. data/lib/multimedia_paradise/gui/gtk3/youtube_downloader/youtube_downloader.rb +32 -0
  153. data/lib/multimedia_paradise/gui/gui_base.rb +92 -0
  154. data/lib/multimedia_paradise/gui/libui/change_metadata_widget/change_metadata_widget.rb +115 -0
  155. data/lib/multimedia_paradise/gui/libui/cut_multimedia/cut_multimedia.rb +119 -0
  156. data/lib/multimedia_paradise/gui/libui/lyrics/lyrics.rb +67 -0
  157. data/lib/multimedia_paradise/gui/libui/simple_play_widget/simple_play_widget.rb +119 -0
  158. data/lib/multimedia_paradise/gui/libui/tag_mp3_files/tag_mp3_files.rb +268 -0
  159. data/lib/multimedia_paradise/gui/libui/video_player/video_player.rb +81 -0
  160. data/lib/multimedia_paradise/gui/libui/widget_increase_or_decrease_audio/widget_increase_or_decrease_audio.rb +126 -0
  161. data/lib/multimedia_paradise/gui/libui/youtube_channels/youtube_channels.rb +116 -0
  162. data/lib/multimedia_paradise/gui/libui/youtube_downloader/youtube_downloader.rb +107 -0
  163. data/lib/multimedia_paradise/gui/shared_code/change_metadata_widget/change_metadata_widget_module.rb +538 -0
  164. data/lib/multimedia_paradise/gui/shared_code/cut_multimedia/cut_multimedia_module.rb +268 -0
  165. data/lib/multimedia_paradise/gui/shared_code/information_about_a_mp3_file/information_about_a_mp3_file_module.rb +120 -0
  166. data/lib/multimedia_paradise/gui/shared_code/lyrics/lyrics_module.rb +141 -0
  167. data/lib/multimedia_paradise/gui/shared_code/multimedia_converter/multimedia_converter_module.rb +478 -0
  168. data/lib/multimedia_paradise/gui/shared_code/multimedia_notebook/multimedia_notebook_module.rb +171 -0
  169. data/lib/multimedia_paradise/gui/shared_code/play_video_from_my_collection/play_video_from_my_collection_module.rb +464 -0
  170. data/lib/multimedia_paradise/gui/shared_code/playlist/playlist_module.rb +151 -0
  171. data/lib/multimedia_paradise/gui/shared_code/simple_play_widget/simple_play_widget_module.rb +257 -0
  172. data/lib/multimedia_paradise/gui/shared_code/sound_effect_widget/sound_effect_widget_module.rb +173 -0
  173. data/lib/multimedia_paradise/gui/shared_code/tag_mp3_files/tag_mp3_files_module.rb +73 -0
  174. data/lib/multimedia_paradise/gui/shared_code/video_editor/video_editor_module.rb +287 -0
  175. data/lib/multimedia_paradise/gui/shared_code/video_player/video_player_module.rb +185 -0
  176. data/lib/multimedia_paradise/gui/shared_code/widget_increase_or_decrease_audio/widget_increase_or_decrease_audio_module.rb +310 -0
  177. data/lib/multimedia_paradise/gui/shared_code/youtube_downloader/youtube_downloader_module.rb +339 -0
  178. data/lib/multimedia_paradise/gui/tk/tk_multimedia_wrapper.rb +60 -0
  179. data/lib/multimedia_paradise/help/help.rb +75 -0
  180. data/lib/multimedia_paradise/images/MULTIMEDIA.jpg +0 -0
  181. data/lib/multimedia_paradise/images/MULTIMEDIA_PARADISE_ID_TAG_GUI_IN_RUBY_GTK3.png +0 -0
  182. data/lib/multimedia_paradise/images/MULTIMEDIA_PARADISE_LOGO.png +0 -0
  183. data/lib/multimedia_paradise/images/UK_flag.png +0 -0
  184. data/lib/multimedia_paradise/images/US_flag.png +0 -0
  185. data/lib/multimedia_paradise/images/austrian_flag.png +0 -0
  186. data/lib/multimedia_paradise/images/french_flag.png +0 -0
  187. data/lib/multimedia_paradise/images/german_flag.png +0 -0
  188. data/lib/multimedia_paradise/images/radio_image.png +0 -0
  189. data/lib/multimedia_paradise/images/trance.png +0 -0
  190. data/lib/multimedia_paradise/java/AudioPlayer.class +0 -0
  191. data/lib/multimedia_paradise/java/AudioPlayer.java +103 -0
  192. data/lib/multimedia_paradise/java/README.md +3 -0
  193. data/lib/multimedia_paradise/misc/long_format_to_milliseconds_converter.rb +182 -0
  194. data/lib/multimedia_paradise/misc/milliseconds_to_long_format_converter.rb +186 -0
  195. data/lib/multimedia_paradise/multimedia/analyse_multimedia_file.rb +180 -0
  196. data/lib/multimedia_paradise/multimedia/avisynth/README.md +4 -0
  197. data/lib/multimedia_paradise/multimedia/avisynth/avisynth_code.avs +471 -0
  198. data/lib/multimedia_paradise/multimedia/base.rb +60 -0
  199. data/lib/multimedia_paradise/multimedia/chord.rb +174 -0
  200. data/lib/multimedia_paradise/multimedia/convert_audio_to_video_with_image.rb +171 -0
  201. data/lib/multimedia_paradise/multimedia/cut_multimedia/10_minutes_chop.rb +29 -0
  202. data/lib/multimedia_paradise/multimedia/cut_multimedia/15_minutes_chop.rb +29 -0
  203. data/lib/multimedia_paradise/multimedia/cut_multimedia/30_minutes_chop.rb +29 -0
  204. data/lib/multimedia_paradise/multimedia/cut_multimedia/5_minutes_chop.rb +29 -0
  205. data/lib/multimedia_paradise/multimedia/cut_multimedia/cut_multimedia.rb +2017 -0
  206. data/lib/multimedia_paradise/multimedia/cut_multimedia/evaluate_from_this_file.rb +79 -0
  207. data/lib/multimedia_paradise/multimedia/cut_multimedia/interactive_menu.rb +514 -0
  208. data/lib/multimedia_paradise/multimedia/interactive_shell.rb +84 -0
  209. data/lib/multimedia_paradise/multimedia/merge_multimedia.rb +125 -0
  210. data/lib/multimedia_paradise/multimedia/note.rb +500 -0
  211. data/lib/multimedia_paradise/multimedia/play_from_this_list.rb +163 -0
  212. data/lib/multimedia_paradise/multimedia/read_meta_tags.rb +173 -0
  213. data/lib/multimedia_paradise/multimedia/simulate_youtube_playlist.rb +209 -0
  214. data/lib/multimedia_paradise/multimedia/start_length_duration.rb +205 -0
  215. data/lib/multimedia_paradise/multimedia/video_downloader/video_downloader.rb +143 -0
  216. data/lib/multimedia_paradise/project/project.rb +47 -0
  217. data/lib/multimedia_paradise/requires/require_audio_files.rb +74 -0
  218. data/lib/multimedia_paradise/requires/require_cut_multimedia.rb +7 -0
  219. data/lib/multimedia_paradise/requires/require_extract_audio.rb +7 -0
  220. data/lib/multimedia_paradise/requires/require_file_duration.rb +7 -0
  221. data/lib/multimedia_paradise/requires/require_streamripper.rb +7 -0
  222. data/lib/multimedia_paradise/requires/require_the_audio_player.rb +7 -0
  223. data/lib/multimedia_paradise/requires/require_the_multimedia_paradise_project.rb +38 -0
  224. data/lib/multimedia_paradise/requires/require_the_sinatra_components.rb +7 -0
  225. data/lib/multimedia_paradise/requires/require_toplevel_methods_files.rb +25 -0
  226. data/lib/multimedia_paradise/requires/require_video_files.rb +25 -0
  227. data/lib/multimedia_paradise/requires/require_video_player.rb +7 -0
  228. data/lib/multimedia_paradise/sinatra/app.rb +311 -0
  229. data/lib/multimedia_paradise/sinatra/embeddable_interface.rb +379 -0
  230. data/lib/multimedia_paradise/sound_effects/README.md +12 -0
  231. data/lib/multimedia_paradise/sound_effects/cat_meow.mp3 +0 -0
  232. data/lib/multimedia_paradise/sound_effects/channel_opened.mp3 +0 -0
  233. data/lib/multimedia_paradise/sound_effects/phone_ring.mp3 +0 -0
  234. data/lib/multimedia_paradise/statistics/README.md +5 -0
  235. data/lib/multimedia_paradise/statistics/video.rb +84 -0
  236. data/lib/multimedia_paradise/toplevel_cut_audio.rb +16 -0
  237. data/lib/multimedia_paradise/toplevel_methods/analyze_audio_stream.rb +31 -0
  238. data/lib/multimedia_paradise/toplevel_methods/chop_into_segments_of_n_seconds_size.rb +32 -0
  239. data/lib/multimedia_paradise/toplevel_methods/chop_off_first_five_minutes.rb +22 -0
  240. data/lib/multimedia_paradise/toplevel_methods/chop_off_first_n_seconds.rb +92 -0
  241. data/lib/multimedia_paradise/toplevel_methods/chop_off_first_ten_minutes.rb +22 -0
  242. data/lib/multimedia_paradise/toplevel_methods/chop_off_first_two_minutes.rb +24 -0
  243. data/lib/multimedia_paradise/toplevel_methods/codecs.rb +50 -0
  244. data/lib/multimedia_paradise/toplevel_methods/copy_and_merge_this_video_n_times.rb +51 -0
  245. data/lib/multimedia_paradise/toplevel_methods/copy_file.rb +18 -0
  246. data/lib/multimedia_paradise/toplevel_methods/create_video_from_this_audio.rb +65 -0
  247. data/lib/multimedia_paradise/toplevel_methods/cut_from_to.rb +156 -0
  248. data/lib/multimedia_paradise/toplevel_methods/delay_audio.rb +31 -0
  249. data/lib/multimedia_paradise/toplevel_methods/denoise.rb +90 -0
  250. data/lib/multimedia_paradise/toplevel_methods/deshake.rb +43 -0
  251. data/lib/multimedia_paradise/toplevel_methods/e.rb +16 -0
  252. data/lib/multimedia_paradise/toplevel_methods/encode_this_video.rb +49 -0
  253. data/lib/multimedia_paradise/toplevel_methods/ensure_that_the_output_directory_exists.rb +27 -0
  254. data/lib/multimedia_paradise/toplevel_methods/esystem.rb +43 -0
  255. data/lib/multimedia_paradise/toplevel_methods/files_and_directories.rb +90 -0
  256. data/lib/multimedia_paradise/toplevel_methods/flip_and_rotate.rb +58 -0
  257. data/lib/multimedia_paradise/toplevel_methods/increase_volume_of_this_audio_file.rb +61 -0
  258. data/lib/multimedia_paradise/toplevel_methods/is_a_multimedia_file.rb +27 -0
  259. data/lib/multimedia_paradise/toplevel_methods/is_audio_file.rb +27 -0
  260. data/lib/multimedia_paradise/toplevel_methods/is_image_file.rb +31 -0
  261. data/lib/multimedia_paradise/toplevel_methods/is_on_roebe.rb +17 -0
  262. data/lib/multimedia_paradise/toplevel_methods/is_video_file.rb +62 -0
  263. data/lib/multimedia_paradise/toplevel_methods/merge_multimedia_file.rb +327 -0
  264. data/lib/multimedia_paradise/toplevel_methods/merge_these_videos.rb +105 -0
  265. data/lib/multimedia_paradise/toplevel_methods/misc.rb +885 -0
  266. data/lib/multimedia_paradise/toplevel_methods/n_local_videos.rb +56 -0
  267. data/lib/multimedia_paradise/toplevel_methods/opn.rb +24 -0
  268. data/lib/multimedia_paradise/toplevel_methods/output_directory.rb +59 -0
  269. data/lib/multimedia_paradise/toplevel_methods/player_in_use.rb +80 -0
  270. data/lib/multimedia_paradise/toplevel_methods/query_the_audio_codec_of_this_file.rb +24 -0
  271. data/lib/multimedia_paradise/toplevel_methods/radio.rb +360 -0
  272. data/lib/multimedia_paradise/toplevel_methods/rds.rb +24 -0
  273. data/lib/multimedia_paradise/toplevel_methods/return_all_video_files.rb +64 -0
  274. data/lib/multimedia_paradise/toplevel_methods/return_data_from_video_collection_file_for_this_entry.rb +38 -0
  275. data/lib/multimedia_paradise/toplevel_methods/return_duration_of_this_multimedia_file.rb +27 -0
  276. data/lib/multimedia_paradise/toplevel_methods/return_full_name_for_video_at_this_position.rb +54 -0
  277. data/lib/multimedia_paradise/toplevel_methods/return_path_to_random_simpsons_video_file.rb +43 -0
  278. data/lib/multimedia_paradise/toplevel_methods/return_random_video_file_from_the_video_collection.rb +73 -0
  279. data/lib/multimedia_paradise/toplevel_methods/return_screen_resolution.rb +24 -0
  280. data/lib/multimedia_paradise/toplevel_methods/run_sys_command.rb +30 -0
  281. data/lib/multimedia_paradise/toplevel_methods/scale_video.rb +27 -0
  282. data/lib/multimedia_paradise/toplevel_methods/set_title_of.rb +65 -0
  283. data/lib/multimedia_paradise/toplevel_methods/slow_down_this_video_file.rb +33 -0
  284. data/lib/multimedia_paradise/toplevel_methods/start_screencast.rb +70 -0
  285. data/lib/multimedia_paradise/toplevel_methods/subtitles.rb +59 -0
  286. data/lib/multimedia_paradise/toplevel_methods/to_flac.rb +30 -0
  287. data/lib/multimedia_paradise/toplevel_methods/to_mp4.rb +24 -0
  288. data/lib/multimedia_paradise/toplevel_methods/total_duration.rb +35 -0
  289. data/lib/multimedia_paradise/toplevel_methods/use_lame_codec.rb +32 -0
  290. data/lib/multimedia_paradise/toplevel_methods/video_dataset.rb +76 -0
  291. data/lib/multimedia_paradise/version/version.rb +28 -0
  292. data/lib/multimedia_paradise/video/all_videos.rb +101 -0
  293. data/lib/multimedia_paradise/video/capture_screen.rb +285 -0
  294. data/lib/multimedia_paradise/video/check_numbers.rb +215 -0
  295. data/lib/multimedia_paradise/video/columbo/columbo.rb +139 -0
  296. data/lib/multimedia_paradise/video/copy_missing_video_files.rb +293 -0
  297. data/lib/multimedia_paradise/video/copy_random_video.rb +98 -0
  298. data/lib/multimedia_paradise/video/correct_video_numbers.rb +278 -0
  299. data/lib/multimedia_paradise/video/create_dvd.rb +50 -0
  300. data/lib/multimedia_paradise/video/encode_video.rb +81 -0
  301. data/lib/multimedia_paradise/video/ffmpeg_options.rb +156 -0
  302. data/lib/multimedia_paradise/video/find_video/constants.rb +23 -0
  303. data/lib/multimedia_paradise/video/find_video/find_video.rb +493 -0
  304. data/lib/multimedia_paradise/video/fix_married_with_children_videos.rb +70 -0
  305. data/lib/multimedia_paradise/video/guess_video_name.rb +189 -0
  306. data/lib/multimedia_paradise/video/imdb_rating/imdb_rating.rb +141 -0
  307. data/lib/multimedia_paradise/video/mike_hammer/mike_hammer.rb +74 -0
  308. data/lib/multimedia_paradise/video/missing_video_files/missing_video_files.rb +286 -0
  309. data/lib/multimedia_paradise/video/movie_searcher.rb +281 -0
  310. data/lib/multimedia_paradise/video/mplayer_wrapper.rb +504 -0
  311. data/lib/multimedia_paradise/video/play_random_file.rb +91 -0
  312. data/lib/multimedia_paradise/video/play_random_realvideo.rb +87 -0
  313. data/lib/multimedia_paradise/video/prepare_video_lecture.rb +272 -0
  314. data/lib/multimedia_paradise/video/random_video.rb +310 -0
  315. data/lib/multimedia_paradise/video/registered_video_file.rb +131 -0
  316. data/lib/multimedia_paradise/video/remove_metadata.rb +52 -0
  317. data/lib/multimedia_paradise/video/rename_video_file.rb +149 -0
  318. data/lib/multimedia_paradise/video/report_local_videos.rb +106 -0
  319. data/lib/multimedia_paradise/video/report_missing_videos_in_the_yaml_file.rb +107 -0
  320. data/lib/multimedia_paradise/video/resolution.rb +159 -0
  321. data/lib/multimedia_paradise/video/simpsons.rb +129 -0
  322. data/lib/multimedia_paradise/video/speed_up_video.rb +135 -0
  323. data/lib/multimedia_paradise/video/split_this_video.rb +126 -0
  324. data/lib/multimedia_paradise/video/srt_regex.rb +211 -0
  325. data/lib/multimedia_paradise/video/store_available_video_files.rb +138 -0
  326. data/lib/multimedia_paradise/video/the_simpsons/README.md +9 -0
  327. data/lib/multimedia_paradise/video/the_simpsons/good_the_simpsons_episodes.rb +107 -0
  328. data/lib/multimedia_paradise/video/the_simpsons/the_simpsons.rb +82 -0
  329. data/lib/multimedia_paradise/video/video.rb +14 -0
  330. data/lib/multimedia_paradise/video/video_encoding_settings.rb +57 -0
  331. data/lib/multimedia_paradise/video/video_genres.rb +337 -0
  332. data/lib/multimedia_paradise/video/video_information.rb +443 -0
  333. data/lib/multimedia_paradise/video/video_metadata.rb +132 -0
  334. data/lib/multimedia_paradise/video/video_player.rb +581 -0
  335. data/lib/multimedia_paradise/video/video_renamer.rb +160 -0
  336. data/lib/multimedia_paradise/video/watermark.rb +290 -0
  337. data/lib/multimedia_paradise/video/youtube/youtube.rb +17 -0
  338. data/lib/multimedia_paradise/video/youtube_embedder.rb +235 -0
  339. data/lib/multimedia_paradise/www/GIS/GIS.cgi +147 -0
  340. data/lib/multimedia_paradise/www/HDMI/HDMI.cgi +34 -0
  341. data/lib/multimedia_paradise/www/TALES_FROM_THE_CRYPT.html +71 -0
  342. data/lib/multimedia_paradise/www/alsa/alsa.cgi +7 -0
  343. data/lib/multimedia_paradise/www/alsa/alsa.rb +309 -0
  344. data/lib/multimedia_paradise/www/alsa/alsa.sinatra +56 -0
  345. data/lib/multimedia_paradise/www/audacity.cgi +30 -0
  346. data/lib/multimedia_paradise/www/audio/audio.cgi +9 -0
  347. data/lib/multimedia_paradise/www/audio/audio.rb +2739 -0
  348. data/lib/multimedia_paradise/www/audio/audio.sinatra +56 -0
  349. data/lib/multimedia_paradise/www/avisynth/avisynth.cgi +172 -0
  350. data/lib/multimedia_paradise/www/best_voices/best_voices.cgi +60 -0
  351. data/lib/multimedia_paradise/www/cassette/cassette.cgi +723 -0
  352. data/lib/multimedia_paradise/www/codecs/codecs.cgi +95 -0
  353. data/lib/multimedia_paradise/www/componists/vivaldi.cgi +218 -0
  354. data/lib/multimedia_paradise/www/decibel.cgi +79 -0
  355. data/lib/multimedia_paradise/www/ffmpeg/ffmpeg.cgi +439 -0
  356. data/lib/multimedia_paradise/www/lame/lame.cgi +7 -0
  357. data/lib/multimedia_paradise/www/lame/lame.rb +101 -0
  358. data/lib/multimedia_paradise/www/lame/lame.sinatra +56 -0
  359. data/lib/multimedia_paradise/www/lilypond.cgi +96 -0
  360. data/lib/multimedia_paradise/www/lyrics/lyrics.cgi +49 -0
  361. data/lib/multimedia_paradise/www/midi/al_adagi.mid +0 -0
  362. data/lib/multimedia_paradise/www/play_songs.cgi +102 -0
  363. data/lib/multimedia_paradise/www/play_this_video_file.cgi +100 -0
  364. data/lib/multimedia_paradise/www/pulseaudio/pulseaudio.cgi +7 -0
  365. data/lib/multimedia_paradise/www/pulseaudio/pulseaudio.rb +168 -0
  366. data/lib/multimedia_paradise/www/pulseaudio/pulseaudio.sinatra +56 -0
  367. data/lib/multimedia_paradise/www/rhythmbox/rhythmbox.cgi +120 -0
  368. data/lib/multimedia_paradise/www/sound_theory.cgi +163 -0
  369. data/lib/multimedia_paradise/www/tv/tv.cgi +182 -0
  370. data/lib/multimedia_paradise/www/video/video.cgi +7 -0
  371. data/lib/multimedia_paradise/www/video/video.rb +7709 -0
  372. data/lib/multimedia_paradise/www/video/video.sinatra +52 -0
  373. data/lib/multimedia_paradise/www/web_streams.cgi +58 -0
  374. data/lib/multimedia_paradise/yaml/audio_formats.yml +14 -0
  375. data/lib/multimedia_paradise/yaml/best_songs_in_an_era/eurodance/top20.yml +28 -0
  376. data/lib/multimedia_paradise/yaml/game_shows/ruck_zuck/ruck_zuck.yml +25 -0
  377. data/lib/multimedia_paradise/yaml/genres/1980s.yml +198 -0
  378. data/lib/multimedia_paradise/yaml/genres/README.md +5 -0
  379. data/lib/multimedia_paradise/yaml/genres/boogie.yml +68 -0
  380. data/lib/multimedia_paradise/yaml/genres/concerts.yml +29 -0
  381. data/lib/multimedia_paradise/yaml/genres/eurodance.yml +456 -0
  382. data/lib/multimedia_paradise/yaml/genres/hip_hop.yml +49 -0
  383. data/lib/multimedia_paradise/yaml/genres/italian_songs.yml +53 -0
  384. data/lib/multimedia_paradise/yaml/genres/trance.yml +167 -0
  385. data/lib/multimedia_paradise/yaml/good_horror_movies/good_horror_movies.yml +12 -0
  386. data/lib/multimedia_paradise/yaml/good_movie_actors/good_movie_actors.yml +6 -0
  387. data/lib/multimedia_paradise/yaml/image_formats.yml +8 -0
  388. data/lib/multimedia_paradise/yaml/internal/README.md +2 -0
  389. data/lib/multimedia_paradise/yaml/internal/installed_binaries.yml +31 -0
  390. data/lib/multimedia_paradise/yaml/lyrics.yml +6275 -0
  391. data/lib/multimedia_paradise/yaml/movie_reviews/the_hateful_eight_september_2016.md +305 -0
  392. data/lib/multimedia_paradise/yaml/music_genres.yml +51 -0
  393. data/lib/multimedia_paradise/yaml/playlist.yml +127 -0
  394. data/lib/multimedia_paradise/yaml/radio/README.md +5 -0
  395. data/lib/multimedia_paradise/yaml/radio/radio_stations.yml +359 -0
  396. data/lib/multimedia_paradise/yaml/song_tags.yml +815 -0
  397. data/lib/multimedia_paradise/yaml/tales_from_the_crypt/tales_from_the_crypt.yml +418 -0
  398. data/lib/multimedia_paradise/yaml/tom_and_jerry/README.md +2 -0
  399. data/lib/multimedia_paradise/yaml/tom_and_jerry/tom_and_jerry_episodes.yml +27 -0
  400. data/lib/multimedia_paradise/yaml/tv_channels/tv_channels.yml +46 -0
  401. data/lib/multimedia_paradise/yaml/use_this_video_player.yml +1 -0
  402. data/lib/multimedia_paradise/yaml/video/video.yml +26 -0
  403. data/lib/multimedia_paradise/yaml/video_collection/video_collection.yml +1933 -0
  404. data/lib/multimedia_paradise/yaml/video_encoding_settings.yml +62 -0
  405. data/lib/multimedia_paradise/yaml/video_filter_aliases.yml +221 -0
  406. data/lib/multimedia_paradise/yaml/youtube/alltagsgeschichte/alltagsgeschichte.yml +172 -0
  407. data/lib/multimedia_paradise/yaml/youtube/songs/README.md +3 -0
  408. data/lib/multimedia_paradise/yaml/youtube/songs/songs.yml +6 -0
  409. data/lib/multimedia_paradise/yaml/youtube_playlist/youtube_playlist.yml +6 -0
  410. data/lib/multimedia_paradise.rb +5 -0
  411. data/multimedia_paradise.gemspec +76 -0
  412. data/test/testing_audio_player.rb +15 -0
  413. data/test/testing_ffmpeg_options.rb +14 -0
  414. data/test/testing_file_duration.rb +17 -0
  415. data/test/testing_modify_year_of_audio_file.rb +14 -0
  416. data/test/testing_multimedia_paradise_project.rb +151 -0
  417. metadata +581 -0
@@ -0,0 +1,1559 @@
1
+ #!/usr/bin/ruby -w
2
+ # Encoding: UTF-8
3
+ # frozen_string_literal: true
4
+ # =========================================================================== #
5
+ # === MultimediaParadise::Playlist
6
+ #
7
+ # This class shall handle everything related to audio playlists.
8
+ #
9
+ # We can either use a yaml file or a .m3u playlist file.
10
+ #
11
+ # Write a playlist generator:
12
+ #
13
+ # playlist? # show all
14
+ # playlist +33 # add file at position 33
15
+ # playlist -33 # remove file at playlist-position 33
16
+ # playlist --genres # show all registered music-genres
17
+ #
18
+ # Usage example from ruby:
19
+ #
20
+ # MultimediaParadise::Playlist.new(ARGV)
21
+ #
22
+ # And from the commandline
23
+ #
24
+ # plist?
25
+ #
26
+ # Another usage example:
27
+ #
28
+ # MultimediaParadise::Playlist[]
29
+ #
30
+ # =========================================================================== #
31
+ # require 'multimedia_paradise/audio/playlist/playlist.rb'
32
+ # =========================================================================== #
33
+ require 'multimedia_paradise/audio/create_m3u_playlist.rb'
34
+ require 'multimedia_paradise/audio/base.rb'
35
+ require 'multimedia_paradise/audio/genres/constants.rb'
36
+
37
+ module MultimediaParadise
38
+
39
+ class Playlist < MultimediaParadise::AudioBase # === MultimediaParadise::Playlist
40
+
41
+ # ========================================================================= #
42
+ # === initialize
43
+ # ========================================================================= #
44
+ def initialize(
45
+ commandline_arguments = nil,
46
+ run_already = true
47
+ )
48
+ register_sigint {
49
+ :clear_kde_konsole_tab_on_exit_if_is_on_roebe
50
+ }
51
+ reset
52
+ consider_requiring_the_kde_konsole_specific_files
53
+ set_commandline_arguments(
54
+ commandline_arguments
55
+ )
56
+ case run_already
57
+ # ======================================================================= #
58
+ # === :dont_run_yet
59
+ # ======================================================================= #
60
+ when :dont_run_yet
61
+ run_already = false
62
+ end
63
+ # ======================================================================= #
64
+ # === Handle blocks given to .new() next
65
+ # ======================================================================= #
66
+ if block_given?
67
+ yielded = yield
68
+ case yielded
69
+ # ===================================================================== #
70
+ # === :be_quiet
71
+ # ===================================================================== #
72
+ when :be_quiet
73
+ @be_verbose = false
74
+ end
75
+ end
76
+ run if run_already
77
+ end
78
+
79
+ # ========================================================================= #
80
+ # === reset (reset tag)
81
+ # ========================================================================= #
82
+ def reset
83
+ super()
84
+ # ======================================================================= #
85
+ # === @be_verbose
86
+ # ======================================================================= #
87
+ set_be_verbose
88
+ # ======================================================================= #
89
+ # === @playlist_file
90
+ # ======================================================================= #
91
+ @playlist_file = PLAYLIST_FILE
92
+ # ======================================================================= #
93
+ # === @report_namespace
94
+ # ======================================================================= #
95
+ @report_namespace = REPORT_NAMESPACE
96
+ # ======================================================================= #
97
+ # === @playlist
98
+ #
99
+ # The main Array containing all songs that can be played is stored
100
+ # here.
101
+ # ======================================================================= #
102
+ @playlist = []
103
+ # ======================================================================= #
104
+ # === @array_these_songs_will_be_played
105
+ #
106
+ # This variable keeps track as to which songs will be played.
107
+ # ======================================================================= #
108
+ @array_these_songs_will_be_played = []
109
+ populate_the_playlist
110
+ end
111
+
112
+ # ========================================================================= #
113
+ # === add_to_play_these_songs
114
+ # ========================================================================= #
115
+ def add_to_play_these_songs(*i)
116
+ i.flatten.each {|entry|
117
+ @array_these_songs_will_be_played << entry
118
+ @array_these_songs_will_be_played.flatten!
119
+ }
120
+ end; alias add_to_playlist add_to_play_these_songs # === add_to_playlist
121
+
122
+ # ========================================================================= #
123
+ # === add_this_entry
124
+ #
125
+ # Pass a file to this method.
126
+ # ========================================================================= #
127
+ def add_this_entry(i)
128
+ i = i.join(' ') if i.is_a? Array
129
+ i = i.to_s.delete('+')
130
+ i = i.dup if i.frozen?
131
+ if i.start_with? '-add'
132
+ i[0, '-add'.size] = ''
133
+ end
134
+ i.strip!
135
+ if File.exist? i # If the file exists in the current directory.
136
+ this_entry = i
137
+ elsif File.exist? SONG_DIR+i
138
+ this_entry = SONG_DIR+i
139
+ else
140
+ this_entry = return_entry_from_this_position(i)
141
+ end
142
+ add(this_entry)
143
+ end
144
+
145
+ # ========================================================================= #
146
+ # === add (add tag)
147
+ #
148
+ # Use this method to add a song to the playlist.
149
+ # ========================================================================= #
150
+ def add(i)
151
+ i = i.to_s
152
+ i = rds(return_pwd+i) unless i.include? '/'
153
+ if @playlist.include?(i)
154
+ opne rev+'We will not add the file '+konsole_colour_peru(i)
155
+ opne 'as it already is a part of this playlist.'
156
+ elsif File.exist?(i) and File.directory?(i)
157
+ opne 'Can not add '+sdir(i)+' because it is a directory.'
158
+ opne 'We can only add files to the playlist, for now.'
159
+ opne 'Please provide a file as argument.'
160
+ else
161
+ opne "#{rev}Now adding the file #{konsole_colour_peru(i)}"
162
+ opne "to our playlist at `#{sfile(playlist_location?)}`."
163
+ @playlist << i
164
+ save_yaml_dataset
165
+ end
166
+ end
167
+
168
+ # ========================================================================= #
169
+ # === MultimediaParadise::Playlist.add
170
+ # ========================================================================= #
171
+ def self.add(i)
172
+ if i.is_a? Array
173
+ i.each {|entry| Playlist.add(entry) } # A recursive call.
174
+ else
175
+ Playlist.new.add(i)
176
+ end
177
+ end; self.instance_eval { alias add_this_song add } # === MultimediaParadise::Playlist.add_this_song
178
+
179
+ # ========================================================================= #
180
+ # === NAMESPACE
181
+ # ========================================================================= #
182
+ NAMESPACE = inspect
183
+
184
+ # ========================================================================= #
185
+ # === REPORT_NAMESPACE
186
+ #
187
+ # If true then we will use opnn to report the namespace.
188
+ # ========================================================================= #
189
+ REPORT_NAMESPACE = false
190
+
191
+ # ========================================================================= #
192
+ # === PLAYLIST_M3U_FILE
193
+ # ========================================================================= #
194
+ PLAYLIST_M3U_FILE = 'playlist.m3u'
195
+ DEFAULT_NAME_FOR_THE_M3U_PLAYLIST = PLAYLIST_M3U_FILE # === DEFAULT_NAME_FOR_THE_M3U_PLAYLIST
196
+
197
+ # ========================================================================= #
198
+ # === ARRAY_REGISTERED_GENRES
199
+ # ========================================================================= #
200
+ ARRAY_REGISTERED_GENRES = %w(
201
+ eurodance
202
+ trance
203
+ hip_hop
204
+ italian
205
+ boogie
206
+ the_1980s
207
+ )
208
+
209
+ # ========================================================================= #
210
+ # === ARRAY_REGISTERED_AUDIO_TAGS
211
+ #
212
+ # This is similar to registered genres but only valid for my local
213
+ # audio collection - meaning that we will use some extra tags.
214
+ #
215
+ # As of May 2017, this has 6 registered entries. As of 2019, there are
216
+ # more than 6 registered entries now.
217
+ # ========================================================================= #
218
+ ARRAY_REGISTERED_AUDIO_TAGS = ARRAY_REGISTERED_GENRES + %w(
219
+ movie
220
+ pop
221
+ techno
222
+ )
223
+
224
+ # ========================================================================= #
225
+ # === PLAYLIST_FILE
226
+ #
227
+ # Where to store the playlist. On my system this will be different
228
+ # than on other people's systems.
229
+ #
230
+ # bl /Depot/Information/playlist.yml
231
+ # ========================================================================= #
232
+ if ENV['IS_ROEBE'].to_i == 1 # On my home system, I will use another playlist.
233
+ PLAYLIST_FILE = # cat $RSRC/multimedia_paradise/lib/multimedia_paradise/yaml/playlist.yml
234
+ "#{ENV['RUBY_SRC']}/multimedia_paradise/lib/multimedia_paradise/yaml/playlist.yml"
235
+ else # Else, normal users will use another location.
236
+ if File.directory? '/Depot/Information/'
237
+ PLAYLIST_FILE = '/Depot/Information/playlist.yml'
238
+ else # This one should be valid for most users.
239
+ PLAYLIST_FILE = '/tmp/playlist.yml'
240
+ end
241
+ end
242
+
243
+ # ========================================================================= #
244
+ # === show_help (help tag)
245
+ #
246
+ # This is the generic help-section for all playlist-based classes.
247
+ #
248
+ # Invocation example:
249
+ #
250
+ # playlist --help
251
+ #
252
+ # ========================================================================= #
253
+ def show_help
254
+ e
255
+ opne 'This class ('+steelblue('class MultimediaParadise::Playlist')+
256
+ ') will provide/handle an audio playlist.'
257
+ opne
258
+ opne mediumslateblue('The documented options for this class are as follows:')
259
+ opne
260
+ opnn; ecomment ' - # delete the last entry; '\
261
+ 'this also works via --delete-last-entry'
262
+ opnn; ecomment ' --batch # process all audio files from the '\
263
+ 'current directory'
264
+ opnn; ecomment ' --generate # generate a .m3u playlist'
265
+ opnn; ecomment ' --show_playlist # show the playlist '\
266
+ '(this is the default - SHOW is an alias)'
267
+ opnn; ecomment ' --play # play the files in the playlist'
268
+ opnn; ecomment ' --play_shuffle # shuffle, then play all '\
269
+ 'files in the playlist'
270
+ opnn; ecomment ' --delete 38 # remove the entry at '\
271
+ 'position 38 from our playlist'
272
+ opnn; ecomment ' --remove=38 # this works the same as ^^^, '\
273
+ 'merely uses a = instead'
274
+ opnn; ecomment ' --purge-everything # empty the playlist. That '\
275
+ 'way you can start to populate a new one, from scratch.'
276
+ opnn; ecomment ' --reshuffle # permanently reshuffle '\
277
+ 'the playlist - the songs will have different '\
278
+ 'entries as a result'
279
+ opnn; ecomment ' --random # play ONE random file'
280
+ opnn; ecomment ' --reverse-play # play in reverse, '\
281
+ 'from last to first song'
282
+ opnn; ecomment ' --reverse # ^^^ a convenience alias '\
283
+ 'to the above'
284
+ opnn; ecomment ' --trance # play all (local) trance songs'
285
+ opnn; ecomment ' --last-two # play the last '\
286
+ 'two songs. Works as well with other english language'
287
+ opnn; ecomment ' # words, such as three '\
288
+ 'and four and so on'
289
+ opnn; ecomment ' number1 number 2 # exchange these two '\
290
+ 'entries in the playlist with one another such'
291
+ opnn; ecomment ' # as: playlist '\
292
+ '5 6 would swap position'
293
+ opnn; ecomment ' --exchange=114,113 # the same as '\
294
+ '^^^ above, essentially'
295
+ opnn; ecomment ' add <NUMBER/NAME> # add the file '\
296
+ 'at position NUMBER or the FILENAME to the playlist'
297
+ opnn; ecomment ' eurodance # this would play all '\
298
+ 'eurodance-songs. The songs must be available'
299
+ opnn; ecomment ' # locally though, '\
300
+ 'where the AUDIO_DIR constant points at.'
301
+ opnn; ecomment ' playlist --genres # show all '\
302
+ 'registered music-genres (in the '\
303
+ 'multimedia_paradise gem)'
304
+ opnn; ecomment ' playlist --only-names # show only '\
305
+ 'the names of the songs, not the full path'
306
+ opnn; ecomment ' playlist 88,87,86,85,84,83 # play songs '\
307
+ 'at these positions from the playlist'
308
+ opnn; ecomment ' playlist 88 87 86 85 84 83 # same as ^^^ '\
309
+ 'above, just without ","'
310
+ opnn; ecomment ' playlist "95 -> 94" # exchange these '\
311
+ 'two positions with one another e. g. '\
312
+ 'position 95 to 94 and vice versa'
313
+ if is_on_roebe?
314
+ # ===================================================================== #
315
+ # Display extra options on roebe-systems only.
316
+ # ===================================================================== #
317
+ e
318
+ opnn; ecomment ' playlist --tales-from-the-crypt # generate '\
319
+ 'tales-from-the-crypt .m3u playlist'
320
+ e
321
+ end
322
+ e
323
+ end
324
+
325
+ # ========================================================================= #
326
+ # === menu (menu tag)
327
+ # ========================================================================= #
328
+ def menu(
329
+ i = commandline_arguments?
330
+ )
331
+ if i.is_a? Array
332
+ if i.empty?
333
+ show_playlist
334
+ else
335
+ i.each {|entry| menu(entry) }
336
+ end
337
+ else
338
+ case i # case tag
339
+ # ===================================================================== #
340
+ # === playlist --remove=38
341
+ #
342
+ # This entry point is a bit different to the variant defined
343
+ # below. Here we will provide the positional argument already,
344
+ # whereas in the variant below we depend on a ' ' token before
345
+ # the number appears.
346
+ #
347
+ # Usage example:
348
+ #
349
+ # playlist --remove-entry=126
350
+ #
351
+ # ===================================================================== #
352
+ when /^-?-?remove=(\d+)$/i, # === $1
353
+ /^-?-?remove(-|_)?entry=(\d+)$/i # === $2
354
+ _ = $1.to_s.dup
355
+ _ = $2.to_s.dup if $2
356
+ remove_this_entry(_)
357
+ # ===================================================================== #
358
+ # === playlist --add
359
+ #
360
+ # Usage example:
361
+ #
362
+ # playlist --add=Cu_Chill_Thoi_DJ_TuSo_And_LEA_remix.mp3
363
+ #
364
+ # ===================================================================== #
365
+ when /^-?-?add=(.+)$/i
366
+ add_this_entry($1.to_s.dup)
367
+ exit
368
+ # ===================================================================== #
369
+ # === playlist --add
370
+ # ===================================================================== #
371
+ when /^-?-?add$/i
372
+ add_this_entry(commandline_arguments_as_string)
373
+ exit
374
+ # ===================================================================== #
375
+ # === playlist "95 -> 94"
376
+ #
377
+ # This entry point can be used to exchange two positions with
378
+ # one another, e. g. in the example above, position 95 with
379
+ # position 94.
380
+ #
381
+ # You can also use this here:
382
+ #
383
+ # playlist --exchange=114,113
384
+ #
385
+ # ===================================================================== #
386
+ when /^(\d{1,4})\s?->\s?(\d{1,4})$/,
387
+ /^(\d{1,4})\s?→\s?(\d{1,4})$/,
388
+ /^-?-?exchange=(\d+),(\d+)$/i
389
+ exchange_these_two_positions(
390
+ $1.to_s.dup,
391
+ $2.to_s.dup
392
+ )
393
+ exit
394
+ # ===================================================================== #
395
+ # === playlist --last=20
396
+ #
397
+ # This entry point can be used to play e. g. the last 20 songs, in
398
+ # reverse order - starting with the very last song, down to and
399
+ # including the entry at position 20.
400
+ # ===================================================================== #
401
+ when /^-?-?last=(\d+)$/i
402
+ _ = $1.to_s.dup
403
+ opnn; e rev+'Now playing the last '+steelblue(_.size.to_s)+' songs.'
404
+ play_song(:last_songs, _) # Just play the last song.
405
+ exit
406
+ # ===================================================================== #
407
+ # === playlist --last
408
+ # ===================================================================== #
409
+ when /^-?-?last$/i
410
+ play_song(:last_song) # Just play the last song.
411
+ exit
412
+ # ===================================================================== #
413
+ # === playlist --delete-last-entry
414
+ # ===================================================================== #
415
+ when '-',
416
+ /^-?-?delete(-|_)?last(-|_)?entry/
417
+ remove_this_entry :last
418
+ # ===================================================================== #
419
+ # === playlist --tales-from-the-crypt
420
+ #
421
+ # This will generate the file tales_from_the_crypt.m3u.
422
+ # ===================================================================== #
423
+ when /^-?-?tales(-|_)?from(-|_)?the(-|_)?crypt$/i
424
+ # =================================================================== #
425
+ # Hardcoded for my system. This will create the tales from the
426
+ # crypt playlist.
427
+ # =================================================================== #
428
+ create_tales_from_the_crypt_playlist
429
+ # ===================================================================== #
430
+ # === playlist 10-20
431
+ #
432
+ # This entry point allows us to handle numbers.
433
+ #
434
+ # Invocation examples:
435
+ #
436
+ # playlist 10-20
437
+ # playlist 111-115
438
+ # playlist 82..33
439
+ #
440
+ # ===================================================================== #
441
+ when /(\d{1,3}-\d{1,3})/,
442
+ /(\d{1,3}\.\.\d{1,3})/
443
+ _ = $1.to_s.dup.sub(/\.\./,'-')
444
+ play_these_songs_based_on_numbered_input(_)
445
+ exit
446
+ # ===================================================================== #
447
+ # === playlist +
448
+ # ===================================================================== #
449
+ when /\+/ # We will catch all '+' characters here.
450
+ add_this_entry(i)
451
+ # ===================================================================== #
452
+ # === playlist 5
453
+ #
454
+ # This handles numbered input. The specified number will be played
455
+ # from the playlist.
456
+ #
457
+ # Usage example:
458
+ #
459
+ # playlist 32
460
+ #
461
+ # ===================================================================== #
462
+ when /^(\d+)$/
463
+ _ = $1.to_s.dup.to_i # Work on a copy past this point.
464
+ _ = at?(_)
465
+ add_to_play_these_songs(_)
466
+ # ===================================================================== #
467
+ # === playlist 5,7
468
+ #
469
+ # This handles numbered input separated by ',' tokens. The user
470
+ # wants to play more than one song when yielding these instructions.
471
+ #
472
+ # Usage examples:
473
+ #
474
+ # playlist 6,7
475
+ # playlist 114,115
476
+ #
477
+ # ===================================================================== #
478
+ when /^(\d+),+(\d+)*$/
479
+ add_to_play_these_songs($1.to_s.dup.to_i, $2.to_s.dup.to_i,)
480
+ # ===================================================================== #
481
+ # === playlist --genres
482
+ #
483
+ # This entry point can be used to show all genres.
484
+ # ===================================================================== #
485
+ when /^-?-?genres$/
486
+ show_all_genres
487
+ # ===================================================================== #
488
+ # === playlist --help
489
+ # ===================================================================== #
490
+ when /^-?-?show_?all/,
491
+ 'all',
492
+ 'he',
493
+ /^-?-?help?$/i
494
+ show_help
495
+ # ===================================================================== #
496
+ # === playlist --use-this-yaml-file=/home/x/data/video/yaml/tales_from_the_crypt.yml
497
+ # ===================================================================== #
498
+ when /^-?-?use(-|_)?this(-|_)?yaml(-|_)?file=(.+)/ # === $4
499
+ do_report_the_namespace
500
+ use_this_file = $4.to_s.dup
501
+ convert_to_m3u_playlist(use_this_file)
502
+ # ===================================================================== #
503
+ # === playlist --convert
504
+ # ===================================================================== #
505
+ when /convert(-|_)?to(-|_)?playlist/,
506
+ /^-?-?convert$/i,
507
+ /^-?-?generate$/i,'GENERATE',
508
+ /^-?-?generate(-|_)?playlist$/i,
509
+ /^-?-?create(-|_)?playlist$/i
510
+ convert_to_m3u_playlist
511
+ exit
512
+ # ===================================================================== #
513
+ # === playlist --purge-everything
514
+ # ===================================================================== #
515
+ when /^-?-?purge(-|_)?everything$/,
516
+ 'reset'
517
+ purge_the_playlist
518
+ exit
519
+ # ===================================================================== #
520
+ # === playlist --location?
521
+ # ===================================================================== #
522
+ when '--location?',
523
+ '--location',
524
+ '--file?',
525
+ '--file'
526
+ report_where_to_find_the_yaml_file
527
+ exit
528
+ # ===================================================================== #
529
+ # === playlist --purge
530
+ # ===================================================================== #
531
+ when /^-?-?purge$/i
532
+ purge_non_existing_files_from_playlist
533
+ exit
534
+ # ===================================================================== #
535
+ # === playlist --last-two
536
+ # ===================================================================== #
537
+ when /-?-?last-?(\w+)/ # See: https://rubular.com/r/7gsa4hhPBW
538
+ # =================================================================== #
539
+ # The variable number will tell us how many of the last songs
540
+ # we will play.
541
+ # =================================================================== #
542
+ number = convert_english_number_to_letter($1.to_s.dup) # playlist --last-three
543
+ size = playlist?.size
544
+ array = size.downto(size - (number - 1)).map {|entry|
545
+ entry
546
+ }.reverse # Reverse because we start at 1, and so we end with the last.
547
+ play_these_songs_based_on_numbered_input(array)
548
+ exit
549
+ # ===================================================================== #
550
+ # === playlist --play
551
+ # ===================================================================== #
552
+ when /^-?-?play$/i,
553
+ /play-?everything$/i,
554
+ /^-?-?play(-|_)?all$/i
555
+ play_every_song_in_the_playlist
556
+ exit
557
+ # ===================================================================== #
558
+ # === playlist --reshuffle
559
+ # ===================================================================== #
560
+ when /^-?-?re-?shuffle$/ # playlist --reshuffle
561
+ reshuffle_the_playlist
562
+ exit
563
+ # ===================================================================== #
564
+ # === playlist --random
565
+ # ===================================================================== #
566
+ when /^-?-?random$/i
567
+ play_random_song
568
+ exit
569
+ # ===================================================================== #
570
+ # === playlist --open
571
+ # ===================================================================== #
572
+ when /^-?-?open$/i
573
+ open_yaml_file_in_editor
574
+ exit
575
+ # ===================================================================== #
576
+ # === playlist --batch
577
+ # ===================================================================== #
578
+ when /^-?-?batch$/i
579
+ ask_interactively_in_batch_format_for_each_audio_file
580
+ exit
581
+ # ===================================================================== #
582
+ # === playlist --play_shuffle
583
+ # ===================================================================== #
584
+ when /^-?-?play(_|-)?shuffle$/i,
585
+ /^-?-?shuffle$/,
586
+ /^-?-?play(-|_)?random/,
587
+ /shuffle$/,
588
+ /^-?-?random(-|_)?play/,
589
+ /^-?-?play(-|_)?all(-|_)?random$/,
590
+ /^-?-?all$/
591
+ play_every_song_in_the_playlist :shuffle # Play every song in a random way.
592
+ exit
593
+ # ===================================================================== #
594
+ # === playlist --only-names
595
+ #
596
+ # This entry point allows us to show only the names of the song,
597
+ # without seeing the full path (pathname) to the song at hand.
598
+ # ===================================================================== #
599
+ when /^-?-?only(-|_)?names$/
600
+ playlist?.map! {|entry| File.basename(entry) }
601
+ show_playlist
602
+ # ===================================================================== #
603
+ # === playlist --reverse-play
604
+ #
605
+ # This entry point can be used to play the songs of the playlist
606
+ # in reverse, starting with the last entry, and finishing up to
607
+ # the first entry.
608
+ # ===================================================================== #
609
+ when /^-?-?reverse$/,
610
+ /^-?-?reverse(-| )?play$/i
611
+ play_every_song_in_the_playlist(:reversed)
612
+ exit
613
+ # ===================================================================== #
614
+ # === playlist --show
615
+ # ===================================================================== #
616
+ when 'playlist?',
617
+ 'SHOW',
618
+ 'FEEDBACK',
619
+ 'ALL',
620
+ '?',
621
+ /^-?-?show(_|-)?playlist/,
622
+ /^-?-?show$/,
623
+ /^-?-?view$/,
624
+ ''
625
+ show_playlist
626
+ else
627
+ if File.exist?(i.to_s)
628
+ add_to_playlist(i.to_s)
629
+ else
630
+ show_playlist
631
+ end
632
+ end
633
+ end
634
+ end
635
+
636
+ # ========================================================================= #
637
+ # === show_all_genres
638
+ # ========================================================================= #
639
+ def show_all_genres
640
+ e
641
+ e rev+'The available genres are:'
642
+ e
643
+ ARRAY_REGISTERED_GENRES.each_with_index {|this_genre, index| index += 1
644
+ e royalblue(
645
+ ' ('+index.to_s+') '
646
+ )+
647
+ steelblue(this_genre)
648
+ }
649
+ e
650
+ end
651
+
652
+ # ========================================================================= #
653
+ # === is_a_registered_genre?
654
+ #
655
+ # This method will return true if the given input is part of the
656
+ # Array containing all registered genres.
657
+ # ========================================================================= #
658
+ def is_a_registered_genre?(this_genre)
659
+ ARRAY_REGISTERED_GENRES.include?(
660
+ this_genre.to_s.delete('-')
661
+ )
662
+ end
663
+
664
+ # ========================================================================= #
665
+ # === return_last_position_as_number
666
+ #
667
+ # We return the position of the last song here. If we have 42
668
+ # entries then we will return as number 41 (Arrays start as
669
+ # 0 in Ruby).
670
+ # ========================================================================= #
671
+ def return_last_position_as_number
672
+ @playlist.size - 1
673
+ end
674
+
675
+ # ========================================================================= #
676
+ # === play_all_audio_files_based_on_this_genre
677
+ #
678
+ # Use this method to play all audio files based on the given genre at
679
+ # hand, such as "trance" or "eurodance".
680
+ #
681
+ # This presently works solely on the audio name of the file in question.
682
+ #
683
+ # Note that you have to add the genre file manually to the following
684
+ # case menu.
685
+ #
686
+ # Also note that this is far from perfect - it is more of a hack. If
687
+ # I use it more regularly then perhaps I will invest more time into
688
+ # this code.
689
+ #
690
+ # Invocation example:
691
+ #
692
+ # playlist --trance
693
+ #
694
+ # ========================================================================= #
695
+ def play_all_audio_files_based_on_this_genre(
696
+ i, use_this_song_dir = SONG_DIR
697
+ )
698
+ i = i.dup if i.frozen? and i.is_a?(String)
699
+ i.delete!('-')
700
+ # ======================================================================= #
701
+ # Load up the playlist file here.
702
+ # ======================================================================= #
703
+ case i # case tag
704
+ when 'trance'
705
+ array_holding_all_files_that_can_be_played = []
706
+ _ = MultimediaParadise::Genres::TRANCE_FILE
707
+ if File.exist? _
708
+ dataset = YAML.load_file(_)
709
+ array_allowed_keys = dataset.keys.map {|entry|
710
+ entry = entry.dup
711
+ entry.force_encoding(USE_THIS_ENCODING).delete(' ').downcase
712
+ }
713
+ files = Dir[use_this_song_dir+'*'].select {|entry|
714
+ is_audio_file?(entry)
715
+ }.map {|entry| File.basename(entry)}
716
+ # =================================================================== #
717
+ # We obtain all audio songs.
718
+ # =================================================================== #
719
+ files.each {|this_audio_file|
720
+ downcased = this_audio_file.downcase
721
+ result = array_allowed_keys.any? {|substring|
722
+ downcased.include?(substring)
723
+ }
724
+ if result # if true
725
+ array_holding_all_files_that_can_be_played << this_audio_file
726
+ end
727
+ }
728
+ opne rev+
729
+ 'We will play '+
730
+ sfancy(array_holding_all_files_that_can_be_played.size.to_s)+
731
+ ' songs next.'
732
+ play_song(
733
+ array_holding_all_files_that_can_be_played.shuffle.map {|entry|
734
+ "#{use_this_song_dir}#{entry}"
735
+ }
736
+ )
737
+ end
738
+ when *ARRAY_REGISTERED_AUDIO_TAGS
739
+ array_holding_all_files_that_can_be_played = songs_whose_tag_matches_to(i)
740
+ play_song(
741
+ array_holding_all_files_that_can_be_played
742
+ )
743
+ end
744
+ end
745
+
746
+ # ========================================================================= #
747
+ # === sanitize_the_commandline
748
+ #
749
+ # This method name is a slight misnomer, as it will also intercept
750
+ # "faulty" commandline arguments which we do not want to handle
751
+ # at a later point.
752
+ # ========================================================================= #
753
+ def sanitize_the_commandline(
754
+ i = commandline_arguments?
755
+ )
756
+ #if all_input_starts_with_a_number?(i) and (i.size > 1)
757
+ # # ===================================================================== #
758
+ # # === If the user did input only numbers and there are at the least two arguments
759
+ # #
760
+ # # This entry point can be used to change two positions in the
761
+ # # playlist.
762
+ # #
763
+ # # Usage example:
764
+ # #
765
+ # # playlist 114 113
766
+ # #
767
+ # # ===================================================================== #
768
+ # exchange_these_two_positions(i[0], i[1])
769
+ # exit
770
+ # ^^^ not sure if we retain this; at a later time we should reconsider
771
+ # ======================================================================= #
772
+ # === playlist --remove 38
773
+ # ======================================================================= #
774
+ if commandline_arguments_as_a_string.include?('remove')
775
+ remove_this_entry(
776
+ commandline_arguments_as_a_string.scan(/remove ?(\d+)/).
777
+ flatten.first.to_s
778
+ )
779
+ # ======================================================================= #
780
+ # === playlist --delete 38
781
+ # ======================================================================= #
782
+ elsif commandline_arguments_as_a_string.include?('delete')
783
+ remove_this_entry(
784
+ commandline_arguments_as_a_string.scan(/delete ?(\d+)/).
785
+ flatten.first.to_s
786
+ )
787
+ # ======================================================================= #
788
+ # === Handle String input that includes ',' and has only numbers
789
+ # ======================================================================= #
790
+ elsif i.is_a?(String) and
791
+ i.include?(',') and
792
+ only_numbers?(i.split(','))
793
+ # ===================================================================== #
794
+ # Ok, the user did input something like this here then:
795
+ #
796
+ # playlist 10,9,18
797
+ #
798
+ # So now we must grab the relevant entries.
799
+ # ===================================================================== #
800
+ splitted = i.split(',')
801
+ i = splitted.map {|inner_entry| at?(inner_entry.to_i - 1) }
802
+ # ======================================================================= #
803
+ # === Handle String input that includes ',' and has only numbers
804
+ # ======================================================================= #
805
+ elsif i and !i.empty? and i.first and i.first.respond_to?(:include?) and i.first.include?(',')
806
+ i.map! {|entry|
807
+ if entry.is_a?(String) and
808
+ entry.include?(',') and
809
+ only_numbers?(entry.split(',')) and
810
+ !entry.include?('=')
811
+ # =================================================================== #
812
+ # Ok, the user did input something like this here then:
813
+ # playlist 10,9,18
814
+ # So now we must grab the relevant entries. But the user could
815
+ # also input "--exchange=114,113" so we made the exception as
816
+ # specified above.
817
+ # =================================================================== #
818
+ splitted = entry.split(',')
819
+ entry = splitted.map {|inner_entry| at?(inner_entry.to_i) }
820
+ entry
821
+ end
822
+ entry
823
+ }
824
+ end
825
+ i.flatten!
826
+ # local_audio_directory = directory_containing_the_local_songs?
827
+ i.each {|entry|
828
+ # ===================================================================== #
829
+ # Add the file to the playlist if it exists.
830
+ # ===================================================================== #
831
+ # if File.exist? entry
832
+ # add(entry)
833
+ # # ===================================================================== #
834
+ # # === Also check the AUDIO_DIRECTORY
835
+ # # ===================================================================== #
836
+ # elsif File.exist?(local_audio_directory+entry) and
837
+ # File.file?(local_audio_directory+entry)
838
+ # add("#{local_audio_directory}#{entry}")
839
+ # ===================================================================== #
840
+ # === Query whether it is a registered genre or not
841
+ # ===================================================================== #
842
+ if is_a_registered_genre?(entry)
843
+ # =================================================================== #
844
+ # Then this is a registered genre, such as "trance" or
845
+ # "eurodance".
846
+ #
847
+ # Invocation example:
848
+ #
849
+ # playlist --trance
850
+ #
851
+ # =================================================================== #
852
+ play_all_audio_files_based_on_this_genre(entry)
853
+ # ===================================================================== #
854
+ # === Handle registered audio tags next
855
+ # ===================================================================== #
856
+ elsif ARRAY_REGISTERED_AUDIO_TAGS.include? entry.to_s.delete('-')
857
+ # =================================================================== #
858
+ # Find out whether this is a registered audio tag.
859
+ #
860
+ # Invocation example:
861
+ #
862
+ # playlist eurodance
863
+ #
864
+ # =================================================================== #
865
+ play_song(
866
+ songs_whose_tag_matches_to(entry)
867
+ )
868
+ end
869
+ }
870
+ i.flatten!
871
+ @commandline_arguments = i
872
+ end
873
+
874
+ # ========================================================================= #
875
+ # === verbose_play_these_songs
876
+ #
877
+ # First argument should be an Array.
878
+ # ========================================================================= #
879
+ def verbose_play_these_songs(
880
+ i, optional_special_instructions = nil
881
+ )
882
+ case i
883
+ # ======================================================================= #
884
+ # === :last_songs
885
+ #
886
+ # This is deliberately distinct from :last_song.
887
+ #
888
+ # Usage example:
889
+ #
890
+ # playlist --last=20
891
+ #
892
+ # ======================================================================= #
893
+ when :last_songs
894
+ i = playlist?.reverse[0 .. optional_special_instructions.to_i]
895
+ # ======================================================================= #
896
+ # === :last_song
897
+ # ======================================================================= #
898
+ when :last_song
899
+ i = playlist?[-1]
900
+ end
901
+ unless i.is_a? Array
902
+ i = [i]
903
+ end # We require an Array past this point.
904
+ i.flatten!
905
+ i.map! {|entry|
906
+ if !File.exist?(entry.to_s) and (entry.to_s =~ /\d+/)
907
+ entry = at?(entry)
908
+ end
909
+ entry
910
+ }
911
+ return if i.empty? # Early return if the array is empty.
912
+ # ======================================================================= #
913
+ # Play these songs next:
914
+ # ======================================================================= #
915
+ i.each_with_index {|song, counter|
916
+ song = song.first if song.is_a? Array
917
+ counter += 1
918
+ if Object.const_defined?(:Roebe)
919
+ use_this_as_tab_title = 'Playlist - '.dup
920
+ use_this_as_tab_title << File.basename(song).
921
+ tr('_',' ').
922
+ sub(/#{File.extname(song)}$/, '')
923
+ e Roebe.return_audio_logo(use_this_as_tab_title)
924
+ end
925
+ e
926
+ e yel(counter.to_s.rjust(3))+
927
+ ') Playing the song `'+sfile(song)+'` next.'
928
+ e
929
+ play song
930
+ }
931
+ if is_on_roebe?
932
+ begin
933
+ require 'roebe/classes/kde/kde_konsole/kde_konsole.rb'
934
+ e Roebe.konsole_tab_title('.') # Rename the tab again.
935
+ rescue LoadError; end
936
+ end
937
+ end; alias play_song verbose_play_these_songs # === play_song
938
+ alias play_these_songs verbose_play_these_songs # === play_these_songs
939
+
940
+ # ========================================================================= #
941
+ # === exchange_these_two_positions
942
+ #
943
+ # The user can use this method should she/she wish to exchange two
944
+ # entries in the given playlist at hand. Logically this requires
945
+ # two different arguments.
946
+ # ========================================================================= #
947
+ def exchange_these_two_positions(
948
+ one, two
949
+ )
950
+ if one == two
951
+ opne 'Please provide different positions. Given position '\
952
+ 'was: '+steelblue(one)
953
+ return
954
+ end
955
+ entry_one = @playlist[one.to_i - 1]
956
+ entry_two = @playlist[two.to_i - 1]
957
+ opne rev+'We will next exchange two positions in our playlist.'
958
+ opne 'Entry '+simp(one.to_s)+' ('+sfile(entry_one)+') with '\
959
+ 'Entry '+simp(two.to_s)+' ('+sfile(entry_two)+').'
960
+ opne 'The new playlist will also be shown.'
961
+ # ======================================================================= #
962
+ # Here, we do the manipulation.
963
+ # ======================================================================= #
964
+ @playlist[one.to_i - 1] = entry_two
965
+ @playlist[two.to_i - 1] = entry_one
966
+ show_playlist # Show it here to see that we did a change.
967
+ save_dataset
968
+ opne 'Exchange operation between '+
969
+ steelblue(one.to_s)+' and '+
970
+ steelblue(two.to_s)+
971
+ ' finished! '+
972
+ gold('\o/')
973
+ end
974
+
975
+ # ========================================================================= #
976
+ # === at?
977
+ #
978
+ # This method returns the entry at a specific location.
979
+ # ========================================================================= #
980
+ def at?(i = 1)
981
+ playlist?[i.to_i - 1]
982
+ end
983
+
984
+ # ========================================================================= #
985
+ # === play_every_song_in_the_playlist
986
+ #
987
+ # The optional argument determines how to play the songs or whether
988
+ # to apply some changes, before playing the songs. For instance,
989
+ # :reverse means that we will play the songs in the reverse order,
990
+ # that is, starting with the last song first etc..
991
+ # ========================================================================= #
992
+ def play_every_song_in_the_playlist(optional_input = nil)
993
+ update_playlist
994
+ _ = playlist?
995
+ case optional_input
996
+ when :shuffle
997
+ _.shuffle!
998
+ when :reversed
999
+ _ = _.reverse
1000
+ end
1001
+ verbose_play_these_songs(_)
1002
+ end
1003
+
1004
+ # ========================================================================= #
1005
+ # === only_numbers?
1006
+ # ========================================================================= #
1007
+ def only_numbers?(i)
1008
+ return_value = false
1009
+ if i.is_a? Array
1010
+ return_value = i.all? {|entry| entry =~ /\d+/ }
1011
+ end
1012
+ return return_value
1013
+ end
1014
+
1015
+ # ========================================================================= #
1016
+ # === open_yaml_file_in_editor
1017
+ # ========================================================================= #
1018
+ def open_yaml_file_in_editor
1019
+ _ = "bluefish #{playlist_file?}"
1020
+ esystem(_)
1021
+ end
1022
+
1023
+ # ========================================================================= #
1024
+ # === playlist_file?
1025
+ # ========================================================================= #
1026
+ def playlist_file?
1027
+ @playlist_file
1028
+ end; alias yaml_file? playlist_file? # === yaml_file?
1029
+
1030
+ # ========================================================================= #
1031
+ # === return_entry_from_this_position (return tag)
1032
+ # ========================================================================= #
1033
+ def return_entry_from_this_position(i)
1034
+ entries = Dir['*'].sort
1035
+ position = i.to_i - 1
1036
+ if position > entries.size
1037
+ position = (entries.size - 1)
1038
+ end
1039
+ return entries[position]
1040
+ end
1041
+
1042
+ # ========================================================================= #
1043
+ # === convert_english_number_to_letter
1044
+ # ========================================================================= #
1045
+ def convert_english_number_to_letter(i)
1046
+ case i
1047
+ when 'one'
1048
+ 1
1049
+ when 'two'
1050
+ 2
1051
+ when 'three'
1052
+ 3
1053
+ when 'four'
1054
+ 4
1055
+ when 'five'
1056
+ 5
1057
+ when 'six'
1058
+ 6
1059
+ when 'seven'
1060
+ 7
1061
+ when 'eight'
1062
+ 8
1063
+ when 'nine'
1064
+ 9
1065
+ end
1066
+ end
1067
+
1068
+ # ========================================================================= #
1069
+ # === store_where?
1070
+ # ========================================================================= #
1071
+ def store_where?
1072
+ @playlist_file
1073
+ end; alias playlist_location? store_where? # === playlist_location?
1074
+
1075
+ # ========================================================================= #
1076
+ # === do_report_the_namespace
1077
+ # ========================================================================= #
1078
+ def do_report_the_namespace
1079
+ @report_namespace = true
1080
+ end
1081
+
1082
+ # ========================================================================= #
1083
+ # === playlist?
1084
+ # ========================================================================= #
1085
+ def playlist?
1086
+ @playlist
1087
+ end; alias dataset? playlist? # === dataset?
1088
+ alias dataset playlist? # === dataset
1089
+ alias data? playlist? # === data?
1090
+ alias all_songs playlist? # === all_songs
1091
+
1092
+ # ========================================================================= #
1093
+ # === purge_non_existing_files_from_playlist
1094
+ #
1095
+ # This method will purge non-existing files from the playlist.
1096
+ # ========================================================================= #
1097
+ def purge_non_existing_files_from_playlist
1098
+ opne 'Now purging non-existing files from the playlist.'
1099
+ new_array = []
1100
+ # ======================================================================= #
1101
+ # Next, make sure that the dataset was properly loaded.
1102
+ # ======================================================================= #
1103
+ load_yaml_dataset if playlist?.empty?
1104
+ playlist?.each {|entry|
1105
+ # ===================================================================== #
1106
+ # We store only multimedia files, hence the following check.
1107
+ # ===================================================================== #
1108
+ if File.exist?(entry) and MultimediaParadise.is_audio_file?(entry)
1109
+ new_array << entry
1110
+ else
1111
+ now_removing_this_entry(entry)
1112
+ end
1113
+ }
1114
+ store_this_playlist(new_array)
1115
+ end
1116
+
1117
+ # ========================================================================= #
1118
+ # === now_removing_this_entry
1119
+ # ========================================================================= #
1120
+ def now_removing_this_entry(i)
1121
+ opne 'Now removing the entry '+sfile(i)+' (from the playlist).'
1122
+ end
1123
+
1124
+ # ========================================================================= #
1125
+ # === ask_interactively_in_batch_format_for_each_audio_file
1126
+ #
1127
+ # To invoke this, try:
1128
+ #
1129
+ # playlist --batch
1130
+ #
1131
+ # ========================================================================= #
1132
+ def ask_interactively_in_batch_format_for_each_audio_file
1133
+ opne 'We will now ask you for every audio file in the current'
1134
+ opne 'directory whether you want to add it into the playlist.'
1135
+ audio_files = Dir['*'].select {|file|
1136
+ MultimediaParadise.is_audio_file? file
1137
+ }.sort
1138
+ audio_files.each {|file|
1139
+ e 'Do you want to add the file '+sfile(file)+' to the playlist? [y/n]'
1140
+ user_input = $stdin.getch # Only evaluate the first character, at once.
1141
+ case user_input
1142
+ when 'y'
1143
+ add file
1144
+ when 'n' # pass through.
1145
+ end
1146
+ }
1147
+ end
1148
+
1149
+ # ========================================================================= #
1150
+ # === play_random_song
1151
+ # ========================================================================= #
1152
+ def play_random_song
1153
+ play playlist?.sample
1154
+ end
1155
+
1156
+ # ========================================================================= #
1157
+ # === report_where_to_find_the_yaml_file
1158
+ # ========================================================================= #
1159
+ def report_where_to_find_the_yaml_file
1160
+ opne 'The yaml file can be found here:'
1161
+ e
1162
+ e ' `'+sfile(yaml_file?)+'`'
1163
+ e
1164
+ end
1165
+
1166
+ # ========================================================================= #
1167
+ # === purge_the_playlist
1168
+ # ========================================================================= #
1169
+ def purge_the_playlist
1170
+ save_yaml_dataset(:reset)
1171
+ opne 'The playlist was emptied.'
1172
+ end
1173
+
1174
+ # ========================================================================= #
1175
+ # === save_yaml_dataset (save tag)
1176
+ #
1177
+ # The first argument should be an Array containing all the songs that
1178
+ # are part of your playlist. We will then store it into the default
1179
+ # file location, specified by store_what?.
1180
+ # ========================================================================= #
1181
+ def save_yaml_dataset(
1182
+ this_dataset = playlist?
1183
+ )
1184
+ case this_dataset
1185
+ when :reset
1186
+ dataset = []
1187
+ else # This is the default here.
1188
+ dataset = YAML.dump(this_dataset)
1189
+ dataset << N unless dataset.end_with? N
1190
+ # Next we prepend a ' - ' but only if we don't start with this
1191
+ # token OR if we do not start with '---'
1192
+ unless dataset.start_with? ' - '
1193
+ dataset.prepend(' - ') unless dataset.start_with?('---')
1194
+ end
1195
+ end
1196
+ SaveFile.write_what_into(dataset, store_where?)
1197
+ end; alias store_this_playlist save_yaml_dataset # === store_this_playlist
1198
+ alias save_dataset save_yaml_dataset # === save_dataset
1199
+ alias save_playlist save_yaml_dataset # === save_playlist
1200
+
1201
+ # ========================================================================= #
1202
+ # === play (play tag)
1203
+ #
1204
+ # This will always output the file that will be played.
1205
+ # ========================================================================= #
1206
+ def play(i = '')
1207
+ case i
1208
+ when :last_song
1209
+ i = playlist?[-1]
1210
+ end
1211
+ if i.is_a? Array
1212
+ i.each {|entry| play(entry) }
1213
+ else
1214
+ unless File.exist?(i)
1215
+ i.prepend(directory_to_the_local_songs?) unless i.include?(directory_to_the_local_songs?)
1216
+ end
1217
+ _ = "#{use_which_multimedia_player?} #{i}"
1218
+ e _
1219
+ system _
1220
+ end
1221
+ end; alias play_this_song play # === play_this_song
1222
+
1223
+ # ========================================================================= #
1224
+ # === use_which_multimedia_player?
1225
+ # ========================================================================= #
1226
+ def use_which_multimedia_player?
1227
+ _ = 'mplayer'
1228
+ if ENV.has_key? 'USE_THIS_VIDEO_PLAYER'
1229
+ _ = ENV['USE_THIS_VIDEO_PLAYER'].to_s.dup
1230
+ end
1231
+ return _
1232
+ end
1233
+
1234
+ # ========================================================================= #
1235
+ # === reshuffle_the_playlist
1236
+ #
1237
+ # This method will randomly re-arrange the playlist in use.
1238
+ # ========================================================================= #
1239
+ def reshuffle_the_playlist(be_verbose = true)
1240
+ if be_verbose
1241
+ opne 'Reshuffling the playlist next.'
1242
+ end
1243
+ dataset = all_songs.shuffle
1244
+ save_playlist(dataset)
1245
+ end
1246
+
1247
+ # ========================================================================= #
1248
+ # === remove (remove tag)
1249
+ #
1250
+ # This method will notify the user that we will remove an entry, and
1251
+ # then proceed to do so.
1252
+ # ========================================================================= #
1253
+ def remove(i)
1254
+ if playlist?.include? i
1255
+ now_removing_this_entry(i)
1256
+ @playlist.delete(i)
1257
+ save_yaml_dataset
1258
+ else
1259
+ e 'The entry '+sfancy(i)+' was not found in the playlist, thus'
1260
+ e 'it can not be removed.'
1261
+ end
1262
+ end
1263
+
1264
+ # ========================================================================= #
1265
+ # === try_to_play_songs_matching_this_input
1266
+ # ========================================================================= #
1267
+ def try_to_play_songs_matching_this_input(i)
1268
+ if i.is_a? Array
1269
+ i.each {|entry|
1270
+ try_to_play_songs_matching_this_input(entry)
1271
+ }
1272
+ else
1273
+ if i.include? ', ' # In this case, sanitize the input first.
1274
+ i = i.dup if i.frozen?
1275
+ i.delete!(' ')
1276
+ end if i.is_a? String
1277
+ if i.include? 'last'
1278
+ i.sub!(/last/, return_last_position_as_number.to_s)
1279
+ end
1280
+ if i =~ /^\d+$/ # If it is a number
1281
+ i = @playlist[i.to_i - 1]
1282
+ end
1283
+ if i.include? ','
1284
+ try_to_play_songs_matching_this_input(
1285
+ i.split(',')
1286
+ )
1287
+ else
1288
+ possible_matches = @playlist.grep(/#{i}/)
1289
+ unless possible_matches.empty?
1290
+ # =================================================================== #
1291
+ # Play these songs then.
1292
+ # =================================================================== #
1293
+ play_these_songs(possible_matches)
1294
+ end
1295
+ end
1296
+ end
1297
+ end
1298
+
1299
+ # ========================================================================= #
1300
+ # === songs_whose_tag_matches_to
1301
+ #
1302
+ # This will select based on the file called song_tags.yml
1303
+ # ========================================================================= #
1304
+ def songs_whose_tag_matches_to(i)
1305
+ i = i.dup if i.frozen?
1306
+ i.delete!('-')
1307
+ dataset = YAML.load_file(FILE_SONG_TAGS)
1308
+ dataset.select! {|key, value|
1309
+ value.include?(i) if value
1310
+ }
1311
+ keys = dataset.keys
1312
+ # ======================================================================= #
1313
+ # Next, add the filepath to them.
1314
+ # ======================================================================= #
1315
+ keys.map! {|file|
1316
+ file = file.dup if file.frozen?
1317
+ file.prepend(SONG_DIR)
1318
+ file = Dir[file+'*']
1319
+ file
1320
+ }
1321
+ return keys
1322
+ end
1323
+
1324
+ # ========================================================================= #
1325
+ # === play_these_songs_based_on_numbered_input
1326
+ #
1327
+ # The input to this method should be numbers.
1328
+ #
1329
+ # The second argument will rarely be necessary.
1330
+ #
1331
+ # The input can be a String such as "5-12", which means "play all
1332
+ # songs from position 5 up to, and including, 12".
1333
+ # ========================================================================= #
1334
+ def play_these_songs_based_on_numbered_input(
1335
+ i,
1336
+ optional_original_input_to_menu = nil
1337
+ )
1338
+ if i.is_a?(String) and i.include?('-') and i =~ /\d{1,2}-\d{1,2}/ # Handle 5-10
1339
+ splitted = i.split('-').map(&:to_i)
1340
+ range = splitted # <- may be [10, 20] or [76, 56] now.
1341
+ if range.last < range.first
1342
+ i = range.first.downto(range.last).to_a
1343
+ else
1344
+ i = Range.new(*range).to_a
1345
+ end
1346
+ end
1347
+ if i.is_a? Array
1348
+ i.each {|entry|
1349
+ play_these_songs_based_on_numbered_input(
1350
+ entry, optional_original_input_to_menu
1351
+ )
1352
+ }
1353
+ else
1354
+ this_song = playlist?[i - 1]
1355
+ if optional_original_input_to_menu
1356
+ if optional_original_input_to_menu.include?(',') and $2
1357
+ this_song = [this_song, playlist?[$2.to_s.dup.to_i - 1]]
1358
+ end
1359
+ end
1360
+ verbose_play_these_songs(this_song) # play_this_song(this_song)
1361
+ end
1362
+ end
1363
+
1364
+ # ========================================================================= #
1365
+ # === opnn
1366
+ # ========================================================================= #
1367
+ def opnn
1368
+ super(NAMESPACE) if @report_namespace
1369
+ end
1370
+
1371
+ # ========================================================================= #
1372
+ # === opne
1373
+ # ========================================================================= #
1374
+ def opne(i = '')
1375
+ opnn; e i
1376
+ end
1377
+
1378
+ # ========================================================================= #
1379
+ # === remove_this_entry
1380
+ #
1381
+ # This method can be used to remove an entry from our playlist.
1382
+ #
1383
+ # The input to this method should ideally be a number, such as
1384
+ # 5. This refers to removing the song number 5.
1385
+ # ========================================================================= #
1386
+ def remove_this_entry(i)
1387
+ i = i.join(' ') if i.is_a? Array
1388
+ case i
1389
+ when :last
1390
+ i = data?.last
1391
+ end
1392
+ i = i.to_s.delete('-')
1393
+ if i =~ /^\d+$/ # If only numbers, then fetch the entry
1394
+ i = playlist?[i.to_i - 1]
1395
+ end
1396
+ remove i
1397
+ end
1398
+
1399
+ # ========================================================================= #
1400
+ # === consider_requiring_the_kde_konsole_specific_files
1401
+ # ========================================================================= #
1402
+ def consider_requiring_the_kde_konsole_specific_files
1403
+ if is_on_roebe?
1404
+ begin
1405
+ require 'roebe/classes/kde/kde_konsole/kde_konsole.rb'
1406
+ rescue LoadError; end
1407
+ end
1408
+ end
1409
+
1410
+ # ========================================================================= #
1411
+ # === convert_to_m3u_playlist
1412
+ #
1413
+ # Use this method if you wish to create a .m3u list.
1414
+ #
1415
+ # More information about .m3u files can be found here:
1416
+ #
1417
+ # https://en.wikipedia.org/wiki/M3U
1418
+ #
1419
+ # ========================================================================= #
1420
+ def convert_to_m3u_playlist(
1421
+ i = store_where?,
1422
+ use_this_name_for_the_m3u_file = DEFAULT_NAME_FOR_THE_M3U_PLAYLIST
1423
+ )
1424
+ opne 'We will next create a new .m3u file at '\
1425
+ '`'+sfile(use_this_name_for_the_m3u_file)+'`.'
1426
+ if File.exist? i
1427
+ dataset = load_dataset(i) # ← This is a Hash.
1428
+ create_this_m3u_file(dataset, 'tales_from_the_crypt.m3u')
1429
+ else
1430
+ opnn; no_file_exists_at(i)
1431
+ end
1432
+ end
1433
+
1434
+ # ========================================================================= #
1435
+ # === create_this_m3u_file
1436
+ #
1437
+ # The first argument should be the dataset that contains all the
1438
+ # files.
1439
+ #
1440
+ # To trigger this, do:
1441
+ #
1442
+ # playlist --convert
1443
+ #
1444
+ # ========================================================================= #
1445
+ def create_this_m3u_file(
1446
+ dataset_that_is_to_be_used,
1447
+ name_of_the_file = PLAYLIST_M3U_FILE
1448
+ )
1449
+ CreateM3uPlaylist.new(
1450
+ dataset_that_is_to_be_used, name_of_the_file
1451
+ ) # This comes from $MULTIMEDIA_PARADISE/audio/create_m3u_playlist.rb
1452
+ end
1453
+
1454
+ # ========================================================================= #
1455
+ # === load_yaml_dataset (load tag)
1456
+ #
1457
+ # This method will populate the instance variable @playlist with the
1458
+ # proper dataset.
1459
+ # ========================================================================= #
1460
+ def load_yaml_dataset(i = store_where?)
1461
+ if File.exist? i
1462
+ @playlist = YAML.load_file(i)
1463
+ end
1464
+ return @playlist # Return it as well here.
1465
+ end; alias load_dataset load_yaml_dataset # === load_dataset
1466
+ alias update_playlist load_yaml_dataset # === update_playlist
1467
+ alias populate_the_playlist load_yaml_dataset # === populate_the_playlist
1468
+
1469
+ # ========================================================================= #
1470
+ # === create_tales_from_the_crypt_playlist
1471
+ #
1472
+ # This method will generate a .m3u playlist for the tales-from-the-crypt
1473
+ # videos. The input should be a yaml file.
1474
+ # ========================================================================= #
1475
+ def create_tales_from_the_crypt_playlist(
1476
+ use_this_yaml_file =
1477
+ ::MultimediaParadise.file_tales_from_the_crypt
1478
+ )
1479
+ do_report_the_namespace
1480
+ convert_to_m3u_playlist(use_this_yaml_file)
1481
+ end
1482
+
1483
+ # ========================================================================= #
1484
+ # === MultimediaParadise::Playlist.playlist?
1485
+ #
1486
+ # Feedback which playlist is in use.
1487
+ # ========================================================================= #
1488
+ def self.playlist?
1489
+ MultimediaParadise::Playlist.new(:dont_run_yet) { :be_quiet }.playlist?
1490
+ end; self.instance_eval { alias return_array playlist? } # === MultimediaParadise::Playlist.return_array?
1491
+
1492
+ # ========================================================================= #
1493
+ # === run (run tag)
1494
+ # ========================================================================= #
1495
+ def run
1496
+ sanitize_the_commandline
1497
+ menu
1498
+ verbose_play_these_songs(
1499
+ @array_these_songs_will_be_played
1500
+ )
1501
+ end
1502
+
1503
+ # ========================================================================= #
1504
+ # === show_playlist (show tag)
1505
+ #
1506
+ # This method will display, on the commandline, the current playlist
1507
+ # in use.
1508
+ # ========================================================================= #
1509
+ def show_playlist(
1510
+ be_verbose = @be_verbose
1511
+ )
1512
+ if be_verbose
1513
+ _ = playlist?
1514
+ if _.is_a?(FalseClass) or _.empty?
1515
+ opne 'The playlist is currently empty.'
1516
+ e
1517
+ opne 'You can use '+steelblue('--add')+
1518
+ rev+' to add files to the playlist.'
1519
+ e
1520
+ opne 'Example:'
1521
+ e
1522
+ opne sfancy(' playlist -add UtahSaints_SomethingGood.mp3')
1523
+ e
1524
+ else
1525
+ opne "#{rev}We found these #{simp(_.size.to_s)} entries "\
1526
+ "as part of the playlist:"
1527
+ e
1528
+ _.each_with_index {|entry, index|
1529
+ index += 1
1530
+ left = ' '.dup
1531
+ left << (' ' * (3 - index.to_s.size))
1532
+ left << ('('+royalblue(index.to_s)+')')
1533
+ e "#{left} #{olivedrab(entry)}"
1534
+ }; e
1535
+ end
1536
+ end
1537
+ end
1538
+
1539
+ # ========================================================================= #
1540
+ # === MultimediaParadise::Playlist.show_playlist
1541
+ # ========================================================================= #
1542
+ def self.show_playlist
1543
+ new.show_playlist
1544
+ end; self.instance_eval { alias [] show_playlist } # === MultimediaParadise::Playlist[]
1545
+
1546
+ end
1547
+
1548
+ # =========================================================================== #
1549
+ # === MultimediaParadise.add_this_song_to_the_playlist
1550
+ # =========================================================================== #
1551
+ def self.add_this_song_to_the_playlist(i)
1552
+ ::MultimediaParadise::Playlist.add(i)
1553
+ end
1554
+
1555
+ end
1556
+
1557
+ if __FILE__ == $PROGRAM_NAME
1558
+ MultimediaParadise::Playlist.new(ARGV[0], ARGV[1])
1559
+ end # playlist