one-k-rmov 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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