libmediainfo 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +3 -0
- data/.gitignore +27 -0
- data/.rspec +1 -0
- data/.yardopts +1 -0
- data/ChangeLog.md +8 -0
- data/Gemfile +3 -0
- data/LICENSE.txt +675 -0
- data/README.md +38 -0
- data/Rakefile +51 -0
- data/example/dump_everything.rb +28 -0
- data/example/specific_fields.rb +49 -0
- data/ext/mediainfo/api.c +39 -0
- data/ext/mediainfo/api.h +21 -0
- data/ext/mediainfo/common.h +19 -0
- data/ext/mediainfo/constants.c +61 -0
- data/ext/mediainfo/constants.h +11 -0
- data/ext/mediainfo/extconf.rb +20 -0
- data/ext/mediainfo/libmediainfo.c +17 -0
- data/ext/mediainfo/libmediainfo.h +6 -0
- data/ext/mediainfo/mediainfo.c +384 -0
- data/ext/mediainfo/mediainfo.h +33 -0
- data/ext/mediainfo/stream_type.c +171 -0
- data/ext/mediainfo/stream_type.h +26 -0
- data/ext/mediainfo/track.c +205 -0
- data/ext/mediainfo/track.h +24 -0
- data/ext/mediainfo/unicode.c +76 -0
- data/ext/mediainfo/unicode.h +24 -0
- data/lib/mediainfo.rb +1 -0
- data/lib/mediainfo/version.rb +71 -0
- data/libmediainfo.gemspec +30 -0
- data/spec/libmediainfo_spec.rb +30 -0
- data/spec/spec_helper.rb +5 -0
- metadata +195 -0
data/README.md
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
# libmediainfo
|
2
|
+
|
3
|
+
Ruby bindings for [mediainfo][] that direct use `libmediainfo.so`
|
4
|
+
instead of parsing the command-line utility.
|
5
|
+
|
6
|
+
[mediainfo]: http://mediainfo.sourceforge.net
|
7
|
+
|
8
|
+
* [Homepage](https://github.com/pdkl95/ruby-libmediainfo#readme)
|
9
|
+
* [Issues](https://github.com/pdkl95/ruby-libmediainfo/issues)
|
10
|
+
* [Documentation](http://rubydoc.info/gems/libmediainfo/frames)
|
11
|
+
* [Email](mailto:pdkl95@thoughtnoise.net)
|
12
|
+
|
13
|
+
|
14
|
+
# Requirements
|
15
|
+
|
16
|
+
* [libmediainfo.so][] itself and any of its requirements (`libzen`)
|
17
|
+
* `MediaInfoDLL.h` which should come with the library, but may
|
18
|
+
require installing an additional "`-dev`" package if you use the
|
19
|
+
pre-compiled package available for some distros.
|
20
|
+
|
21
|
+
[libmediainfo]: http://mediainfo.sourceforge.net/en/Download
|
22
|
+
|
23
|
+
# Installation
|
24
|
+
|
25
|
+
```bash
|
26
|
+
gem install libmediainfo
|
27
|
+
```
|
28
|
+
|
29
|
+
# Usage
|
30
|
+
|
31
|
+
See the [examples][] directory. I'll write some proper documentation
|
32
|
+
some day.
|
33
|
+
|
34
|
+
# Copyright
|
35
|
+
|
36
|
+
Copyright 2013 Brent Sanders
|
37
|
+
|
38
|
+
See LICENSE.txt for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
|
5
|
+
begin
|
6
|
+
require 'bundler'
|
7
|
+
rescue LoadError => e
|
8
|
+
warn e.message
|
9
|
+
warn "Run `gem install bundler` to install Bundler."
|
10
|
+
exit -1
|
11
|
+
end
|
12
|
+
|
13
|
+
begin
|
14
|
+
Bundler.setup(:development)
|
15
|
+
rescue Bundler::BundlerError => e
|
16
|
+
warn e.message
|
17
|
+
warn "Run `bundle install` to install missing gems."
|
18
|
+
exit e.status_code
|
19
|
+
end
|
20
|
+
|
21
|
+
require 'rake'
|
22
|
+
require 'rake/extensiontask'
|
23
|
+
|
24
|
+
spec = Gem::Specification.load('libmediainfo.gemspec')
|
25
|
+
|
26
|
+
Rake::ExtensionTask.new do |ext|
|
27
|
+
ext.name = 'mediainfo'
|
28
|
+
ext.ext_dir = 'ext/mediainfo'
|
29
|
+
ext.lib_dir = 'lib/mediainfo'
|
30
|
+
ext.tmp_dir = 'tmp'
|
31
|
+
ext.source_pattern = '*.{c,h}'
|
32
|
+
ext.gem_spec = spec
|
33
|
+
end
|
34
|
+
|
35
|
+
require 'rubygems/tasks'
|
36
|
+
Gem::Tasks.new checksum: true, pgp: true
|
37
|
+
|
38
|
+
|
39
|
+
require 'rspec/core/rake_task'
|
40
|
+
RSpec::Core::RakeTask.new
|
41
|
+
|
42
|
+
task :test => :spec
|
43
|
+
task :default => :spec
|
44
|
+
|
45
|
+
|
46
|
+
require 'yard'
|
47
|
+
YARD::Rake::YardocTask.new
|
48
|
+
task :doc => :yard
|
49
|
+
|
50
|
+
|
51
|
+
|
@@ -0,0 +1,28 @@
|
|
1
|
+
#!/bin/env ruby
|
2
|
+
#
|
3
|
+
# This demo simply iterats through each field in
|
4
|
+
# each track that libmediainfo provided.
|
5
|
+
|
6
|
+
$LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
|
7
|
+
require 'mediainfo'
|
8
|
+
|
9
|
+
def show(path)
|
10
|
+
puts ">>> \"#{path}\""
|
11
|
+
info = MediaInfo.new(path)
|
12
|
+
|
13
|
+
info.each_track do |track|
|
14
|
+
track.each_field do|k,v|
|
15
|
+
puts "#{track.stream_type.name}[#{track.id}] #{k}: #{v.inspect}"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
if ARGV.length < 1
|
21
|
+
puts "usage: #{File.basename($0)} <media_file> [<media_file> [...]]"
|
22
|
+
exit 1
|
23
|
+
end
|
24
|
+
|
25
|
+
ARGV.each do |media_file|
|
26
|
+
show media_file
|
27
|
+
end
|
28
|
+
|
@@ -0,0 +1,49 @@
|
|
1
|
+
#!/bin/env ruby
|
2
|
+
#
|
3
|
+
# An example that demonstrates how to request
|
4
|
+
# specific data fields about individual tracks.
|
5
|
+
|
6
|
+
$LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
|
7
|
+
require 'mediainfo'
|
8
|
+
|
9
|
+
def show(path)
|
10
|
+
puts "*** MediaInfo.new(\"#{path}\") ***"
|
11
|
+
info = MediaInfo.new(path)
|
12
|
+
puts info
|
13
|
+
|
14
|
+
g = info.general[0]
|
15
|
+
puts "Format: #{g['Format']} - #{g['Format/Info']}"
|
16
|
+
puts "Duration: #{g['Duration/String']}"
|
17
|
+
|
18
|
+
info.video.each do |track|
|
19
|
+
puts
|
20
|
+
puts "#{track}"
|
21
|
+
puts "VIDEO[#{track.id}] Codec: #{track['Codec']} - #{track['Codec/Info']}"
|
22
|
+
puts "VIDEO[#{track.id}] Resolution: #{track['Width']}x#{track['Height']}"
|
23
|
+
puts "VIDEO[#{track.id}] FrameRate: #{track['FrameRate/String']}"
|
24
|
+
puts "VIDEO[#{track.id}] Bits/Pixel: #{track['Bits-(Pixel*Frame)']}"
|
25
|
+
puts "VIDEO[#{track.id}] BitRate: #{track['BitRate/String']}"
|
26
|
+
end
|
27
|
+
|
28
|
+
info.audio.each do |track|
|
29
|
+
puts
|
30
|
+
puts "#{track}"
|
31
|
+
puts "AUDIO[#{track.id}] Codec: #{track['Codec']} - #{track['Codec/Info']}"
|
32
|
+
puts "AUDIO[#{track.id}] Channels: #{track['Channel(s)']}"
|
33
|
+
puts "AUDIO[#{track.id}] BitDepth: #{track['BitDepth/String']}"
|
34
|
+
puts "AUDIO[#{track.id}] Channels: #{track['SamplingRate']} (#{track['SamplingRate/String']})"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
if ARGV.length < 1
|
39
|
+
puts "usage: #{File.basename($0)} <media_file> [<media_file> [...]]"
|
40
|
+
exit 1
|
41
|
+
end
|
42
|
+
|
43
|
+
ARGV.each do |media_file|
|
44
|
+
show media_file
|
45
|
+
end
|
46
|
+
|
47
|
+
#puts "***********"
|
48
|
+
#puts x.print_report!
|
49
|
+
#puts "***********"
|
data/ext/mediainfo/api.c
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
#include "common.h"
|
2
|
+
#include "api.h"
|
3
|
+
|
4
|
+
mediainfo_api_t cMediaInfoAPI;
|
5
|
+
|
6
|
+
static void
|
7
|
+
check_binding(void *func, char *name)
|
8
|
+
{
|
9
|
+
if (!func) {
|
10
|
+
rb_raise(rb_eLoadError,
|
11
|
+
"Failed to bind MediaInfo_%s() from libmediainfo.so",
|
12
|
+
name);
|
13
|
+
}
|
14
|
+
}
|
15
|
+
|
16
|
+
void
|
17
|
+
Init_mediainfo_api(void)
|
18
|
+
{
|
19
|
+
MediaInfoDLL_Load();
|
20
|
+
if (!MediaInfoDLL_IsLoaded()) {
|
21
|
+
rb_raise(rb_eLoadError, "Mediainfo.so not loaded!\n");
|
22
|
+
}
|
23
|
+
|
24
|
+
#define MI_API(field, name) \
|
25
|
+
cMediaInfoAPI.field = JOIN(MediaInfo_,name); \
|
26
|
+
check_binding(cMediaInfoAPI.field, Q(name));
|
27
|
+
|
28
|
+
MI_API(new,New);
|
29
|
+
MI_API(delete,Delete);
|
30
|
+
MI_API(open,Open);
|
31
|
+
MI_API(close,Close);
|
32
|
+
MI_API(inform,Inform);
|
33
|
+
MI_API(geti,GetI);
|
34
|
+
MI_API(get,Get);
|
35
|
+
MI_API(option,Option);
|
36
|
+
MI_API(state_get,State_Get);
|
37
|
+
MI_API(count_get,Count_Get);
|
38
|
+
#undef MI_API
|
39
|
+
}
|
data/ext/mediainfo/api.h
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
#ifndef GEM_MEDIAINFO_API_H
|
2
|
+
#define GEM_MEDIAINFO_API_H
|
3
|
+
|
4
|
+
struct mediainfo_api {
|
5
|
+
void * (*new)();
|
6
|
+
void (*delete)(void *);
|
7
|
+
size_t (*open)(void *, const MediaInfo_Char *);
|
8
|
+
void (*close)(void *);
|
9
|
+
const MediaInfo_Char * (*inform)(void *, size_t);
|
10
|
+
const MediaInfo_Char * (*geti)(void *, MediaInfo_stream_C, size_t, size_t, MediaInfo_info_C);
|
11
|
+
const MediaInfo_Char * (*get)(void *, MediaInfo_stream_C, size_t, const MediaInfo_Char *, MediaInfo_info_C, MediaInfo_info_C);
|
12
|
+
const MediaInfo_Char * (*option)(void *, const MediaInfo_Char *, const MediaInfo_Char *);
|
13
|
+
size_t (*state_get)(void *);
|
14
|
+
size_t (*count_get)(void *, MediaInfo_stream_C, size_t);
|
15
|
+
};
|
16
|
+
typedef struct mediainfo_api mediainfo_api_t;
|
17
|
+
|
18
|
+
extern mediainfo_api_t cMediaInfoAPI;
|
19
|
+
|
20
|
+
|
21
|
+
#endif /*GEM_MEDIAINFO_API_H*/
|
@@ -0,0 +1,19 @@
|
|
1
|
+
#ifndef LIBMI_MEDIAINFO_H
|
2
|
+
#define LIBMI_MEDIAINFO_H
|
3
|
+
|
4
|
+
#include <ruby.h>
|
5
|
+
#include <MediaInfoDLL/MediaInfoDLL.h>
|
6
|
+
|
7
|
+
#define Q(x) #x
|
8
|
+
#define JOIN_(a,b) a##b
|
9
|
+
#define JOIN(a,b) JOIN_(a,b)
|
10
|
+
|
11
|
+
#define GET_CLASS_STRUCT(type_t, mi, selfptr) \
|
12
|
+
type_t *mi; \
|
13
|
+
Data_Get_Struct(selfptr, type_t, mi);
|
14
|
+
|
15
|
+
#define MARK(x) \
|
16
|
+
if (x != Qnil) { rb_gc_mark(x); }
|
17
|
+
|
18
|
+
|
19
|
+
#endif /*GEM_MEDIAINFO_MEDIAINFO_H*/
|
@@ -0,0 +1,61 @@
|
|
1
|
+
#include "common.h"
|
2
|
+
#include "constants.h"
|
3
|
+
#include "mediainfo.h"
|
4
|
+
|
5
|
+
VALUE cMediaInfo_mStream;
|
6
|
+
VALUE cMediaInfo_mInfo;
|
7
|
+
VALUE cMediaInfo_mInfoOption;
|
8
|
+
VALUE cMediaInfo_mFileOption;
|
9
|
+
|
10
|
+
void
|
11
|
+
Init_mediainfo_constants(void)
|
12
|
+
{
|
13
|
+
#define MOD(name) \
|
14
|
+
JOIN(cMediaInfo_m,name) = rb_define_module_under(cMediaInfo, Q(name))
|
15
|
+
|
16
|
+
MOD(Stream);
|
17
|
+
MOD(Info);
|
18
|
+
MOD(InfoOption);
|
19
|
+
MOD(FileOption);
|
20
|
+
#undef MOD
|
21
|
+
|
22
|
+
#define MI_CONST(cat, name) \
|
23
|
+
JOIN(JOIN(MediaInfo_,cat),JOIN(_,name))
|
24
|
+
|
25
|
+
#define C(cat, name) \
|
26
|
+
rb_define_const( JOIN(cMediaInfo_m,cat), \
|
27
|
+
Q(name), \
|
28
|
+
INT2NUM(MI_CONST(cat,name)))
|
29
|
+
|
30
|
+
C(Stream,General);
|
31
|
+
C(Stream,Video);
|
32
|
+
C(Stream,Audio);
|
33
|
+
C(Stream,Text);
|
34
|
+
C(Stream,Chapters);
|
35
|
+
C(Stream,Image);
|
36
|
+
C(Stream,Menu);
|
37
|
+
C(Stream,Max);
|
38
|
+
|
39
|
+
C(Info,Name);
|
40
|
+
C(Info,Text);
|
41
|
+
C(Info,Measure);
|
42
|
+
C(Info,Options);
|
43
|
+
C(Info,Name_Text);
|
44
|
+
C(Info,Measure_Text);
|
45
|
+
C(Info,Info);
|
46
|
+
C(Info,HowTo);
|
47
|
+
C(Info,Max);
|
48
|
+
|
49
|
+
C(InfoOption,ShowInInform);
|
50
|
+
C(InfoOption,Reserved);
|
51
|
+
C(InfoOption,ShowInSupported);
|
52
|
+
C(InfoOption,TypeOfValue);
|
53
|
+
C(InfoOption,Max);
|
54
|
+
|
55
|
+
C(FileOption,Nothing);
|
56
|
+
C(FileOption,NoRecursive);
|
57
|
+
C(FileOption,CloseAll);
|
58
|
+
C(FileOption,Max);
|
59
|
+
#undef C
|
60
|
+
#undef MI_CONST_NAME
|
61
|
+
}
|
@@ -0,0 +1,11 @@
|
|
1
|
+
#ifndef GEM_MEDIAINFO_CONSTANTS_H
|
2
|
+
#define GEM_MEDIAINFO_CONSTANTS_H
|
3
|
+
|
4
|
+
extern VALUE cMediaInfo_mStream;
|
5
|
+
extern VALUE cMediaInfo_mInfo;
|
6
|
+
extern VALUE cMediaInfo_mInfoOption;
|
7
|
+
extern VALUE cMediaInfo_mFileOption;
|
8
|
+
|
9
|
+
void Init_mediainfo_constants(void);
|
10
|
+
|
11
|
+
#endif /*GEM_MEDIAINFO_CONSTANTS_H*/
|
@@ -0,0 +1,20 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'mkmf'
|
4
|
+
|
5
|
+
[ 'stdlib.h', 'string.h', 'wchar.h'
|
6
|
+
].each do |hdr|
|
7
|
+
find_header(hdr) or fail "missing required header: #{hdr}"
|
8
|
+
end
|
9
|
+
|
10
|
+
pkg_config 'libmediainfo' or fail "pkg_config failed for libmediainfo"
|
11
|
+
|
12
|
+
mi_hdr = 'MediaInfoDLL/MediaInfoDLL.h'
|
13
|
+
have_header(mi_hdr) or fail "missing libmediainfo header \"#{mi_hdr}\""
|
14
|
+
|
15
|
+
#create_header
|
16
|
+
create_makefile 'mediainfo'
|
17
|
+
|
18
|
+
if ENV['V'] == '1'
|
19
|
+
system("sed -i -e 's/^V = 0/V = 1/' Makefile")
|
20
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
#include "common.h"
|
2
|
+
#include "libmediainfo.h"
|
3
|
+
#include "api.h"
|
4
|
+
#include "constants.h"
|
5
|
+
#include "mediainfo.h"
|
6
|
+
#include "stream_type.h"
|
7
|
+
#include "track.h"
|
8
|
+
|
9
|
+
void
|
10
|
+
Init_mediainfo(void)
|
11
|
+
{
|
12
|
+
Init_mediainfo_api();
|
13
|
+
Init_mediainfo_MediaInfo();
|
14
|
+
Init_mediainfo_MediaInfo_StreamType();
|
15
|
+
Init_mediainfo_MediaInfo_Track();
|
16
|
+
Init_mediainfo_constants();
|
17
|
+
}
|
@@ -0,0 +1,384 @@
|
|
1
|
+
#include "common.h"
|
2
|
+
#include "mediainfo.h"
|
3
|
+
#include "unicode.h"
|
4
|
+
#include "api.h"
|
5
|
+
#include "constants.h"
|
6
|
+
#include "stream_type.h"
|
7
|
+
|
8
|
+
VALUE cMediaInfo;
|
9
|
+
|
10
|
+
/***************************************************************************
|
11
|
+
* struct mediainfo
|
12
|
+
*/
|
13
|
+
|
14
|
+
static mediainfo_t *
|
15
|
+
mediainfo_alloc()
|
16
|
+
{
|
17
|
+
mediainfo_t *mi;
|
18
|
+
mi = ALLOC(mediainfo_t);
|
19
|
+
mi->handle = cMediaInfoAPI.new();
|
20
|
+
|
21
|
+
mi->path = Qnil;
|
22
|
+
mi->stream_types = Qnil;
|
23
|
+
mi->tracks = Qnil;
|
24
|
+
mi->general = Qnil;
|
25
|
+
mi->video = Qnil;
|
26
|
+
mi->audio = Qnil;
|
27
|
+
mi->text = Qnil;
|
28
|
+
mi->chapters = Qnil;
|
29
|
+
mi->image = Qnil;
|
30
|
+
mi->menu = Qnil;
|
31
|
+
|
32
|
+
return mi;
|
33
|
+
}
|
34
|
+
|
35
|
+
static void
|
36
|
+
mediainfo_free(mediainfo_t *mi)
|
37
|
+
{
|
38
|
+
cMediaInfoAPI.delete(mi->handle);
|
39
|
+
xfree(mi);
|
40
|
+
}
|
41
|
+
|
42
|
+
static void
|
43
|
+
mediainfo_mark(mediainfo_t *mi)
|
44
|
+
{
|
45
|
+
MARK(mi->path);
|
46
|
+
MARK(mi->stream_types);
|
47
|
+
MARK(mi->tracks);
|
48
|
+
MARK(mi->general);
|
49
|
+
MARK(mi->video);
|
50
|
+
MARK(mi->audio);
|
51
|
+
MARK(mi->text);
|
52
|
+
MARK(mi->chapters);
|
53
|
+
MARK(mi->image);
|
54
|
+
MARK(mi->menu);
|
55
|
+
}
|
56
|
+
|
57
|
+
static VALUE
|
58
|
+
mediainfo_allocate(VALUE klass) {
|
59
|
+
mediainfo_t *mi = mediainfo_alloc();
|
60
|
+
if (!mi->handle) {
|
61
|
+
rb_raise(rb_eRuntimeError, "MediaInfo_New() failed!");
|
62
|
+
}
|
63
|
+
|
64
|
+
mi->stream_types = rb_ary_new();
|
65
|
+
mi->tracks = rb_ary_new();
|
66
|
+
|
67
|
+
return Data_Wrap_Struct(klass,
|
68
|
+
mediainfo_mark,
|
69
|
+
mediainfo_free,
|
70
|
+
mi);
|
71
|
+
}
|
72
|
+
|
73
|
+
#define GETTER(name) \
|
74
|
+
static VALUE \
|
75
|
+
JOIN(mediainfo_get_,name)(VALUE self) \
|
76
|
+
{ \
|
77
|
+
UNPACK_MI; \
|
78
|
+
return mi->name; \
|
79
|
+
}
|
80
|
+
GETTER(path);
|
81
|
+
GETTER(stream_types);
|
82
|
+
GETTER(tracks);
|
83
|
+
GETTER(general);
|
84
|
+
GETTER(video);
|
85
|
+
GETTER(audio);
|
86
|
+
GETTER(text);
|
87
|
+
GETTER(chapters);
|
88
|
+
GETTER(image);
|
89
|
+
GETTER(menu);
|
90
|
+
#undef GETTER
|
91
|
+
|
92
|
+
static VALUE
|
93
|
+
mediainfo_compare(VALUE self, VALUE other)
|
94
|
+
{
|
95
|
+
GET_MEDIAINFO(a, self);
|
96
|
+
GET_MEDIAINFO(b, other);
|
97
|
+
return rb_funcall(a->path, rb_intern("<=>"), 1, b->path);
|
98
|
+
}
|
99
|
+
|
100
|
+
static VALUE
|
101
|
+
mediainfo_inspect(VALUE self)
|
102
|
+
{
|
103
|
+
char *buf;
|
104
|
+
UNPACK_MI;
|
105
|
+
|
106
|
+
if (mi->path == Qnil) {
|
107
|
+
return rb_str_new2("#<MediaInfo nil>");
|
108
|
+
} else {
|
109
|
+
#define INSPECT_FMT "#<MediaInfo \"%s\">"
|
110
|
+
buf = alloca(RSTRING_LEN(mi->path) + sizeof(INSPECT_FMT));
|
111
|
+
sprintf(buf, INSPECT_FMT, RSTRING_PTR(mi->path));
|
112
|
+
#undef INSPECT_FMT
|
113
|
+
return rb_str_new2(buf);
|
114
|
+
}
|
115
|
+
}
|
116
|
+
|
117
|
+
static VALUE
|
118
|
+
mediainfo_to_s(VALUE self)
|
119
|
+
{
|
120
|
+
return mediainfo_inspect(self);
|
121
|
+
}
|
122
|
+
|
123
|
+
static VALUE
|
124
|
+
mediainfo_load_track_info(VALUE self)
|
125
|
+
{
|
126
|
+
VALUE st;
|
127
|
+
VALUE argv[2];
|
128
|
+
VALUE types[MediaInfo_Stream_Max];
|
129
|
+
int stream_type;
|
130
|
+
UNPACK_MI;
|
131
|
+
|
132
|
+
argv[0] = self;
|
133
|
+
|
134
|
+
for (stream_type = 0; stream_type < MediaInfo_Stream_Max; stream_type++) {
|
135
|
+
argv[1] = INT2NUM(stream_type);
|
136
|
+
st = rb_class_new_instance(2, argv, cMediaInfo_cStreamType);
|
137
|
+
rb_ary_push(mi->stream_types, st);
|
138
|
+
types[stream_type] = st;
|
139
|
+
}
|
140
|
+
|
141
|
+
mi->general = types[MediaInfo_Stream_General];
|
142
|
+
mi->video = types[MediaInfo_Stream_Video];
|
143
|
+
mi->audio = types[MediaInfo_Stream_Audio];
|
144
|
+
mi->text = types[MediaInfo_Stream_Text];
|
145
|
+
mi->chapters = types[MediaInfo_Stream_Chapters];
|
146
|
+
mi->image = types[MediaInfo_Stream_Image];
|
147
|
+
mi->menu = types[MediaInfo_Stream_Menu];
|
148
|
+
|
149
|
+
return self;
|
150
|
+
}
|
151
|
+
|
152
|
+
static VALUE
|
153
|
+
mediainfo_open(int argc, VALUE *argv, VALUE self)
|
154
|
+
{
|
155
|
+
MediaInfo_Char *path;
|
156
|
+
size_t retval;
|
157
|
+
UNPACK_MI;
|
158
|
+
|
159
|
+
rb_scan_args(argc, argv, "10", &mi->path);
|
160
|
+
mi->path = StringValue(mi->path);
|
161
|
+
path = rstring_to_mediainfo_chars(mi->path);
|
162
|
+
|
163
|
+
if (!cMediaInfoAPI.open(mi->handle, path)) {
|
164
|
+
rb_raise(rb_eIOError, "MediaInfo_Open() failed");
|
165
|
+
}
|
166
|
+
RSTRING_TO_MINFO_FREE(path);
|
167
|
+
|
168
|
+
return mediainfo_load_track_info(self);
|
169
|
+
}
|
170
|
+
|
171
|
+
static VALUE
|
172
|
+
mediainfo_initialize(int argc, VALUE *argv, VALUE self)
|
173
|
+
{
|
174
|
+
if (argc > 0 ) {
|
175
|
+
return mediainfo_open(argc, argv, self);
|
176
|
+
} else {
|
177
|
+
return self;
|
178
|
+
}
|
179
|
+
}
|
180
|
+
|
181
|
+
static VALUE
|
182
|
+
mediainfo_close(VALUE self)
|
183
|
+
{
|
184
|
+
UNPACK_MI;
|
185
|
+
cMediaInfoAPI.close(mi->handle);
|
186
|
+
return self;
|
187
|
+
}
|
188
|
+
|
189
|
+
static const MediaInfo_Char *
|
190
|
+
mediainfo_report_string(mediainfo_t *mi)
|
191
|
+
{
|
192
|
+
const MediaInfo_Char *str = cMediaInfoAPI.inform(mi->handle, 0);
|
193
|
+
return str;
|
194
|
+
}
|
195
|
+
|
196
|
+
static VALUE
|
197
|
+
mediainfo_inform(VALUE self)
|
198
|
+
{
|
199
|
+
VALUE rstr;
|
200
|
+
const MediaInfo_Char *str;
|
201
|
+
UNPACK_MI;
|
202
|
+
|
203
|
+
str = mediainfo_report_string(mi);
|
204
|
+
rstr = mediainfo_chars_to_rstring(str);
|
205
|
+
return rstr;
|
206
|
+
}
|
207
|
+
|
208
|
+
VALUE
|
209
|
+
mediainfo_get_i(VALUE self, VALUE stream_type, VALUE stream_id, VALUE field_id, VALUE request_type)
|
210
|
+
{
|
211
|
+
const MediaInfo_Char *mi_str;
|
212
|
+
UNPACK_MI;
|
213
|
+
|
214
|
+
mi_str = cMediaInfoAPI.geti(mi->handle,
|
215
|
+
NUM2INT(stream_type),
|
216
|
+
NUM2INT(stream_id),
|
217
|
+
NUM2INT(field_id),
|
218
|
+
NUM2INT(request_type));
|
219
|
+
|
220
|
+
return mediainfo_string_to_rb(mi_str);
|
221
|
+
}
|
222
|
+
|
223
|
+
static VALUE
|
224
|
+
mediainfo_get(VALUE self, VALUE stream_type, VALUE stream_id, VALUE field_name, VALUE request_type)
|
225
|
+
{
|
226
|
+
MediaInfo_Char *mi_field_name;
|
227
|
+
const MediaInfo_Char *mi_str;
|
228
|
+
UNPACK_MI;
|
229
|
+
|
230
|
+
mi_field_name = rstring_to_mediainfo_chars(field_name);
|
231
|
+
|
232
|
+
mi_str = cMediaInfoAPI.get(mi->handle,
|
233
|
+
NUM2INT(stream_type),
|
234
|
+
NUM2INT(stream_id),
|
235
|
+
mi_field_name,
|
236
|
+
NUM2INT(request_type),
|
237
|
+
0);
|
238
|
+
|
239
|
+
RSTRING_TO_MINFO_FREE(mi_field_name);
|
240
|
+
|
241
|
+
return mediainfo_string_to_rb(mi_str);
|
242
|
+
}
|
243
|
+
|
244
|
+
static VALUE
|
245
|
+
mediainfo_option(VALUE self, VALUE name, VALUE value)
|
246
|
+
{
|
247
|
+
VALUE rstr;
|
248
|
+
MediaInfo_Char *mi_name;
|
249
|
+
MediaInfo_Char *mi_value;
|
250
|
+
const MediaInfo_Char *mi_str;
|
251
|
+
UNPACK_MI;
|
252
|
+
|
253
|
+
mi_name = rstring_to_mediainfo_chars(name);
|
254
|
+
mi_value = rstring_to_mediainfo_chars(value);
|
255
|
+
|
256
|
+
mi_str = cMediaInfoAPI.option(mi->handle, mi_name, mi_value);
|
257
|
+
|
258
|
+
RSTRING_TO_MINFO_FREE(mi_value);
|
259
|
+
RSTRING_TO_MINFO_FREE(mi_name);
|
260
|
+
|
261
|
+
rstr = mediainfo_chars_to_rstring(mi_str);
|
262
|
+
return rstr;
|
263
|
+
}
|
264
|
+
|
265
|
+
static VALUE
|
266
|
+
mediainfo_state_get(VALUE self)
|
267
|
+
{
|
268
|
+
UNPACK_MI;
|
269
|
+
return INT2NUM(cMediaInfoAPI.state_get(mi->handle));
|
270
|
+
}
|
271
|
+
|
272
|
+
VALUE
|
273
|
+
mediainfo_count_get(VALUE self, VALUE stream_type, VALUE stream_id)
|
274
|
+
{
|
275
|
+
UNPACK_MI;
|
276
|
+
return INT2NUM(cMediaInfoAPI.count_get(mi->handle,
|
277
|
+
NUM2INT(stream_type),
|
278
|
+
NUM2INT(stream_id)));
|
279
|
+
}
|
280
|
+
|
281
|
+
static VALUE
|
282
|
+
mediainfo_stream_type(int argc, VALUE *argv, VALUE self)
|
283
|
+
{
|
284
|
+
VALUE type_number;
|
285
|
+
rb_scan_args(argc, argv, "10", &type_number);
|
286
|
+
return rb_intern( mediainfo_stream_type_to_name(NUM2INT(type_number)) );
|
287
|
+
}
|
288
|
+
|
289
|
+
|
290
|
+
static VALUE
|
291
|
+
mediainfo_num_streams(VALUE self, VALUE type)
|
292
|
+
{
|
293
|
+
return mediainfo_count_get(self, type, INT2NUM(-1));
|
294
|
+
}
|
295
|
+
|
296
|
+
static VALUE
|
297
|
+
mediainfo_num_fields(VALUE self, VALUE type, VALUE stream_id)
|
298
|
+
{
|
299
|
+
return mediainfo_count_get(self, type, stream_id);
|
300
|
+
}
|
301
|
+
|
302
|
+
static VALUE
|
303
|
+
mediainfo_get_field(VALUE self, VALUE stream_type, VALUE stream_id, VALUE field_name)
|
304
|
+
{
|
305
|
+
return mediainfo_get(self, stream_type, stream_id, field_name,
|
306
|
+
INT2NUM(MediaInfo_Info_Text));
|
307
|
+
}
|
308
|
+
|
309
|
+
#define FIELD_GET(t,T) \
|
310
|
+
static VALUE \
|
311
|
+
JOIN(mediainfo_f_,t)(VALUE self, VALUE stream_id, VALUE field_name) \
|
312
|
+
{ \
|
313
|
+
return mediainfo_get_field(self, INT2NUM(JOIN(MediaInfo_Stream_,T)), \
|
314
|
+
stream_id, field_name); \
|
315
|
+
}
|
316
|
+
FIELD_GET(general,General);
|
317
|
+
FIELD_GET(video,Video);
|
318
|
+
FIELD_GET(audio,Audio);
|
319
|
+
FIELD_GET(text,Text);
|
320
|
+
FIELD_GET(chapters,Chapters);
|
321
|
+
FIELD_GET(image,Image);
|
322
|
+
FIELD_GET(menu,Menu);
|
323
|
+
#undef FIELD_GET
|
324
|
+
|
325
|
+
static VALUE
|
326
|
+
mediainfo_each(VALUE self)
|
327
|
+
{
|
328
|
+
UNPACK_MI;
|
329
|
+
return rb_ary_each(mi->tracks);
|
330
|
+
}
|
331
|
+
|
332
|
+
void
|
333
|
+
Init_mediainfo_MediaInfo(void)
|
334
|
+
{
|
335
|
+
cMediaInfo = rb_define_class("MediaInfo", rb_cObject);
|
336
|
+
rb_define_alloc_func(cMediaInfo, mediainfo_allocate);
|
337
|
+
|
338
|
+
rb_define_method(cMediaInfo, "<=>", mediainfo_compare, 1);
|
339
|
+
rb_define_method(cMediaInfo, "each_track", mediainfo_each, 0);
|
340
|
+
|
341
|
+
#define GET(name) \
|
342
|
+
rb_define_method(cMediaInfo, \
|
343
|
+
Q(name), \
|
344
|
+
JOIN(mediainfo_get_,name), \
|
345
|
+
0);
|
346
|
+
GET(path);
|
347
|
+
GET(stream_types);
|
348
|
+
GET(tracks);
|
349
|
+
GET(general);
|
350
|
+
GET(video);
|
351
|
+
GET(audio);
|
352
|
+
GET(text);
|
353
|
+
GET(chapters);
|
354
|
+
GET(image);
|
355
|
+
GET(menu);
|
356
|
+
#undef GET
|
357
|
+
|
358
|
+
#define M(name, numargs) \
|
359
|
+
rb_define_method(cMediaInfo, Q(name), JOIN(mediainfo_,name), numargs);
|
360
|
+
M(initialize, -1);
|
361
|
+
M(inspect, 0);
|
362
|
+
M(to_s, 0);
|
363
|
+
M(open, -1);
|
364
|
+
M(close, 0);
|
365
|
+
M(inform, 0);
|
366
|
+
M(get_i, 4);
|
367
|
+
M(get, 4);
|
368
|
+
M(option, 2);
|
369
|
+
M(state_get, 0);
|
370
|
+
M(count_get, 2);
|
371
|
+
M(stream_type, -1);
|
372
|
+
M(num_streams, 1);
|
373
|
+
M(num_fields, 2);
|
374
|
+
M(get_field, 3);
|
375
|
+
M(f_general, 2);
|
376
|
+
M(f_video, 2);
|
377
|
+
M(f_audio, 2);
|
378
|
+
M(f_text, 2);
|
379
|
+
M(f_chapters, 2);
|
380
|
+
M(f_image, 2);
|
381
|
+
M(f_menu, 2);
|
382
|
+
M(each, 0);
|
383
|
+
#undef M
|
384
|
+
}
|