multimedia_paradise 1.1.344

Sign up to get free protection for your applications and to get access to all the features.
Files changed (382) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +2720 -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/extract_images_from_this_video_file +7 -0
  10. data/bin/ffmpeg_merge +7 -0
  11. data/bin/file_duration +7 -0
  12. data/bin/gtk_radio +7 -0
  13. data/bin/has_audio +7 -0
  14. data/bin/loop_this_video +7 -0
  15. data/bin/merge_avi_files +7 -0
  16. data/bin/merge_mp3 +7 -0
  17. data/bin/missing_video_files +7 -0
  18. data/bin/movie_searcher +7 -0
  19. data/bin/mp3_to_opus +7 -0
  20. data/bin/mpg_to_mp4 +7 -0
  21. data/bin/mplayer_wrapper +7 -0
  22. data/bin/multimedia_information +11 -0
  23. data/bin/multimedia_paradise +9 -0
  24. data/bin/multimedia_paradise_sinatra +7 -0
  25. data/bin/play_random_simpsons_video +7 -0
  26. data/bin/playlist +7 -0
  27. data/bin/random_video +7 -0
  28. data/bin/remove_audio +9 -0
  29. data/bin/remove_last_second +7 -0
  30. data/bin/remove_subtitles +7 -0
  31. data/bin/reverse_video +7 -0
  32. data/bin/rubio +58 -0
  33. data/bin/tag_mp3_files +7 -0
  34. data/bin/to_aiff +10 -0
  35. data/bin/to_mp4 +7 -0
  36. data/bin/verbose_analyse_this_mp3_file_for_id3_tags +9 -0
  37. data/bin/video_codec +7 -0
  38. data/bin/video_information +8 -0
  39. data/bin/video_player +11 -0
  40. data/bin/video_thumbnail +7 -0
  41. data/bin/video_to_images +7 -0
  42. data/bin/vp9 +9 -0
  43. data/bin/waveform +73 -0
  44. data/doc/CHANGELOG.md +44 -0
  45. data/doc/LINKS.md +6 -0
  46. data/doc/MOTIVATION_FOR_THIS_PROJECT.md +22 -0
  47. data/doc/MergingVideoLectures.md +12 -0
  48. data/doc/README.gen +2658 -0
  49. data/doc/Readme_for_the_cut_audio_component.md +168 -0
  50. data/doc/todo/todo_for_the_GUIs.md +0 -0
  51. data/doc/todo/todo_for_the_multimedia_paradise_project.md +111 -0
  52. data/lib/multimedia_paradise/audio/audio_player/audio_player.rb +1143 -0
  53. data/lib/multimedia_paradise/audio/audio_tag_reader/README.md +7 -0
  54. data/lib/multimedia_paradise/audio/audio_tag_reader/audio_tag_reader.rb +503 -0
  55. data/lib/multimedia_paradise/audio/base.rb +67 -0
  56. data/lib/multimedia_paradise/audio/compress.rb +97 -0
  57. data/lib/multimedia_paradise/audio/create_m3u_playlist.rb +256 -0
  58. data/lib/multimedia_paradise/audio/extract_audio/constants.rb +37 -0
  59. data/lib/multimedia_paradise/audio/extract_audio/extract_audio.rb +417 -0
  60. data/lib/multimedia_paradise/audio/file_duration/constants.rb +53 -0
  61. data/lib/multimedia_paradise/audio/file_duration/file_duration.rb +606 -0
  62. data/lib/multimedia_paradise/audio/genres/boogie.rb +35 -0
  63. data/lib/multimedia_paradise/audio/genres/concerts.rb +35 -0
  64. data/lib/multimedia_paradise/audio/genres/constants.rb +53 -0
  65. data/lib/multimedia_paradise/audio/genres/eurodance.rb +35 -0
  66. data/lib/multimedia_paradise/audio/genres/genre.rb +696 -0
  67. data/lib/multimedia_paradise/audio/genres/hip_hop.rb +35 -0
  68. data/lib/multimedia_paradise/audio/genres/italian_songs.rb +35 -0
  69. data/lib/multimedia_paradise/audio/genres/the_1980s.rb +35 -0
  70. data/lib/multimedia_paradise/audio/genres/trance.rb +35 -0
  71. data/lib/multimedia_paradise/audio/lyrics_fetcher.rb +238 -0
  72. data/lib/multimedia_paradise/audio/merge_audio_files.rb +114 -0
  73. data/lib/multimedia_paradise/audio/modify_year_of_audio_file.rb +136 -0
  74. data/lib/multimedia_paradise/audio/n_audio_songs.rb +208 -0
  75. data/lib/multimedia_paradise/audio/play_all_audio_files.rb +122 -0
  76. data/lib/multimedia_paradise/audio/playlist/playlist.rb +1636 -0
  77. data/lib/multimedia_paradise/audio/remove_audio.rb +98 -0
  78. data/lib/multimedia_paradise/audio/remove_last_second.rb +83 -0
  79. data/lib/multimedia_paradise/audio/report_missing_id.rb +131 -0
  80. data/lib/multimedia_paradise/audio/streamripper/constants.rb +51 -0
  81. data/lib/multimedia_paradise/audio/streamripper/streamripper_wrapper.rb +279 -0
  82. data/lib/multimedia_paradise/audio/to_mp3.rb +138 -0
  83. data/lib/multimedia_paradise/audio/to_ogg.rb +104 -0
  84. data/lib/multimedia_paradise/audio/wav_to_mp3.rb +87 -0
  85. data/lib/multimedia_paradise/audio/waveform/class.rb +341 -0
  86. data/lib/multimedia_paradise/audio/waveform/constants.rb +38 -0
  87. data/lib/multimedia_paradise/audio/waveform/log.rb +101 -0
  88. data/lib/multimedia_paradise/autoinclude.rb +3 -0
  89. data/lib/multimedia_paradise/autoinclude_remove_audio.rb +6 -0
  90. data/lib/multimedia_paradise/base/base.rb +34 -0
  91. data/lib/multimedia_paradise/base/colours.rb +391 -0
  92. data/lib/multimedia_paradise/base/commandline_arguments.rb +60 -0
  93. data/lib/multimedia_paradise/base/constants.rb +19 -0
  94. data/lib/multimedia_paradise/base/encoding.rb +31 -0
  95. data/lib/multimedia_paradise/base/misc.rb +665 -0
  96. data/lib/multimedia_paradise/base/namespace.rb +36 -0
  97. data/lib/multimedia_paradise/base/time.rb +25 -0
  98. data/lib/multimedia_paradise/colours/colours.rb +89 -0
  99. data/lib/multimedia_paradise/commandline/menu.rb +463 -0
  100. data/lib/multimedia_paradise/configuration/play_zoomed.yml +1 -0
  101. data/lib/multimedia_paradise/constants/constants.rb +23 -0
  102. data/lib/multimedia_paradise/constants/conversions.rb +62 -0
  103. data/lib/multimedia_paradise/constants/directory_constants.rb +139 -0
  104. data/lib/multimedia_paradise/constants/encodings.rb +26 -0
  105. data/lib/multimedia_paradise/constants/file_constants.rb +176 -0
  106. data/lib/multimedia_paradise/constants/misc.rb +80 -0
  107. data/lib/multimedia_paradise/constants/my_video_directory.rb +30 -0
  108. data/lib/multimedia_paradise/constants/namespace.rb +14 -0
  109. data/lib/multimedia_paradise/constants/newline.rb +14 -0
  110. data/lib/multimedia_paradise/constants/video_filetypes.rb +27 -0
  111. data/lib/multimedia_paradise/constants/web_constants.rb +150 -0
  112. data/lib/multimedia_paradise/conversions/README.md +2 -0
  113. data/lib/multimedia_paradise/conversions/conversions.rb +930 -0
  114. data/lib/multimedia_paradise/css/project.css +15 -0
  115. data/lib/multimedia_paradise/data/asoundrc +12 -0
  116. data/lib/multimedia_paradise/ffmpeg/README.md +2 -0
  117. data/lib/multimedia_paradise/ffmpeg/ffmpeg.rb +620 -0
  118. data/lib/multimedia_paradise/gui/fox/play_from_radio_station.rb +75 -0
  119. data/lib/multimedia_paradise/gui/glimmer/rubio/model/bookmark.rb +61 -0
  120. data/lib/multimedia_paradise/gui/glimmer/rubio/model/player.rb +226 -0
  121. data/lib/multimedia_paradise/gui/glimmer/rubio/model/radio_browser.rb +57 -0
  122. data/lib/multimedia_paradise/gui/glimmer/rubio/model/radio_presenter.rb +132 -0
  123. data/lib/multimedia_paradise/gui/glimmer/rubio/model/station.rb +48 -0
  124. data/lib/multimedia_paradise/gui/glimmer/rubio/view/radio.rb +296 -0
  125. data/lib/multimedia_paradise/gui/gosu/video_player/video_player.rb +109 -0
  126. data/lib/multimedia_paradise/gui/gtk2/multimedia_converter/multimedia_converter.rb +33 -0
  127. data/lib/multimedia_paradise/gui/gtk2/notebook.rb +144 -0
  128. data/lib/multimedia_paradise/gui/gtk2/play_video_from_my_collection/play_video_from_my_collection.rb +43 -0
  129. data/lib/multimedia_paradise/gui/gtk2/simple_play_widget/README.md +12 -0
  130. data/lib/multimedia_paradise/gui/gtk2/simple_play_widget/simple_play_widget.rb +40 -0
  131. data/lib/multimedia_paradise/gui/gtk2/widget_increase_or_decrease_audio/widget_increase_or_decrease_audio.rb +42 -0
  132. data/lib/multimedia_paradise/gui/gtk2/youtube_downloader/youtube_downloader.rb +32 -0
  133. data/lib/multimedia_paradise/gui/gtk3/lyrics/lyrics.rb +0 -0
  134. data/lib/multimedia_paradise/gui/gtk3/multimedia_converter/multimedia_converter.rb +34 -0
  135. data/lib/multimedia_paradise/gui/gtk3/multimedia_notebook/multimedia_notebook.rb +34 -0
  136. data/lib/multimedia_paradise/gui/gtk3/play_video_from_my_collection/play_video_from_my_collection.rb +34 -0
  137. data/lib/multimedia_paradise/gui/gtk3/playlist/playlist.rb +34 -0
  138. data/lib/multimedia_paradise/gui/gtk3/simple_play_widget/simple_play_widget.rb +38 -0
  139. data/lib/multimedia_paradise/gui/gtk3/video_editor/video_editor.rb +34 -0
  140. data/lib/multimedia_paradise/gui/gtk3/video_player/video_player.rb +34 -0
  141. data/lib/multimedia_paradise/gui/gtk3/webcam_widget/webcam_widget.rb +425 -0
  142. data/lib/multimedia_paradise/gui/gtk3/widget_increase_or_decrease_audio/widget_increase_or_decrease_audio.rb +36 -0
  143. data/lib/multimedia_paradise/gui/gtk3/youtube_channels/youtube_channels.rb +210 -0
  144. data/lib/multimedia_paradise/gui/gtk3/youtube_downloader/youtube_downloader.rb +32 -0
  145. data/lib/multimedia_paradise/gui/gui_base.rb +92 -0
  146. data/lib/multimedia_paradise/gui/libui/change_metadata_widget/change_metadata_widget.rb +115 -0
  147. data/lib/multimedia_paradise/gui/libui/cut_multimedia/cut_multimedia.rb +119 -0
  148. data/lib/multimedia_paradise/gui/libui/lyrics/lyrics.rb +67 -0
  149. data/lib/multimedia_paradise/gui/libui/simple_play_widget/simple_play_widget.rb +119 -0
  150. data/lib/multimedia_paradise/gui/libui/video_player/video_player.rb +81 -0
  151. data/lib/multimedia_paradise/gui/libui/widget_increase_or_decrease_audio/widget_increase_or_decrease_audio.rb +126 -0
  152. data/lib/multimedia_paradise/gui/libui/youtube_channels/youtube_channels.rb +116 -0
  153. data/lib/multimedia_paradise/gui/libui/youtube_downloader/youtube_downloader.rb +107 -0
  154. data/lib/multimedia_paradise/gui/shared_code/lyrics/lyrics_module.rb +0 -0
  155. data/lib/multimedia_paradise/gui/shared_code/multimedia_converter/multimedia_converter_module.rb +478 -0
  156. data/lib/multimedia_paradise/gui/shared_code/multimedia_notebook/multimedia_notebook_module.rb +171 -0
  157. data/lib/multimedia_paradise/gui/shared_code/play_video_from_my_collection/play_video_from_my_collection_module.rb +464 -0
  158. data/lib/multimedia_paradise/gui/shared_code/playlist/playlist_module.rb +151 -0
  159. data/lib/multimedia_paradise/gui/shared_code/simple_play_widget/simple_play_widget_module.rb +257 -0
  160. data/lib/multimedia_paradise/gui/shared_code/sound_effect_widget/sound_effect_widget_module.rb +0 -0
  161. data/lib/multimedia_paradise/gui/shared_code/video_editor/video_editor_module.rb +287 -0
  162. data/lib/multimedia_paradise/gui/shared_code/video_player/video_player_module.rb +185 -0
  163. data/lib/multimedia_paradise/gui/shared_code/widget_increase_or_decrease_audio/widget_increase_or_decrease_audio_module.rb +310 -0
  164. data/lib/multimedia_paradise/gui/shared_code/youtube_downloader/youtube_downloader_module.rb +339 -0
  165. data/lib/multimedia_paradise/gui/tk/tk_multimedia_wrapper.rb +60 -0
  166. data/lib/multimedia_paradise/gui/universal_widgets/change_metadata_widget/README.md +3 -0
  167. data/lib/multimedia_paradise/gui/universal_widgets/change_metadata_widget/change_metadata_widget.rb +751 -0
  168. data/lib/multimedia_paradise/gui/universal_widgets/cut_multimedia/cut_multimedia.rb +657 -0
  169. data/lib/multimedia_paradise/gui/universal_widgets/information_about_a_mp3_file/information_about_a_mp3_file.rb +597 -0
  170. data/lib/multimedia_paradise/gui/universal_widgets/lyrics/lyrics.rb +265 -0
  171. data/lib/multimedia_paradise/gui/universal_widgets/radio/radio.rb +1364 -0
  172. data/lib/multimedia_paradise/gui/universal_widgets/sound_effect_widget/sound_effect_widget.rb +265 -0
  173. data/lib/multimedia_paradise/gui/universal_widgets/tag_mp3_files/tag_mp3_files.config +6 -0
  174. data/lib/multimedia_paradise/gui/universal_widgets/tag_mp3_files/tag_mp3_files.rb +2429 -0
  175. data/lib/multimedia_paradise/gui/universal_widgets/video_collection/video_collection.rb +246 -0
  176. data/lib/multimedia_paradise/help/help.rb +75 -0
  177. data/lib/multimedia_paradise/images/MULTIMEDIA.jpg +0 -0
  178. data/lib/multimedia_paradise/images/MULTIMEDIA_PARADISE_ID_TAG_GUI_IN_RUBY_GTK3.png +0 -0
  179. data/lib/multimedia_paradise/images/MULTIMEDIA_PARADISE_LOGO.png +0 -0
  180. data/lib/multimedia_paradise/images/UK_flag.png +0 -0
  181. data/lib/multimedia_paradise/images/US_flag.png +0 -0
  182. data/lib/multimedia_paradise/images/austrian_flag.png +0 -0
  183. data/lib/multimedia_paradise/images/french_flag.png +0 -0
  184. data/lib/multimedia_paradise/images/german_flag.png +0 -0
  185. data/lib/multimedia_paradise/images/radio_image.png +0 -0
  186. data/lib/multimedia_paradise/images/trance.png +0 -0
  187. data/lib/multimedia_paradise/java/AudioPlayer.class +0 -0
  188. data/lib/multimedia_paradise/java/AudioPlayer.java +103 -0
  189. data/lib/multimedia_paradise/java/README.md +3 -0
  190. data/lib/multimedia_paradise/misc/long_format_to_milliseconds_converter.rb +182 -0
  191. data/lib/multimedia_paradise/misc/milliseconds_to_long_format_converter.rb +186 -0
  192. data/lib/multimedia_paradise/multimedia/analyse_multimedia_file.rb +180 -0
  193. data/lib/multimedia_paradise/multimedia/avisynth/README.md +4 -0
  194. data/lib/multimedia_paradise/multimedia/avisynth/avisynth_code.avs +471 -0
  195. data/lib/multimedia_paradise/multimedia/base.rb +60 -0
  196. data/lib/multimedia_paradise/multimedia/chord.rb +174 -0
  197. data/lib/multimedia_paradise/multimedia/convert_audio_to_video_with_image.rb +171 -0
  198. data/lib/multimedia_paradise/multimedia/cut_multimedia/10_minutes_chop.rb +29 -0
  199. data/lib/multimedia_paradise/multimedia/cut_multimedia/15_minutes_chop.rb +29 -0
  200. data/lib/multimedia_paradise/multimedia/cut_multimedia/30_minutes_chop.rb +29 -0
  201. data/lib/multimedia_paradise/multimedia/cut_multimedia/5_minutes_chop.rb +29 -0
  202. data/lib/multimedia_paradise/multimedia/cut_multimedia/cut_multimedia.rb +2021 -0
  203. data/lib/multimedia_paradise/multimedia/cut_multimedia/evaluate_from_this_file.rb +79 -0
  204. data/lib/multimedia_paradise/multimedia/cut_multimedia/interactive_menu.rb +525 -0
  205. data/lib/multimedia_paradise/multimedia/interactive_shell.rb +84 -0
  206. data/lib/multimedia_paradise/multimedia/merge_multimedia.rb +127 -0
  207. data/lib/multimedia_paradise/multimedia/note.rb +500 -0
  208. data/lib/multimedia_paradise/multimedia/play_from_this_list.rb +163 -0
  209. data/lib/multimedia_paradise/multimedia/read_meta_tags.rb +173 -0
  210. data/lib/multimedia_paradise/multimedia/simulate_youtube_playlist.rb +209 -0
  211. data/lib/multimedia_paradise/multimedia/start_length_duration.rb +205 -0
  212. data/lib/multimedia_paradise/multimedia/video_downloader/video_downloader.rb +135 -0
  213. data/lib/multimedia_paradise/project/project.rb +47 -0
  214. data/lib/multimedia_paradise/requires/require_audio_files.rb +74 -0
  215. data/lib/multimedia_paradise/requires/require_cut_multimedia.rb +7 -0
  216. data/lib/multimedia_paradise/requires/require_extract_audio.rb +7 -0
  217. data/lib/multimedia_paradise/requires/require_file_duration.rb +7 -0
  218. data/lib/multimedia_paradise/requires/require_streamripper.rb +7 -0
  219. data/lib/multimedia_paradise/requires/require_the_audio_player.rb +7 -0
  220. data/lib/multimedia_paradise/requires/require_the_multimedia_paradise_project.rb +38 -0
  221. data/lib/multimedia_paradise/requires/require_the_sinatra_components.rb +7 -0
  222. data/lib/multimedia_paradise/requires/require_toplevel_methods_files.rb +25 -0
  223. data/lib/multimedia_paradise/requires/require_video_files.rb +25 -0
  224. data/lib/multimedia_paradise/requires/require_video_player.rb +7 -0
  225. data/lib/multimedia_paradise/sinatra/app.rb +318 -0
  226. data/lib/multimedia_paradise/sinatra/embeddable_interface.rb +379 -0
  227. data/lib/multimedia_paradise/sound_effects/README.md +12 -0
  228. data/lib/multimedia_paradise/sound_effects/cat_meow.mp3 +0 -0
  229. data/lib/multimedia_paradise/sound_effects/channel_opened.mp3 +0 -0
  230. data/lib/multimedia_paradise/sound_effects/phone_ring.mp3 +0 -0
  231. data/lib/multimedia_paradise/statistics/README.md +5 -0
  232. data/lib/multimedia_paradise/statistics/video.rb +84 -0
  233. data/lib/multimedia_paradise/toplevel_cut_audio.rb +16 -0
  234. data/lib/multimedia_paradise/toplevel_methods/analyze_audio_stream.rb +31 -0
  235. data/lib/multimedia_paradise/toplevel_methods/chop_into_segments_of_n_seconds_size.rb +32 -0
  236. data/lib/multimedia_paradise/toplevel_methods/chop_off_first_five_minutes.rb +22 -0
  237. data/lib/multimedia_paradise/toplevel_methods/chop_off_first_n_seconds.rb +92 -0
  238. data/lib/multimedia_paradise/toplevel_methods/chop_off_first_ten_minutes.rb +22 -0
  239. data/lib/multimedia_paradise/toplevel_methods/chop_off_first_two_minutes.rb +24 -0
  240. data/lib/multimedia_paradise/toplevel_methods/codecs.rb +50 -0
  241. data/lib/multimedia_paradise/toplevel_methods/copy_and_merge_this_video_n_times.rb +51 -0
  242. data/lib/multimedia_paradise/toplevel_methods/copy_file.rb +18 -0
  243. data/lib/multimedia_paradise/toplevel_methods/create_video_from_this_audio.rb +65 -0
  244. data/lib/multimedia_paradise/toplevel_methods/cut_from_to.rb +156 -0
  245. data/lib/multimedia_paradise/toplevel_methods/delay_audio.rb +31 -0
  246. data/lib/multimedia_paradise/toplevel_methods/denoise.rb +90 -0
  247. data/lib/multimedia_paradise/toplevel_methods/deshake.rb +43 -0
  248. data/lib/multimedia_paradise/toplevel_methods/e.rb +16 -0
  249. data/lib/multimedia_paradise/toplevel_methods/encode_this_video.rb +49 -0
  250. data/lib/multimedia_paradise/toplevel_methods/ensure_that_the_output_directory_exists.rb +27 -0
  251. data/lib/multimedia_paradise/toplevel_methods/esystem.rb +43 -0
  252. data/lib/multimedia_paradise/toplevel_methods/files_and_directories.rb +92 -0
  253. data/lib/multimedia_paradise/toplevel_methods/flip_and_rotate.rb +58 -0
  254. data/lib/multimedia_paradise/toplevel_methods/has_audio.rb +48 -0
  255. data/lib/multimedia_paradise/toplevel_methods/increase_volume_of_this_audio_file.rb +61 -0
  256. data/lib/multimedia_paradise/toplevel_methods/is_a_multimedia_file.rb +27 -0
  257. data/lib/multimedia_paradise/toplevel_methods/is_audio_file.rb +27 -0
  258. data/lib/multimedia_paradise/toplevel_methods/is_image_file.rb +31 -0
  259. data/lib/multimedia_paradise/toplevel_methods/is_on_roebe.rb +17 -0
  260. data/lib/multimedia_paradise/toplevel_methods/is_video_file.rb +62 -0
  261. data/lib/multimedia_paradise/toplevel_methods/merge_multimedia_file.rb +331 -0
  262. data/lib/multimedia_paradise/toplevel_methods/merge_these_videos.rb +106 -0
  263. data/lib/multimedia_paradise/toplevel_methods/misc.rb +964 -0
  264. data/lib/multimedia_paradise/toplevel_methods/opn.rb +24 -0
  265. data/lib/multimedia_paradise/toplevel_methods/output_directory.rb +61 -0
  266. data/lib/multimedia_paradise/toplevel_methods/player_in_use.rb +80 -0
  267. data/lib/multimedia_paradise/toplevel_methods/query_the_audio_codec_of_this_file.rb +24 -0
  268. data/lib/multimedia_paradise/toplevel_methods/radio.rb +381 -0
  269. data/lib/multimedia_paradise/toplevel_methods/rds.rb +24 -0
  270. data/lib/multimedia_paradise/toplevel_methods/return_all_video_files.rb +64 -0
  271. data/lib/multimedia_paradise/toplevel_methods/return_data_from_video_collection_file_for_this_entry.rb +38 -0
  272. data/lib/multimedia_paradise/toplevel_methods/return_duration_of_this_multimedia_file.rb +27 -0
  273. data/lib/multimedia_paradise/toplevel_methods/return_full_name_for_video_at_this_position.rb +54 -0
  274. data/lib/multimedia_paradise/toplevel_methods/return_path_to_random_simpsons_video_file.rb +43 -0
  275. data/lib/multimedia_paradise/toplevel_methods/return_random_video_file_from_the_video_collection.rb +73 -0
  276. data/lib/multimedia_paradise/toplevel_methods/return_screen_resolution.rb +24 -0
  277. data/lib/multimedia_paradise/toplevel_methods/run_sys_command.rb +30 -0
  278. data/lib/multimedia_paradise/toplevel_methods/scale_video.rb +27 -0
  279. data/lib/multimedia_paradise/toplevel_methods/set_title_of.rb +65 -0
  280. data/lib/multimedia_paradise/toplevel_methods/slow_down_this_video_file.rb +33 -0
  281. data/lib/multimedia_paradise/toplevel_methods/start_screencast.rb +70 -0
  282. data/lib/multimedia_paradise/toplevel_methods/subtitles.rb +59 -0
  283. data/lib/multimedia_paradise/toplevel_methods/to_flac.rb +30 -0
  284. data/lib/multimedia_paradise/toplevel_methods/to_mp4.rb +24 -0
  285. data/lib/multimedia_paradise/toplevel_methods/total_duration.rb +35 -0
  286. data/lib/multimedia_paradise/toplevel_methods/use_lame_codec.rb +32 -0
  287. data/lib/multimedia_paradise/toplevel_methods/video_dataset.rb +76 -0
  288. data/lib/multimedia_paradise/version/version.rb +28 -0
  289. data/lib/multimedia_paradise/video/all_videos.rb +101 -0
  290. data/lib/multimedia_paradise/video/capture_screen.rb +285 -0
  291. data/lib/multimedia_paradise/video/check_numbers.rb +215 -0
  292. data/lib/multimedia_paradise/video/columbo/columbo.rb +139 -0
  293. data/lib/multimedia_paradise/video/copy_missing_video_files.rb +292 -0
  294. data/lib/multimedia_paradise/video/copy_random_video.rb +98 -0
  295. data/lib/multimedia_paradise/video/correct_video_numbers.rb +263 -0
  296. data/lib/multimedia_paradise/video/create_dvd.rb +50 -0
  297. data/lib/multimedia_paradise/video/create_video_thumbnails.rb +137 -0
  298. data/lib/multimedia_paradise/video/encode_video.rb +81 -0
  299. data/lib/multimedia_paradise/video/ffmpeg_options.rb +156 -0
  300. data/lib/multimedia_paradise/video/find_video/find_video.rb +668 -0
  301. data/lib/multimedia_paradise/video/fix_married_with_children_videos.rb +70 -0
  302. data/lib/multimedia_paradise/video/genres.rb +333 -0
  303. data/lib/multimedia_paradise/video/guess_video_name.rb +189 -0
  304. data/lib/multimedia_paradise/video/imdb_rating/imdb_rating.rb +133 -0
  305. data/lib/multimedia_paradise/video/mike_hammer/mike_hammer.rb +74 -0
  306. data/lib/multimedia_paradise/video/missing_video_files/missing_video_files.rb +286 -0
  307. data/lib/multimedia_paradise/video/movie_searcher.rb +281 -0
  308. data/lib/multimedia_paradise/video/mplayer_wrapper.rb +504 -0
  309. data/lib/multimedia_paradise/video/n_videos.rb +142 -0
  310. data/lib/multimedia_paradise/video/play_random_file.rb +91 -0
  311. data/lib/multimedia_paradise/video/play_random_realvideo.rb +92 -0
  312. data/lib/multimedia_paradise/video/prepare_video_lecture.rb +267 -0
  313. data/lib/multimedia_paradise/video/random_video.rb +302 -0
  314. data/lib/multimedia_paradise/video/registered_video_file.rb +131 -0
  315. data/lib/multimedia_paradise/video/remove_metadata.rb +52 -0
  316. data/lib/multimedia_paradise/video/rename_video_file.rb +149 -0
  317. data/lib/multimedia_paradise/video/report_local_videos.rb +106 -0
  318. data/lib/multimedia_paradise/video/report_missing_videos_in_the_yaml_file.rb +107 -0
  319. data/lib/multimedia_paradise/video/resolution.rb +194 -0
  320. data/lib/multimedia_paradise/video/reverse_video.rb +74 -0
  321. data/lib/multimedia_paradise/video/simpsons.rb +129 -0
  322. data/lib/multimedia_paradise/video/smart_animals/smart_animals.rb +188 -0
  323. data/lib/multimedia_paradise/video/speed_up_video.rb +135 -0
  324. data/lib/multimedia_paradise/video/split_this_video.rb +126 -0
  325. data/lib/multimedia_paradise/video/srt_regex.rb +211 -0
  326. data/lib/multimedia_paradise/video/store_available_video_files.rb +138 -0
  327. data/lib/multimedia_paradise/video/the_simpsons/README.md +9 -0
  328. data/lib/multimedia_paradise/video/the_simpsons/good_the_simpsons_episodes.rb +107 -0
  329. data/lib/multimedia_paradise/video/the_simpsons/the_simpsons.rb +87 -0
  330. data/lib/multimedia_paradise/video/video.rb +14 -0
  331. data/lib/multimedia_paradise/video/video_encoding_settings.rb +57 -0
  332. data/lib/multimedia_paradise/video/video_information.rb +445 -0
  333. data/lib/multimedia_paradise/video/video_metadata.rb +132 -0
  334. data/lib/multimedia_paradise/video/video_player.rb +580 -0
  335. data/lib/multimedia_paradise/video/video_renamer.rb +161 -0
  336. data/lib/multimedia_paradise/video/watermark.rb +282 -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/yaml/audio_formats.yml +14 -0
  340. data/lib/multimedia_paradise/yaml/best_songs_in_an_era/eurodance/top20.yml +28 -0
  341. data/lib/multimedia_paradise/yaml/game_shows/ruck_zuck/ruck_zuck.yml +25 -0
  342. data/lib/multimedia_paradise/yaml/genres/1980s.yml +198 -0
  343. data/lib/multimedia_paradise/yaml/genres/README.md +5 -0
  344. data/lib/multimedia_paradise/yaml/genres/boogie.yml +68 -0
  345. data/lib/multimedia_paradise/yaml/genres/concerts.yml +29 -0
  346. data/lib/multimedia_paradise/yaml/genres/eurodance.yml +456 -0
  347. data/lib/multimedia_paradise/yaml/genres/hip_hop.yml +49 -0
  348. data/lib/multimedia_paradise/yaml/genres/italian_songs.yml +53 -0
  349. data/lib/multimedia_paradise/yaml/genres/trance.yml +167 -0
  350. data/lib/multimedia_paradise/yaml/good_horror_movies/good_horror_movies.yml +12 -0
  351. data/lib/multimedia_paradise/yaml/good_movie_actors/good_movie_actors.yml +6 -0
  352. data/lib/multimedia_paradise/yaml/image_formats.yml +8 -0
  353. data/lib/multimedia_paradise/yaml/internal/README.md +2 -0
  354. data/lib/multimedia_paradise/yaml/internal/installed_binaries.yml +31 -0
  355. data/lib/multimedia_paradise/yaml/lyrics.yml +6323 -0
  356. data/lib/multimedia_paradise/yaml/movie_reviews/the_hateful_eight_september_2016.md +305 -0
  357. data/lib/multimedia_paradise/yaml/music_genres.yml +51 -0
  358. data/lib/multimedia_paradise/yaml/playlist.yml +130 -0
  359. data/lib/multimedia_paradise/yaml/radio/README.md +5 -0
  360. data/lib/multimedia_paradise/yaml/radio/radio_stations.yml +359 -0
  361. data/lib/multimedia_paradise/yaml/song_tags.yml +818 -0
  362. data/lib/multimedia_paradise/yaml/tales_from_the_crypt/tales_from_the_crypt.yml +426 -0
  363. data/lib/multimedia_paradise/yaml/tom_and_jerry/README.md +2 -0
  364. data/lib/multimedia_paradise/yaml/tom_and_jerry/tom_and_jerry_episodes.yml +27 -0
  365. data/lib/multimedia_paradise/yaml/tv_channels/tv_channels.yml +46 -0
  366. data/lib/multimedia_paradise/yaml/use_this_video_player.yml +1 -0
  367. data/lib/multimedia_paradise/yaml/video/video.yml +26 -0
  368. data/lib/multimedia_paradise/yaml/video_collection/video_collection.yml +1933 -0
  369. data/lib/multimedia_paradise/yaml/video_encoding_settings.yml +62 -0
  370. data/lib/multimedia_paradise/yaml/video_filter_aliases.yml +221 -0
  371. data/lib/multimedia_paradise/yaml/youtube/alltagsgeschichte/alltagsgeschichte.yml +190 -0
  372. data/lib/multimedia_paradise/yaml/youtube/songs/README.md +3 -0
  373. data/lib/multimedia_paradise/yaml/youtube/songs/songs.yml +6 -0
  374. data/lib/multimedia_paradise/yaml/youtube_playlist/youtube_playlist.yml +6 -0
  375. data/lib/multimedia_paradise.rb +5 -0
  376. data/multimedia_paradise.gemspec +74 -0
  377. data/test/testing_audio_player.rb +15 -0
  378. data/test/testing_ffmpeg_options.rb +14 -0
  379. data/test/testing_file_duration.rb +17 -0
  380. data/test/testing_modify_year_of_audio_file.rb +14 -0
  381. data/test/testing_multimedia_paradise_project.rb +151 -0
  382. metadata +560 -0
