Class: QuickTime::Movie

Inherits:
Object
  • Object
show all
Defined in:
lib/quicktime/movie.rb,
ext/movie.c

Overview

see ext/movie.c for additional methods

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.emptyObject

Returns a new, empty movie.



10
11
12
# File 'lib/quicktime/movie.rb', line 10

def self.empty
  new.load_empty
end

.open(filepath) ⇒ Object

Opens a movie at filepath.



5
6
7
# File 'lib/quicktime/movie.rb', line 5

def self.open(filepath)
  new.load_from_file(filepath)
end

Instance Method Details

#add_into_selection(movie) ⇒ Object

Adds the tracks of given movie into called movie’s current selection.

You can track the progress of this operation by passing a block to this method. It will be called regularly during the process and pass the percentage complete (0.0 to 1.0) as an argument to the block.



183
184
185
186
187
188
189
190
191
192
193
194
# File 'ext/movie.c', line 183

static VALUE movie_add_into_selection(VALUE obj, VALUE src)
{
  if (rb_block_given_p())
    SetMovieProgressProc(MOVIE(obj), (MovieProgressUPP)movie_progress_proc, rb_block_proc());
  
  AddMovieSelection(MOVIE(obj), MOVIE(src));
  
  if (rb_block_given_p())
    SetMovieProgressProc(MOVIE(obj), 0, 0);
  
  return obj;
}

#append_movie(movie, &block) ⇒ Object

Adds given movie to the end of movie which this method is called on.

You can track the progress of this operation by passing a block to this method. It will be called regularly during the process and pass the percentage complete (0.0 to 1.0) as an argument to the block.



124
125
126
127
128
# File 'lib/quicktime/movie.rb', line 124

def append_movie(movie, &block)
  select(duration, 0)
  insert_into_selection(movie, &block)
  deselect
end

#audio_tracksObject

Returns an array of audio tracks in this movie.



38
39
40
# File 'lib/quicktime/movie.rb', line 38

def audio_tracks
  tracks.select { |t| t.audio? }
end

#boundsObject

Returns a hash of boundaries. The hash contains four keys: :left, :top, :right, :bottom. Each holds an integer representing the pixel value.



140
141
142
143
144
145
146
147
148
149
150
# File 'ext/movie.c', line 140

static VALUE movie_bounds(VALUE obj)
{
  VALUE bounds_hash = rb_hash_new();
  Rect bounds;
  GetMovieBox(MOVIE(obj), &bounds);
  rb_hash_aset(bounds_hash, ID2SYM(rb_intern("left")), INT2NUM(bounds.left));
  rb_hash_aset(bounds_hash, ID2SYM(rb_intern("top")), INT2NUM(bounds.top));
  rb_hash_aset(bounds_hash, ID2SYM(rb_intern("right")), INT2NUM(bounds.right));
  rb_hash_aset(bounds_hash, ID2SYM(rb_intern("bottom")), INT2NUM(bounds.bottom));
  return bounds_hash;
}

#changed?Boolean

Determine if a movie has changed since opening. Returns true/false. See reset_changed_status to reset this value.

Returns:

  • (Boolean)


285
286
287
288
289
290
291
292
# File 'ext/movie.c', line 285

static VALUE movie_changed(VALUE obj)
{
  if (HasMovieChanged(MOVIE(obj))) {
    return Qtrue;
  } else {
    return Qfalse;
  }
}

#clear_changed_statusObject

Resets the “changed?” status. Does not revert the movie itself.



299
300
301
302
303
# File 'ext/movie.c', line 299

static VALUE movie_clear_changed_status(VALUE obj)
{
  ClearMovieChanged(MOVIE(obj));
  return Qnil;
}

#clip_section(position = 0, duration = 0, &block) ⇒ Object

Deletes the specified section on movie and returns a new movie with that content.

You can track the progress of this operation by passing a block to this method. It will be called regularly during the process and pass the percentage complete (0.0 to 1.0) as an argument to the block.



160
161
162
163
164
165
# File 'lib/quicktime/movie.rb', line 160

def clip_section(position = 0, duration = 0, &block)
  select(position, duration)
  movie = clip_selection(&block)
  deselect
  movie
end

#clip_selectionObject

Deletes current selection on movie and returns a new movie with that content.

You can track the progress of this operation by passing a block to this method. It will be called regularly during the process and pass the percentage complete (0.0 to 1.0) as an argument to the block.



