content-editing-movie-player 0.38.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitmodules +3 -0
- data/.rvmrc +1 -0
- data/LICENSE.TXT +20 -0
- data/README.TXT +225 -0
- data/Rakefile +206 -0
- data/TODO +740 -0
- data/VERSION +1 -0
- data/_DO_NOT_RUN_IT_FROM_HERE_DOWNLOAD_THE_RELEASE_ZIP_FROM_SOURCEFORGE_INSTEAD +0 -0
- data/bin/sensible-cinema +60 -0
- data/bin/sensible-cinema-cli +161 -0
- data/business_ideas.txt +21 -0
- data/change_log_with_feature_list.txt +952 -0
- data/documentation/DOCUMENTATION_README.TXT +44 -0
- data/documentation/how_to_get_files_from_dvd.txt +30 -0
- data/documentation/is_it_legal_to_copy_dvds.txt +97 -0
- data/documentation/troubleshooting.txt +30 -0
- data/documentation/upconversion.txt +4 -0
- data/experimental_online_player_ocr_readme.txt +45 -0
- data/go +1 -0
- data/go.bat +2 -0
- data/go.sh +1 -0
- data/go_ocr_tracker.bat +1 -0
- data/goc +1 -0
- data/goc.bat +1 -0
- data/goc.sh +1 -0
- data/gpl-2.0.txt +339 -0
- data/gplv3.txt +219 -0
- data/history_and_related_works_list.txt +108 -0
- data/inventionzy_files/cone.png +0 -0
- data/inventionzy_files/md5s.txt +53 -0
- data/inventionzy_files/play_with_inserted_scene.bat +8 -0
- data/inventionzy_files/play_with_overlay.bat +24 -0
- data/inventionzy_files/transcript_mute_vlc.txt +117 -0
- data/legal_draft +23 -0
- data/lib/add_any_bundled_gems_to_load_path.rb +32 -0
- data/lib/auto_window_finder.rb +41 -0
- data/lib/blanker.rb +104 -0
- data/lib/check_installed_mac.rb +34 -0
- data/lib/convert_thirty_fps.rb +20 -0
- data/lib/edl_parser.rb +387 -0
- data/lib/eight_three.rb +28 -0
- data/lib/extract/dumpstream.bat +1 -0
- data/lib/extract/get_init.bat +3 -0
- data/lib/extract/pause_early.rb +13 -0
- data/lib/fake_blanker.rb +35 -0
- data/lib/frame_accurate.rb +3 -0
- data/lib/gui/base.rb +748 -0
- data/lib/gui/create-file.rb +24 -0
- data/lib/gui/create.rb +581 -0
- data/lib/gui/dependencies.rb +219 -0
- data/lib/gui/normal.rb +123 -0
- data/lib/gui/upconvert.rb +284 -0
- data/lib/keyboard_input.rb +60 -0
- data/lib/media_info_parser.rb +27 -0
- data/lib/mouse_forever.rb +19 -0
- data/lib/movie_hasher.rb +27 -0
- data/lib/mplayer_edl.rb +42 -0
- data/lib/muter.rb +87 -0
- data/lib/ocr.rb +125 -0
- data/lib/ocr_seed/netflix_b9.bmp +0 -0
- data/lib/overlayer.rb +373 -0
- data/lib/screen_tracker.rb +269 -0
- data/lib/subtitle_profanity_finder.rb +294 -0
- data/lib/vlc_programmer.rb +112 -0
- data/lib/zoom_player_max_edl.rb +50 -0
- data/never_do +40 -0
- data/notes_for_potential_developers.txt +46 -0
- data/preamble +17 -0
- data/roadmap_possibilities +12 -0
- data/spec/arse.srt +41 -0
- data/spec/auto_window_finder.spec.rb +65 -0
- data/spec/bad_beginning.srt +3778 -0
- data/spec/blanker.spec.rb +60 -0
- data/spec/common.rb +81 -0
- data/spec/convert_image.rb +25 -0
- data/spec/deity_end.srt +11 -0
- data/spec/dragon.srt +34 -0
- data/spec/edl_parser.spec.rb +270 -0
- data/spec/frame_accurate.spec.rb +71 -0
- data/spec/keyboard_input.spec.rb +73 -0
- data/spec/media_info_parser.spec.rb +29 -0
- data/spec/mplayer_edl.spec.rb +100 -0
- data/spec/muter.spec.rb +50 -0
- data/spec/notes +4996 -0
- data/spec/ocr.spec.rb +119 -0
- data/spec/overlayer.spec.rb +440 -0
- data/spec/screen_tracker.spec.rb +318 -0
- data/spec/sensible_cinema_gui.spec.rb +452 -0
- data/spec/subtitle_profanity_finder.spec.rb +224 -0
- data/spec/test_yaml.yml +4 -0
- data/spec/tsmuxer.output +33 -0
- data/spec/vlc_programmer.spec.rb +124 -0
- data/spec/youtube_edl.spec.rb +28 -0
- data/spec/zoom_player_max_edl.spec.rb +29 -0
- data/template_bats/README_DISTRO.TXT +8 -0
- data/template_bats/RUN SENSIBLE CINEMA CLICK HERE WINDOWS.bat +25 -0
- data/template_bats/_DO_NOT_RUN_IT_FROM_HERE_DOWNLOAD_THE_RELEASE_ZIP_FROM_SOURCEFORGE_INSTEAD +0 -0
- data/template_bats/mac/RUN SENSIBLE CINEMA CLICK HERE.command +5 -0
- data/template_bats/mac/advanced--create or edit sensible cinema edit list files.command +3 -0
- data/template_bats/mac/advanced--run-upconverting-video-player.command +3 -0
- data/template_bats/pc/advanced--create or edit sensible cinema edit list files.bat +2 -0
- data/template_bats/pc/advanced--run-upconverting-video-player.bat +2 -0
- data/todo.build_library.txt +11 -0
- data/todo.inventionzy.txt +162 -0
- data/todo.open_edl_list_org.txt +169 -0
- data/todo.propaganda +107 -0
- data/todo.subtitle +17 -0
- data/todo.upconvert +53 -0
- data/upconvert.bat +1 -0
- data/upconvert_from_screen/go_upscaling.bat +12 -0
- data/upconvert_from_screen/go_upscaling_works +0 -0
- data/upconvert_from_screen/old/latest2/combine_video.avs +23 -0
- data/upconvert_from_screen/old/latest2/go_no_upscaling.bat +1 -0
- data/upconvert_from_screen/old/latest2/go_upscaling.bat +12 -0
- data/upconvert_from_screen/old/latest2/push2.GRF +0 -0
- data/upconvert_from_screen/old/latest2/push3.grf +0 -0
- data/upconvert_from_screen/old/latest2/setup_capture_coords.rb +27 -0
- data/upconvert_from_screen/old/latest2/setup_directshow_filter_params.rb +29 -0
- data/upconvert_from_screen/old/latest2/upconvert_from_screen_me2.avs +19 -0
- data/upconvert_from_screen/old/latest_now_possibly_oudated/push2.GRF +0 -0
- data/upconvert_from_screen/old/latest_now_possibly_oudated/upconvert_from_screen_me2.avs +18 -0
- data/upconvert_from_screen/old/position_window.png +0 -0
- data/upconvert_from_screen/old/push_source_desktop.GRF +0 -0
- data/upconvert_from_screen/old/record_screen/record.bat +2 -0
- data/upconvert_from_screen/old/upconvert_from_screen.avs +21 -0
- data/upconvert_from_screen/old/upconvert_from_screen_me.avs +21 -0
- data/upconvert_from_screen/old/upconvert_from_screen_me2.avs +3 -0
- data/upconvert_from_screen/old/upconvert_from_screen_me_push_source.avs +3 -0
- data/upconvert_from_screen/old/uscreen.GRF +0 -0
- data/upconvert_from_screen/old/uscreen_me.GRF +0 -0
- data/upconvert_from_screen/push3.grf +0 -0
- data/upconvert_from_screen/upconvert_from_screen_me2.avs +19 -0
- data/vendor/movie-content-editor-read-only/.metadata/.lock +0 -0
- data/vendor/movie-content-editor-read-only/.metadata/.mylyn/.tasks.xml.zip +0 -0
- data/vendor/movie-content-editor-read-only/.metadata/.mylyn/repositories.xml.zip +0 -0
- data/vendor/movie-content-editor-read-only/.metadata/.mylyn/tasks.xml.zip +0 -0
- data/vendor/movie-content-editor-read-only/.metadata/.plugins/org.eclipse.core.resources/.root/.indexes/history.version +1 -0
- data/vendor/movie-content-editor-read-only/.metadata/.plugins/org.eclipse.core.resources/.root/.indexes/properties.index +0 -0
- data/vendor/movie-content-editor-read-only/.metadata/.plugins/org.eclipse.core.resources/.root/.indexes/properties.version +1 -0
- data/vendor/movie-content-editor-read-only/.metadata/.plugins/org.eclipse.core.resources/.root/2.tree +0 -0
- data/vendor/movie-content-editor-read-only/.metadata/.plugins/org.eclipse.core.resources/.safetable/org.eclipse.core.resources +0 -0
- data/vendor/movie-content-editor-read-only/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.core.resources.prefs +3 -0
- data/vendor/movie-content-editor-read-only/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.jdt.ui.prefs +14 -0
- data/vendor/movie-content-editor-read-only/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.mylyn.context.core.prefs +3 -0
- data/vendor/movie-content-editor-read-only/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.ui.ide.prefs +5 -0
- data/vendor/movie-content-editor-read-only/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.ui.prefs +3 -0
- data/vendor/movie-content-editor-read-only/.metadata/.plugins/org.eclipse.jdt.core/nonChainingJarsCache +0 -0
- data/vendor/movie-content-editor-read-only/.metadata/.plugins/org.eclipse.jdt.core/variablesAndContainers.dat +0 -0
- data/vendor/movie-content-editor-read-only/.metadata/.plugins/org.eclipse.jdt.ui/OpenTypeHistory.xml +2 -0
- data/vendor/movie-content-editor-read-only/.metadata/.plugins/org.eclipse.jdt.ui/QualifiedTypeNameHistory.xml +2 -0
- data/vendor/movie-content-editor-read-only/.metadata/.plugins/org.eclipse.jdt.ui/dialog_settings.xml +10 -0
- data/vendor/movie-content-editor-read-only/.metadata/.plugins/org.eclipse.ui.ide/dialog_settings.xml +11 -0
- data/vendor/movie-content-editor-read-only/.metadata/.plugins/org.eclipse.ui.intro/dialog_settings.xml +4 -0
- data/vendor/movie-content-editor-read-only/.metadata/.plugins/org.eclipse.ui.workbench/dialog_settings.xml +10 -0
- data/vendor/movie-content-editor-read-only/.metadata/.plugins/org.eclipse.ui.workbench/workbench.xml +232 -0
- data/vendor/movie-content-editor-read-only/.metadata/.plugins/org.eclipse.ui.workbench/workingsets.xml +4 -0
- data/vendor/movie-content-editor-read-only/.metadata/version.ini +1 -0
- data/vendor/movie-content-editor-read-only/.project +17 -0
- data/vendor/movie-content-editor-read-only/.pydevproject +11 -0
- data/vendor/movie-content-editor-read-only/.settings/org.eclipse.core.resources.prefs +6 -0
- data/vendor/movie-content-editor-read-only/SubIt.py +171 -0
- data/vendor/movie-content-editor-read-only/VLCMacVideo.py +257 -0
- data/vendor/movie-content-editor-read-only/VideoMac.ui +102 -0
- data/vendor/movie-content-editor-read-only/badwords.txt +4 -0
- data/vendor/movie-content-editor-read-only/blank.srt +4 -0
- data/vendor/movie-content-editor-read-only/edit.py +197 -0
- data/vendor/movie-content-editor-read-only/mergeCommands.py +73 -0
- data/vendor/movie-content-editor-read-only/mute.txt +5 -0
- data/vendor/movie-content-editor-read-only/panda.srt +4235 -0
- data/vendor/movie-content-editor-read-only/panda_custom.txt +3 -0
- data/vendor/movie-content-editor-read-only/panda_edit.srt +4235 -0
- data/vendor/movie-content-editor-read-only/subtitle.py +90 -0
- data/vendor/movie-content-editor-read-only/vlc.py +5579 -0
- data/vendor/movie-content-editor-read-only/vlcwidget.py +154 -0
- data/vendor/mplayer_patches/how_to_doze.bat +6 -0
- data/vendor/mplayer_patches/port_dir/PortIndex.quick +2 -0
- data/vendor/mplayer_patches/port_dir/how_to +20 -0
- data/vendor/mplayer_patches/port_dir/multimedia/mplayer-edl/Portfile +285 -0
- data/vendor/mplayer_patches/port_dir/multimedia/mplayer-edl/files/configure.x11.patch +20 -0
- data/vendor/mplayer_patches/port_dir/multimedia/mplayer-edl/files/llvm-gcc-workaround.patch +11 -0
- data/vendor/mplayer_patches/port_dir/multimedia/rdp-projects/Portfile +43 -0
- data/vendor/mplayer_patches/port_dir_is_for_mac +0 -0
- data/www/content_editor.html +92 -0
- data/www/index.html +47 -0
- data/www/upconverting_movie_player.html +62 -0
- data/www/video reel.jpg +0 -0
- data/www/youtube_edl/.htaccess +44 -0
- data/www/youtube_edl/control_youtube.rhtml +141 -0
- data/www/youtube_edl/dispatch.fcgi +25 -0
- data/www/youtube_edl/render_edited.rb +25 -0
- data/www/youtube_edl/server_this_dir.rb +6 -0
- data/www/youtube_edl/todo +23 -0
- data/www/zoomplayer_max.png +0 -0
- data/zamples/edit_decision_lists/dvds/Harry Potter 2 chamber of secrets.txt +22 -0
- data/zamples/edit_decision_lists/dvds/aa_example_delete_list_that_has_no_cuts_in_it.txt +10 -0
- data/zamples/edit_decision_lists/dvds/aladdin.txt +30 -0
- data/zamples/edit_decision_lists/dvds/bambi.txt +17 -0
- data/zamples/edit_decision_lists/dvds/big_buck_bunny_dvd.txt +23 -0
- data/zamples/edit_decision_lists/dvds/bob the builder pets in a pickle.txt +10 -0
- data/zamples/edit_decision_lists/dvds/bobs_big_plan.txt +10 -0
- data/zamples/edit_decision_lists/dvds/cars_2.txt +26 -0
- data/zamples/edit_decision_lists/dvds/cars_disney.txt +40 -0
- data/zamples/edit_decision_lists/dvds/condor_man_widescreen.txt +22 -0
- data/zamples/edit_decision_lists/dvds/cool runnings.txt +53 -0
- data/zamples/edit_decision_lists/dvds/court_jester.txt +24 -0
- data/zamples/edit_decision_lists/dvds/edls_being_edited/amazing_grace.txt +49 -0
- data/zamples/edit_decision_lists/dvds/edls_being_edited/father_goose.txt +41 -0
- data/zamples/edit_decision_lists/dvds/edls_being_edited/harry_potter_and_the_goblet_of_fire.txt +45 -0
- data/zamples/edit_decision_lists/dvds/edls_being_edited/hugo.txt +31 -0
- data/zamples/edit_decision_lists/dvds/edls_being_edited/making_marriage_work.txt +15 -0
- data/zamples/edit_decision_lists/dvds/edls_being_edited/national_treasure.txt +26 -0
- data/zamples/edit_decision_lists/dvds/edls_being_edited/percy_jackson_lightening_thief.txt +40 -0
- data/zamples/edit_decision_lists/dvds/edls_being_edited/percy_jackson_lightening_thief_mute_scary.txt +23 -0
- data/zamples/edit_decision_lists/dvds/edls_being_edited/prince_of_egypt.txt +28 -0
- data/zamples/edit_decision_lists/dvds/edls_being_edited/puss_in_boots.txt +33 -0
- data/zamples/edit_decision_lists/dvds/edls_being_edited/ratatouille.txt +35 -0
- data/zamples/edit_decision_lists/dvds/edls_being_edited/rio.txt +24 -0
- data/zamples/edit_decision_lists/dvds/edls_being_edited/test_delete_list_for_experimenting_with.txt +10 -0
- data/zamples/edit_decision_lists/dvds/edls_being_edited/the_explorers.txt +49 -0
- data/zamples/edit_decision_lists/dvds/finding_neverland.txt +32 -0
- data/zamples/edit_decision_lists/dvds/flight_of_the_navigator.txt +40 -0
- data/zamples/edit_decision_lists/dvds/happiest baby on the block.txt +9 -0
- data/zamples/edit_decision_lists/dvds/harry_potter_3_prisoner_of_azkaban.txt +37 -0
- data/zamples/edit_decision_lists/dvds/hitchhiker's_guide_to_the_galaxy.txt +32 -0
- data/zamples/edit_decision_lists/dvds/how_to_train_your_dragon.txt +25 -0
- data/zamples/edit_decision_lists/dvds/if_a_man_answers.txt +43 -0
- data/zamples/edit_decision_lists/dvds/innerspace.txt +77 -0
- data/zamples/edit_decision_lists/dvds/iq.txt +32 -0
- data/zamples/edit_decision_lists/dvds/king_of_kings.txt +28 -0
- data/zamples/edit_decision_lists/dvds/kung_fu_panda_1.txt +17 -0
- data/zamples/edit_decision_lists/dvds/legend_of_the_guardians_the_owls_of_gahoole.txt +18 -0
- data/zamples/edit_decision_lists/dvds/monsters_vs_aliens.txt +41 -0
- data/zamples/edit_decision_lists/dvds/muppet_treasure_island.txt +21 -0
- data/zamples/edit_decision_lists/dvds/nanny_mcphee.txt +31 -0
- data/zamples/edit_decision_lists/dvds/narnia_voyage_of_the_dawn_treader.txt +16 -0
- data/zamples/edit_decision_lists/dvds/pack_jackson_wedding_2007-03-03.txt +31 -0
- data/zamples/edit_decision_lists/dvds/peter_pan.txt +29 -0
- data/zamples/edit_decision_lists/dvds/remember_the_titans.txt +35 -0
- data/zamples/edit_decision_lists/dvds/sintel_open_source_blender_ntsc_dvd.txt +22 -0
- data/zamples/edit_decision_lists/dvds/snow_white_and_the_7_dwarfs_1937.txt +19 -0
- data/zamples/edit_decision_lists/dvds/speed_racer.txt +47 -0
- data/zamples/edit_decision_lists/dvds/tangled.txt +21 -0
- data/zamples/edit_decision_lists/dvds/tron_legacy.txt +29 -0
- data/zamples/edit_decision_lists/dvds/turn_around_alma_younger.txt +17 -0
- data/zamples/edit_decision_lists/files/conference_music_video.txt +10 -0
- data/zamples/edit_decision_lists/netflix_instant/avatar-last-air-bender-movie.txt +13 -0
- data/zamples/edit_decision_lists/netflix_instant/avatar-last-airbender-series.txt +1 -0
- data/zamples/edit_decision_lists/netflix_instant/greatest_story_ever_told_netflix.txt +10 -0
- data/zamples/edit_decision_lists/netflix_instant/wrinkle-in-time.txt +23 -0
- data/zamples/edit_decision_lists/notes_on_movies_without_edls_yet/tron.txt +10 -0
- data/zamples/edit_decision_lists/old_not_yet_updated/dvds/White Christmas.txt +15 -0
- data/zamples/edit_decision_lists/old_not_yet_updated/dvds/all_dogs_go_to_heaven.txt +9 -0
- data/zamples/edit_decision_lists/old_not_yet_updated/dvds/cars_disney.txt +24 -0
- data/zamples/edit_decision_lists/old_not_yet_updated/dvds/happy_feet.txt +12 -0
- data/zamples/edit_decision_lists/old_not_yet_updated/dvds/labyrinth.txt +17 -0
- data/zamples/edit_decision_lists/old_not_yet_updated/dvds/star_trek_generations_hulu.txt +8 -0
- data/zamples/edit_decision_lists/old_not_yet_updated/example_edit_decision_list.txt +14 -0
- data/zamples/edit_decision_lists/old_not_yet_updated/youtube/gummy_bear_song_youtube.txt +9 -0
- data/zamples/edit_decision_lists/youtube/demo_mutes.txt +12 -0
- data/zamples/edit_decision_lists/youtube/nuki_song_youtube.txt +14 -0
- data/zamples/edit_decision_lists/youtube/nuki_song_youtube_pointer.txt +3 -0
- data/zamples/players/how_to_create_more_players.txt +24 -0
- data/zamples/players/hulu/total_length_over_an_hour.txt +25 -0
- data/zamples/players/netflix/netflix_firefox_non_maximized.txt +25 -0
- data/zamples/players/vlc/full_screened_total_length_over_an_hour.txt +27 -0
- data/zamples/players/vlc/windowed_total_length_over_an_hour.txt +26 -0
- data/zamples/players/vlc/windowed_total_length_under_an_hour.txt +22 -0
- data/zamples/players/youtube/full_screened_1024x768.txt +20 -0
- data/zamples/players/youtube/full_screened_1152x864.txt +20 -0
- data/zamples/players/youtube/full_screened_1680x1050.txt +20 -0
- data/zamples/players/youtube/normal_in_youtube.com.chrome.txt +23 -0
- data/zamples/players/youtube/note_these_assume_less_than_10_minutes_length.txt +2 -0
- metadata +483 -0
data/lib/eight_three.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'ffi'
|
2
|
+
|
3
|
+
module EightThree
|
4
|
+
extend FFI::Library
|
5
|
+
ffi_lib 'kernel32'
|
6
|
+
ffi_convention :stdcall
|
7
|
+
|
8
|
+
=begin
|
9
|
+
DWORD WINAPI GetShortPathName(
|
10
|
+
__in LPCTSTR lpszLongPath,
|
11
|
+
__out LPTSTR lpszShortPath,
|
12
|
+
__in DWORD cchBuffer
|
13
|
+
);
|
14
|
+
=end
|
15
|
+
|
16
|
+
attach_function :path_to_8_3, :GetShortPathNameA, [:pointer, :pointer, :uint], :uint
|
17
|
+
def self.convert_path_to_8_3 path
|
18
|
+
out = FFI::MemoryPointer.new 256 # bytes
|
19
|
+
path_to_8_3(path, out, out.size)
|
20
|
+
out = out.get_string 0
|
21
|
+
if out.size == 0
|
22
|
+
raise 'unable to convert--probably file does not exist yet ' + path
|
23
|
+
else
|
24
|
+
out
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
mplayer -dumpstream dvd://1 -dvd-device d: -dumpfile dvdout.mpg
|
@@ -0,0 +1,13 @@
|
|
1
|
+
start = 33.26
|
2
|
+
#play_this = "g:\\Video\\Sintel_NTSC\\Sintel_NTSC-2.m4v"
|
3
|
+
play_this = "dvdnav://1/d:"
|
4
|
+
#play_this = "dvd://1/d:"
|
5
|
+
#play_this = "title00.ts"
|
6
|
+
#play_this = "dvdout.mpg"
|
7
|
+
in_out = IO.popen("mplayer -vo direct3d -osdlevel 2 #{play_this} -ss #{start} -slave -font c:\\windows\\fonts\\arial.ttf", 'w')
|
8
|
+
in_out.puts "pause"
|
9
|
+
loop {
|
10
|
+
p 'accepting from console'
|
11
|
+
incoming = STDIN.gets
|
12
|
+
in_out.puts incoming.strip
|
13
|
+
}
|
data/lib/fake_blanker.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
=begin
|
2
|
+
Copyright 2010, Roger Pack
|
3
|
+
This file is part of Sensible Cinema.
|
4
|
+
|
5
|
+
Sensible Cinema is free software: you can redistribute it and/or modify
|
6
|
+
it under the terms of the GNU General Public License as published by
|
7
|
+
the Free Software Foundation, either version 3 of the License, or
|
8
|
+
(at your option) any later version.
|
9
|
+
|
10
|
+
Sensible Cinema is distributed in the hope that it will be useful,
|
11
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
GNU General Public License for more details.
|
14
|
+
|
15
|
+
You should have received a copy of the GNU General Public License
|
16
|
+
along with Sensible Cinema. If not, see <http://www.gnu.org/licenses/>.
|
17
|
+
=end
|
18
|
+
puts 'warning--using fake blanker'
|
19
|
+
|
20
|
+
class Blanker
|
21
|
+
|
22
|
+
def self.startup
|
23
|
+
end
|
24
|
+
def self.shutdown
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.blank_full_screen! text
|
28
|
+
puts 'the screen is now...blank!'
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.unblank_full_screen!
|
32
|
+
puts 'the screen is now...visible!'
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
data/lib/gui/base.rb
ADDED
@@ -0,0 +1,748 @@
|
|
1
|
+
#!/usr/bin/ruby # so my editor will like the file...
|
2
|
+
=begin
|
3
|
+
Copyright 2010, Roger Pack
|
4
|
+
This file is part of Sensible Cinema.
|
5
|
+
|
6
|
+
Sensible Cinema is free software: you can redistribute it and/or modify
|
7
|
+
it under the terms of the GNU General Public License as published by
|
8
|
+
the Free Software Foundation, either version 3 of the License, or
|
9
|
+
(at your option) any later version.
|
10
|
+
|
11
|
+
Sensible Cinema is distributed in the hope that it will be useful,
|
12
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
GNU General Public License for more details.
|
15
|
+
|
16
|
+
You should have received a copy of the GNU General Public License
|
17
|
+
along with Sensible Cinema. If not, see <http://www.gnu.org/licenses/>.
|
18
|
+
=end
|
19
|
+
|
20
|
+
alias system_original system
|
21
|
+
require 'fileutils'
|
22
|
+
|
23
|
+
class String
|
24
|
+
def snake_case
|
25
|
+
self.gsub(/::/, '/').
|
26
|
+
gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
|
27
|
+
gsub(/([a-z\d])([A-Z])/,'\1_\2').
|
28
|
+
tr("-", "_").
|
29
|
+
downcase
|
30
|
+
end
|
31
|
+
def quotify
|
32
|
+
'"' + self + '"'
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# a few I'll always need no matter what...
|
37
|
+
require_relative '../jruby-swing-helpers/swing_helpers'
|
38
|
+
require_relative '../jruby-swing-helpers/storage'
|
39
|
+
require_relative '../edl_parser'
|
40
|
+
require 'tmpdir'
|
41
|
+
require 'whichr'
|
42
|
+
require 'os'
|
43
|
+
|
44
|
+
if OS.doze?
|
45
|
+
autoload :WMI, 'ruby-wmi'
|
46
|
+
autoload :EightThree, './lib/eight_three'
|
47
|
+
end
|
48
|
+
|
49
|
+
# attempt to load on demand...i.e. faster...gah
|
50
|
+
for kls in [:MplayerEdl, :PlayAudio, :SubtitleProfanityFinder, :ConvertThirtyFps]
|
51
|
+
autoload kls, "./lib/#{kls.to_s.snake_case}"
|
52
|
+
end
|
53
|
+
|
54
|
+
for kls in [:PlayAudio, :RubyClip, :DriveInfo]
|
55
|
+
autoload kls, "./lib/jruby-swing-helpers/#{kls.to_s.snake_case}"
|
56
|
+
end
|
57
|
+
|
58
|
+
if OS.windows?
|
59
|
+
vendor_cache = File.expand_path(File.dirname(__FILE__)) + '/../../vendor/cache'
|
60
|
+
for name in ['.', 'ffmpeg', 'mplayer_edl']
|
61
|
+
# put them all before the old path
|
62
|
+
ENV['PATH'] = (vendor_cache + '/' + name).to_filename + ';' + ENV['PATH']
|
63
|
+
end
|
64
|
+
|
65
|
+
def add_smplayer_paths
|
66
|
+
discovered_smplayer_folders = Dir['{c,d,e,f,g}:/program files*/smplayer']
|
67
|
+
|
68
|
+
for folder in discovered_smplayer_folders
|
69
|
+
ENV['PATH'] = ENV['PATH'] + ";#{folder.gsub('/', "\\")}"
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
add_smplayer_paths
|
74
|
+
|
75
|
+
else
|
76
|
+
# handled in check_mac_installed.rb file
|
77
|
+
|
78
|
+
end
|
79
|
+
|
80
|
+
import 'javax.swing.ImageIcon'
|
81
|
+
|
82
|
+
module SensibleSwing
|
83
|
+
include SwingHelpers # various swing classes
|
84
|
+
JFrame
|
85
|
+
VERSION = File.read(File.dirname(__FILE__) + "/../../VERSION").strip
|
86
|
+
puts "v. " + VERSION
|
87
|
+
|
88
|
+
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()) # <sigh>
|
89
|
+
|
90
|
+
class MainWindow < JFrame
|
91
|
+
include SwingHelpers # work-around?
|
92
|
+
|
93
|
+
def initialize start_visible = true, args = ARGV # lodo not optionals
|
94
|
+
super "Sensible-Cinema #{VERSION} (GPL)"
|
95
|
+
@args = args # save them away so this works with sub-child-windows
|
96
|
+
force_accept_license_first # in other file :P
|
97
|
+
setDefaultCloseOperation JFrame::EXIT_ON_CLOSE # closes the whole app when they hit X ...
|
98
|
+
@panel = JPanel.new
|
99
|
+
@buttons = []
|
100
|
+
@panel.set_layout nil
|
101
|
+
add @panel # why can't I just slap these down? panel? huh?
|
102
|
+
@starting_button_y = 40
|
103
|
+
@button_width = 400
|
104
|
+
|
105
|
+
add_text_line "Welcome to Sensible Cinema!"
|
106
|
+
@starting_button_y += 10 # kinder ugly...
|
107
|
+
add_text_line " Rest mouse over buttons for \"help\" type descriptions (tooltips)."
|
108
|
+
@current_dvds_line1 = add_text_line "Checking present DVD's..."
|
109
|
+
@current_dvds_line2 = add_text_line ""
|
110
|
+
@callbacks_for_dvd_edl_present = []
|
111
|
+
DriveInfo.create_looping_drive_cacher
|
112
|
+
DriveInfo.add_notify_on_changed_disks { update_currently_inserted_dvd_list }
|
113
|
+
icon_filename = __DIR__ + "/../../vendor/profs.png"
|
114
|
+
raise unless File.exist? icon_filename # it doesn't check this for us?
|
115
|
+
setIconImage(ImageIcon.new(icon_filename).getImage())
|
116
|
+
check_for_various_dependencies
|
117
|
+
LocalStorage.set_once('init_preferences_once') {
|
118
|
+
show_blocking_message_dialog "let's setup user preferences once..."
|
119
|
+
set_individual_preferences
|
120
|
+
}
|
121
|
+
set_visible start_visible
|
122
|
+
end
|
123
|
+
|
124
|
+
def add_callback_for_dvd_edl_present &block
|
125
|
+
raise unless block
|
126
|
+
@callbacks_for_dvd_edl_present << block
|
127
|
+
update_currently_inserted_dvd_list # updates them :P
|
128
|
+
end
|
129
|
+
|
130
|
+
def update_currently_inserted_dvd_list
|
131
|
+
present_discs = []
|
132
|
+
DriveInfo.get_dvd_drives_as_openstruct.each{|disk|
|
133
|
+
if disk.VolumeName
|
134
|
+
dvd_id = DriveInfo.md5sum_disk(disk.MountPoint)
|
135
|
+
edit_list_path_if_present = EdlParser.single_edit_list_matches_dvd(dvd_id, true)
|
136
|
+
if edit_list_path_if_present
|
137
|
+
human_name = parse_edl(edit_list_path_if_present)['name']
|
138
|
+
human_name ||= ''
|
139
|
+
end
|
140
|
+
present_discs << [human_name, disk.VolumeName, edit_list_path_if_present]
|
141
|
+
end
|
142
|
+
}
|
143
|
+
found_one = false
|
144
|
+
present_discs.map!{|human_name, volume_name, has_edl|
|
145
|
+
if human_name
|
146
|
+
found_one = true
|
147
|
+
"DVD: #{human_name} has an Edit List available! (#{volume_name})"
|
148
|
+
else
|
149
|
+
"DVD: (#{volume_name}) has NO Edit List available!"
|
150
|
+
end
|
151
|
+
}
|
152
|
+
if present_discs.length > 0
|
153
|
+
@current_dvds_line1.text= ' ' + present_discs[0]
|
154
|
+
@current_dvds_line2.text= ' ' + present_discs[1..2].join(" ")
|
155
|
+
else
|
156
|
+
@current_dvds_line1.text= ' No DVD discs currently inserted.'
|
157
|
+
@current_dvds_line2.text = ''
|
158
|
+
end
|
159
|
+
@callbacks_for_dvd_edl_present.each{|c| c.call(present_discs.length > 0, found_one)}
|
160
|
+
end
|
161
|
+
|
162
|
+
def get_title_track_string descriptors, use_default_of_one = true
|
163
|
+
given = descriptors["dvd_title_track"]
|
164
|
+
given ||= "1" if use_default_of_one
|
165
|
+
given
|
166
|
+
end
|
167
|
+
|
168
|
+
def get_srt_filename descriptors, edl_filename
|
169
|
+
path = descriptors['subtitles_to_display_relative_path'] if descriptors
|
170
|
+
if path
|
171
|
+
path = File.expand_path(File.dirname(edl_filename) + '/' + path)
|
172
|
+
raise 'nonexisting srt file must be relative to the edl file...' + path unless File.exist? path
|
173
|
+
end
|
174
|
+
path
|
175
|
+
end
|
176
|
+
|
177
|
+
def we_are_in_create_mode
|
178
|
+
@args.index("--create-mode")
|
179
|
+
end
|
180
|
+
|
181
|
+
def we_are_in_developer_mode?
|
182
|
+
@args.detect{|a| a == '--developer-mode'}
|
183
|
+
end
|
184
|
+
|
185
|
+
def new_jbutton title, tooltip = nil
|
186
|
+
button = JButton.new title
|
187
|
+
button.tool_tip = tooltip
|
188
|
+
button.set_bounds(44, @starting_button_y, @button_width, 23)
|
189
|
+
@panel.add button
|
190
|
+
@buttons << button
|
191
|
+
if block_given? # allow for new_jbutton("xx") do ... end [this is possible through some miraculous means LOL]
|
192
|
+
button.on_clicked { yield }
|
193
|
+
end
|
194
|
+
increment_button_location
|
195
|
+
button
|
196
|
+
end
|
197
|
+
|
198
|
+
def add_text_line line
|
199
|
+
jlabel = JLabel.new line
|
200
|
+
happy = Font.new("Tahoma", Font::PLAIN, 11)
|
201
|
+
jlabel.setFont(happy)
|
202
|
+
jlabel.set_bounds(44,@starting_button_y ,460,14)
|
203
|
+
@panel.add jlabel
|
204
|
+
increment_button_location 18
|
205
|
+
jlabel
|
206
|
+
end
|
207
|
+
|
208
|
+
def increment_button_location how_much = 30
|
209
|
+
@starting_button_y += how_much
|
210
|
+
setSize @button_width+80, @starting_button_y + 50
|
211
|
+
end
|
212
|
+
|
213
|
+
LocalStorage = Storage.new("sensible_cinema_storage_#{VERSION}")
|
214
|
+
|
215
|
+
def when_thread_done(thread)
|
216
|
+
Thread.new {thread.join; yield }
|
217
|
+
end
|
218
|
+
|
219
|
+
|
220
|
+
# a window that when closed doesn't bring the whole app down
|
221
|
+
def new_child_window
|
222
|
+
child = MainWindow.new true, []
|
223
|
+
child.setDefaultCloseOperation(JFrame::DISPOSE_ON_CLOSE) # don't exit on close
|
224
|
+
child.parent=self # this should have failed in the PPL
|
225
|
+
# make both windows visible by moving the child down and to the right of its parent
|
226
|
+
x, y = self.get_location.x, self.get_location.y
|
227
|
+
child.set_location(x + 100, y + 100)
|
228
|
+
child
|
229
|
+
end
|
230
|
+
|
231
|
+
def run_smplayer_non_blocking *args
|
232
|
+
@background_thread = Thread.new {
|
233
|
+
run_smplayer_blocking *args
|
234
|
+
}
|
235
|
+
end
|
236
|
+
|
237
|
+
# basically run mplayer/smplayer on a file or DVD
|
238
|
+
def run_smplayer_blocking play_this, title_track_maybe_nil, passed_in_extra_options, force_use_mplayer, show_subs, start_full_screen, srt_filename
|
239
|
+
raise unless passed_in_extra_options # cannot be nil
|
240
|
+
extra_options = []
|
241
|
+
# -framedrop is for slow CPU's
|
242
|
+
# same with -autosync to try and help it stay in sync... -mc 0.03 is to A/V correct 1s audio per 2s video
|
243
|
+
# -hardframedrop might help but hurts the eyes just too much
|
244
|
+
extra_options << "-framedrop" # even in create mode, if the audio ever gets off, we're hosed with making accurate timestamps...so drop, until I hear otherwise...
|
245
|
+
extra_options << "-mc 2"
|
246
|
+
extra_options << "-autosync 30"
|
247
|
+
|
248
|
+
if we_are_in_create_mode
|
249
|
+
extra_options << "-osdlevel 2"
|
250
|
+
extra_options << "-osd-verbose" if we_are_in_developer_mode?
|
251
|
+
end
|
252
|
+
extra_options << "-osd-fractions 1"
|
253
|
+
|
254
|
+
if !show_subs && !srt_filename
|
255
|
+
# disable all subtitles :P
|
256
|
+
extra_options << "-nosub -noautosub -forcedsubsonly -sid 1000"
|
257
|
+
end
|
258
|
+
if srt_filename
|
259
|
+
extra_options << "-sub #{srt_filename}"
|
260
|
+
else
|
261
|
+
extra_options << "-alang en"
|
262
|
+
extra_options << "-slang en"
|
263
|
+
end
|
264
|
+
|
265
|
+
force_use_mplayer ||= OS.mac?
|
266
|
+
parent_parent = File.basename(File.dirname(play_this))
|
267
|
+
if parent_parent == 'VIDEO_TS'
|
268
|
+
# case d:\yo\VIDEO_TS\title0.vob
|
269
|
+
dvd_device_dir = normalize_path(File.dirname(play_this))
|
270
|
+
play_this = "\"dvdnav://#{title_track_maybe_nil}/#{dvd_device_dir}/..\""
|
271
|
+
elsif File.exist?(play_this + '/VIDEO_TS') || (play_this =~ /\/dev\/rdisk\d/)
|
272
|
+
# case d:\ where d:\VIDEO_TS exists [DVD mounted in drive, or DVD dir] or mac's /dev/rdisk1
|
273
|
+
play_this = "\"dvdnav://#{title_track_maybe_nil}/#{play_this}\""
|
274
|
+
else
|
275
|
+
# case g:\video\filename.mpg
|
276
|
+
# leave it the same...
|
277
|
+
end
|
278
|
+
if play_this =~ /dvdnav/ && title_track_maybe_nil
|
279
|
+
extra_options << "-msglevel identify=4" # prevent smplayer from using *forever* to look up info on DVD's with -identify ...
|
280
|
+
end
|
281
|
+
|
282
|
+
extra_options << "-mouse-movements #{get_upconvert_secondary_settings}" # just in case smplayer also needs -mouse-movements... :) LODO
|
283
|
+
extra_options << "-lavdopts threads=#{OS.cpu_count}" # just in case this helps [supposed to with h.264] # NB fast *crashes* doze...
|
284
|
+
if force_use_mplayer
|
285
|
+
extra_options << "-font #{File.expand_path('vendor/subfont.ttf')}"
|
286
|
+
key_strokes = <<-EOL
|
287
|
+
RIGHT seek +10
|
288
|
+
LEFT seek -10
|
289
|
+
DOWN seek -60
|
290
|
+
UP seek +60
|
291
|
+
ENTER {dvdnav} dvdnav select
|
292
|
+
MOUSE_BTN0 {dvdnav} dvdnav select
|
293
|
+
MOUSE_BTN0_DBL vo_fullscreen
|
294
|
+
MOUSE_BTN2 vo_fullscreen
|
295
|
+
KP_ENTER dvdnav select
|
296
|
+
# some for os x, some for doze. huh?
|
297
|
+
EOL
|
298
|
+
conf_file = File.expand_path './mplayer_input_conf'
|
299
|
+
File.write conf_file, key_strokes
|
300
|
+
extra_options << "-volume 100" # why start low? mplayer why oh why LODO
|
301
|
+
if OS.windows?
|
302
|
+
# direct3d for windows 7 old nvidia cards' sake [yipes] and also dvdnav sake
|
303
|
+
extra_options << "-vo direct3d"
|
304
|
+
conf_file = conf_file[2..-1] # strip off drive letter, which it doesn't seem to like no sir
|
305
|
+
end
|
306
|
+
if start_full_screen
|
307
|
+
extra_options << "-fs"
|
308
|
+
upconv = get_upconvert_vf_settings
|
309
|
+
upconv = "-vf #{upconv}" if upconv.present?
|
310
|
+
else
|
311
|
+
upconv = ""
|
312
|
+
end
|
313
|
+
if OS.doze?
|
314
|
+
mplayer_loc = LocalModifiedMplayer
|
315
|
+
assert File.exist?(mplayer_loc)
|
316
|
+
else
|
317
|
+
mplayer_loc = "mplayer"
|
318
|
+
end
|
319
|
+
c = "#{mplayer_loc} #{extra_options.join(' ')} #{upconv} -input conf=\"#{conf_file}\" #{passed_in_extra_options} \"#{play_this}\" "
|
320
|
+
else
|
321
|
+
if OS.windows?
|
322
|
+
extra_options << "-vo direct3d" # more light nvidia...should be ok...this wastes cpu...but we have to have it I guess...
|
323
|
+
end
|
324
|
+
set_smplayer_opts extra_options.join(' ') + " " + passed_in_extra_options, get_upconvert_vf_settings, show_subs
|
325
|
+
c = "smplayer \"#{play_this}\" -config-path \"#{File.dirname EightThree.convert_path_to_8_3(SMPlayerIniFile)}\" "
|
326
|
+
c += " -fullscreen " if start_full_screen
|
327
|
+
if !we_are_in_create_mode
|
328
|
+
#c += " -close-at-end " # still too unstable...
|
329
|
+
end
|
330
|
+
end
|
331
|
+
puts c
|
332
|
+
system_blocking c
|
333
|
+
end
|
334
|
+
|
335
|
+
SMPlayerIniFile = File.expand_path("~/.smplayer_sensible_cinema/smplayer.ini")
|
336
|
+
LocalModifiedMplayer = File.expand_path "vendor/cache/mplayer_edl/mplayer.exe"
|
337
|
+
|
338
|
+
def set_smplayer_opts to_this, video_settings, show_subs = false
|
339
|
+
p 'setting smplayer extra opts to this:' + to_this
|
340
|
+
old_prefs = File.read(SMPlayerIniFile) rescue ''
|
341
|
+
unless old_prefs.length > 0
|
342
|
+
# LODO double check the rest here...
|
343
|
+
old_prefs = "[%General]\nmplayer_bin=\n[advanced]\nmplayer_additional_options=\nmplayer_additional_video_filters=\n[subtitles]\nautoload_sub=false\n[performance]\npriority=3"
|
344
|
+
end
|
345
|
+
raise to_this if to_this =~ /"/ # unexpected, unfortunately... <smplayer bug>
|
346
|
+
assert new_prefs = old_prefs.gsub(/mplayer_additional_options=.*/, "mplayer_additional_options=#{to_this}")
|
347
|
+
assert new_prefs.gsub!(/autoload_sub=.*$/, "autoload_sub=#{show_subs.to_s}")
|
348
|
+
raise 'unexpected' if get_upconvert_vf_settings =~ /"/
|
349
|
+
assert new_prefs.gsub!(/mplayer_additional_video_filters=.*$/, "mplayer_additional_video_filters=\"#{video_settings}\"")
|
350
|
+
raise 'smplayer on non doze not expected...' unless OS.doze?
|
351
|
+
mplayer_to_use = LocalModifiedMplayer
|
352
|
+
assert File.exist?(mplayer_to_use)
|
353
|
+
new_value = "\"" + mplayer_to_use.to_filename.gsub("\\", '/') + '"' # forward slashes. Weird.
|
354
|
+
assert new_prefs.gsub!(/mplayer_bin=.*$/, "mplayer_bin=" + new_value)
|
355
|
+
# now some less important ones...
|
356
|
+
new_prefs.gsub!(/priority=.*$/, "priority=3") # normal priority...scary otherwise! lodo tell smplayer...
|
357
|
+
# enable dvdnav navigation, just for kicks I guess.
|
358
|
+
new_prefs.gsub!(/use_dvdnav=.*$/, "use_dvdnav=true")
|
359
|
+
|
360
|
+
FileUtils.mkdir_p File.dirname(SMPlayerIniFile)
|
361
|
+
File.write(SMPlayerIniFile, new_prefs)
|
362
|
+
new_prefs.each_line{|l| print l if l =~ /additional_video/} # debug
|
363
|
+
end
|
364
|
+
|
365
|
+
def system_blocking command
|
366
|
+
return true if command =~ /^@rem/ # JRUBY-5890 bug
|
367
|
+
raise command + " failed env #{ENV['PATH']}" unless system_original command
|
368
|
+
end
|
369
|
+
|
370
|
+
def system_non_blocking command
|
371
|
+
@background_thread = Thread.new { system_original command }
|
372
|
+
end
|
373
|
+
|
374
|
+
# force them choose which system call to use explicitly
|
375
|
+
if respond_to? :system
|
376
|
+
undef system
|
377
|
+
else # it's a reload
|
378
|
+
end
|
379
|
+
|
380
|
+
def play_dvd_smplayer_unedited use_mplayer_instead
|
381
|
+
drive_or_file, dvd_volume_name, dvd_id, edl_path_maybe_nil, descriptors = choose_dvd_or_file_and_edl_for_it(force_choose_edl_file_if_no_easy_match = true)
|
382
|
+
title_track_maybe_nil = get_title_track_string(descriptors, false)
|
383
|
+
if is_dvd?(drive_or_file)
|
384
|
+
dvd_options = get_dvd_playback_options(descriptors)
|
385
|
+
else
|
386
|
+
dvd_options = ''
|
387
|
+
end
|
388
|
+
run_smplayer_non_blocking drive_or_file, title_track_maybe_nil, dvd_options, use_mplayer_instead, true, false, get_srt_filename(descriptors, edl_path_maybe_nil)
|
389
|
+
end
|
390
|
+
|
391
|
+
def get_dvd_playback_options descriptors
|
392
|
+
out = []
|
393
|
+
|
394
|
+
nav, mpeg_time = descriptors['dvd_nav_packet_offset'] # like [0.5, 0.734067]
|
395
|
+
if nav
|
396
|
+
mpeg_time *= 1/1.001 # -> 29.97 fps
|
397
|
+
offset_time = mpeg_time - nav
|
398
|
+
else
|
399
|
+
# readings: 0.213 0.173 0.233 0.21 0.18 0.197 they're almost all right around 0.20...
|
400
|
+
show_blocking_message_dialog "error--your DVD EDL doesn\'t list a start offset time [dvd_nav_packet_offset] which is needed for precise accurate timing. Please run\nadvanced mode -> Display information about current DVD\nand add it to the EDL. Using a default for now...if you tweak any timing info you may want to set this more accurately first!"
|
401
|
+
offset_time = 0.20
|
402
|
+
end
|
403
|
+
raise if offset_time <= 0 # unexpected...
|
404
|
+
# -osd-add is because the initial NAV packet is "x" seconds off from the mpeg, and since
|
405
|
+
# we have it set within mplayer to "prefer to just give you the MPEG time when you haven't passed a DVD block"
|
406
|
+
# we wanted to match that more precisely once we did get past it.
|
407
|
+
# so basically today we are trying to "match" the underlying MPEG time well. Which is wrong, of course.
|
408
|
+
# either match the file or match the DVD, punk!
|
409
|
+
out << "-osd-add #{ "%0.3f" % offset_time}"
|
410
|
+
out.join(' ')
|
411
|
+
end
|
412
|
+
|
413
|
+
if OS.doze? # avoids spaces in filenames :)
|
414
|
+
EdlTempFile = EightThree.convert_path_to_8_3(Dir.tmpdir) + '\\mplayer.edl' # stay 8.3 friendly :)
|
415
|
+
else
|
416
|
+
raise if Dir.tmpdir =~ / / # that would be unexpected, and possibly cause problems...
|
417
|
+
EdlTempFile = Dir.tmpdir + '/mplayer.temp.edl'
|
418
|
+
end
|
419
|
+
|
420
|
+
EdlFilesChosen = {} # allow for switching tapes but still cache EDL loc. :P
|
421
|
+
|
422
|
+
def choose_dvd_or_file_and_edl_for_it force_choose_edl_file_if_no_easy_match = true
|
423
|
+
drive_or_file, dvd_volume_name, dvd_id = choose_dvd_drive_or_file false
|
424
|
+
edl_path = EdlFilesChosen[dvd_id]
|
425
|
+
if !edl_path
|
426
|
+
edl_path = EdlParser.single_edit_list_matches_dvd(dvd_id)
|
427
|
+
if !edl_path && force_choose_edl_file_if_no_easy_match
|
428
|
+
message = "Please pick a DVD Edit List File (none or more than one were found that seem to match #{dvd_volume_name})--may need to create one, if one doesn't exist yet"
|
429
|
+
show_blocking_message_dialog message
|
430
|
+
edl_path = new_existing_file_selector_and_select_file(message, EdlParser::EDL_DIR)
|
431
|
+
end
|
432
|
+
end
|
433
|
+
p 're/loading ' + edl_path # in case it has changed on disk
|
434
|
+
if edl_path # sometimes they don't have to choose one [?]
|
435
|
+
descriptors = nil
|
436
|
+
begin
|
437
|
+
descriptors = parse_edl edl_path
|
438
|
+
rescue SyntaxError => e
|
439
|
+
show_non_blocking_message_dialog("this file has an error--please fix then hit ok: \n" + edl_path + "\n " + e)
|
440
|
+
raise e
|
441
|
+
end
|
442
|
+
end
|
443
|
+
EdlFilesChosen[dvd_id] ||= edl_path
|
444
|
+
[drive_or_file, dvd_volume_name, dvd_id, edl_path, descriptors]
|
445
|
+
end
|
446
|
+
|
447
|
+
LocalStorage.set_default('mplayer_beginning_buffer', 0.5)
|
448
|
+
|
449
|
+
def is_dvd? drive_or_file
|
450
|
+
# it's like a/b/VIDEO_TS or d:/
|
451
|
+
if File.basename(File.dirname(drive_or_file)) == 'VIDEO_TS'
|
452
|
+
# /a/b/c/VIDEO_TS/yo.vob
|
453
|
+
true
|
454
|
+
elsif File.exist?(drive_or_file + '/VIDEO_TS')
|
455
|
+
# d:\
|
456
|
+
true
|
457
|
+
elsif OS.mac? && (drive_or_file =~ /\/dev\/rdisk\d+/)
|
458
|
+
true
|
459
|
+
else
|
460
|
+
false
|
461
|
+
end
|
462
|
+
end
|
463
|
+
|
464
|
+
# MplayerBeginingBuffer = 1.0
|
465
|
+
# MplayerEndBuffer = 0.0
|
466
|
+
def begin_buffer_preference
|
467
|
+
LocalStorage['mplayer_beginning_buffer']
|
468
|
+
end
|
469
|
+
|
470
|
+
def play_smplayer_edl_non_blocking optional_file_with_edl_path = nil, extra_mplayer_commands_array = [], force_mplayer = false, start_full_screen = true, add_secs_end = 0,
|
471
|
+
add_secs_begin = begin_buffer_preference, show_subs = false
|
472
|
+
if we_are_in_create_mode
|
473
|
+
assert(add_secs_begin == 0 && add_secs_end == 0)
|
474
|
+
end
|
475
|
+
if optional_file_with_edl_path
|
476
|
+
drive_or_file, edl_path = optional_file_with_edl_path
|
477
|
+
dvd_id = NonDvd # fake it out...LODO a bit smelly/ugly
|
478
|
+
else
|
479
|
+
drive_or_file, dvd_volume_name, dvd_id, edl_path, descriptors = choose_dvd_or_file_and_edl_for_it
|
480
|
+
end
|
481
|
+
start_add_this_to_all_ts = 0
|
482
|
+
|
483
|
+
if edl_path # some don't have one [?]
|
484
|
+
begin
|
485
|
+
# TODO combine these 2 methods yipzers
|
486
|
+
descriptors = EdlParser.parse_file edl_path
|
487
|
+
splits = [] # TODO not pass as parameter either
|
488
|
+
edl_contents = MplayerEdl.convert_to_edl descriptors, add_secs_end, add_secs_begin, splits, start_add_this_to_all_ts # add a sec to mutes to accomodate for mplayer's oddness..
|
489
|
+
File.write(EdlTempFile, edl_contents)
|
490
|
+
extra_mplayer_commands_array << "-edl #{EdlTempFile}"
|
491
|
+
rescue SyntaxError => e
|
492
|
+
show_blocking_message_dialog "unable to parse file! #{edl_path} #{e}"
|
493
|
+
raise
|
494
|
+
end
|
495
|
+
title_track = get_title_track_string(descriptors)
|
496
|
+
end
|
497
|
+
|
498
|
+
if is_dvd?(drive_or_file)
|
499
|
+
# it's a DVD of some sort
|
500
|
+
extra_mplayer_commands_array << get_dvd_playback_options(descriptors)
|
501
|
+
else
|
502
|
+
check_for_ffmpeg_installed
|
503
|
+
# it's a file
|
504
|
+
# check if it has a start offset...
|
505
|
+
all = `ffmpeg -i "#{drive_or_file}" 2>&1` # => Duration: 01:35:49.59, start: 600.000000
|
506
|
+
all =~ /Duration.*start: ([\d\.]+)/
|
507
|
+
start = $1.to_f
|
508
|
+
if start > 1 # LODO dvd's themselves start at 0.3 [sintel], but I don't think much higher than that never seen it...
|
509
|
+
show_non_blocking_message_dialog "Warning: file seems to start at an extra offset, adding it to the timestamps... #{start}
|
510
|
+
maybe not compatible with XBMC, if that's what you use, and you probably don't" # LODO test it XBMC...
|
511
|
+
start_add_this_to_all_ts = start
|
512
|
+
end
|
513
|
+
end
|
514
|
+
|
515
|
+
run_smplayer_non_blocking drive_or_file, title_track, extra_mplayer_commands_array.join(' '), force_mplayer, show_subs, start_full_screen, get_srt_filename(descriptors, edl_path)
|
516
|
+
end
|
517
|
+
|
518
|
+
def print *args
|
519
|
+
Kernel.print *args # avoid bin\sensible-cinema.rb:83:in `system_blocking': cannot convert instance of class org.jruby.RubyString to class java.awt.Graphics (TypeError)
|
520
|
+
end
|
521
|
+
|
522
|
+
def open_file_to_edit_it filename, options = {} # :start_minimized is the only option
|
523
|
+
if OS.windows?
|
524
|
+
if options[:start_minimized]
|
525
|
+
system_non_blocking "start /min notepad \"#{filename}\""
|
526
|
+
else
|
527
|
+
system_non_blocking "notepad \"#{filename}\""
|
528
|
+
end
|
529
|
+
else
|
530
|
+
# ignore minimized :P
|
531
|
+
system_non_blocking "open -a TextEdit \"#{filename}\""
|
532
|
+
end
|
533
|
+
end
|
534
|
+
|
535
|
+
def new_nonexisting_filechooser_and_go title = nil, default_dir = nil, default_file = nil
|
536
|
+
bring_to_front unless OS.mac? # causes triples on mac! TODO rdp
|
537
|
+
JFileChooser.new_nonexisting_filechooser_and_go title, default_dir, default_file
|
538
|
+
end
|
539
|
+
|
540
|
+
# also caches directory previously selected ...
|
541
|
+
def new_existing_file_selector_and_select_file title, dir = nil
|
542
|
+
bring_to_front unless OS.mac? # causes duplicate prompts or something?
|
543
|
+
unique_trace = caller.inspect
|
544
|
+
if LocalStorage[unique_trace]
|
545
|
+
dir = LocalStorage[unique_trace]
|
546
|
+
end
|
547
|
+
p 'using system default dir' unless dir # happens more frequently after code changes alter the path :P
|
548
|
+
p 'using lookup dir ' + dir, LocalStorage[unique_trace] if $VERBOSE
|
549
|
+
got = SwingHelpers.new_previously_existing_file_selector_and_go title, dir
|
550
|
+
LocalStorage[unique_trace] = File.dirname(got)
|
551
|
+
got
|
552
|
+
end
|
553
|
+
|
554
|
+
def show_blocking_message_dialog(message, title = message.split("\n")[0], style= JOptionPane::INFORMATION_MESSAGE)
|
555
|
+
SwingHelpers.show_blocking_message_dialog message, title, style
|
556
|
+
end
|
557
|
+
|
558
|
+
# call dispose on this to close it if it hasn't been canceled yet...
|
559
|
+
def show_non_blocking_message_dialog message, close_button_text = 'Close'
|
560
|
+
bring_to_front
|
561
|
+
# lodo NonBlockingDialog it can get to the top instead of being so buried...
|
562
|
+
SwingHelpers.show_non_blocking_message_dialog message, close_button_text
|
563
|
+
end
|
564
|
+
|
565
|
+
java_import javax.swing.UIManager
|
566
|
+
|
567
|
+
def get_user_input_with_persistence(message, storage_key)
|
568
|
+
got = get_user_input(message, LocalStorage[storage_key])
|
569
|
+
LocalStorage[storage_key] = got
|
570
|
+
got
|
571
|
+
end
|
572
|
+
def get_user_input(message, default = '', cancel_ok = false)
|
573
|
+
SwingHelpers.get_user_input message, default, cancel_ok
|
574
|
+
end
|
575
|
+
|
576
|
+
def show_copy_pastable_string(message, value)
|
577
|
+
bring_to_front
|
578
|
+
RubyClip.set_clipboard value
|
579
|
+
get_user_input message + " (has been copied to clipboard)", value, true
|
580
|
+
end
|
581
|
+
|
582
|
+
def show_in_explorer filename
|
583
|
+
SwingHelpers.show_in_explorer filename
|
584
|
+
end
|
585
|
+
|
586
|
+
def show_select_buttons_prompt message, names ={}
|
587
|
+
SwingHelpers.show_select_buttons_prompt(message, names)
|
588
|
+
end
|
589
|
+
|
590
|
+
def parse_edl path
|
591
|
+
EdlParser.parse_file path
|
592
|
+
end
|
593
|
+
|
594
|
+
def get_freespace path
|
595
|
+
JFile.new(File.dirname(path)).get_usable_space
|
596
|
+
end
|
597
|
+
|
598
|
+
def get_drive_with_most_space_with_slash
|
599
|
+
DriveInfo.get_drive_with_most_space_with_slash
|
600
|
+
end
|
601
|
+
|
602
|
+
attr_accessor :background_thread, :buttons
|
603
|
+
|
604
|
+
NonDvd = 'non dvd has no dvdid' # we need it for convenience, say you want to go through your indexed vids and convert them all?
|
605
|
+
|
606
|
+
# returns e:\, volume_name, dvd_id
|
607
|
+
# or full_path.mkv, filename, ''
|
608
|
+
def choose_dvd_drive_or_file force_choose_only_dvd_drive
|
609
|
+
opticals = DriveInfo.get_dvd_drives_as_openstruct
|
610
|
+
if @saved_opticals == opticals && @_choose_dvd_drive_or_file
|
611
|
+
# memoize...if disks haven't changed :)
|
612
|
+
return @_choose_dvd_drive_or_file
|
613
|
+
else
|
614
|
+
@saved_opticals = opticals # save currently mounted disk list, so we know if we should re-select later...
|
615
|
+
# is this ok for os x?
|
616
|
+
end
|
617
|
+
|
618
|
+
has_at_least_one_dvd_inserted = opticals.find{|d| d.VolumeName }
|
619
|
+
if !has_at_least_one_dvd_inserted && force_choose_only_dvd_drive
|
620
|
+
show_blocking_message_dialog 'insert a dvd first'
|
621
|
+
raise 'no dvd found'
|
622
|
+
end
|
623
|
+
names = opticals.map{|d| d.Name + "\\" + " (" + (d.VolumeName || 'Insert DVD to use') + ")"}
|
624
|
+
if !force_choose_only_dvd_drive && !has_at_least_one_dvd_inserted
|
625
|
+
names += ['No DVD mounted so click to choose a Local File (or insert DVD, then re-try)']
|
626
|
+
used_local_file_option = true
|
627
|
+
end
|
628
|
+
|
629
|
+
count = 0
|
630
|
+
opticals.each{|d| count += 1 if d.VolumeName}
|
631
|
+
if count == 1 && !used_local_file_option
|
632
|
+
# just choose it if there's only one disk available..
|
633
|
+
p 'selecting only disk currently present in the various DVD drives [if you have more than one, that is]'
|
634
|
+
selected_idx = opticals.index{|d| d.VolumeName}
|
635
|
+
unless selected_idx
|
636
|
+
show_blocking_message_dialog "Please insert a disk first"
|
637
|
+
raise 'inset disk'
|
638
|
+
end
|
639
|
+
else
|
640
|
+
dialog = get_disk_chooser_window names
|
641
|
+
selected_idx = dialog.go_selected_index
|
642
|
+
end
|
643
|
+
if used_local_file_option
|
644
|
+
raise unless selected_idx == 0 # it was our only option...they must have selected it!
|
645
|
+
filename = new_existing_file_selector_and_select_file("Select yer previously grabbed from DVD file")
|
646
|
+
assert_ownership_dialog
|
647
|
+
return [filename, File.basename(filename), NonDvd]
|
648
|
+
else
|
649
|
+
disk = opticals[selected_idx]
|
650
|
+
out = show_non_blocking_message_dialog "calculating current disk's unique id...if this pauses more than 10s then clean your DVD..."
|
651
|
+
begin
|
652
|
+
dvd_id = DriveInfo.md5sum_disk(disk.MountPoint)
|
653
|
+
rescue Exception => e
|
654
|
+
show_blocking_message_dialog e.to_s # todo a bit ugly...
|
655
|
+
raise
|
656
|
+
ensure
|
657
|
+
out.dispose
|
658
|
+
end
|
659
|
+
@_choose_dvd_drive_or_file = [disk.DevicePoint, opticals[selected_idx].VolumeName, dvd_id]
|
660
|
+
return @_choose_dvd_drive_or_file
|
661
|
+
end
|
662
|
+
end
|
663
|
+
|
664
|
+
|
665
|
+
def display_and_raise error_message
|
666
|
+
show_blocking_message_dialog error_message
|
667
|
+
raise error_message
|
668
|
+
end
|
669
|
+
|
670
|
+
def with_autoclose_message(message)
|
671
|
+
a = show_non_blocking_message_dialog message
|
672
|
+
yield
|
673
|
+
a.close
|
674
|
+
end
|
675
|
+
|
676
|
+
def we_are_in_upconvert_mode
|
677
|
+
@args.index("--upconvert-mode")
|
678
|
+
end
|
679
|
+
|
680
|
+
def setup_default_buttons
|
681
|
+
if we_are_in_upconvert_mode
|
682
|
+
add_play_upconvert_buttons
|
683
|
+
else
|
684
|
+
if we_are_in_create_mode
|
685
|
+
setup_create_buttons
|
686
|
+
else
|
687
|
+
setup_normal_buttons
|
688
|
+
end
|
689
|
+
|
690
|
+
end # big else
|
691
|
+
|
692
|
+
@exit = new_jbutton("Exit", "Exits the application and kills any background processes that are running at all--don't exit unless you are done processing all the way!")
|
693
|
+
@exit.on_clicked {
|
694
|
+
Thread.new { self.close } # don't waste the time to close it :P
|
695
|
+
puts 'Thank you for using Sensible Cinema. Come again!'
|
696
|
+
System.exit 0
|
697
|
+
}
|
698
|
+
|
699
|
+
increment_button_location
|
700
|
+
increment_button_location
|
701
|
+
self
|
702
|
+
|
703
|
+
end
|
704
|
+
|
705
|
+
def get_disk_chooser_window names
|
706
|
+
DropDownSelector.new(self, names, "Click to select DVD drive")
|
707
|
+
end
|
708
|
+
|
709
|
+
def get_temp_file_name name_with_ext
|
710
|
+
File.dirname(EdlTempFile) + '/' + name_with_ext
|
711
|
+
end
|
712
|
+
|
713
|
+
# converts to full path, 8.3 if on doze
|
714
|
+
def normalize_path path
|
715
|
+
path = File.expand_path path
|
716
|
+
path = EightThree.convert_path_to_8_3 path if OS.doze?
|
717
|
+
end
|
718
|
+
|
719
|
+
|
720
|
+
end
|
721
|
+
|
722
|
+
end
|
723
|
+
|
724
|
+
|
725
|
+
class ::File
|
726
|
+
def self.get_root_dir this_path
|
727
|
+
this_path = File.expand_path this_path
|
728
|
+
if OS.doze?
|
729
|
+
this_path[0..2]
|
730
|
+
else
|
731
|
+
this_path.split('/')[0]
|
732
|
+
end
|
733
|
+
end
|
734
|
+
|
735
|
+
def self.strip_drive_windows this_complete_path
|
736
|
+
if OS.doze?
|
737
|
+
this_complete_path[2..-1]
|
738
|
+
else
|
739
|
+
this_complete_path
|
740
|
+
end
|
741
|
+
end
|
742
|
+
end
|
743
|
+
|
744
|
+
class ::String
|
745
|
+
def just_letters
|
746
|
+
gsub(/[^a-z0-9]/i, '').downcase
|
747
|
+
end
|
748
|
+
end
|