one-k-rmov 0.2.0 → 0.2.2
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +6 -1
- data/Rakefile +3 -3
- data/ext/track.c +180 -41
- data/rmov.gemspec +4 -4
- metadata +4 -4
data/CHANGELOG
CHANGED
@@ -1,7 +1,12 @@
|
|
1
1
|
|
2
|
+
0.2.1 (February 26, 2009)
|
3
|
+
|
2
4
|
* adding more property information from movie and track, such as codec information
|
3
5
|
|
4
|
-
|
6
|
+
* adds audio channel information
|
7
|
+
|
8
|
+
0.2.0 1K Studios Forked Version
|
9
|
+
purpose is to expose more reporting about movie, track information reporting
|
5
10
|
|
6
11
|
0.1.4 (October 3rd, 2008)
|
7
12
|
|
data/Rakefile
CHANGED
@@ -2,11 +2,11 @@ require 'rubygems'
|
|
2
2
|
require 'rake'
|
3
3
|
require 'echoe'
|
4
4
|
|
5
|
-
Echoe.new('rmov', '0.2.
|
5
|
+
Echoe.new('rmov', '0.2.2') do |p|
|
6
6
|
p.summary = "Ruby wrapper for the QuickTime C API."
|
7
|
-
p.description = "Ruby wrapper for the QuickTime C API."
|
7
|
+
p.description = "Ruby wrapper for the QuickTime C API. Updates by 1K include exposing some movie properties such as codec and audio channel descriptions"
|
8
8
|
p.url = "http://github.com/ryanb/rmov"
|
9
|
-
p.author = 'Ryan Bates'
|
9
|
+
p.author = 'Ryan Bates, with updates by 1K Studios, LLC'
|
10
10
|
p.email = "ryan (at) railscasts (dot) com"
|
11
11
|
p.ignore_pattern = ["script/*", "tmp/*", "spec/output/*", "**/*.o", "**/*.bundle", "**/*.mov"]
|
12
12
|
p.extensions = ["ext/extconf.rb"]
|
data/ext/track.c
CHANGED
@@ -69,6 +69,15 @@ static VALUE track_frame_count(VALUE obj)
|
|
69
69
|
return INT2NUM(GetMediaSampleCount(TRACK_MEDIA(obj)));
|
70
70
|
}
|
71
71
|
|
72
|
+
/* helper function, returns media type of the track
|
73
|
+
*/
|
74
|
+
static OSType track_get_media_type(VALUE obj)
|
75
|
+
{
|
76
|
+
OSType media_type;
|
77
|
+
GetMediaHandlerDescription(TRACK_MEDIA(obj), &media_type, 0, 0);
|
78
|
+
return media_type;
|
79
|
+
}
|
80
|
+
|
72
81
|
/*
|
73
82
|
call-seq: media_type() -> media_type_sym
|
74
83
|
|
@@ -76,9 +85,8 @@ static VALUE track_frame_count(VALUE obj)
|
|
76
85
|
*/
|
77
86
|
static VALUE track_media_type(VALUE obj)
|
78
87
|
{
|
79
|
-
OSType media_type;
|
88
|
+
OSType media_type = track_get_media_type(obj);
|
80
89
|
|
81
|
-
GetMediaHandlerDescription(TRACK_MEDIA(obj), &media_type, 0, 0);
|
82
90
|
if (media_type == SoundMediaType) {
|
83
91
|
return ID2SYM(rb_intern("audio"));
|
84
92
|
} else if (media_type == VideoMediaType) {
|
@@ -95,13 +103,10 @@ static VALUE track_media_type(VALUE obj)
|
|
95
103
|
*/
|
96
104
|
static ImageDescriptionHandle track_image_description(VALUE obj)
|
97
105
|
{
|
98
|
-
|
99
|
-
OSType media_type;
|
100
|
-
OSErr osErr = noErr;
|
106
|
+
OSErr osErr;
|
101
107
|
|
102
108
|
/* restrict reporting to video track */
|
103
|
-
|
104
|
-
if (media_type != VideoMediaType)
|
109
|
+
if (track_get_media_type(obj) != VideoMediaType)
|
105
110
|
return NULL;
|
106
111
|
|
107
112
|
SampleDescriptionHandle sample_description = NULL;
|
@@ -111,7 +116,7 @@ static ImageDescriptionHandle track_image_description(VALUE obj)
|
|
111
116
|
return NULL;
|
112
117
|
}
|
113
118
|
|
114
|
-
GetMediaSampleDescription(
|
119
|
+
GetMediaSampleDescription(TRACK_MEDIA(obj), 1, sample_description);
|
115
120
|
osErr = GetMoviesError();
|
116
121
|
if (osErr != noErr) {
|
117
122
|
rb_raise(eQuickTime, "Movie Error %d when determining image description", osErr);
|
@@ -263,39 +268,6 @@ static VALUE track_set_volume(VALUE obj, VALUE volume_obj)
|
|
263
268
|
return Qnil;
|
264
269
|
}
|
265
270
|
|
266
|
-
|
267
|
-
/* returns the AudioStreamBasicDescription for the track.
|
268
|
-
If it's not an audio track, return NULL
|
269
|
-
*/
|
270
|
-
static SoundDescriptionHandle track_audio_description(VALUE obj)
|
271
|
-
{
|
272
|
-
Media track_media = TRACK_MEDIA(obj);
|
273
|
-
OSType media_type;
|
274
|
-
OSErr osErr = noErr;
|
275
|
-
|
276
|
-
/* restrict reporting to audio track */
|
277
|
-
GetMediaHandlerDescription(track_media, &media_type, 0, 0);
|
278
|
-
if (media_type != SoundMediaType)
|
279
|
-
return NULL;
|
280
|
-
|
281
|
-
SoundDescriptionHandle sample_description = NULL;
|
282
|
-
sample_description = (SoundDescriptionHandle)NewHandle(sizeof(SampleDescription));
|
283
|
-
if (LMGetMemErr() != noErr) {
|
284
|
-
rb_raise(eQuickTime, "Memory Error %d when determining audio description", LMGetMemErr());
|
285
|
-
return NULL;
|
286
|
-
}
|
287
|
-
|
288
|
-
GetMediaSampleDescription(track_media, 1, (SampleDescriptionHandle)sample_description);
|
289
|
-
osErr = GetMoviesError();
|
290
|
-
if (osErr != noErr) {
|
291
|
-
rb_raise(eQuickTime, "GetMediaSampleDescription Error %d when determining audio description", osErr);
|
292
|
-
DisposeHandle((Handle)sample_description);
|
293
|
-
return NULL;
|
294
|
-
}
|
295
|
-
|
296
|
-
return sample_description;
|
297
|
-
}
|
298
|
-
|
299
271
|
/*
|
300
272
|
call-seq: offset() -> seconds
|
301
273
|
|
@@ -359,6 +331,171 @@ static VALUE track_new_text_media(VALUE obj)
|
|
359
331
|
return obj;
|
360
332
|
}
|
361
333
|
|
334
|
+
/* helper function to return the channel layouts
|
335
|
+
returns layout == NULL if there is a problem
|
336
|
+
*/
|
337
|
+
static AudioChannelLayout* track_get_audio_channel_layout(VALUE obj)
|
338
|
+
{
|
339
|
+
/* restrict reporting to audio track */
|
340
|
+
if (track_get_media_type(obj) != SoundMediaType) return NULL;
|
341
|
+
|
342
|
+
UInt32 size = 0;
|
343
|
+
OSErr osErr;
|
344
|
+
AudioChannelLayout* layout = NULL;
|
345
|
+
|
346
|
+
osErr = QTGetTrackPropertyInfo(TRACK(obj), kQTPropertyClass_Audio, kQTAudioPropertyID_ChannelLayout, NULL, &size, NULL);
|
347
|
+
if (osErr != noErr || size <= 0) goto bail;
|
348
|
+
|
349
|
+
layout = (AudioChannelLayout*)calloc(1, size);
|
350
|
+
if (layout == NULL) {
|
351
|
+
osErr = memFullErr;
|
352
|
+
goto bail;
|
353
|
+
}
|
354
|
+
|
355
|
+
osErr = QTGetTrackProperty(TRACK(obj), kQTPropertyClass_Audio, kQTAudioPropertyID_ChannelLayout, size, layout, NULL);
|
356
|
+
if (osErr != noErr) goto bail;
|
357
|
+
|
358
|
+
return layout;
|
359
|
+
|
360
|
+
/* clean up in the event of an error*/
|
361
|
+
bail:
|
362
|
+
rb_raise(eQuickTime, "Error %d when getting audio channel layout", osErr);
|
363
|
+
free(layout);
|
364
|
+
return NULL;
|
365
|
+
}
|
366
|
+
|
367
|
+
/*
|
368
|
+
call-seq: track_get_audio_channel_count() -> number_of_channels
|
369
|
+
*/
|
370
|
+
static VALUE track_get_audio_channel_count(VALUE obj)
|
371
|
+
{
|
372
|
+
AudioChannelLayout *layout = track_get_audio_channel_layout(obj);
|
373
|
+
if (layout == NULL) return Qnil;
|
374
|
+
|
375
|
+
UInt32 numChannels = (layout->mChannelLayoutTag == kAudioChannelLayoutTag_UseChannelDescriptions) ? layout->mNumberChannelDescriptions : AudioChannelLayoutTag_GetNumberOfChannels(layout->mChannelLayoutTag);
|
376
|
+
|
377
|
+
free(layout);
|
378
|
+
|
379
|
+
return INT2NUM(numChannels);
|
380
|
+
}
|
381
|
+
|
382
|
+
// add a channel hash with a given value(v)
|
383
|
+
#define ADD_CHANNEL(ary, c, v) c=rb_hash_new(); rb_ary_push(ary, c); rb_hash_aset(c, ID2SYM(rb_intern("assignment")), ID2SYM(rb_intern(v)))
|
384
|
+
|
385
|
+
static char* track_str_for_AudioChannelLabel(label) {
|
386
|
+
|
387
|
+
char *trackStr = NULL;
|
388
|
+
|
389
|
+
switch (label) {
|
390
|
+
|
391
|
+
case kAudioChannelLabel_Left:
|
392
|
+
trackStr = "left";
|
393
|
+
break;
|
394
|
+
case kAudioChannelLabel_Right:
|
395
|
+
trackStr = "right";
|
396
|
+
break;
|
397
|
+
case kAudioChannelLabel_Center:
|
398
|
+
trackStr = "center";
|
399
|
+
break;
|
400
|
+
case kAudioChannelLabel_LFEScreen:
|
401
|
+
trackStr = "LFEScreen";
|
402
|
+
break;
|
403
|
+
case kAudioChannelLabel_LeftSurround:
|
404
|
+
trackStr = "leftSurround";
|
405
|
+
break;
|
406
|
+
case kAudioChannelLabel_RightSurround:
|
407
|
+
trackStr = "rightSurround";
|
408
|
+
break;
|
409
|
+
case kAudioChannelLabel_LeftCenter:
|
410
|
+
trackStr = "leftCenter";
|
411
|
+
break;
|
412
|
+
case kAudioChannelLabel_RightCenter:
|
413
|
+
trackStr = "rightCenter";
|
414
|
+
break;
|
415
|
+
case kAudioChannelLabel_CenterSurround:
|
416
|
+
trackStr = "centerSurround";
|
417
|
+
break;
|
418
|
+
case kAudioChannelLabel_LeftSurroundDirect:
|
419
|
+
trackStr = "leftSurroundDirect";
|
420
|
+
break;
|
421
|
+
case kAudioChannelLabel_RightSurroundDirect:
|
422
|
+
trackStr = "rightSurroundDirect";
|
423
|
+
break;
|
424
|
+
case kAudioChannelLabel_TopCenterSurround:
|
425
|
+
trackStr = "topCenterSurround";
|
426
|
+
break;
|
427
|
+
|
428
|
+
default:
|
429
|
+
rb_raise(eQuickTime, "Not Implemented: AudioChannelLabel in track_get_audio_channel_map : %d", label);
|
430
|
+
break;
|
431
|
+
}
|
432
|
+
|
433
|
+
return trackStr;
|
434
|
+
}
|
435
|
+
|
436
|
+
static VALUE track_get_audio_channel_map(VALUE obj)
|
437
|
+
{
|
438
|
+
AudioChannelLayout *layout = track_get_audio_channel_layout(obj);
|
439
|
+
if (layout == NULL) return Qnil;
|
440
|
+
|
441
|
+
VALUE channels = Qnil;
|
442
|
+
UInt32 numChannels, x;
|
443
|
+
VALUE channel;
|
444
|
+
AudioChannelLayoutTag layoutTag = layout->mChannelLayoutTag;
|
445
|
+
|
446
|
+
if (layoutTag == kAudioChannelLayoutTag_UseChannelDescriptions) {
|
447
|
+
// using the descriptions
|
448
|
+
// not implemented
|
449
|
+
numChannels = layout->mNumberChannelDescriptions;
|
450
|
+
channels = rb_ary_new2(numChannels);
|
451
|
+
|
452
|
+
// loop through all channels, adding assignment descriptions
|
453
|
+
AudioChannelDescription desc;
|
454
|
+
char *trackStr;
|
455
|
+
for (x=0; x < numChannels; x++) {
|
456
|
+
desc = layout->mChannelDescriptions[x];
|
457
|
+
trackStr = track_str_for_AudioChannelLabel(desc.mChannelLabel);
|
458
|
+
ADD_CHANNEL(channels, channel, trackStr);
|
459
|
+
}
|
460
|
+
|
461
|
+
|
462
|
+
} else {
|
463
|
+
numChannels = AudioChannelLayoutTag_GetNumberOfChannels(layoutTag);
|
464
|
+
channels = rb_ary_new2(numChannels);
|
465
|
+
|
466
|
+
if (layoutTag == kAudioChannelLayoutTag_UseChannelBitmap) {
|
467
|
+
// use the bitmap approach
|
468
|
+
// not implemented
|
469
|
+
rb_raise(eQuickTime, "Not Implemented: kAudioChannelLayoutTag_UseChannelBitmap in track_get_audio_channel_map");
|
470
|
+
|
471
|
+
|
472
|
+
} else {
|
473
|
+
// using a standard LayoutTag
|
474
|
+
switch (layoutTag) {
|
475
|
+
|
476
|
+
case kAudioChannelLayoutTag_Mono:
|
477
|
+
ADD_CHANNEL(channels, channel, "mono");
|
478
|
+
break;
|
479
|
+
|
480
|
+
case kAudioChannelLayoutTag_Stereo:
|
481
|
+
ADD_CHANNEL(channels, channel, "left");
|
482
|
+
ADD_CHANNEL(channels, channel, "right");
|
483
|
+
break;
|
484
|
+
|
485
|
+
default:
|
486
|
+
// unsupported
|
487
|
+
rb_raise(eQuickTime, "Unsupported ChannelLayoutTag in track_get_audio_channel_map: %d", layoutTag);
|
488
|
+
break;
|
489
|
+
}
|
490
|
+
|
491
|
+
}
|
492
|
+
|
493
|
+
}
|
494
|
+
|
495
|
+
free(layout);
|
496
|
+
|
497
|
+
return channels;
|
498
|
+
}
|
362
499
|
|
363
500
|
void Init_quicktime_track()
|
364
501
|
{
|
@@ -375,6 +512,8 @@ void Init_quicktime_track()
|
|
375
512
|
rb_define_method(cTrack, "codec", track_codec, 0);
|
376
513
|
rb_define_method(cTrack, "width", track_width, 0);
|
377
514
|
rb_define_method(cTrack, "height", track_height, 0);
|
515
|
+
rb_define_method(cTrack, "channel_count", track_get_audio_channel_count, 0);
|
516
|
+
rb_define_method(cTrack, "channel_map", track_get_audio_channel_map, 0);
|
378
517
|
|
379
518
|
rb_define_method(cTrack, "id", track_id, 0);
|
380
519
|
rb_define_method(cTrack, "delete", track_delete, 0);
|
data/rmov.gemspec
CHANGED
@@ -2,12 +2,12 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = %q{rmov}
|
5
|
-
s.version = "0.2.
|
5
|
+
s.version = "0.2.2"
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
|
8
|
-
s.authors = ["Ryan Bates"]
|
9
|
-
s.date = %q{2009-02-
|
10
|
-
s.description = %q{Ruby wrapper for the QuickTime C API.}
|
8
|
+
s.authors = ["Ryan Bates, with updates by 1K Studios, LLC"]
|
9
|
+
s.date = %q{2009-02-27}
|
10
|
+
s.description = %q{Ruby wrapper for the QuickTime C API. Updates by 1K include exposing some movie properties such as codec and audio channel descriptions}
|
11
11
|
s.email = %q{ryan (at) railscasts (dot) com}
|
12
12
|
s.extensions = ["ext/extconf.rb"]
|
13
13
|
s.extra_rdoc_files = ["CHANGELOG", "ext/exporter.c", "ext/extconf.rb", "ext/movie.c", "ext/rmov_ext.c", "ext/rmov_ext.h", "ext/track.c", "lib/quicktime/exporter.rb", "lib/quicktime/movie.rb", "lib/quicktime/track.rb", "lib/rmov.rb", "LICENSE", "README.rdoc", "tasks/setup.rake", "tasks/spec.rake", "TODO"]
|
metadata
CHANGED
@@ -1,19 +1,19 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: one-k-rmov
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
|
-
- Ryan Bates
|
7
|
+
- Ryan Bates, with updates by 1K Studios, LLC
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-02-
|
12
|
+
date: 2009-02-27 00:00:00 -08:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
16
|
-
description: Ruby wrapper for the QuickTime C API.
|
16
|
+
description: Ruby wrapper for the QuickTime C API. Updates by 1K include exposing some movie properties such as codec and audio channel descriptions
|
17
17
|
email: ryan (at) railscasts (dot) com
|
18
18
|
executables: []
|
19
19
|
|