253
254
255
256
257
258
259
260
261
262
263
264
265
266
# File 'ext/movie.c', line 253

static VALUE movie_clip_selection(VALUE obj)
{
  VALUE new_movie_obj = rb_obj_alloc(cMovie);
  
  if (rb_block_given_p())
    SetMovieProgressProc(MOVIE(obj), (MovieProgressUPP)movie_progress_proc, rb_block_proc());
  
  RMOVIE(new_movie_obj)->movie = CutMovieSelection(MOVIE(obj));
  
  if (rb_block_given_p())
    SetMovieProgressProc(MOVIE(obj), 0, 0);
  
  return new_movie_obj;
}

#clone_section(position = 0, duration = 0, &block) ⇒ Object

Returns a new movie from the specified portion of called movie.

You can track the progress of this operation by passing a block to this method. It will be called regularly during the process and pass the percentage complete (0.0 to 1.0) as an argument to the block.



147
148
149
150
151
152
# File 'lib/quicktime/movie.rb', line 147

def clone_section(position = 0, duration = 0, &block)
  select(position, duration)
  movie = clone_selection(&block)
  deselect
  movie
end

#clone_selectionObject

Returns a new movie from the current selection. Does not modify original movie.

You can track the progress of this operation by passing a block to this method. It will be called regularly during the process and pass the percentage complete (0.0 to 1.0) as an argument to the block.



228
229
230
231
232
233
234
235
236
237
238
239
240
241
# File 'ext/movie.c', line 228

static VALUE movie_clone_selection(VALUE obj)
{
  VALUE new_movie_obj = rb_obj_alloc(cMovie);
  
  if (rb_block_given_p())
    SetMovieProgressProc(MOVIE(obj), (MovieProgressUPP)movie_progress_proc, rb_block_proc());
  
  RMOVIE(new_movie_obj)->movie = CopyMovieSelection(MOVIE(obj));
  
  if (rb_block_given_p())
    SetMovieProgressProc(MOVIE(obj), 0, 0);
  
  return new_movie_obj;
}

#composite_movie(movie, position = 0, duration = 0, &block) ⇒ Object

Adds the tracks of given movie into called movie. Position will default to beginning of movie. Duration will default to length of given movie.

You can track the progress of this operation by passing a block to this method. It will be called regularly during the process and pass the percentage complete (0.0 to 1.0) as an argument to the block.



113
114
115
116
117
# File 'lib/quicktime/movie.rb', line 113

def composite_movie(movie, position = 0, duration = 0, &block)
  select(position, duration)
  add_into_selection(movie, &block)
  deselect
end

#delete_section(position = 0, duration = 0) ⇒ Object

Deletes the specified section on movie.



168
169
170
171
172
# File 'lib/quicktime/movie.rb', line 168

def delete_section(position = 0, duration = 0)
  select(position, duration)
  delete_selection
  deselect
end

#delete_selectionObject

Removes the portion of the movie which is selected.



273
274
275
276
277
# File 'ext/movie.c', line 273

static VALUE movie_delete_selection(VALUE obj)
{
  ClearMovieSelection(MOVIE(obj));
  return obj;
}

#deselectObject

Reset selection to beginning



103
104
105
# File 'lib/quicktime/movie.rb', line 103

def deselect
  select(0, 0)
end

#disposeObject

Dispose of the loaded QuickTime movie. This will automatically be done when this movie instance is garbage collected. However if you are iterating through many movies it is often helpful to dispose of it as soon as you’re done with it.



44
45
46
47
48
49
50
51
# File 'ext/movie.c', line 44

static VALUE movie_dispose(VALUE obj)
{
  if (MOVIE(obj)) {
    DisposeMovie(MOVIE(obj));
    RMOVIE(obj)->movie = NULL;
  }
  return obj;
}

#durationObject

Returns the length of this movie in seconds using raw_duration and time_scale.



16
17
18
# File 'lib/quicktime/movie.rb', line 16

def duration
  raw_duration.to_f/time_scale
end

#export(*args, &block) ⇒ Object

Convenience method for exporting the movie. See Exporter::export.



58
59
60
# File 'lib/quicktime/movie.rb', line 58

def export(*args, &block)
  exporter.export(*args, &block)
end

#export_image(filepath, seconds) ⇒ Object

Exports a frame of the movie at the given time (in seconds) to the given file. The image format is automatically determined from the file extension. If this cannot be determined from the extension then you can use export_image_type to specify the ostype manually.



87
88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/quicktime/movie.rb', line 87

