one-k-rmov 0.1.4
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +38 -0
- data/LICENSE +20 -0
- data/Manifest +24 -0
- data/README.rdoc +73 -0
- data/Rakefile +16 -0
- data/TODO +15 -0
- data/ext/exporter.c +195 -0
- data/ext/extconf.rb +4 -0
- data/ext/movie.c +457 -0
- data/ext/rmov_ext.c +16 -0
- data/ext/rmov_ext.h +45 -0
- data/ext/track.c +391 -0
- data/lib/quicktime/exporter.rb +10 -0
- data/lib/quicktime/movie.rb +102 -0
- data/lib/quicktime/track.rb +31 -0
- data/lib/rmov.rb +12 -0
- data/rmov.gemspec +32 -0
- data/spec/fixtures/settings.st +0 -0
- data/spec/quicktime/exporter_spec.rb +29 -0
- data/spec/quicktime/movie_spec.rb +189 -0
- data/spec/quicktime/track_spec.rb +86 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +7 -0
- data/tasks/setup.rake +7 -0
- data/tasks/spec.rake +9 -0
- metadata +98 -0
data/CHANGELOG
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
|
2
|
+
* adding more property information from movie and track, such as codec information
|
3
|
+
|
4
|
+
1K Studios Forked Version
|
5
|
+
|
6
|
+
0.1.4 (October 3rd, 2008)
|
7
|
+
|
8
|
+
* adding support for several export_image formats (PNG, JPEG, TIFF, TGA, BMP, PSD)
|
9
|
+
|
10
|
+
* adding movie.export_image as a generic way to export a frame to multiple formats
|
11
|
+
|
12
|
+
0.1.3 (October 3rd, 2008)
|
13
|
+
|
14
|
+
* some support for text tracks
|
15
|
+
|
16
|
+
* adding movie.new_video_track and movie.new_audio_track methods for creating new tracks
|
17
|
+
|
18
|
+
* changing Quicktime module name to QuickTime to match proper casing
|
19
|
+
|
20
|
+
0.1.2 (October 3rd, 2008)
|
21
|
+
|
22
|
+
* movie.poster_time and movie.poster_time=(seconds) for getting and setting a movie's poster time
|
23
|
+
|
24
|
+
* track.offset and track.offset=(seconds) for getting and setting a track's offset time from the start of a movie
|
25
|
+
|
26
|
+
* track.volume and track.volume=(vol) for getting and setting a track's volume
|
27
|
+
|
28
|
+
* QuickTime settings dialog comes into the forground properly
|
29
|
+
|
30
|
+
0.1.1 (October 3rd, 2008)
|
31
|
+
|
32
|
+
* RubyGems 1.3 compatibility (updated Echoe)
|
33
|
+
|
34
|
+
* fixing inline RDocs so call sequence is handled properly
|
35
|
+
|
36
|
+
0.1.0 (October 2nd, 2008)
|
37
|
+
|
38
|
+
* initial release
|
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2008 Ryan Bates
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Manifest
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
CHANGELOG
|
2
|
+
ext/exporter.c
|
3
|
+
ext/extconf.rb
|
4
|
+
ext/movie.c
|
5
|
+
ext/rmov_ext.c
|
6
|
+
ext/rmov_ext.h
|
7
|
+
ext/track.c
|
8
|
+
lib/quicktime/exporter.rb
|
9
|
+
lib/quicktime/movie.rb
|
10
|
+
lib/quicktime/track.rb
|
11
|
+
lib/rmov.rb
|
12
|
+
LICENSE
|
13
|
+
Manifest
|
14
|
+
Rakefile
|
15
|
+
README.rdoc
|
16
|
+
spec/fixtures/settings.st
|
17
|
+
spec/quicktime/exporter_spec.rb
|
18
|
+
spec/quicktime/movie_spec.rb
|
19
|
+
spec/quicktime/track_spec.rb
|
20
|
+
spec/spec.opts
|
21
|
+
spec/spec_helper.rb
|
22
|
+
tasks/setup.rake
|
23
|
+
tasks/spec.rake
|
24
|
+
TODO
|
data/README.rdoc
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
= RMov
|
2
|
+
|
3
|
+
Open, edit, and export QuickTime movies all within Ruby! This is an
|
4
|
+
unofficial wrapper around Apple's QuickTime C API. Mac OS X required.
|
5
|
+
|
6
|
+
|
7
|
+
== Install
|
8
|
+
|
9
|
+
Install the gem:
|
10
|
+
|
11
|
+
gem install rmov
|
12
|
+
|
13
|
+
And then load it in your project:
|
14
|
+
|
15
|
+
require 'rmov'
|
16
|
+
|
17
|
+
|
18
|
+
== Usage
|
19
|
+
|
20
|
+
Use this gem to open QuickTime movies and edit them to your liking.
|
21
|
+
|
22
|
+
movie1 = QuickTime::Movie.open("path/to/movie.mov")
|
23
|
+
movie2 = QuickTime::Movie.open("path/to/another_movie.mov")
|
24
|
+
|
25
|
+
# add movie2 to the end of movie1
|
26
|
+
movie1.append_movie(movie2)
|
27
|
+
|
28
|
+
# make a new movie out of a section of movie 1
|
29
|
+
# this will delete 5 seconds out of the movie at 2 seconds in
|
30
|
+
movie3 = movie1.clip_section(2, 5)
|
31
|
+
|
32
|
+
# You can insert that part back into the movie at 8 seconds in
|
33
|
+
movie1.insert_movie(movie3, 8)
|
34
|
+
|
35
|
+
Now you can export the movie. Usually this is done through a user
|
36
|
+
interface the first time around. The settings can then be saved to
|
37
|
+
a file. After that you can load these settings without interfering
|
38
|
+
the user with the dialog again.
|
39
|
+
|
40
|
+
exporter = movie1.exporter
|
41
|
+
|
42
|
+
# if we already have saved the settings, load those
|
43
|
+
if File.exist? "settings.st"
|
44
|
+
exporter.load_settings("settings.st")
|
45
|
+
else
|
46
|
+
# otherwise open the QuickTime GUI settings dialog
|
47
|
+
exporter.open_settings_dialog
|
48
|
+
|
49
|
+
# save settings to a file so we don't have to bother user next time
|
50
|
+
exporter.save_settings("settings.st")
|
51
|
+
end
|
52
|
+
|
53
|
+
# export the movie to a file and report the progress along the way
|
54
|
+
exporter.export("movie.mov") do |progress|
|
55
|
+
percent = (progress*100).round
|
56
|
+
puts "#{percent}% complete"
|
57
|
+
end
|
58
|
+
|
59
|
+
See QuickTime::Movie in the RDoc for more information.
|
60
|
+
|
61
|
+
http://rmov.rubyforge.org
|
62
|
+
|
63
|
+
|
64
|
+
== Development
|
65
|
+
|
66
|
+
This project can be found on github at the following URL.
|
67
|
+
|
68
|
+
http://github.com/ryanb/rmov
|
69
|
+
|
70
|
+
If you find a bug, please send me a message on GitHub.
|
71
|
+
|
72
|
+
If you would like to contribute to this project, please fork the
|
73
|
+
repository and send me a pull request.
|
data/Rakefile
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
require 'echoe'
|
4
|
+
|
5
|
+
Echoe.new('rmov', '0.1.4') do |p|
|
6
|
+
p.summary = "Ruby wrapper for the QuickTime C API."
|
7
|
+
p.description = "Ruby wrapper for the QuickTime C API."
|
8
|
+
p.url = "http://github.com/ryanb/rmov"
|
9
|
+
p.author = 'Ryan Bates'
|
10
|
+
p.email = "ryan (at) railscasts (dot) com"
|
11
|
+
p.ignore_pattern = ["script/*", "tmp/*", "spec/output/*", "**/*.o", "**/*.bundle", "**/*.mov"]
|
12
|
+
p.extensions = ["ext/extconf.rb"]
|
13
|
+
p.development_dependencies = []
|
14
|
+
end
|
15
|
+
|
16
|
+
Dir["#{File.dirname(__FILE__)}/tasks/*.rake"].sort.each { |ext| load ext }
|
data/TODO
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
Fixes
|
2
|
+
- check if movie/track really exists each time we call it
|
3
|
+
|
4
|
+
Features
|
5
|
+
- resize movie
|
6
|
+
- get movie metadata (album, author, artist, etc.)
|
7
|
+
- set movie metadata
|
8
|
+
- add text track to movie
|
9
|
+
- add chapters to movie
|
10
|
+
|
11
|
+
Possible
|
12
|
+
- time remapping
|
13
|
+
- programatically adjust export settings (framerate, codec, etc.)
|
14
|
+
- export image sequence
|
15
|
+
- import image sequence
|
data/ext/exporter.c
ADDED
@@ -0,0 +1,195 @@
|
|
1
|
+
#include "rmov_ext.h"
|
2
|
+
|
3
|
+
VALUE cExporter;
|
4
|
+
|
5
|
+
static void exporter_free(struct RExporter *rExporter)
|
6
|
+
{
|
7
|
+
if (rExporter->settings) {
|
8
|
+
QTDisposeAtomContainer(rExporter->settings);
|
9
|
+
}
|
10
|
+
}
|
11
|
+
|
12
|
+
static void exporter_mark(struct RExporter *rExporter)
|
13
|
+
{
|
14
|
+
}
|
15
|
+
|
16
|
+
/*
|
17
|
+
call-seq: new(movie) -> exporter
|
18
|
+
|
19
|
+
Creates a new exporter instance. Usually this is done through movie.exporter.
|
20
|
+
*/
|
21
|
+
static VALUE exporter_new(VALUE klass)
|
22
|
+
{
|
23
|
+
struct RExporter *rExporter;
|
24
|
+
return Data_Make_Struct(klass, struct RExporter, exporter_mark, exporter_free, rExporter);
|
25
|
+
}
|
26
|
+
|
27
|
+
static ComponentInstance exporter_component(VALUE obj)
|
28
|
+
{
|
29
|
+
ComponentInstance component = OpenDefaultComponent('spit', 'MooV');
|
30
|
+
if (REXPORTER(obj)->settings) {
|
31
|
+
MovieExportSetSettingsFromAtomContainer(component, REXPORTER(obj)->settings);
|
32
|
+
}
|
33
|
+
return component;
|
34
|
+
}
|
35
|
+
|
36
|
+
/*
|
37
|
+
call-seq: export_to_file(filepath)
|
38
|
+
|
39
|
+
Exports a movie to the given filepath. This will use either the
|
40
|
+
settings you set beforehand, or QuickTime's defaults.
|
41
|
+
|
42
|
+
You can track the progress of this operation by passing a block to this
|
43
|
+
method. It will be called regularly during the process and pass the
|
44
|
+
percentage complete (0.0 to 1.0) as an argument to the block.
|
45
|
+
*/
|
46
|
+
static VALUE exporter_export_to_file(VALUE obj, VALUE filepath)
|
47
|
+
{
|
48
|
+
OSErr err;
|
49
|
+
FSSpec fs;
|
50
|
+
Movie movie = MOVIE(rb_iv_get(obj, "@movie"));
|
51
|
+
ComponentInstance component = exporter_component(obj);
|
52
|
+
|
53
|
+
if (rb_block_given_p())
|
54
|
+
SetMovieProgressProc(movie, (MovieProgressUPP)movie_progress_proc, rb_block_proc());
|
55
|
+
|
56
|
+
// Activate so QuickTime doesn't export a white frame
|
57
|
+
SetMovieActive(movie, TRUE);
|
58
|
+
|
59
|
+
err = NativePathNameToFSSpec(RSTRING(filepath)->ptr, &fs, 0);
|
60
|
+
if (err != fnfErr)
|
61
|
+
rb_raise(eQuickTime, "Error %d occurred while opening file for export at %s.", err, RSTRING(filepath)->ptr);
|
62
|
+
|
63
|
+
// TODO use exporter settings when converting movie
|
64
|
+
err = ConvertMovieToFile(movie, 0, &fs, 'MooV', 'TVOD', 0, 0, 0, component);
|
65
|
+
if (err != noErr)
|
66
|
+
rb_raise(eQuickTime, "Error %d occurred while attempting to export movie to file %s.", err, RSTRING(filepath)->ptr);
|
67
|
+
|
68
|
+
if (rb_block_given_p())
|
69
|
+
SetMovieProgressProc(movie, 0, 0);
|
70
|
+
|
71
|
+
CloseComponent(component);
|
72
|
+
|
73
|
+
return Qnil;
|
74
|
+
}
|
75
|
+
|
76
|
+
/*
|
77
|
+
call-seq: open_settings_dialog()
|
78
|
+
|
79
|
+
Opens the offical QuickTime GUI settings dialog. The process will be
|
80
|
+
suspended until the user closes the dialogue. If the user clicks Okay
|
81
|
+
the settings will be applied to this Exporter. You can then use
|
82
|
+
save_settings to save them to a file, and load_settings to load them
|
83
|
+
back again.
|
84
|
+
*/
|
85
|
+
static VALUE exporter_open_settings_dialog(VALUE obj)
|
86
|
+
{
|
87
|
+
Boolean canceled;
|
88
|
+
OSErr err;
|
89
|
+
ProcessSerialNumber current_process = {0, kCurrentProcess};
|
90
|
+
Movie movie = MOVIE(rb_iv_get(obj, "@movie"));
|
91
|
+
ComponentInstance component = exporter_component(obj);
|
92
|
+
|
93
|
+
// Bring this process to the front
|
94
|
+
err = TransformProcessType(¤t_process, kProcessTransformToForegroundApplication);
|
95
|
+
if (err != noErr) {
|
96
|
+
rb_raise(eQuickTime, "Error %d occurred while brining this application to the forground.", err);
|
97
|
+
}
|
98
|
+
SetFrontProcess(¤t_process);
|
99
|
+
|
100
|
+
// Show export dialog and save settings
|
101
|
+
err = MovieExportDoUserDialog(component, movie, 0, 0, GetMovieDuration(movie), &canceled);
|
102
|
+
if (err != noErr) {
|
103
|
+
rb_raise(eQuickTime, "Error %d occurred while opening export dialog.", err);
|
104
|
+
}
|
105
|
+
|
106
|
+
if (!canceled) {
|
107
|
+
// Clear existing settings if there are any
|
108
|
+
if (REXPORTER(obj)->settings) {
|
109
|
+
QTDisposeAtomContainer(REXPORTER(obj)->settings);
|
110
|
+
}
|
111
|
+
MovieExportGetSettingsAsAtomContainer(component, &REXPORTER(obj)->settings);
|
112
|
+
}
|
113
|
+
|
114
|
+
CloseComponent(component);
|
115
|
+
|
116
|
+
if (canceled) {
|
117
|
+
return Qfalse;
|
118
|
+
} else {
|
119
|
+
return Qtrue;
|
120
|
+
}
|
121
|
+
}
|
122
|
+
|
123
|
+
/*
|
124
|
+
call-seq: load_settings(filepath)
|
125
|
+
|
126
|
+
Loads the settings at the given filepath. See save_settings.
|
127
|
+
*/
|
128
|
+
static VALUE exporter_load_settings(VALUE obj, VALUE filepath)
|
129
|
+
{
|
130
|
+
FILE *file;
|
131
|
+
long length, read_length;
|
132
|
+
|
133
|
+
file = fopen(RSTRING(filepath)->ptr, "r+b");
|
134
|
+
if (!file) {
|
135
|
+
rb_raise(eQuickTime, "Unable to open file for loading at %s.", RSTRING(filepath)->ptr);
|
136
|
+
}
|
137
|
+
|
138
|
+
// obtain file size:
|
139
|
+
fseek(file , 0, SEEK_END);
|
140
|
+
length = ftell(file);
|
141
|
+
rewind(file);
|
142
|
+
|
143
|
+
// clear existing settings if there are any
|
144
|
+
if (REXPORTER(obj)->settings) {
|
145
|
+
QTDisposeAtomContainer(REXPORTER(obj)->settings);
|
146
|
+
}
|
147
|
+
|
148
|
+
// load the file into settings
|
149
|
+
REXPORTER(obj)->settings = (QTAtomContainer)NewHandleClear(length);
|
150
|
+
read_length = fread(*(Handle)REXPORTER(obj)->settings, 1, length, file);
|
151
|
+
if (read_length != length) {
|
152
|
+
rb_raise(eQuickTime, "Unable to read entire file at %s.", RSTRING(filepath)->ptr);
|
153
|
+
}
|
154
|
+
|
155
|
+
fclose(file);
|
156
|
+
|
157
|
+
return Qnil;
|
158
|
+
}
|
159
|
+
|
160
|
+
/*
|
161
|
+
call-seq: save_settings(filepath)
|
162
|
+
|
163
|
+
Saves the settings to the given filepath (usually with .st extension).
|
164
|
+
See open_settings_dialog and load_settings.
|
165
|
+
*/
|
166
|
+
static VALUE exporter_save_settings(VALUE obj, VALUE filepath)
|
167
|
+
{
|
168
|
+
FILE *file;
|
169
|
+
QTAtomContainer settings = REXPORTER(obj)->settings;
|
170
|
+
|
171
|
+
if (!settings) {
|
172
|
+
rb_raise(eQuickTime, "Unable to save settings because no settings are specified.");
|
173
|
+
}
|
174
|
+
|
175
|
+
file = fopen(RSTRING(filepath)->ptr, "wb");
|
176
|
+
if (!file) {
|
177
|
+
rb_raise(eQuickTime, "Unable to open file for saving at %s.", RSTRING(filepath)->ptr);
|
178
|
+
}
|
179
|
+
fwrite(&settings, GetHandleSize((Handle)settings), 1, file);
|
180
|
+
fclose(file);
|
181
|
+
|
182
|
+
return Qnil;
|
183
|
+
}
|
184
|
+
|
185
|
+
void Init_quicktime_exporter()
|
186
|
+
{
|
187
|
+
VALUE mQuickTime;
|
188
|
+
mQuickTime = rb_define_module("QuickTime");
|
189
|
+
cExporter = rb_define_class_under(mQuickTime, "Exporter", rb_cObject);
|
190
|
+
rb_define_alloc_func(cExporter, exporter_new);
|
191
|
+
rb_define_method(cExporter, "export", exporter_export_to_file, 1);
|
192
|
+
rb_define_method(cExporter, "open_settings_dialog", exporter_open_settings_dialog, 0);
|
193
|
+
rb_define_method(cExporter, "load_settings", exporter_load_settings, 1);
|
194
|
+
rb_define_method(cExporter, "save_settings", exporter_save_settings, 1);
|
195
|
+
}
|
data/ext/extconf.rb
ADDED