@@ -0,0 +1,2021 @@
1
+ #!/usr/bin/ruby -w
2
+ # Encoding: UTF-8
3
+ # frozen_string_literal: true
4
+ # =========================================================================== #
5
+ # === MultimediaParadise::CutMultimedia
6
+ #
7
+ # This class can be used to cut audio and video files, and merge the
8
+ # newly created files together.
9
+ #
10
+ # This is mostly a standalone class and thus you can require it in a
11
+ # special way:
12
+ #
13
+ # require 'multimedia_paradise/toplevel_cut_multimedia'
14
+ #
15
+ # Note that this class can operate in two ways:
16
+ #
17
+ # - from the commandline, without interactive questions
18
+ # - in an interactive manner, with the user typing in
19
+ # instructions that will be evaluated (thus the REPL
20
+ # mode)
21
+ #
22
+ # See to the end of this file for specific usage examples.
23
+ #
24
+ # Usage examples in Ruby Code:
25
+ #
26
+ # MultimediaParadise::CutMultimedia.new
27
+ # MultimediaParadise::CutMultimedia.new(ARGV)
28
+ # MultimediaParadise::CutMultimedia.new("foo.mp3")
29
+ # cut_multimedia = MultimediaParadise::CutMultimedia.new("foo.mp3", :do_not_run_yet)
30
+ #
31
+ # =========================================================================== #
32
+ # require 'multimedia_paradise/multimedia/cut_multimedia/cut_multimedia.rb'
33
+ # MultimediaParadise::CutMultimedia.new(ARGV) { :gui }
34
+ # =========================================================================== #
35
+ require 'multimedia_paradise/multimedia/base.rb'
36
+ require 'multimedia_paradise/multimedia/cut_multimedia/interactive_menu.rb'
37
+
38
+ module MultimediaParadise
39
+
40
+ class CutMultimedia < ::MultimediaParadise::MultimediaBase # === MultimediaParadise::CutMultimedia
41
+
42
+ begin
43
+ require 'hours_to_seconds/hours_to_seconds.rb'
44
+ rescue LoadError; end
45
+
46
+ begin # Try to use the KdeKonsole if it is available.
47
+ require 'roebe/requires/require_kde_konsole.rb'
48
+ rescue LoadError; end
49
+
50
+ require 'multimedia_paradise/toplevel_methods/chop_into_segments_of_n_seconds_size.rb'
51
+ require 'multimedia_paradise/audio/file_duration/file_duration.rb'
52
+
53
+ # ========================================================================= #
54
+ # === NAMESPACE
55
+ # ========================================================================= #
56
+ NAMESPACE = inspect
57
+
58
+ # ========================================================================= #
59
+ # === Determine whether Readline is available or whether it is not
60
+ #
61
+ # If readline is available then we will try to use it.
62
+ # ========================================================================= #
63
+ begin
64
+ require 'readline'
65
+ IS_READLINE_AVAILABLE = true
66
+ rescue LoadError
67
+ IS_READLINE_AVAILABLE = false
68
+ end
69
+
70
+ # ========================================================================= #
71
+ # === DEFAULT_INPUT_FILE
72
+ # ========================================================================= #
73
+ DEFAULT_INPUT_FILE =
74
+ '/home/x/songs/Womack_and_Womack_Teardrops.mp3'
75
+
76
+ # ========================================================================= #
77
+ # === FILE_LAST_USED
78
+ # ========================================================================= #
79
+ FILE_LAST_USED =
80
+ "#{MultimediaParadise.log_dir?}cut_audio_last_file_used.yml"
81
+
82
+ # ========================================================================= #
83
+ # === CREATE_A_LOG_FILE
84
+ #
85
+ # If this constant is true then we will create a log file.
86
+ # ========================================================================= #
87
+ CREATE_A_LOG_FILE = false
88
+
89
+ # ========================================================================= #
90
+ # === PROMPT_TO_USE
91
+ # ========================================================================= #
92
+ PROMPT_TO_USE = '> '
93
+
94
+ require 'multimedia_paradise/toplevel_methods/player_in_use.rb'
95
+ # ========================================================================= #
96
+ # === USE_THIS_PLAYER
97
+ #
98
+ # Which audio/video player to use for audio-playback.
99
+ #
100
+ # By default we will use the player set on the toplevel MultimediaParadise
101
+ # namespace.
102
+ #
103
+ # This constant will then return e. g. a String such as "mpv".
104
+ # ========================================================================= #
105
+ USE_THIS_PLAYER = MultimediaParadise.player?
106
+
107
+ # ========================================================================= #
108
+ # === ARRAY_LOCATIONS_TO_CHECK_FOR_FFMPEG
109
+ #
110
+ # The following constant defines where to check for ffmpeg.
111
+ #
112
+ # This may be necessary so that we can determine whether the user
113
+ # has ffmpg installed.
114
+ # ========================================================================= #
115
+ array = %w(
116
+ /usr/bin/
117
+ c:\usr\bin
118
+ ) # Build-up our Array here.
119
+ array << '/usr/local/bin/'
120
+ array << ENV['MY_SYSBIN'].to_s+'/' if ENV['MY_SYSBIN']
121
+ # ========================================================================= #
122
+ # Append the locations found in the PATH variable next.
123
+ # ========================================================================= #
124
+ if ENV['PATH']
125
+ array << ENV['PATH'].to_s.split(':') # Also add the PATH variable.
126
+ end
127
+ ARRAY_LOCATIONS_TO_CHECK_FOR_FFMPEG = array.flatten.uniq # Set it here.
128
+
129
+ # ========================================================================= #
130
+ # === initialize
131
+ #
132
+ # The very first argument to this class should be location to the
133
+ # file that you may want to edit.
134
+ # ========================================================================= #
135
+ def initialize(
136
+ commandline_arguments = nil,
137
+ run_already = true
138
+ )
139
+ register_sigint
140
+ reset
141
+ # ======================================================================= #
142
+ # First handle special Symbols given to this class.
143
+ # ======================================================================= #
144
+ case commandline_arguments
145
+ when :interactive,
146
+ :run_interactive
147
+ set_interactive_mode_then_enter_interactive_mode
148
+ end
149
+ if commandline_arguments and commandline_arguments.is_a?(Array) and
150
+ commandline_arguments.empty?
151
+ commandline_arguments << DEFAULT_INPUT_FILE
152
+ end
153
+ set_commandline_arguments(
154
+ commandline_arguments
155
+ )
156
+ # ======================================================================= #
157
+ # === Handle blocks next
158
+ # ======================================================================= #
159
+ if block_given?
160
+ yielded = yield
161
+ case yielded
162
+ # ===================================================================== #
163
+ # === :gui
164
+ # ===================================================================== #
165
+ when :gui
166
+ @usage_mode = :gui
167
+ end
168
+ end
169
+ # ======================================================================= #
170
+ # Next check whether a file exists, before we enter the interactive
171
+ # part potentially.
172
+ # ======================================================================= #
173
+ check_whether_the_commandline_arguments_contain_a_file_and_assign_this_as_the_main_file
174
+ # ======================================================================= #
175
+ # The following check must happen before we invoke set_file()
176
+ # because set_file may also exit the program. This is not
177
+ # deserved when we run the program in interactive mode.
178
+ # ======================================================================= #
179
+ case run_already
180
+ # ======================================================================= #
181
+ # === :dont_run_yet
182
+ # ======================================================================= #
183
+ when :dont_run_yet,
184
+ :do_not_run_yet
185
+ run_already = false
186
+ # ======================================================================= #
187
+ # === :interactive
188
+ # ======================================================================= #
189
+ when :interactive,
190
+ :run_interactive
191
+ set_interactive_mode_then_enter_interactive_mode
192
+ run_already = false
193
+ end
194
+ run if run_already
195
+ end
196
+
197
+ # ========================================================================= #
198
+ # === reset (reset tag)
199
+ # ========================================================================= #
200
+ def reset
201
+ super()
202
+ # ======================================================================= #
203
+ # === @namespace
204
+ # ======================================================================= #
205
+ @namespace = NAMESPACE
206
+ # ======================================================================= #
207
+ # === @toggle
208
+ # ======================================================================= #
209
+ @toggle = false
210
+ # ======================================================================= #
211
+ # === @user_input
212
+ #
213
+ # Set the user input nil on startup.
214
+ # ======================================================================= #
215
+ @user_input = nil
216
+ # ======================================================================= #
217
+ # === @array_input_history
218
+ #
219
+ # Keep the input-history stored in the following Array.
220
+ # ======================================================================= #
221
+ @array_input_history = []
222
+ # ======================================================================= #
223
+ # === @we_are_allowed_to_run_system_command
224
+ # ======================================================================= #
225
+ @we_are_allowed_to_run_system_command = true
226
+ # ======================================================================= #
227
+ # === @work_on_this_file
228
+ #
229
+ # This variable will keep track on which file (audio or video) we
230
+ # will work on for the running instance. It will, once set,
231
+ # contain the path (a String) to the local file.
232
+ # ======================================================================= #
233
+ @work_on_this_file = nil
234
+ # ======================================================================= #
235
+ # === @output_file
236
+ #
237
+ # We keep track of the output file, so that any possible GUI we may
238
+ # use also benefits from this.
239
+ # ======================================================================= #
240
+ @output_file = nil
241
+ # ======================================================================= #
242
+ # === @may_we_exit
243
+ # ======================================================================= #
244
+ @may_we_exit = false
245
+ # ======================================================================= #
246
+ # === @array_all_start_positions
247
+ # ======================================================================= #
248
+ @array_all_start_positions = []
249
+ # ======================================================================= #
250
+ # === @create_a_log_file
251
+ #
252
+ # Next determine whether we will create a log file or whether we
253
+ # will not.
254
+ # ======================================================================= #
255
+ @create_a_log_file = CREATE_A_LOG_FILE
256
+ # ======================================================================= #
257
+ # === @t
258
+ # ======================================================================= #
259
+ @t = nil
260
+ # ======================================================================= #
261
+ # === @usage_mode
262
+ #
263
+ # This variable can have the following modes:
264
+ #
265
+ # :interactive
266
+ # :gui
267
+ #
268
+ # ======================================================================= #
269
+ @usage_mode = :interactive
270
+ # ======================================================================= #
271
+ # Re-set the two main Arrays that keep track of start and end positions
272
+ # on the assigned main file.
273
+ # ======================================================================= #
274
+ clear_setpoints
275
+ initialize_twentyfour_hours_notation_object
276
+ end
277
+
278
+ # ========================================================================= #
279
+ # === in_commandline_mode?
280
+ # ========================================================================= #
281
+ def in_commandline_mode?
282
+ @usage_mode == :interactive
283
+ end
284
+
285
+ # ========================================================================= #
286
+ # === start_position?
287
+ #
288
+ # This method depends on the method called array_all_start_positions?.
289
+ # ========================================================================= #
290
+ def start_position?
291
+ start_positions?.first # For now, always use the first entry.
292
+ end; alias start_position start_position? # === start_position
293
+ alias starting_position? start_position? # === starting_position?
294
+
295
+ # ========================================================================= #
296
+ # === modify_the_main_file_by_prepending_the_upcased_string_done_to_it
297
+ #
298
+ # The point of this method is to mark an audio file as "done".
299
+ # ========================================================================= #
300
+ def modify_the_main_file_by_prepending_the_upcased_string_done_to_it(
301
+ from = @work_on_this_file,
302
+ to = "DONE_#{@work_on_this_file}"
303
+ )
304
+ if from.include? '/'
305
+ # ===================================================================== #
306
+ # In this case, the above won't work, so we must use another approach.
307
+ # ===================================================================== #
308
+ splitted = from.split('/')
309
+ splitted.last.prepend('DONE_')
310
+ to = splitted.join('/')
311
+ end
312
+ opne "Now renaming #{sfile(from)} to #{sfile(to)}."
313
+ File.rename(from, to)
314
+ set_work_on_this_file(to)
315
+ end
316
+
317
+ # ========================================================================= #
318
+ # === start_position=
319
+ # ========================================================================= #
320
+ def start_position=(i) # This will always set to the first entry point of our array.
321
+ all_start_positions?[0,0] = i.to_i
322
+ end
323
+
324
+ # ========================================================================= #
325
+ # === emphasis
326
+ #
327
+ # Internal emphasis.
328
+ # ========================================================================= #
329
+ def emphasis(i)
330
+ orange(i)
331
+ end
332
+
333
+ # ========================================================================= #
334
+ # === ensure_that_array_cut_end_is_valid
335
+ #
336
+ # The end positions should always be valid.
337
+ # ========================================================================= #
338
+ def ensure_that_array_cut_end_is_valid(i = duration?)
339
+ if end_positions?.empty? # We must ensure that it has the length.
340
+ set_length(i)
341
+ end
342
+ end
343
+
344
+ # ========================================================================= #
345
+ # === array_all_end_positions?
346
+ # ========================================================================= #
347
+ def array_all_end_positions?
348
+ @array_all_end_positions
349
+ end; alias end_positions? array_all_end_positions? # === end_positions?
350
+ alias end_position? array_all_end_positions? # === end_positions?
351
+ alias all_end_positions? array_all_end_positions? # === all_end_positions?
352
+
353
+ # ========================================================================= #
354
+ # === feedback_all_end_points
355
+ # ========================================================================= #
356
+ def feedback_all_end_points(
357
+ i = all_end_positions?
358
+ )
359
+ e "#{rev}Feedbacking all #{emphasis('end-points')} #{rev}next."
360
+ pp i
361
+ end
362
+
363
+ # ========================================================================= #
364
+ # === sanitize
365
+ #
366
+ # This method will sanitize the input that represents time. We want
367
+ # a number to mean "n seconds".
368
+ # ========================================================================= #
369
+ def sanitize(i)
370
+ # ======================================================================= #
371
+ # Simply replace all ',' with '.', in the event the user typed these.
372
+ # ======================================================================= #
373
+ i.tr!(',','.') if i.include? ','
374
+ # ======================================================================= #
375
+ # Since as of Dec 2015 we will also check for the input containing
376
+ # ':' tokens. If so then we assume that the user wants to use
377
+ # the 24 hours notation such as 05:30, which would mean 5 minutes
378
+ # and 30 seconds.
379
+ # ======================================================================= #
380
+ if i.include? ':'
381
+ i[0,1] = '' if i.start_with? 'e' # Chop off leading 'e' parts.
382
+ # ===================================================================== #
383
+ # The following code will also work for .mp3 files that are longer
384
+ # than 59:59 seconds.
385
+ # ===================================================================== #
386
+ splitted = i.split(':') # Split on all ':'
387
+ if splitted.size < 3
388
+ # =================================================================== #
389
+ # Prepend 00 in this case.
390
+ # =================================================================== #
391
+ splitted[0,0] = '00'
392
+ end
393
+ i = splitted.join(':')
394
+ # ===================================================================== #
395
+ # Next, convert it into the amount o seconds.
396
+ # ===================================================================== #
397
+ i = HoursToSeconds[i, :be_quiet]
398
+ end
399
+ return i.to_s # This must always return a String.
400
+ end
401
+
402
+ # ========================================================================= #
403
+ # === display_the_prompt_in_use_to_the_user
404
+ # ========================================================================= #
405
+ def display_the_prompt_in_use_to_the_user
406
+ print PROMPT_TO_USE
407
+ end
408
+
409
+ # ========================================================================= #
410
+ # === obtain_user_input
411
+ #
412
+ # This method will designate @user_input - in other words it will obtain
413
+ # the user input.
414
+ # ========================================================================= #
415
+ def obtain_user_input
416
+ if use_readline?
417
+ @user_input = Readline.readline('', true)
418
+ else
419
+ @user_input = $stdin.gets.chomp
420
+ end
421
+ end
422
+
423
+ # ========================================================================= #
424
+ # === determine_the_duration
425
+ #
426
+ # Set @duration here.
427
+ # ========================================================================= #
428
+ def determine_the_duration(
429
+ i = main_file?
430
+ ) # This will determine the ivar @duration.
431
+ @duration = MultimediaParadise::FileDuration.new(i) { :be_quiet } # Also get the duration of the file here.
432
+ return @duration.duration? # This should return the duration in question, as a Float.
433
+ end; alias determine_duration determine_the_duration # === determine_duration
434
+
435
+ # ========================================================================= #
436
+ # === overwrite_old_file
437
+ #
438
+ # Note that when we overwrite the old file, we must re-assign the
439
+ # main file to that file again.
440
+ # ========================================================================= #
441
+ def overwrite_old_file(
442
+ optional_argument_be_verbose = false
443
+ )
444
+ old_file = output_file?
445
+ case optional_argument_be_verbose
446
+ when :be_verbose
447
+ optional_argument_be_verbose = true
448
+ end
449
+ if optional_argument_be_verbose
450
+ e "#{rev}Now overwriting the file `#{sfile(old_file)}`."
451
+ end
452
+ new_file = input_file?
453
+ mv(old_file, new_file)
454
+ assign_file(new_file) # Assign the new file again here.
455
+ end
456
+
457
+ # ========================================================================= #
458
+ # === editor?
459
+ # ========================================================================= #
460
+ def editor?
461
+ ::MultimediaParadise::YOUR_EDITOR
462
+ end
463
+
464
+ # ========================================================================= #
465
+ # === report_half_the_duration
466
+ # ========================================================================= #
467
+ def report_half_the_duration
468
+ e rev+'Half the duration, in seconds, is:'
469
+ e
470
+ e simp(' '+(duration?/2.0).to_s)
471
+ e
472
+ end
473
+
474
+ # ========================================================================= #
475
+ # === end?
476
+ #
477
+ # Only return the very last entry here, from all stored end positions.
478
+ # ========================================================================= #
479
+ def end?
480
+ all_end_positions?.last
481
+ end
482
+
483
+ # ========================================================================= #
484
+ # === start_point_was_defined_yet?
485
+ # ========================================================================= #
486
+ def start_point_was_defined_yet?
487
+ !all_start_positions?.empty?
488
+ end
489
+
490
+ # ========================================================================= #
491
+ # === no_start_point_was_defined_yet?
492
+ # ========================================================================= #
493
+ def no_start_point_was_defined_yet?
494
+ all_start_positions?.empty?
495
+ end
496
+
497
+ # ========================================================================= #
498
+ # === end_point_was_defined_yet?
499
+ # ========================================================================= #
500
+ def end_point_was_defined_yet?
501
+ !all_end_positions?.empty?
502
+ end
503
+
504
+ # ========================================================================= #
505
+ # === no_end_point_was_defined_yet?
506
+ # ========================================================================= #
507
+ def no_end_point_was_defined_yet?
508
+ !end_point_was_defined_yet?
509
+ end
510
+
511
+ # ========================================================================= #
512
+ # === user_did_input_only_numbers
513
+ #
514
+ # Simplified start an end point notation.
515
+ # ========================================================================= #
516
+ def user_did_input_only_numbers(i)
517
+ @toggle = !@toggle # Toggle it here.
518
+ case @toggle
519
+ when true
520
+ set_start(i)
521
+ when false
522
+ set_end(i)
523
+ end
524
+ end
525
+
526
+ # ========================================================================= #
527
+ # === show_output_files
528
+ # ========================================================================= #
529
+ def show_output_files(
530
+ i = @array_output_files
531
+ )
532
+ unless i.empty?
533
+ e N+'We created these output files:'
534
+ e
535
+ end
536
+ i.each_with_index {|entry, index|
537
+ entry = entry.to_s
538
+ index += 1
539
+ index = ('('+index.to_s + ')').rjust(4)
540
+ if entry.start_with? '"' and entry.end_with? '"'
541
+ entry = entry[1..-2]
542
+ end
543
+ e ' '+index+' '+sfancy(entry)
544
+ }; e
545
+ end
546
+
547
+ # ========================================================================= #
548
+ # === set_start_and_end_position
549
+ #
550
+ # This variant combines set_start() with set_end().
551
+ # ========================================================================= #
552
+ def set_start_and_end_position(i)
553
+ splitted = i.split('-')
554
+ set_start(splitted.first)
555
+ set_end(splitted[1])
556
+ end
557
+
558
+ # ========================================================================= #
559
+ # === play_the_audio_file
560
+ # ========================================================================= #
561
+ def play_the_audio_file(i = file?)
562
+ if i
563
+ e "#{Colours.rev}Now playing the assigned "\
564
+ "file `#{sfile(i.to_s)}`."
565
+ esystem("#{MultimediaParadise.player?} #{i}")
566
+ else
567
+ e 'No file was found.'
568
+ end
569
+ end
570
+
571
+ # ========================================================================= #
572
+ # === feedback_start_cutting_at
573
+ # ========================================================================= #
574
+ def feedback_start_cutting_at
575
+ here = all_start_positions?
576
+ if here.empty?
577
+ e 'No start positions have been determined yet.'
578
+ else
579
+ e 'We will start cutting at '+
580
+ simp(here.first.to_s)+' seconds.'
581
+ end
582
+ end
583
+
584
+ # ========================================================================= #
585
+ # === register_sigint
586
+ # ========================================================================= #
587
+ def register_sigint
588
+ Signal.trap('SIGINT') {
589
+ exit_properly
590
+ }
591
+ end
592
+
593
+ # ========================================================================= #
594
+ # === do_general_exit_actions (exit tag)
595
+ # ========================================================================= #
596
+ def do_general_exit_actions
597
+ try_to_rename_kde_konsole_tab('_')
598
+ :exit
599
+ end
600
+
601
+ # ========================================================================= #
602
+ # === green_colour
603
+ # ========================================================================= #
604
+ def green_colour
605
+ if use_colours?
606
+ ::Colours::CGREEN
607
+ else
608
+ ''.dup
609
+ end
610
+ end
611
+
612
+ # ========================================================================= #
613
+ # === try_to_use_the_last_file
614
+ #
615
+ # This method can be used to re-use the last used file from a prior
616
+ # run.
617
+ # ========================================================================= #
618
+ def try_to_use_the_last_file(
619
+ i = FILE_LAST_USED
620
+ )
621
+ if File.exist? i
622
+ set_file(
623
+ YAML.load_file(i).strip,
624
+ :do_not_keep_track # <- So to not save into a local .yml file.
625
+ )
626
+ else
627
+ opnn; no_file_exists_at(i)
628
+ end
629
+ end
630
+
631
+ # ========================================================================= #
632
+ # === report_duration_of_multimedia_file
633
+ #
634
+ # This method will report the duration of the multimedia file.
635
+ #
636
+ # There exists an optional argument called `this_file`. If this argument
637
+ # is used, then we will report the duration of that file instead.
638
+ #
639
+ # feedback_duration is an alias to this method.
640
+ # ========================================================================= #
641
+ def report_duration_of_multimedia_file(
642
+ this_file = nil
643
+ )
644
+ use_this_file = file? # Default assignment.
645
+ use_this_file = this_file if this_file
646
+ duration = duration?
647
+ if use_this_file and File.exist?(use_this_file.to_s) # Handle alternative duration.
648
+ duration = determine_duration(use_this_file) # Calculate the new duration of that file.
649
+ if duration
650
+ long_form = '('+Time.at(duration).utc.strftime('%H:%M:%S').to_s+')'
651
+ e
652
+ e "#{rev}The duration of the file #{sfile(use_this_file)} #{rev}is: "
653
+ e
654
+ e simp(" #{duration} seconds #{long_form}")
655
+ e
656
+ end
657
+ else
658
+ report_no_file_is_assigned
659
+ end
660
+ end; alias feedback_duration report_duration_of_multimedia_file # === feedback_duration
661
+ alias report_duration_of_this_file report_duration_of_multimedia_file # === report_duration_of_this_file
662
+ alias report_length report_duration_of_multimedia_file # === report_length
663
+
664
+ # ========================================================================= #
665
+ # === show_history
666
+ #
667
+ # This method will show the input-history used for CutMultimedia.
668
+ # ========================================================================= #
669
+ def show_history(
670
+ i = @array_input_history
671
+ )
672
+ e; i.each_with_index {|command, index|
673
+ index += 1
674
+ e index.to_s.rjust(3)+' '+sfancy(command)
675
+ }; e
676
+ end
677
+
678
+ # ========================================================================= #
679
+ # === intersect
680
+ #
681
+ # This method will cut out some middle/central part from a .mp3 file.
682
+ #
683
+ # Usage example:
684
+ #
685
+ # intersect 29:23-29:45
686
+ # intersect 11:20-15:45
687
+ #
688
+ # ========================================================================= #
689
+ def intersect(i)
690
+ i = i.first if i.is_a? Array
691
+ unless main_file?
692
+ opne 'Please assign a valid, existing file.'
693
+ return
694
+ end
695
+ if i.include? '-' # Ok, then we can split there.
696
+ splitted = i.split '-'
697
+ first, last = *splitted
698
+ # ===================================================================== #
699
+ # Next, we must convert these numbers into seconds, if it includes
700
+ # at least one ':' character.
701
+ # ===================================================================== #
702
+ if first.include? ':'
703
+ first.prepend '00:' if first.count(':') == 1
704
+ first = HoursToSeconds[first, :be_silent].to_s
705
+ last.prepend '00:' if last.count(':') == 1
706
+ last = HoursToSeconds[last, :be_silent].to_s
707
+ end
708
+ # ===================================================================== #
709
+ # === Operate on the leading segment first:
710
+ # ===================================================================== #
711
+ e '(1) We will next chop out the leading segment:'
712
+ clear_setpoints
713
+ set_start(0)
714
+ set_end(first)
715
+ do_cut
716
+ clear_setpoints
717
+ # ===================================================================== #
718
+ # === Operater on the trailing segment next:
719
+ # ===================================================================== #
720
+ e '(2) We will next chop out the trailing segment:'
721
+ set_start(last)
722
+ set_end(return_end_of_file_in_seconds)
723
+ do_cut
724
+ clear_setpoints
725
+ end
726
+ store_here = "MERGED_FILES_#{input_file?}" # Where to store the merged files.
727
+ merge(
728
+ output_files?, store_here
729
+ )
730
+ if File.exist? store_here
731
+ opne "The file should now exist at #{sfile(store_here)}."
732
+ remove(output_files?)
733
+ end
734
+ end
735
+
736
+ # ========================================================================= #
737
+ # === report_that_we_are_finished_now
738
+ #
739
+ # This method will notify the user that we have finished cutting our
740
+ # audio files.
741
+ # ========================================================================= #
742
+ def report_that_we_are_finished_now(
743
+ shall_we_report_errors = true
744
+ )
745
+ case shall_we_report_errors
746
+ when :no_error_reporting
747
+ shall_we_report_errors = false
748
+ end
749
+ e "#{rev}We have finished cutting our audio files now."
750
+ e
751
+ _ = output_file?
752
+ if _.nil?
753
+ e 'No output file was assigned.'
754
+ return
755
+ end
756
+ if _.include?(' ') # Handle ' ' characters.
757
+ if _.start_with? '"' and _.end_with? '"'
758
+ _ = _[1..-2]
759
+ end
760
+ end
761
+ if File.exist?(_) and !File.zero?(_)
762
+ output_files = [output_files?].flatten.compact
763
+ if output_files.size > 1
764
+ e 'The output files should now be available at:'
765
+ output_files.each {|file|
766
+ e " #{sfile(file)}"
767
+ }
768
+ e 'If you want to merge these above-listed files together, '\
769
+ 'input "merge".'
770
+ else # Else just one file.
771
+ # =================================================================== #
772
+ # Report the duration of that new file.
773
+ # =================================================================== #
774
+ report_duration_of_this_file(_)
775
+ e "#{rev}The output file should now be available at:"
776
+ e
777
+ e " #{sfile(_)}"
778
+ e
779
+ end
780
+ else
781
+ if shall_we_report_errors
782
+ e 'It seems as if something has failed. Please check the '\
783
+ 'above output from ffmpeg,'
784
+ e 'it may be that ffmpeg faced a problem such as missing '\
785
+ '.mp3 support.'
786
+ end
787
+ end
788
+ end
789
+
790
+ # ========================================================================= #
791
+ # === report_points
792
+ #
793
+ # This method can be used to report all start and end positions.
794
+ # ========================================================================= #
795
+ def report_points
796
+ unless all_start_positions?.empty?
797
+ e simp('Startpoints')+' for cutting:'
798
+ print ' '; pp all_start_positions?
799
+ end
800
+ unless all_end_positions?.empty?
801
+ e simp('Endpoints')+' for cutting:'
802
+ print ' '; pp all_end_positions?
803
+ end
804
+ # ======================================================================= #
805
+ # Next check whether both are empty.
806
+ # ======================================================================= #
807
+ if all_end_positions?.empty? and
808
+ all_start_positions?.empty?
809
+ e 'It seems as if you have not yet determined any boundaries '\
810
+ 'as to where to cut at, yet.'
811
+ end
812
+ end
813
+
814
+ # ========================================================================= #
815
+ # === feedback_cutting
816
+ # ========================================================================= #
817
+ def feedback_cutting # the verbose variant.
818
+ e 'We will cut the file '+sfile(work_on_which_file?)+'.'
819
+ start_cutting_when = 'We will start cutting at '+
820
+ sfancy(all_start_positions?.first.to_s)+' seconds.'
821
+ if all_start_positions?.size > 1
822
+ start_cutting_when << ' Additionally we found entries at '+
823
+ sfancy(all_start_positions?[1..-1].join(', '))+'.'
824
+ end
825
+ e start_cutting_when
826
+ if !all_end_positions?.empty?
827
+ end_cutting_when = 'We will end the cutting at '+
828
+ sfancy(all_end_positions?.first.to_s)+
829
+ ' seconds. '
830
+ if all_end_positions?.size > 1
831
+ end_cutting_when << ' Additionally we found entries at '+
832
+ sfancy(all_end_positions?[1..-1].join(', '))+'.'
833
+ end
834
+ e end_cutting_when
835
+ else
836
+ e 'We have not yet defined an end position for our file.'
837
+ e 'You can do this with the command '+sfancy('cut_end')+'.'
838
+ end
839
+ duration = all_end_positions?.first.to_i - all_start_positions?.first.to_i
840
+ e "#{rev}The duration of our new file will be "\
841
+ "#{sfancy(duration.to_s)} seconds." if duration?
842
+ end; private :feedback_cutting
843
+
844
+ # ========================================================================= #
845
+ # === show_invocation_usage
846
+ # ========================================================================= #
847
+ def show_invocation_usage
848
+ if in_commandline_mode?
849
+ cliner
850
+ e 'Usage from the commandline:'
851
+ e
852
+ e ' cut_multimedia name_of_audio_file_goes_here'
853
+ e ' cut_multimedia name_of_video_file_goes_here'
854
+ e
855
+ cliner
856
+ end
857
+ end
858
+
859
+ # ========================================================================= #
860
+ # === append_the_user_input_onto_the_history
861
+ # ========================================================================= #
862
+ def append_the_user_input_onto_the_history(
863
+ i = @user_input
864
+ )
865
+ # ======================================================================= #
866
+ # Keep track of the input-history next.
867
+ # ======================================================================= #
868
+ @array_input_history << i if i
869
+ end
870
+
871
+ # ========================================================================= #
872
+ # === report_which_player_we_will_use
873
+ # ========================================================================= #
874
+ def report_which_player_we_will_use
875
+ e "#{rev}We will use `#{sfancy(MultimediaParadise.player?)}` "\
876
+ "to play multimedia files."
877
+ end
878
+
879
+ # ========================================================================= #
880
+ # === report_no_file_is_assigned
881
+ # ========================================================================= #
882
+ def report_no_file_is_assigned
883
+ opne 'No file is assigned.'
884
+ end
885
+
886
+ # ========================================================================= #
887
+ # === report_does_the_main_file_exist?
888
+ #
889
+ # Notify us whether the main file exists or whether it does not.
890
+ # ========================================================================= #
891
+ def report_does_the_main_file_exist?
892
+ e 'Does the main file exist? '+sfancy(
893
+ verbose_truth(File.exist?(main_file?.to_s).to_s)
894
+ )
895
+ end
896
+
897
+ # ========================================================================= #
898
+ # === create_a_log_file?
899
+ # ========================================================================= #
900
+ def create_a_log_file?
901
+ @create_a_log_file
902
+ end; alias create_log_file? create_a_log_file? # === create_log_file?
903
+
904
+ # ========================================================================= #
905
+ # === duration?
906
+ # ========================================================================= #
907
+ def duration?
908
+ if @work_on_this_file
909
+ @duration.n_seconds?
910
+ else
911
+ report_no_file_is_assigned
912
+ 0 # 0 seconds in this case.
913
+ end
914
+ end
915
+
916
+ # ========================================================================= #
917
+ # === use_readline?
918
+ # ========================================================================= #
919
+ def use_readline?
920
+ IS_READLINE_AVAILABLE
921
+ end; private :use_readline?
922
+
923
+ # ========================================================================= #
924
+ # === show_audio_files
925
+ # ========================================================================= #
926
+ def show_audio_files
927
+ Dir['*'].each {|entry|
928
+ if is_an_audio_file?(entry)
929
+ e sfile(entry)
930
+ end
931
+ }
932
+ end
933
+
934
+ # ========================================================================= #
935
+ # === open_this_file_in_editor
936
+ # ========================================================================= #
937
+ def open_this_file_in_editor
938
+ _ = editor?+' '+__FILE__
939
+ esystem _
940
+ end; private :open_this_file_in_editor
941
+
942
+ # ========================================================================= #
943
+ # === esystem
944
+ # ========================================================================= #
945
+ def esystem(i)
946
+ e " #{teal(i)}"
947
+ system(i) if @we_are_allowed_to_run_system_command
948
+ end
949
+
950
+ # ========================================================================= #
951
+ # === delete_audio_file
952
+ # ========================================================================= #
953
+ def delete_audio_file(
954
+ i = main_file?
955
+ )
956
+ File.delete(i) if File.exist? i
957
+ end; private :delete_audio_file
958
+
959
+ # ========================================================================= #
960
+ # === return_end_of_file_in_seconds
961
+ #
962
+ # Will always return a String.
963
+ # ========================================================================= #
964
+ def return_end_of_file_in_seconds
965
+ duration?.to_s
966
+ end; alias length_of_audio_file return_end_of_file_in_seconds # === length_of_audio_file
967
+ alias length_of_audio_file? return_end_of_file_in_seconds # === length_of_audio_file?
968
+
969
+ # ========================================================================= #
970
+ # === show_help (help tag, usage tag)
971
+ #
972
+ # This method will show the help-options for this class.
973
+ #
974
+ # To invoke this from the commandline, try:
975
+ #
976
+ # cut_audio --help
977
+ #
978
+ # ========================================================================= #
979
+ def show_help(
980
+ i = main_file?,
981
+ shall_we_exit = :do_not_exit
982
+ )
983
+ case shall_we_exit
984
+ when :then_exit
985
+ shall_we_exit = true
986
+ else
987
+ shall_we_exit = false
988
+ end
989
+ report_status if File.exist? i.to_s
990
+ show_invocation_usage
991
+ e "#{N}The available options for the #{sfancy('CutMultimedia class')}"\
992
+ " are:#{green_colour}#{N}#{N}"
993
+ e
994
+ eparse ' trim # this will trim from the left-hand '\
995
+ 'side of the multimedia-file'
996
+ eparse ' # ^^^ also known as left-chop or just lchop'
997
+ eparse ' show_audio_files # show the local audio files'
998
+ eparse ' report_half_the_duration # report the half-duration of a song'
999
+ eparse ' report_which_player_we_will_use # report which multimedia-player is in use'
1000
+ eparse ' play # play the currently active song/video file'
1001
+ eparse ' q # q for quit, to exit. Or '\
1002
+ 'just use "exit" or "quit".'
1003
+ eparse ' feedback # provide some general '\
1004
+ 'information about this class'
1005
+ eparse ' cut # do the actual cutting'
1006
+ eparse ' disable # dont run system '\
1007
+ 'command (in case you have to debug something)'
1008
+ eparse ' duration? # show the duration '\
1009
+ 'of the file in question'
1010
+ eparse ' s[number] # start to cut at this '\
1011
+ 'start-position in seconds - example: s5'
1012
+ eparse ' e[number] # stop to cut at this end-position'
1013
+ eparse ' play # to use mplayer to '\
1014
+ 'play that file; p is a shorter alias to it'
1015
+ eparse ' merge # merge the cutted audio files together'
1016
+ eparse ' --last-file # re-use the last file that was used '\
1017
+ 'in a prior run'
1018
+ eparse ' open # open the file cut_audio.rb in your editor'
1019
+ eparse ' overwrite # overwrite the old file, with the new file'
1020
+ eparse ' points? # feedback all start and end points'
1021
+ eparse ' split # split an audio file into half'
1022
+ eparse ' chop # to chop off some seconds '\
1023
+ 'from the .mp3 file'
1024
+ eparse ' gui # start the ruby-gtk3 '\
1025
+ 'widget, a graphical user interface'
1026
+ e
1027
+ e
1028
+ cliner
1029
+ exit_properly if shall_we_exit
1030
+ end; alias show_usage show_help # === show_usage
1031
+
1032
+ # ========================================================================= #
1033
+ # === log_cut_action
1034
+ #
1035
+ # We will only create a log file if @create_log_file is true.
1036
+ #
1037
+ # This method requires four arguments.
1038
+ # ========================================================================= #
1039
+ def log_cut_action(
1040
+ start_position,
1041
+ end_position,
1042
+ command_that_was_used,
1043
+ output_file
1044
+ )
1045
+ append_what_into(
1046
+ 'Start position: '+start_position.to_s+N,
1047
+ output_file)
1048
+ append_what_into(
1049
+ 'End position: '+end_position.to_s+N,
1050
+ output_file)
1051
+ append_what_into(
1052
+ 'Command that was used:'+N+' '+command_that_was_used.to_s+N,
1053
+ output_file)
1054
+ end
1055
+
1056
+ # ========================================================================= #
1057
+ # === clear_setpoints
1058
+ #
1059
+ # This method will clear all setpoints, both the beginning and
1060
+ # the end array.
1061
+ # ========================================================================= #
1062
+ def clear_setpoints
1063
+ @array_all_start_positions = []
1064
+ @array_all_end_positions = []
1065
+ end
1066
+
1067
+ # ========================================================================= #
1068
+ # === do_use_mpv
1069
+ # ========================================================================= #
1070
+ def do_use_mpv
1071
+ e 'We will try to use mpv.'
1072
+ MultimediaParadise.set_use_this_multimedia_player(:mpv)
1073
+ end
1074
+
1075
+ # ========================================================================= #
1076
+ # === do_use_mplayer
1077
+ # ========================================================================= #
1078
+ def do_use_mplayer
1079
+ e 'We will try to use mplayer.'
1080
+ MultimediaParadise.set_use_this_multimedia_player(:mplayer)
1081
+ end
1082
+
1083
+ # ========================================================================= #
1084
+ # === do_reset_all_values_to_their_default_values
1085
+ # ========================================================================= #
1086
+ def do_reset_all_values_to_their_default_values
1087
+ opne 'Resetting all values to their defaults again.'
1088
+ _ = file? # Obtain a reference to the old file.
1089
+ reset # Then reset it.
1090
+ set_file(_)
1091
+ end
1092
+
1093
+ # ========================================================================= #
1094
+ # === array_all_start_positions?
1095
+ # ========================================================================= #
1096
+ def array_all_start_positions?
1097
+ @array_all_start_positions
1098
+ end; alias start_positions? array_all_start_positions? # === start_positions?
1099
+ alias all_start_positions? array_all_start_positions? # === all_start_positions?
1100
+
1101
+ # ========================================================================= #
1102
+ # === end_position= (end tag)
1103
+ #
1104
+ # Usage example:
1105
+ #
1106
+ # self.end_position = 5
1107
+ #
1108
+ # ========================================================================= #
1109
+ def end_position=(i = 1000)
1110
+ case i
1111
+ when :end # special instruction then
1112
+ i = duration?.to_f
1113
+ end
1114
+ all_end_positions?[0,0] = i.to_i
1115
+ end; alias set_length end_position= # === set_length
1116
+
1117
+ # ========================================================================= #
1118
+ # === delete_individual_audio_files
1119
+ #
1120
+ # This will delete
1121
+ # ========================================================================= #
1122
+ def delete_individual_audio_files
1123
+ _ = output_file?
1124
+ if _.empty?
1125
+ opne 'Nothing to delete.'
1126
+ else
1127
+ _ = _.join(', ') if _.is_a? Array
1128
+ if File.exist? _
1129
+ opne "Next deleting the file `#{sfile(_)}`."
1130
+ delete(_)
1131
+ else
1132
+ opnn; no_file_exists_at(_)
1133
+ end
1134
+ end
1135
+ end
1136
+
1137
+ # ========================================================================= #
1138
+ # === merge_these_files (merge tag)
1139
+ # ========================================================================= #
1140
+ def merge_these_files(
1141
+ array = @array_output_files,
1142
+ output_file = nil
1143
+ )
1144
+ if array.respond_to? :join
1145
+ array = array.join('\|')
1146
+ output_file = 'GENERIC_OUTPUT_FILE_'+input? if output_file.nil?
1147
+ cmd = 'ffmpeg -i concat:'+array+' -acodec copy '+output_file.to_s
1148
+ esystem cmd
1149
+ else
1150
+ e 'The input to the method merge_these_files() was not correct.'
1151
+ e 'Its class is: '+sfancy(array.class)
1152
+ end
1153
+ end; alias merge merge_these_files # === merge
1154
+
1155
+ # ========================================================================= #
1156
+ # === set_output_file
1157
+ # ========================================================================= #
1158
+ def set_output_file(i)
1159
+ i = i.to_s.dup
1160
+ # file_exists = false
1161
+ # file_exists = true if File.exist? i # Check whether the file exists.
1162
+ i = '"'+i+'"' if i.include? ' '
1163
+ @output_file = i
1164
+ end
1165
+
1166
+ # ========================================================================= #
1167
+ # === merge_created_files (merge tag)
1168
+ #
1169
+ # This will merge the various audio files.
1170
+ # ========================================================================= #
1171
+ def merge_created_files
1172
+ if output_files?.size > 1
1173
+ output_file = 'merged_audio_files_'+
1174
+ output_file?.
1175
+ sub(/\.mp3$/,'')+'.mp3'
1176
+ e 'Next merging the '+sfancy(output_files?.size.to_s)+
1177
+ ' files into '+sfile(output_file)+'.'
1178
+ merge_these_files(@array_output_files, output_file)
1179
+ if File.exist? output_file
1180
+ e; cliner {
1181
+ e 'We created a new file at `'+sfile(output_file)+'`.'
1182
+ e 'You can input the command "'+simp('mpl')+'" or "'+
1183
+ simp('play')+'" to play this new file.'
1184
+ set_main_file(output_file)
1185
+ }; e
1186
+ else
1187
+ e 'The file at `'+sfile(output_file)+'` does not exist.'
1188
+ end
1189
+ else
1190
+ e 'You seem to have specified only one file ('+sfile(file?)+').'
1191
+ e 'We need at least two files for the merge action though.'
1192
+ end
1193
+ end
1194
+
1195
+ # ========================================================================= #
1196
+ # === output_file?
1197
+ #
1198
+ # This refers to the file that will be created.
1199
+ # ========================================================================= #
1200
+ def output_file?
1201
+ @output_file
1202
+ end; alias output_files? output_file? # === output_files?
1203
+
1204
+ # ========================================================================= #
1205
+ # === chop_off_the_first_n_minutes
1206
+ #
1207
+ # This method can be used to chop away the first n minutes of an audio
1208
+ # track. This may be useful if you have some audio-recording of a
1209
+ # lecture, and you already know the beginning part, so you quickly
1210
+ # chop it away.
1211
+ #
1212
+ # Invocation examples:
1213
+ #
1214
+ # 7min
1215
+ # 13min
1216
+ #
1217
+ # ========================================================================= #
1218
+ def chop_off_the_first_n_minutes(
1219
+ n_minutes = 5
1220
+ )
1221
+ n_seconds = n_minutes.to_f * 60
1222
+ set_start_point(n_seconds)
1223
+ set_end_point(:to_the_end)
1224
+ do_cut_the_multimedia_file
1225
+ end
1226
+
1227
+ # ========================================================================= #
1228
+ # === calculate
1229
+ #
1230
+ # Calculcate how many seconds are here.
1231
+ # ========================================================================= #
1232
+ def calculate(
1233
+ n_seconds
1234
+ )
1235
+ n_minutes, n_seconds = n_seconds.to_s.split(':')
1236
+ return ((n_minutes.to_i * 60).to_i + n_seconds.to_i).to_s
1237
+ end
1238
+
1239
+ # ========================================================================= #
1240
+ # === delete_the_original_file
1241
+ #
1242
+ # This method will remove the original file.
1243
+ # ========================================================================= #
1244
+ def delete_the_original_file(
1245
+ i = work_on_which_file?
1246
+ )
1247
+ unless i
1248
+ opnn; no_file_exists
1249
+ return
1250
+ end
1251
+ _ = File.basename(i) if i
1252
+ if i and File.exist?(_)
1253
+ opne 'Now deleting the original file at '+sfile(_)+'.'
1254
+ remove_file(_)
1255
+ else
1256
+ opnn; no_file_exists_at(_)
1257
+ end
1258
+ end
1259
+
1260
+ # ========================================================================= #
1261
+ # === is_interactive?
1262
+ # ========================================================================= #
1263
+ def is_interactive?
1264
+ @usage_mode == :interactive
1265
+ end
1266
+
1267
+ # ========================================================================= #
1268
+ # === we_may_quit
1269
+ # ========================================================================= #
1270
+ def we_may_quit
1271
+ @may_we_exit = true
1272
+ end
1273
+
1274
+ # ========================================================================= #
1275
+ # === chop_off
1276
+ #
1277
+ # Use this method if you want to chop off some seconds from a song,
1278
+ # for instance, to get rid of the last 3 seconds of a song.
1279
+ #
1280
+ # The argument passed will be assumed to be the number of seconds that
1281
+ # you wish to chop off from an audio file - starting from the end.
1282
+ #
1283
+ # So, chop_off(3) simply means to chop off the last 3 seconds.
1284
+ #
1285
+ # Usage example:
1286
+ #
1287
+ # chop off 3 seconds
1288
+ # chop_off 3
1289
+ #
1290
+ # ========================================================================= #
1291
+ def chop_off(i = 1)
1292
+ if i.is_a? Array
1293
+ i << 1 if i.empty?
1294
+ i = i.join(' ')
1295
+ end
1296
+ i = i.to_s.strip.to_f # We need to strip the input here. And use a Float.
1297
+ # ======================================================================= #
1298
+ # Deduct the input from the end position. We either use the
1299
+ # duration, or the last entry.
1300
+ # ======================================================================= #
1301
+ if duration?
1302
+ if end_position? and end_position?.empty?
1303
+ the_end_position = duration?.to_f - i
1304
+ else # else it is not empty
1305
+ last_position = end_positions?.pop.to_f
1306
+ the_end_position = last_position - i
1307
+ end
1308
+ if no_start_point_was_defined_yet?
1309
+ set_start(0, :be_silent) # Only set a start point if we do not have defined one yet.
1310
+ end
1311
+ set_end(the_end_position, :be_silent)
1312
+ e "We will chop off the last #{simp(i.to_s)} seconds."
1313
+ notify_user_that_he_could_commit_now
1314
+ else
1315
+ e 'No duration was set. Can not chop off anything.'
1316
+ end
1317
+ end
1318
+
1319
+ # ========================================================================= #
1320
+ # === notify_user_that_he_could_commit_now
1321
+ # ========================================================================= #
1322
+ def notify_user_that_he_could_commit_now
1323
+ e 'You could now "'+sfancy('commit')+
1324
+ '" to cut the audio file.'
1325
+ end
1326
+
1327
+ # ========================================================================= #
1328
+ # === chop_into_segments_of_n_seconds_size
1329
+ #
1330
+ # Use this method if you wish to chop the input into different sizes,
1331
+ # based on seconds.
1332
+ #
1333
+ # Invocation example:
1334
+ #
1335
+ # chop 300
1336
+ #
1337
+ # ========================================================================= #
1338
+ def chop_into_segments_of_n_seconds_size(n_seconds = 60) # 60 seconds by default.
1339
+ n_seconds = n_seconds.first.to_f if n_seconds.is_a? Array
1340
+ e "Now chopping up into segments of `#{sfancy(n_seconds.to_s)}"\
1341
+ "` seconds duration."
1342
+ ::MultimediaParadise.chop_into_segments_of_n_seconds_size(
1343
+ main_file?, n_seconds
1344
+ )
1345
+ end
1346
+
1347
+ # ========================================================================= #
1348
+ # === left_chop_off
1349
+ #
1350
+ # This method will chop off to the left side of an audio file.
1351
+ # ========================================================================= #
1352
+ def left_chop_off(i)
1353
+ i = i.join(' ').to_s.strip if i.is_a? Array
1354
+ set_start(i)
1355
+ if no_end_point_was_defined_yet?
1356
+ set_end(duration?, :be_silent) # Only set a start point if we do not have defined one yet.
1357
+ end
1358
+ notify_user_that_he_could_commit_now
1359
+ end
1360
+
1361
+ # ========================================================================= #
1362
+ # === notify_the_user_that_interactive_mode_is_ready_now
1363
+ # ========================================================================= #
1364
+ def notify_the_user_that_interactive_mode_is_ready_now(
1365
+ this_file = File.basename(work_on_which_file?.to_s)
1366
+ )
1367
+ # ======================================================================= #
1368
+ # Build up the intro-string.
1369
+ # ======================================================================= #
1370
+ intro = rev+'We are in interactive mode'.dup
1371
+ if File.exist? this_file
1372
+ intro << ', for the file `'+sfile(this_file)+'`.'
1373
+ else
1374
+ intro << '. No file has yet been assigned to work on.'+N
1375
+ intro << 'Use "assign" to assign to a file to work with.'
1376
+ end
1377
+ e intro
1378
+ e
1379
+ e rev+'You can now start to assign start and end positions'
1380
+ e rev+'of your file in question. When you are '\
1381
+ 'done, input '+sfancy('run')
1382
+ e rev+'to start the cutting. (Remember: Start positions are '+
1383
+ 'like '+sfancy('s1')+', end'
1384
+ e "#{rev}positions are like #{sfancy('e40')}.)#{N}#{N}"
1385
+ e rev+'You can also use some extra commands, like "'+
1386
+ simp(:length).to_s+'".'
1387
+ e rev+'Use "help" to display the help menu.'
1388
+ e "#{N}#{simp('Hint:')} #{rev}You can use #{simp('s11')}"\
1389
+ "#{rev} and #{simp('e22')} #{rev}to denote a start time"
1390
+ e rev+' at position '+simp('11').to_s+rev+' seconds and an end '+
1391
+ rev+'time at position '+simp('22').to_s+rev+' seconds.'
1392
+ e
1393
+ e
1394
+ e "#{rev}Input your command next or type \"help\" for help."
1395
+ end
1396
+
1397
+ # ========================================================================= #
1398
+ # === show_how_to_use_intersect
1399
+ #
1400
+ # This method will give the user some hints how to use the intersect
1401
+ # part. The intersect part allows us to cut out a middle segment
1402
+ # from a .mp3 file.
1403
+ # ========================================================================= #
1404
+ def show_how_to_use_intersect
1405
+ e 'intersect can be used to chop out middle-segments from an '\
1406
+ 'audio file.'
1407
+ e
1408
+ e 'The format should be something exactly like this:'
1409
+ e
1410
+ e simp(' intersect 29:23-29:45')
1411
+ e
1412
+ end
1413
+
1414
+ # ========================================================================= #
1415
+ # === enter_the_main_loop
1416
+ #
1417
+ # The main loop is only to be entered if we are in interactive mode.
1418
+ # The GUI in ruby-gtk3 will handle a loop on its own.
1419
+ # ========================================================================= #
1420
+ def enter_the_main_loop
1421
+ loop {
1422
+ display_the_prompt_in_use_to_the_user
1423
+ obtain_user_input
1424
+ append_the_user_input_onto_the_history
1425
+ interactive_menu # Feed the input in the interactive menu here.
1426
+ break if @may_we_exit
1427
+ }
1428
+ end
1429
+
1430
+ # ========================================================================= #
1431
+ # === set_interactive_mode_then_enter_interactive_mode
1432
+ # ========================================================================= #
1433
+ def set_interactive_mode_then_enter_interactive_mode
1434
+ @usage_mode = :interactive
1435
+ enter_interactive_mode
1436
+ end
1437
+
1438
+ # ========================================================================= #
1439
+ # === MultimediaParadise::CutMultimedia[]
1440
+ #
1441
+ # This class-method also allows some extra instructions such as to
1442
+ # limit the duration.
1443
+ #
1444
+ # Example:
1445
+ #
1446
+ # MultimediaParadise::CutMultimedia['*.mp3', '60 seconds']
1447
+ #
1448
+ # This will fetch all .mp3 files.
1449
+ # ========================================================================= #
1450
+ def self.[](
1451
+ i, optional_limitation_of_duration = nil
1452
+ )
1453
+ if i.is_a? String and i.include?('*')
1454
+ i = Dir[i] # This performs a glob, essentially.
1455
+ end
1456
+ if i.is_a? Array
1457
+ # ===================================================================== #
1458
+ # Work in batch-processing mode in this case.
1459
+ # ===================================================================== #
1460
+ if optional_limitation_of_duration and
1461
+ optional_limitation_of_duration.include?('seconds')
1462
+ i.each {|entry|
1463
+ _ = self.new(entry, :do_not_run_yet)
1464
+ _.set_start_at 0
1465
+ _.set_end_at(
1466
+ optional_limitation_of_duration.to_s.gsub(/seconds/,'').strip.to_f
1467
+ )
1468
+ _.cut
1469
+ }
1470
+ end
1471
+ else
1472
+ new(i, :run_interactive)
1473
+ end
1474
+ end
1475
+
1476
+ # ========================================================================= #
1477
+ # === split_audio_file_in_half
1478
+ #
1479
+ # This method will simply split the audio file in half.
1480
+ #
1481
+ # To invoke this method, try this command:
1482
+ #
1483
+ # split_audio_file_in_half
1484
+ #
1485
+ # ========================================================================= #
1486
+ def split_audio_file_in_half(
1487
+ i = main_file?
1488
+ )
1489
+ if File.exist? i
1490
+ e 'We will next split the audio file `'+sfile(i)+'` in '\
1491
+ 'half, thus, into two parts.'
1492
+ set_start 0
1493
+ set_end '50%'
1494
+ cut # Perform the first cut operation here.
1495
+ set_start '50%'
1496
+ set_end '100%'
1497
+ cut # Perform the second cut operation there.
1498
+ # delete_audio_file # Not sure if we should delete it.
1499
+ e 'The audio was split in two equal parts.'
1500
+ else
1501
+ e 'No file called `'+sfile(i)+'` exists.'
1502
+ end
1503
+ end
1504
+
1505
+ # ========================================================================= #
1506
+ # === start_the_graphical_user_interface
1507
+ # ========================================================================= #
1508
+ def start_the_graphical_user_interface
1509
+ require 'multimedia_paradise/gui/gtk3/cut_multimedia/cut_multimedia.rb'
1510
+ ::MultimediaParadise::GUI::Gtk::CutMultimedia.run
1511
+ end
1512
+
1513
+ # ========================================================================= #
1514
+ # === check_whether_ffmpeg_is_installed
1515
+ #
1516
+ # We have to check whether the user has ffmpeg installed. Because if
1517
+ # ffmpeg is unavailable, then cut_audio will not work.
1518
+ # ========================================================================= #
1519
+ def check_whether_ffmpeg_is_installed
1520
+ _ = ARRAY_LOCATIONS_TO_CHECK_FOR_FFMPEG
1521
+ is_ffmpeg_installed = false
1522
+ _.each {|path|
1523
+ is_ffmpeg_installed = true if File.exist? path+'ffmpeg'
1524
+ }
1525
+ unless is_ffmpeg_installed
1526
+ opnn { :no_trailing_colon }; e
1527
+ e
1528
+ e ' FFmpeg is not installed or could not be found. Please '\
1529
+ 'install it.'
1530
+ e
1531
+ e ' The class CutMultimedia, part of the MultimediaParadise namespace,'
1532
+ e ' currently requires that ffmpeg is installed.'
1533
+ e
1534
+ e ' The following paths were checked for the availability of ffmpeg:'
1535
+ e
1536
+ _.each {|this_path|
1537
+ e " #{sfancy(this_path)}"
1538
+ }
1539
+ # exit_properly
1540
+ end
1541
+ return is_ffmpeg_installed
1542
+ end
1543
+
1544
+ # ========================================================================= #
1545
+ # === initialize_twentyfour_hours_notation_object
1546
+ # ========================================================================= #
1547
+ def initialize_twentyfour_hours_notation_object
1548
+ begin
1549
+ require 'roebe/classes/twentyfour_hours_notation.rb'
1550
+ rescue LoadError; end
1551
+ if Object.const_defined?(:Roebe) and Roebe.const_defined?(:TwentyfourHoursNotation)
1552
+ @t = Roebe::TwentyfourHoursNotation.new # bl $RUBY_TIME/twentyfour_hours_notation.rb
1553
+ else
1554
+ e 'The twentyfour_hours_notation class, part of the roebe gem, '\
1555
+ 'appears to be unavailable.'
1556
+ e
1557
+ e 'Please consider installing it, such as via:'
1558
+ e
1559
+ e ' gem install roebe'
1560
+ e
1561
+ end
1562
+ end
1563
+
1564
+ # ========================================================================= #
1565
+ # === set_work_on_this_file
1566
+ # ========================================================================= #
1567
+ def set_work_on_this_file(
1568
+ i = :default,
1569
+ also_keep_track_of_which_file_we_will_use = true
1570
+ )
1571
+ i = i.first if i.is_a? Array # For now we use only the first entry of an Array.
1572
+ case also_keep_track_of_which_file_we_will_use
1573
+ when :do_not_keep_track
1574
+ also_keep_track_of_which_file_we_will_use = false
1575
+ end
1576
+ case i
1577
+ # ======================================================================= #
1578
+ # === --help
1579
+ # ======================================================================= #
1580
+ when /-?-?help/i
1581
+ show_help :then_exit
1582
+ # ======================================================================= #
1583
+ # === :default
1584
+ #
1585
+ # This entry point will cover :default as well as nil-values.
1586
+ # ======================================================================= #
1587
+ when :default,
1588
+ nil
1589
+ i = DEFAULT_INPUT_FILE
1590
+ end
1591
+ # ======================================================================= #
1592
+ # === Make use of the absolute path, if possible
1593
+ # ======================================================================= #
1594
+ unless i.include? '/'
1595
+ i = File.absolute_path(i)
1596
+ end
1597
+ if i and File.file?(i)
1598
+ @work_on_this_file = i
1599
+ # ===================================================================== #
1600
+ # Always set the duration upon assigning a new file to work with.
1601
+ # ===================================================================== #
1602
+ determine_the_duration(i) if File.exist? i
1603
+ # ===================================================================== #
1604
+ # And also always determine the proper output file.
1605
+ # ===================================================================== #
1606
+ determine_the_output_file
1607
+ if also_keep_track_of_which_file_we_will_use and
1608
+ File.exist?(i)
1609
+ # =================================================================== #
1610
+ # We will also keep track of this file in the local filesystem,
1611
+ # if the output directory has been set.
1612
+ # =================================================================== #
1613
+ _ = ::MultimediaParadise.output_directory?
1614
+ unless File.directory? _
1615
+ mkdir(_)
1616
+ end
1617
+ if _ and File.directory?(_)
1618
+ into = FILE_LAST_USED
1619
+ if is_on_roebe?
1620
+ opne 'Keeping track of the main file in'
1621
+ opne '`'+sfile(into)+'`.'
1622
+ end
1623
+ # =================================================================== #
1624
+ # We must rescue the YAML.dump operation, as it may fail otherwise
1625
+ # sometimes, e. g. via:
1626
+ #
1627
+ # invalid byte sequence in US-ASCII (ArgumentError)
1628
+ #
1629
+ # =================================================================== #
1630
+ begin
1631
+ what = YAML.dump(@work_on_this_file)
1632
+ write_what_into(
1633
+ what, into
1634
+ )
1635
+ rescue ArgumentError => error
1636
+ pp error
1637
+ pp error.class
1638
+ end
1639
+ end
1640
+ else
1641
+ opne 'File '+sfile(i)+' does not exist.'
1642
+ end
1643
+ end
1644
+ end; alias set_main_file set_work_on_this_file # === set_main_file
1645
+ alias set_file set_work_on_this_file # === set_file
1646
+ alias assign_file set_work_on_this_file # === assign_file
1647
+ alias assign set_work_on_this_file # === assign (assign tag)
1648
+ alias assign_this_file set_work_on_this_file # === assign_this_file
1649
+
1650
+ # ========================================================================= #
1651
+ # === absolute_path_of_the_output_file?
1652
+ # ========================================================================= #
1653
+ def absolute_path_of_the_output_file?(
1654
+ output_file = output_file?
1655
+ )
1656
+ File.absolute_path(output_file) if output_file
1657
+ end
1658
+
1659
+ # ========================================================================= #
1660
+ # === ensure_that_there_is_at_least_one_end_position
1661
+ #
1662
+ # This method will make sure that the end-array has at least one
1663
+ # entry.
1664
+ # ========================================================================= #
1665
+ def ensure_that_there_is_at_least_one_end_position
1666
+ if end_positions?.empty?
1667
+ e "#{rev}Note that there is no end position designated yet for "\
1668
+ "this file. We will thus set"
1669
+ e 'one to the end position of the audio file.'
1670
+ set_end :end_of_the_file
1671
+ end
1672
+ end
1673
+
1674
+ # ========================================================================= #
1675
+ # === determine_the_output_file
1676
+ #
1677
+ # This method will determine the output file based on the input file.
1678
+ # ========================================================================= #
1679
+ def determine_the_output_file(
1680
+ i = input_file?
1681
+ )
1682
+ i = File.basename(i).dup
1683
+ i.prepend('OUTPUT_FILE_') unless i.start_with?('OUTPUT_FILE_')
1684
+ i = File.absolute_path(i)
1685
+ set_output_file(i)
1686
+ end
1687
+
1688
+ # ========================================================================= #
1689
+ # === work_on_this_file? (file tag)
1690
+ # ========================================================================= #
1691
+ def work_on_this_file?
1692
+ @work_on_this_file
1693
+ end; alias main_file? work_on_this_file? # === main_file?
1694
+ alias work_on_which_file? work_on_this_file? # === work_on_which_file?
1695
+ alias file? work_on_this_file? # === file?
1696
+ alias input_file? work_on_this_file? # === input_file?
1697
+
1698
+ # ========================================================================= #
1699
+ # === exit_properly
1700
+ # ========================================================================= #
1701
+ def exit_properly
1702
+ do_general_exit_actions
1703
+ exit # unless is_interactive?
1704
+ end
1705
+
1706
+ # ========================================================================= #
1707
+ # === check_whether_the_commandline_arguments_contain_a_file_and_assign_this_as_the_main_file
1708
+ # ========================================================================= #
1709
+ def check_whether_the_commandline_arguments_contain_a_file_and_assign_this_as_the_main_file(
1710
+ i = commandline_arguments?
1711
+ )
1712
+ if i.is_a? Array
1713
+ i.each {|entry| check_whether_the_commandline_arguments_contain_a_file_and_assign_this_as_the_main_file(entry) }
1714
+ else
1715
+ if i and File.exist?(i)
1716
+ # =================================================================== #
1717
+ # Designate this as the new file to work with, on startup of
1718
+ # this class.
1719
+ # =================================================================== #
1720
+ set_work_on_this_file(i)
1721
+ end
1722
+ end
1723
+ end
1724
+
1725
+ # ========================================================================= #
1726
+ # === run_in_interactive_mode
1727
+ # ========================================================================= #
1728
+ def run_in_interactive_mode
1729
+ try_to_rename_kde_konsole_tab(work_on_which_file?)
1730
+ notify_the_user_that_interactive_mode_is_ready_now
1731
+ enter_the_main_loop
1732
+ end; alias enter_interactive_mode run_in_interactive_mode # === enter_interactive_mode
1733
+ alias run_interactively run_in_interactive_mode # === run_interactively
1734
+
1735
+ # ========================================================================= #
1736
+ # === run (run tag)
1737
+ # ========================================================================= #
1738
+ def run
1739
+ check_whether_ffmpeg_is_installed # After this point we know that ffmpeg is installed.
1740
+ if File.exist? work_on_which_file?.to_s
1741
+ feedback_duration
1742
+ end
1743
+ # ======================================================================= #
1744
+ # Check against the usage mode.
1745
+ # ======================================================================= #
1746
+ case @usage_mode
1747
+ when :interactive,
1748
+ :default
1749
+ run_in_interactive_mode
1750
+ exit 0 # Signal normal exit.
1751
+ when :gui
1752
+ # Do nothing for now in this event.
1753
+ end
1754
+ end
1755
+
1756
+ # ========================================================================= #
1757
+ # === feedback_all_start_points
1758
+ # ========================================================================= #
1759
+ def feedback_all_start_points(
1760
+ i = start_positions?
1761
+ )
1762
+ e "#{rev}Feedbacking all #{emphasis('start-points')} #{rev}next."
1763
+ pp i
1764
+ end
1765
+
1766
+ # ========================================================================= #
1767
+ # === define_start_point (set_start tag)
1768
+ #
1769
+ # This method will define a start position, at which we will start to
1770
+ # cut an audio file.
1771
+ #
1772
+ # set_start is an alias to this method.
1773
+ # ========================================================================= #
1774
+ def define_start_point(
1775
+ i,
1776
+ be_verbose = true
1777
+ )
1778
+ case be_verbose
1779
+ when :be_silent
1780
+ be_verbose = false
1781
+ end
1782
+ i = i.first if i.is_a? Array
1783
+ i = i.to_s.strip
1784
+ i[0,5] = '' if i.start_with? 'start'
1785
+ i[0,1] = '' if i.start_with? 's'
1786
+ i = sanitize(i)
1787
+ if i.empty?
1788
+ e "#{rev}Won't append empty start points."
1789
+ elsif i.include? '%' # User requested percentage-based manipulation here.
1790
+ i = ((duration? * (i.delete('%').to_i)) / 100)
1791
+ define_start_point(i) # Call itself again.
1792
+ else
1793
+ # ===================================================================== #
1794
+ # Simply append to our main Array.
1795
+ # ===================================================================== #
1796
+ @array_all_start_positions << i.to_f # Store as float.
1797
+ if be_verbose
1798
+ twentyfour_notation = forestgreen(to_twentyfour_notation(i))
1799
+ e "#{rev}Setting a start point at: #{simp(i)} [#{twentyfour_notation}]"
1800
+ feedback_all_start_points
1801
+ end
1802
+ end
1803
+ end; alias set_start define_start_point # === set_start
1804
+ alias set_start_at define_start_point # === set_start_at
1805
+ alias set_start_point define_start_point # === set_start_point
1806
+ alias determine_start_position define_start_point # === determine_start_position
1807
+ alias set_start_position define_start_point # === set_start_position
1808
+
1809
+ # ========================================================================= #
1810
+ # === define_end_point
1811
+ #
1812
+ # This method can be used to set the end point of an audio file, as to
1813
+ # where we will stop to cut. For example, an end point of "5" is assumed
1814
+ # to mean a cut point at 5 seconds.
1815
+ #
1816
+ # set_end() is an alias to this method.
1817
+ # ========================================================================= #
1818
+ def define_end_point(
1819
+ i, be_verbose = true
1820
+ )
1821
+ be_verbose = false if be_verbose == :be_silent
1822
+ i = i.first if i.is_a? Array
1823
+ if i.is_a? Symbol
1824
+ case i
1825
+ when :end_of_the_file,
1826
+ :to_the_end
1827
+ i = length_of_audio_file?
1828
+ end
1829
+ end
1830
+ i = i.to_s.strip # We require a String past this point here.
1831
+ i[0,3] = '' if i.start_with? 'end'
1832
+ i[0,1] = '' if i.start_with? 'e'
1833
+ i = sanitize(i)
1834
+ if i.empty?
1835
+ e "#{rev}Won't append empty end points."
1836
+ elsif i.include? '%' # User requested percentage-based manipulation.
1837
+ i = ((duration? * (i.delete('%').to_i)) / 100)
1838
+ define_end_point(i) # Recursive call again.
1839
+ else
1840
+ # ===================================================================== #
1841
+ # Convert into seconds if it includes a ':'.
1842
+ # ===================================================================== #
1843
+ if i.include?(':') and Object.const_defined?(:HoursToSeconds)
1844
+ i = HoursToSeconds[i, :be_quiet]
1845
+ end
1846
+ # ===================================================================== #
1847
+ # Until 19.04.2019 we had the following code to detect a logic error,
1848
+ # but it was then realized that not all numbers constitute a logic
1849
+ # error, so this was removed again.
1850
+ #
1851
+ # if i.to_f < starting_position?.to_f
1852
+ # e 'This input ('+sfancy(i.to_s)+') must be invalid because '\
1853
+ # 'it is'
1854
+ # e 'smaller than the starting position.'
1855
+ # return
1856
+ # end
1857
+ # ===================================================================== #
1858
+ # ===================================================================== #
1859
+ # === Check for too long size given
1860
+ #
1861
+ # The following code has been added at 31.08.2019. If i is larger
1862
+ # than the length of the audio file then we will notify the user
1863
+ # about it, then set it to the maximum length instead.
1864
+ #
1865
+ # This, however had, only makes sense if the length is larger
1866
+ # than 0, hence the double-check below.
1867
+ # ===================================================================== #
1868
+ length_of_audio_file = length_of_audio_file?.to_f
1869
+ if (length_of_audio_file.to_f > 0) and (i.to_f > length_of_audio_file.to_f)
1870
+ e "#{rev}Note that #{sfancy(i)} #{rev}is larger than the length of "\
1871
+ "the audio file."
1872
+ e "#{rev}This is of little practical use, so the input here been reset"
1873
+ e "#{rev}to the #{steelblue('maximum length')} #{rev}instead "\
1874
+ "(#{seagreen(length_of_audio_file)} #{rev}seconds)."
1875
+ i = length_of_audio_file.to_f
1876
+ end
1877
+ end_positions? << i.to_f # Append the end point as a float-value here.
1878
+ if be_verbose
1879
+ twentyfour_notation = forestgreen(to_twentyfour_notation(i).to_f.to_s)
1880
+ e "#{rev}Setting an end point at: #{simp(i)} #{rev}[#{twentyfour_notation}]"
1881
+ feedback_all_end_points
1882
+ end
1883
+ end
1884
+ end; alias set_end define_end_point # === set_end
1885
+ alias set_end_at define_end_point # === set_end_at
1886
+ alias set_end_point define_end_point # === set_end_point
1887
+ alias set_end_position define_end_point # === set_end_position
1888
+
1889
+ # ========================================================================= #
1890
+ # === do_cut_the_multimedia_file
1891
+ # ========================================================================= #
1892
+ def do_cut_the_multimedia_file
1893
+ start_cutting
1894
+ report_that_we_are_finished_now
1895
+ return absolute_path_of_the_output_file?
1896
+ end; alias do_cut do_cut_the_multimedia_file # === do_cut
1897
+
1898
+ # ========================================================================= #
1899
+ # === report_status
1900
+ # ========================================================================= #
1901
+ def report_status
1902
+ report_duration_of_multimedia_file
1903
+ report_points
1904
+ end
1905
+
1906
+ # ========================================================================= #
1907
+ # === do_the_cutting
1908
+ #
1909
+ # This will cut our audio file.
1910
+ # ========================================================================= #
1911
+ def do_the_cutting(optional_input = nil)
1912
+ build_ffmpeg_command
1913
+ end; alias cut do_the_cutting # === cut (cut tag)
1914
+ alias start_cutting do_the_cutting # === start_cutting
1915
+
1916
+ # ========================================================================= #
1917
+ # === build_ffmpeg_command
1918
+ #
1919
+ # This method will build the proper ffmpeg command.
1920
+ # ========================================================================= #
1921
+ def build_ffmpeg_command( # Assemble the FFMPEG main string here.
1922
+ this_file = main_file?,
1923
+ duration = duration?
1924
+ )
1925
+ ensure_that_there_is_at_least_one_end_position
1926
+ # ======================================================================= #
1927
+ # Next, we must ensure that the @array_all_end_positions is never nil.
1928
+ # ======================================================================= #
1929
+ ensure_that_array_cut_end_is_valid
1930
+ # ======================================================================= #
1931
+ # Merge it all into one Array.
1932
+ # ======================================================================= #
1933
+ merged_array = all_start_positions?.zip(all_end_positions?)
1934
+ # ======================================================================= #
1935
+ # Iterate over that Array next.
1936
+ # ======================================================================= #
1937
+ merged_array.each {|entry|
1938
+ the_start_position = entry.first # Grab the first entry.
1939
+ the_end_position = entry[1] # Grab the second entry.
1940
+ the_end_position = duration.to_f if the_end_position.to_f > duration.to_f
1941
+ # ===================================================================== #
1942
+ # the_end position should never be nil at this point.
1943
+ # ===================================================================== #
1944
+ @t.set_start_position = the_start_position
1945
+ @t.set_end_position = the_end_position
1946
+ e 'Now cutting multimedia-file '+sfancy('`'+this_file+'`')+','
1947
+ e "starting at position #{simp(the_start_position.to_s)} and ending at "\
1948
+ "position #{simp(the_end_position.to_s)}:"
1949
+ e
1950
+ # ===================================================================== #
1951
+ # Label our output file properly, by prepending the word "cutted_",
1952
+ # the start position and the end position.
1953
+ # ===================================================================== #
1954
+ output_file = 'cutted_'+the_start_position.to_s+
1955
+ '-'+the_end_position.to_s+'_seconds_'+
1956
+ File.basename(this_file)
1957
+ set_output_file(output_file)
1958
+ # ===================================================================== #
1959
+ # === Does the output file exist
1960
+ #
1961
+ # Check whether the output file exists or whether it does not.
1962
+ # ===================================================================== #
1963
+ if File.exist? output_file?.to_s
1964
+ e "File `#{sfile(output_file?)}` already exists."
1965
+ e 'We will remove it before continuing.'
1966
+ remove(output_file?)
1967
+ end
1968
+ # ===================================================================== #
1969
+ # Next, build up the ffmpeg command.
1970
+ # ===================================================================== #
1971
+ if this_file.include? ' '
1972
+ this_file = '"'+this_file+'"'
1973
+ end
1974
+ difference_in_seconds = the_end_position.to_f - the_start_position.to_f
1975
+ the_start_position = @t.convert_to_long_format(the_start_position)
1976
+ # ===================================================================== #
1977
+ # Ok, here we start the real ffmpeg command.
1978
+ # ===================================================================== #
1979
+ _ = 'ffmpeg -i '.dup
1980
+ _ << this_file+' '
1981
+ _ << '-acodec copy ' # This will copy. See Stackoverflow here: http://stackoverflow.com/a/44032/722915
1982
+ if is_video_file?(this_file)
1983
+ _ << '-vcodec copy '
1984
+ end
1985
+ _ << '-ss '+
1986
+ the_start_position
1987
+ _ << ' -t '+
1988
+ @t.convert_to_long_format(difference_in_seconds)+
1989
+ ' '+output_file?.to_s # Relies on ffmpeg.
1990
+ # ===================================================================== #
1991
+ # Next, determine whether we will log into a text file or whether
1992
+ # we will not.
1993
+ # ===================================================================== #
1994
+ if create_log_file?
1995
+ output_file = output_file.dup if output_file.frozen?
1996
+ output_file << '.md'
1997
+ log_cut_action(@t.start?, @t.end?, _, output_file)
1998
+ end
1999
+ cliner
2000
+ e
2001
+ e steelblue(_) # Feedback the command we will use to the user here.
2002
+ e
2003
+ cliner
2004
+ e # And a newline too.
2005
+ system _
2006
+ }
2007
+ end
2008
+
2009
+ end
2010
+
2011
+ # =========================================================================== #
2012
+ # Add two aliases next.
2013
+ # =========================================================================== #
2014
+ CutAudio = CutMultimedia
2015
+ CutVideo = CutMultimedia
2016
+
2017
+ end
2018
+
2019
+ if __FILE__ == $PROGRAM_NAME
2020
+ MultimediaParadise::CutMultimedia.new(ARGV)
2021
+ end # cutmultimedia