def export_image(filepath, seconds)
  # TODO support more file types
  type = case File.extname(filepath).downcase
    when '.pct', '.pict' then 'PICT'
    when '.tif', '.tiff' then 'TIFF'
    when '.jpg', '.jpeg' then 'JPEG'
    when '.png'          then 'PNGf'
    when '.tga'          then 'TPIC'
    when '.bmp'          then 'BMPf'
    when '.psd'          then '8BPS'
    else raise QuickTime::Error, "Unable to guess ostype from file extension of #{filepath}"
  end
  export_image_type(filepath, seconds, type)
end

#export_image_type(filepath, time, ostype) ⇒ Object

Exports an image as the given ostype. It is best to use export_image instead if the ostype can be determined from the filepath extension.



372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
# File 'ext/movie.c', line 372

static VALUE movie_export_image_type(VALUE obj, VALUE filepath, VALUE frame_time, VALUE ostype_obj)
{
  GraphicsImportComponent component;
  PicHandle picture;
  Handle handle;
  FSSpec fs;
  OSErr err;
  
  picture = GetMoviePict(MOVIE(obj), MOVIE_TIME(obj, frame_time));
  
  err = NativePathNameToFSSpec(RSTRING(filepath)->ptr, &fs, 0);
  if (err != fnfErr)
    rb_raise(eQuickTime, "Error %d occurred while opening file for export at %s.", err, RSTRING(filepath)->ptr);
  
  // Convert the picture handle into a PICT file (still in a handle)
  // by adding a 512-byte header to the start.
  handle = NewHandleClear(512);
  err = HandAndHand((Handle)picture, handle);
  if (err != noErr)
    rb_raise(eQuickTime, "Error %d occurred while converting handle for pict export %s.", err, RSTRING(filepath)->ptr);
  
  err = OpenADefaultComponent(GraphicsImporterComponentType, kQTFileTypePicture, &component);
  if (err != noErr)
    rb_raise(eQuickTime, "Error %d occurred while opening picture component for %s.", err, RSTRING(filepath)->ptr);
  
  err = GraphicsImportSetDataHandle(component, handle);
  if (err != noErr)
    rb_raise(eQuickTime, "Error %d occurred while setting graphics importer data handle for %s.", err, RSTRING(filepath)->ptr);
  
  err = GraphicsImportExportImageFile(component, OSTYPE(RSTRING(ostype_obj)->ptr), 0, &fs, smSystemScript);
  if (err != noErr)
    rb_raise(eQuickTime, "Error %d occurred while exporting pict to file %s.", err, RSTRING(filepath)->ptr);
  
  CloseComponent(component);
  DisposeHandle(handle);
  DisposeHandle((Handle)picture);
  
  return Qnil;
}

#exporterObject

Returns an Exporter instance for this movie.



53
54
55
# File 'lib/quicktime/movie.rb', line 53

def exporter
  Exporter.new(self)
end

#flatten(filepath) ⇒ Object

Saves the movie to the given filepath by flattening it.



311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
# File 'ext/movie.c', line 311

static VALUE movie_flatten(VALUE obj, VALUE filepath)
{
  OSErr err;
  FSSpec fs;
  VALUE new_movie_obj = rb_obj_alloc(cMovie);
  
  err = NativePathNameToFSSpec(RSTRING(filepath)->ptr, &fs, 0);
  if (err != fnfErr)
    rb_raise(eQuickTime, "Error %d occurred while opening file for export at %s", err, RSTRING(filepath)->ptr);
  
  // TODO make these flags settable through an options hash
  RMOVIE(new_movie_obj)->movie = FlattenMovieData(MOVIE(obj),
                                  flattenDontInterleaveFlatten
                                  | flattenCompressMovieResource
                                  | flattenAddMovieToDataFork
                                  | flattenForceMovieResourceBeforeMovieData,
                                  &fs, 'TVOD', smSystemScript, createMovieFileDontCreateResFile);
  return new_movie_obj;
}

#heightObject

Returns the bounding height of this movie in number of pixels.



26
27
28
# File 'lib/quicktime/movie.rb', line 26

def height
  bounds[:bottom] - bounds[:top]
end

#insert_into_selection(movie) ⇒ Object

Inserts the given movie into called movie, replacing any current selection.

You can track the progress of this operation by passing a block to this method. It will be called regularly during the process and pass the percentage complete (0.0 to 1.0) as an argument to the block.



205
206
207
208
209
210
211
212
213
214
215
216
# File 'ext/movie.c', line 205

static VALUE movie_insert_into_selection(VALUE obj, VALUE src)
{
  if (rb_block_given_p())
    SetMovieProgressProc(MOVIE(obj), (MovieProgressUPP)movie_progress_proc, rb_block_proc());
  
  PasteMovieSelection(MOVIE(obj), MOVIE(src));
  
  if (rb_block_given_p())
    SetMovieProgressProc(MOVIE(obj), 0, 0);
  
  return obj;
}

#insert_movie(movie, position = 0, duration = 0, &block) ⇒ Object

Inserts given movie into called movie. The position defaults to the beginning of the movie. If a duration is passed, that amount of the movie will be replaced.

You can track the progress of this operation by passing a block to this method. It will be called regularly during the process and pass the percentage complete (0.0 to 1.0) as an argument to the block.



136
137
138
139
140
# File 'lib/quicktime/movie.rb', line 136

def insert_movie(movie, position = 0, duration = 0, &block)
  select(position, duration)
  insert_into_selection(movie, &block)
  deselect
end

#load_emptyObject

Loads a new, empty QuickTime movie. Should only be called if no movie has been loaded (or it has been disposed). Usually you go through Movie.empty.



102
103
104
105
106
107
108
109
110
# File 'ext/movie.c', line 102

static VALUE movie_load_empty(VALUE obj)
{
  if (MOVIE(obj)) {
    rb_raise(eQuickTime, "Movie has already been loaded.");
  } else {
    RMOVIE(obj)->movie = NewMovie(0);
    return obj; 
  }
}

#load_from_file(filepath) ⇒ Object

Loads a new, empty QuickTime movie at given filepath. Should only be called if no movie has been loaded (or it has been disposed). Usually you go through Movie.open.



60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'ext/movie.c', line 60

static VALUE movie_load_from_file(VALUE obj, VALUE filepath)
{
  if (MOVIE(obj)) {
    rb_raise(eQuickTime, "Movie has already been loaded.");
  } else {
    OSErr err;
    FSSpec fs;
    short resRefNum = -1;
    short resId = 0;
    Movie *movie = ALLOC(Movie);
    
    err = NativePathNameToFSSpec(RSTRING(filepath)->ptr, &fs, 0);
    if (err != 0)
      rb_raise(eQuickTime, "Error %d occurred while reading file at %s", err, RSTRING(filepath)->ptr);
    
    err = OpenMovieFile(&fs, &resRefNum, fsRdPerm);
    if (err != 0)
      rb_raise(eQuickTime, "Error %d occurred while opening movie at %s", err, RSTRING(filepath)->ptr);
    
    err = NewMovieFromFile(movie, resRefNum, &resId, 0, newMovieActive, 0);
    if (err != 0)
      rb_raise(eQuickTime, "Error %d occurred while loading movie at %s", err, RSTRING(filepath)->ptr);
    
    err = CloseMovieFile(resRefNum);
    if (err != 0)
      rb_raise(eQuickTime, "Error %d occurred while closing movie file at %s", err, RSTRING(filepath)->ptr);
    
    RMOVIE(obj)->movie = *movie;
    RMOVIE(obj)->filepath = RSTRING(filepath)->ptr;
    RMOVIE(obj)->resId = resId;
    
    return obj;
  }
}

#new_audio_track(width, height) ⇒ Object

Creates a new audio track with given width/height on movie and returns it.



70
71
72
73
74
# File 'lib/quicktime/movie.rb', line 70

def new_audio_track(width, height)
  track = new_track(width, height)
  track.new_audio_media
  track
end

#new_text_track(width, height) ⇒ Object

Creates a new text track with given width/height on movie and returns it.



77
78
79
80
81
# File 'lib/quicktime/movie.rb', line 77

def new_text_track(width, height)
  track = new_track(width, height)
  track.new_text_media
  track
end

#new_track(width, height) ⇒ Object

Creates a new track with the given width/height on the movie and returns it.

This method is generally not called directly. Instead you should call new_video_track or new_audio_track. If you call method make sure to call new_media on track to setup the media.



442
443
444
445
446
447
# File 'ext/movie.c', line 442

static VALUE movie_new_track(VALUE obj, VALUE width, VALUE height)
{
  VALUE track_obj = rb_obj_alloc(cTrack);
  RTRACK(track_obj)->track = NewMovieTrack(MOVIE(obj), NUM2INT(width), NUM2INT(height), kFullVolume);
  return track_obj;
}

#new_video_track(width, height) ⇒ Object

Creates a new video track with given width/height on movie and returns it.



63
64
65
66
67
# File 'lib/quicktime/movie.rb', line 63

def new_video_track(width, height)
  track = new_track(width, height)
  track.new_video_media
  track
end

#poster_timeObject

Returns the poster time of the movie (in seconds).



417
418
419
420
# File 'ext/movie.c', line 417

static VALUE movie_get_poster_time(VALUE obj)
{
  return rb_float_new((double)GetMoviePosterTime(MOVIE(obj))/GetMovieTimeScale(MOVIE(obj)));
}

#poster_time=(seconds) ⇒ Object

Sets the poster_time of the movie (in seconds).



427
428
429
430
431
# File 'ext/movie.c', line 427

static VALUE movie_set_poster_time(VALUE obj, VALUE seconds)
{
  SetMoviePosterTime(MOVIE(obj), MOVIE_TIME(obj, seconds));
  return Qnil;
}

#raw_durationObject

Returns the raw duration of the movie. Combine this with time_scale to reach the duration in seconds.



118
119
120
121
# File 'ext/movie.c', line 118

static VALUE movie_raw_duration(VALUE obj)
{
  return INT2NUM(GetMovieDuration(MOVIE(obj)));
}

#saveObject

Saves the movie to the current file.



337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
# File 'ext/movie.c', line 337

static VALUE movie_save(VALUE obj)
{
  OSErr err;
  FSSpec fs;
  short resRefNum = -1;
  
  if (!RMOVIE(obj)->filepath || !RMOVIE(obj)->resId) {
    rb_raise(eQuickTime, "Unable to save movie because it does not have an associated file.");
  } else {
    err = NativePathNameToFSSpec(RMOVIE(obj)->filepath, &fs, 0);
    if (err != 0)
      rb_raise(eQuickTime, "Error %d occurred while reading file at %s", err, RMOVIE(obj)->filepath);
    
    err = OpenMovieFile(&fs, &resRefNum, fsWrPerm);
    if (err != 0)
      rb_raise(eQuickTime, "Error %d occurred while opening movie at %s", err, RMOVIE(obj)->filepath);
    
    err = UpdateMovieResource(MOVIE(obj), resRefNum, RMOVIE(obj)->resId, 0);
    if (err != 0)
      rb_raise(eQuickTime, "Error %d occurred while saving movie file", err);
    
    err = CloseMovieFile(resRefNum);
    if (err != 0)
      rb_raise(eQuickTime, "Error %d occurred while closing movie file at %s", err, RMOVIE(obj)->filepath);
    
    return Qnil;
  }
}

#select(position, duration) ⇒ Object

Select a portion of a movie. Both position and duration should be floats representing seconds.



168
169
170
171
172
# File 'ext/movie.c', line 168

static VALUE movie_select(VALUE obj, VALUE position, VALUE duration)
{
  SetMovieSelection(MOVIE(obj), MOVIE_TIME(obj, position), MOVIE_TIME(obj, duration));
  return obj;
}

#text_tracksObject

Returns an array of text tracks in this movie.



48
49
50
# File 'lib/quicktime/movie.rb', line 48

def text_tracks
  tracks.select { |t| t.text? }
end

#time_scaleObject

Returns the time scale of the movie. Usually only needed when working with raw_duration.



129
130
131
132
# File 'ext/movie.c', line 129

static VALUE movie_time_scale(VALUE obj)
{
  return INT2NUM(GetMovieTimeScale(MOVIE(obj)));
}

#track_countObject

Returns the number of tracks in the movie.



157
158
159
160
# File 'ext/movie.c', line 157

static VALUE movie_track_count(VALUE obj)
{
  return INT2NUM(GetMovieTrackCount(MOVIE(obj)));
}

#tracksObject

Returns an array of tracks in this movie.



31
32
33
34
35
# File 'lib/quicktime/movie.rb', line 31

def tracks
  (1..track_count).map do |i|
    Track.new.load_from_movie(self, i)
  end
end

#video_tracksObject

Returns an array of video tracks in this movie.



43
44
45
# File 'lib/quicktime/movie.rb', line 43

def video_tracks
  tracks.select { |t| t.video? }
end

#widthObject

Returns the bounding width of this movie in number of pixels.



21
22
23
# File 'lib/quicktime/movie.rb', line 21

def width
  bounds[:right] - bounds[:left]
end