media-organizer 0.1.1 → 0.1.2

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.
@@ -5,108 +5,112 @@
5
5
  require 'scrapers/image.rb'
6
6
  require 'scrapers/music.rb'
7
7
 
8
- class FileNotValidError < StandardError ; end
9
8
 
10
- class Filescanner
11
- include Image
12
- include Music
9
+ module MediaOrganizer
13
10
 
14
- attr_reader :root_nodes
15
- attr_accessor :source_list
11
+ class FileNotValidError < StandardError ; end
16
12
 
13
+ class Filescanner
14
+ include Image
15
+ include Music
17
16
 
18
- def initialize()
19
- @root_nodes = []
20
- @source_list = []
21
- end
17
+ attr_reader :root_nodes
18
+ attr_accessor :source_list
22
19
 
23
- #
24
- #Filescanner.open(String, {}): scans directory tree for media files, starting at String specified in first argument.
25
- #
26
- #==Inputs
27
- #===Required
28
- #(1) String: String containing the URI of the top of the directory tree to scan
29
- #
30
- #===Optional
31
- #(2) Arguments Hash:
32
- #*:mode => (:single) -- if set to :single, only the given URI will be scanned. Subdirectories will be ignored.
33
- #*:music => (true, false) -- if true, music files will be included in the scan. Set to false to exclude music files. Defaults to true
34
- #*:image => (true, false) -- if true, image files will be included in the scan. Set to false to exclude image files. Defaults to true
35
- #
36
- #==Outputs
37
- #Returns array of strings, where each string is a file URI for a music or image file.
38
- #
39
- #
40
- #==Usage Example
41
- #Filescanner.open("/absolute/path/for/top/of/directory/tree")
42
- #
43
- def open(uri = "", args = {})
44
- unless !uri.nil? && uri.is_a?(String) && (File.directory?(uri) || File.exists?(uri))
45
- raise FileNotFoundError, "Directory given (#{uri}) could not be accessed."
46
- end
47
-
48
- include_images = true unless args[:image] == false
49
- include_music = true unless args[:music] == false
50
- files = []
51
- if args[:mode] == :single
52
- files = Dir.glob("#{uri}/*")
53
- else
54
- files = Dir.glob("#{uri}/**/*")
20
+
21
+ def initialize()
22
+ @root_nodes = []
23
+ @source_list = []
55
24
  end
56
-
57
- #add all files found to @source_list, if they are music files
58
- files.each do |f|
59
- if (Music.is_music?(f) && include_music) || (Image.is_image?(f) && include_images)
60
- @source_list << f
25
+
26
+ #
27
+ #Filescanner.open(String, {}): scans directory tree for media files, starting at String specified in first argument.
28
+ #
29
+ #==Inputs
30
+ #===Required
31
+ #(1) String: String containing the URI of the top of the directory tree to scan
32
+ #
33
+ #===Optional
34
+ #(2) Arguments Hash:
35
+ #*:mode => (:single) -- if set to :single, only the given URI will be scanned. Subdirectories will be ignored.
36
+ #*:music => (true, false) -- if true, music files will be included in the scan. Set to false to exclude music files. Defaults to true
37
+ #*:image => (true, false) -- if true, image files will be included in the scan. Set to false to exclude image files. Defaults to true
38
+ #
39
+ #==Outputs
40
+ #Returns array of strings, where each string is a file URI for a music or image file.
41
+ #
42
+ #
43
+ #==Usage Example
44
+ #Filescanner.open("/absolute/path/for/top/of/directory/tree")
45
+ #
46
+ def open(uri = "", args = {})
47
+ unless !uri.nil? && uri.is_a?(String) && (File.directory?(uri) || File.exists?(uri))
48
+ raise FileNotFoundError, "Directory given (#{uri}) could not be accessed."
49
+ end
50
+
51
+ include_images = true unless args[:image] == false
52
+ include_music = true unless args[:music] == false
53
+ files = []
54
+ if args[:mode] == :single
55
+ files = Dir.glob("#{uri}/*")
56
+ else
57
+ files = Dir.glob("#{uri}/**/*")
61
58
  end
59
+
60
+ #add all files found to @source_list, if they are music files
61
+ files.each do |f|
62
+ if (Music.is_music?(f) && include_music) || (Image.is_image?(f) && include_images)
63
+ @source_list << f
64
+ end
65
+ end
66
+
67
+ return @source_list
68
+
69
+ rescue FileNotFoundError => e
70
+ puts e.message
71
+ puts e.backtrace.inspect
72
+ return false
62
73
  end
63
74
 
64
- return @source_list
75
+ #alternative run mode. Add multiple "root" directories to scan at once
76
+ def addRoot(dir_uri)
77
+ unless !dir_uri.nil? && dir_uri.is_a?(String) && File.directory?(dir_uri)
78
+ raise FileNotFoundError, "Directory given (#{dir_uri}) could not be accessed."
79
+ end
80
+ @root_nodes << dir_uri
81
+ rescue FileNotFoundError => e
82
+ puts e.message
83
+ puts e.backtrace.inspect
84
+ return false
85
+ end
65
86
 
66
- rescue FileNotFoundError => e
67
- puts e.message
68
- puts e.backtrace.inspect
69
- return false
70
- end
87
+ #<<(): synonym for addRoot(). Also a deformed emoticon.
88
+ # def << (dir_uri) addRoot(dir_uri) end
71
89
 
72
- #alternative run mode. Add multiple "root" directories to scan at once
73
- def addRoot(dir_uri)
74
- unless !dir_uri.nil? && dir_uri.is_a?(String) && File.directory?(dir_uri)
75
- raise FileNotFoundError, "Directory given (#{dir_uri}) could not be accessed."
90
+ #
91
+ #multiscan(): scans multiple directories added to @root_nodes using the addRoot() method.
92
+ #
93
+ #==Inputs
94
+ #===Required
95
+ #none
96
+ #
97
+ #===Optional
98
+ #(1) Arguments Hash:
99
+ #*:mode => (:single, :multiple)
100
+ #*:music => (true, false) -- if true, music files will be included in the scan. Set to false to exclude music files. Defaults to true
101
+ #*:image => (true, false) -- if true, image files will be included in the scan. Set to false to exclude image files. Defaults to true
102
+ #
103
+ #==Outputs
104
+ #Array of strings, where each string is a file URI for a music or image file.
105
+ #
106
+ def multiscan(args = {})
107
+ @root_nodes.each do |uri|
108
+ open(uri, args)
76
109
  end
77
- @root_nodes << dir_uri
78
- rescue FileNotFoundError => e
79
- puts e.message
80
- puts e.backtrace.inspect
81
- return false
82
- end
83
-
84
- #<<(): synonym for addRoot(). Also a deformed emoticon.
85
- # def << (dir_uri) addRoot(dir_uri) end
86
-
87
- #
88
- #multiscan(): scans multiple directories added to @root_nodes using the addRoot() method.
89
- #
90
- #==Inputs
91
- #===Required
92
- #none
93
- #
94
- #===Optional
95
- #(1) Arguments Hash:
96
- #*:mode => (:single, :multiple)
97
- #*:music => (true, false) -- if true, music files will be included in the scan. Set to false to exclude music files. Defaults to true
98
- #*:image => (true, false) -- if true, image files will be included in the scan. Set to false to exclude image files. Defaults to true
99
- #
100
- #==Outputs
101
- #Array of strings, where each string is a file URI for a music or image file.
102
- #
103
- def multiscan(args = {})
104
- @root_nodes.each do |uri|
105
- open(uri, args)
110
+ return @source_list
106
111
  end
107
- return @source_list
112
+
108
113
  end
109
-
110
- end
111
114
 
115
+ end
112
116
 
@@ -3,7 +3,8 @@
3
3
  require 'renamer.rb'
4
4
  require 'filescanner.rb'
5
5
 
6
- class MediaRenamer < Renamer
7
-
6
+ module MediaOrganizer
7
+ VERSION = "0.1.2"
8
+
8
9
  end
9
10
 
@@ -1,163 +1,212 @@
1
1
  #renamer.rb: main codebase for the media-renamer gem.
2
2
  #Currently configured to only rename JPG and TIF files (using EXIFR to extract metadata)
3
3
  #next major release will include support
4
-
5
-
6
4
  require 'scrapers/image.rb'
7
5
  require 'scrapers/music.rb'
8
6
 
9
- class FileNotValidError < StandardError ; end
10
- class InvalidArgumentError < StandardError ; end
11
- class UnsupportedFileTypeError < StandardError ; end
12
- class RenameFailedError < StandardError ; end
7
+ module MediaOrganizer
13
8
 
14
- class Renamer
15
- include Image
16
- include Music
9
+ class FileNotValidError < StandardError ; end
10
+ class InvalidArgumentError < StandardError ; end
11
+ class UnsupportedFileTypeError < StandardError ; end
12
+ class RenameFailedError < StandardError ; end
13
+
14
+ #Renamer: primary class to use for renaming files. Allows renaming of a given list of files to a user-defined scheme based on each file's metadata.
15
+ #
16
+ #===Key Methods
17
+ # *setNamingScheme()
18
+ # *generateRenameList()
19
+ # *overwrite()
20
+ #
21
+ #===Example Usage
22
+ #
23
+ # old_uris = ['./test/data/hs-2003-24-a-full_tif.tif']
24
+ #
25
+ # scheme = ["Test-", :date_time]
26
+ #
27
+ # r = Renamer.new()
28
+ #
29
+ # r.setNamingScheme(scheme)
30
+ #
31
+ # new_uris = r.generateRenameList(old_uris)
32
+ #
33
+ # r.overwrite(new_uris) #new filename: "./test/data/Test-2003-09-03 12_52_43 -0400.tif")
34
+ #
35
+ class Renamer
36
+ DISALLOWED_CHARACTERS = /[\\:\?\*<>\|"\/]/ #Characters that are not allowed in file names by many file systems. Replaced with @subchar character.
37
+
38
+ attr_accessor :naming_scheme #Array of strings and literals used to construct filenames. Set thruough setNamingScheme as opposed to typical/default accessor.
39
+ attr_accessor :subchar #Character with which to substitute disallowed characters
40
+
41
+ def initialize(args = {})
42
+ @naming_scheme = ["Renamed-default-"]
43
+ @subchar = "_"
44
+ end
17
45
 
18
- DISALLOWED_CHARACTERS = /[\\:\?\*<>\|"\/]/
46
+ #Renamer.setNamingScheme(): sets the naming scheme for the generateRenameList method.
47
+ #
48
+ #===Inputs
49
+ # 1. Array containing strings and symbols.
50
+ #
51
+ #===Outputs
52
+ #None (sets instance variable @naming_scheme)
53
+ #
54
+ #===Example
55
+ #setNamingScheme(["Vacation_Photos_", :date_taken]).
56
+ #This will rename files into a format like "Vacation_Photos_2014_05_22.png" based on the file's date_taken metadata field.
57
+ def setNamingScheme(arr = [])
58
+ @naming_scheme = setScheme(arr)
59
+ end
19
60
 
20
- attr_accessor :naming_scheme # => array of strings and literals used to construct filenames
21
- attr_accessor :subchar
61
+ #Renamer.generateRenameList(): Creates a hash mapping the original filenames to the new (renamed) filenames
62
+ #
63
+ #===Inputs
64
+ # 1. List of URIs in the form of an array
65
+ # 2. Optional hash of arguments.
66
+ # *:scheme - array of strings and symbols specifying file naming convention
67
+ #
68
+ #===Outputs
69
+ #Hash of "file name pairs." old_file => new_file
70
+ def generateRenameList(uri_list = [], args = {})
71
+ if args[:scheme] != nil && args[:scheme].is_a?(Array) && !args[:scheme].empty?
72
+ scheme = setScheme(args[:scheme])
73
+ else
74
+ scheme = @naming_scheme
75
+ end
76
+ unless !uri_list.nil? && uri_list.is_a?(Array)
77
+ raise InvalidArgumentError
78
+ end
22
79
 
23
- def initialize(args = {})
24
- @naming_scheme = ["Renamed-default-"]
25
- @subchar = "_"
26
- end
80
+ filename_pairs = {}
81
+ uri_list.each do |i|
82
+ new_string = handleFile(i, scheme)
83
+ #If this is a valid file path, add it to the filename_pairs
84
+ #puts "New file rename added: #{new_string}"
85
+ if new_string != nil && new_string != ""
86
+ filename_pairs[i] = new_string
87
+ end
88
+ end
27
89
 
28
- def setNamingScheme(arr = [])
29
- @naming_scheme = setScheme(arr)
30
- end
31
- #Input: list of URIs in the form of an array
32
- #Output: hash of "file name pairs." old_file => new_file
33
- #Accepts optional arguments: :scheme (array of strings and symbols specifying file naming convention)
34
- def generateRenameList(uri_list = [], args = {})
35
- if args[:scheme] != nil && args[:scheme].is_a?(Array) && !args[:scheme].empty?
36
- scheme = setScheme(args[:scheme])
37
- else
38
- scheme = @naming_scheme
39
- end
40
- unless !uri_list.nil? && uri_list.is_a?(Array)
41
- raise InvalidArgumentError
90
+ return filename_pairs
91
+
92
+ rescue InvalidArgumentError => arg_e
93
+ puts arg_e
94
+ puts "Invalid arguments provided. Expected: uri_list = [], args = {}"
95
+ puts arg_e.backtrace.inspect
96
+ rescue => e
97
+ puts e
98
+ puts e.message
99
+ puts e.backtrace.inspect
42
100
  end
43
101
 
44
- filename_pairs = {}
45
- uri_list.each do |i|
46
- new_string = handleFile(i, scheme)
47
- #If this is a valid file path, add it to the filename_pairs
48
- #puts "New file rename added: #{new_string}"
49
- if new_string != nil && new_string != ""
50
- filename_pairs[i] = new_string
102
+ #Renamer.overwrite(): Writes new file names based upon mapping provided in hash argument. NOTE: this will create changes to file names!
103
+ #
104
+ #===Inputs
105
+ # 1. Hash containing mappings between old filenames (full URI) and new filenames (full URI). Example: {"/path/to/oldfile.jpg" => "/path/to/newfile.jpg"}
106
+ #
107
+ #===Outputs
108
+ #none (file names are overwritten)
109
+ def overwrite(renames_hash = {})
110
+ renames_hash.each do |old_name, new_name|
111
+ begin
112
+ #error/integrity checking on old_name and new_name
113
+ raise FileNotValidError, "Could not access specified source file: #{i}." unless old_name.is_a?(String) && File.exists?(old_name)
114
+ raise FileNotValidError, "New file name provided is not a string" unless new_name.is_a?(String)
115
+
116
+ #puts (File.dirname(File.absolute_path(old_name)) + "/" + new_name) #Comment this line out unless testing
117
+ File.rename(File.absolute_path(old_name),File.dirname(File.absolute_path(old_name)) + "/" + new_name)
118
+
119
+ #check that renamed file exists - Commented out because this currently does not work.
120
+ #unless new_name.is_a?(String) && File.exists?(new_name)
121
+ # raise RenameFailedError, "Could not successfuly rename file: #{old_name} => #{new_name}. Invalid URI or file does not exist."
122
+ #end
123
+ rescue => e
124
+ puts "Ignoring rename for #{old_name} => #{new_name}"
125
+ puts e
126
+ puts e.backtrace.inspect
127
+ end
51
128
  end
52
129
  end
53
130
 
54
- return filename_pairs
55
-
56
- rescue InvalidArgumentError => arg_e
57
- puts arg_e
58
- puts "Invalid arguments provided. Expected: uri_list = [], args = {}"
59
- puts arg_e.backtrace.inspect
60
- rescue => e
61
- puts e
62
- puts e.message
63
- puts e.backtrace.inspect
64
- end
65
-
66
- def overwrite(renames_hash = {})
67
- renames_hash.each do |old_name, new_name|
68
- begin
69
- #error/integrity checking on old_name and new_name
70
- raise FileNotValidError, "Could not access specified source file: #{i}." unless old_name.is_a?(String) && File.exists?(old_name)
71
- raise FileNotValidError, "New file name provided is not a string" unless new_name.is_a?(String)
72
-
73
- #puts (File.dirname(File.absolute_path(old_name)) + "/" + new_name) #Comment this line out unless testing
74
- File.rename(File.absolute_path(old_name),File.dirname(File.absolute_path(old_name)) + "/" + new_name)
75
-
76
- #check that renamed file exists - Commented out because this currently does not work.
77
- #unless new_name.is_a?(String) && File.exists?(new_name)
78
- # raise RenameFailedError, "Could not successfuly rename file: #{old_name} => #{new_name}. Invalid URI or file does not exist."
79
- #end
80
- rescue => e
81
- puts "Ignoring rename for #{old_name} => #{new_name}"
82
- puts e
83
- puts e.backtrace.inspect
131
+ #Routes metadata scrape based on file type (currently relies on extension - future version should use MIME)
132
+ #currently assumes file was checked for validity in calling code.
133
+ #
134
+ #===Inputs
135
+ #String containing full file URI (path and filename)
136
+ #
137
+ #===Outputs
138
+ #Returns hash of metadata for file, or nil if none/error.
139
+ def getFileMetadata(file)
140
+
141
+ #LOAD EXIF DATA
142
+ case File.extname(file).downcase
143
+ when '.jpg'
144
+ Image::getJpegData(file)
145
+ when '.tif'
146
+ Image::getTiffData(file)
147
+ when '.mp3' , '.wav' , '.flac' , '.aiff', '.ogg', '.m4a', '.asf'
148
+ Music::getMusicData(file)
149
+ else
150
+ raise UnsupportedFileTypeError, "Error processing #{file}"
84
151
  end
152
+ rescue UnsupportedFileTypeError => e
153
+ puts "Could not process file: Extension #{File.extname(file)} is not supported."
154
+ puts e.backtrace.inspect
85
155
  end
86
- end
87
-
88
- #Routes metadata scrape based on file type (currently relies on extension - future version should use MIME)
89
- #currently assumes file was checked for validity in calling code
90
- def getFileMetadata(file)
91
-
92
- #LOAD EXIF DATA
93
- case File.extname(file).downcase
94
- when '.jpg'
95
- Image::getJpegData(file)
96
- when '.tif'
97
- Image::getTiffData(file)
98
- when '.mp3' , '.wav' , '.flac' , '.aiff', '.ogg', '.m4a', '.asf'
99
- Music::getMusicData(file)
100
- else
101
- raise UnsupportedFileTypeError, "Error processing #{file}"
102
- end
103
- #otherwise, outsource
104
- rescue UnsupportedFileTypeError => e
105
- puts "Could not process file: Extension #{File.extname(file)} is not supported."
106
- puts e.backtrace.inspect
107
- end
108
156
 
109
157
 
110
- private
111
- def handleFile(file, scheme)
112
- #Check file is real
113
- unless file.is_a?(String) && File.exists?(file)
114
- raise FileNotValidError, "Could not access specified file file: #{file}."
115
- end
116
- #convert URI (i) to absolute path
117
-
118
- #get metadata hash for this file (i)
119
- metadata = getFileMetadata(File.absolute_path(file))
120
- #build URI string
121
- new_string = ""
122
- scheme.each do |j|
123
- if j.is_a?(String) then new_string += j
124
- elsif j.is_a?(Symbol)
125
- begin
126
- raise EmptyMetadataError unless metadata[j] != nil
127
- new_string += metadata[j].to_s
128
- rescue => e
129
- puts "Could not get string for metadata tag provided in scheme: #{j} for file #{file}."
130
- puts "Ignoring file #{file}"
131
- puts e.backtrace.inspect
132
- return nil
158
+ private
159
+ def handleFile(file, scheme)
160
+ #Check file is real
161
+ unless file.is_a?(String) && File.exists?(file)
162
+ raise FileNotValidError, "Could not access specified file file: #{file}."
163
+ end
164
+ #convert URI (i) to absolute path
165
+
166
+ #get metadata hash for this file (i)
167
+ metadata = getFileMetadata(File.absolute_path(file))
168
+ #build URI string
169
+ new_string = ""
170
+ scheme.each do |j|
171
+ if j.is_a?(String) then new_string += j
172
+ elsif j.is_a?(Symbol)
173
+ begin
174
+ raise EmptyMetadataError unless metadata[j] != nil
175
+ new_string += metadata[j].to_s
176
+ rescue => e
177
+ puts "Could not get string for metadata tag provided in scheme: #{j} for file #{file}."
178
+ puts "Ignoring file #{file}"
179
+ puts e.backtrace.inspect
180
+ return nil
181
+ end
133
182
  end
134
183
  end
184
+ #puts "Found file metadata: #{metadata[:date_time]}"
185
+ return subHazardousChars(new_string + File.extname(file))
186
+ rescue FileNotValidError => e
187
+ puts ("Ignoring file #{file}")
188
+ puts e
189
+ puts e.backtrace
190
+ return nil
191
+ rescue => e
192
+ puts e.message
193
+ puts e.backtrace.inspect
194
+ return nil
135
195
  end
136
- #puts "Found file metadata: #{metadata[:date_time]}"
137
- return subHazardousChars(new_string + File.extname(file))
138
- rescue FileNotValidError => e
139
- puts ("Ignoring file #{file}")
140
- puts e
141
- puts e.backtrace
142
- return nil
143
- rescue => e
144
- puts e.message
145
- puts e.backtrace.inspect
146
- return nil
147
- end
148
196
 
149
- def setScheme(input_arr = [])
150
- clean_scheme = []
151
- input_arr.each do |i|
152
- if i.is_a?(String) || i.is_a?(Symbol)
153
- clean_scheme << i
197
+ def setScheme(input_arr = [])
198
+ clean_scheme = []
199
+ input_arr.each do |i|
200
+ if i.is_a?(String) || i.is_a?(Symbol)
201
+ clean_scheme << i
202
+ end
154
203
  end
204
+ return clean_scheme
155
205
  end
156
- return clean_scheme
157
- end
158
206
 
159
- def subHazardousChars(str = "")
160
- return str.gsub(DISALLOWED_CHARACTERS, @subchar)
207
+ def subHazardousChars(str = "")
208
+ return str.gsub(DISALLOWED_CHARACTERS, @subchar)
209
+ end
161
210
  end
162
- end
163
211
 
212
+ end
@@ -2,40 +2,43 @@ require 'exifr'
2
2
 
3
3
  class FileNotFoundError < StandardError ; end
4
4
 
5
- module Image
6
- SUPPORTED_FILETYPES = %w{.jpg .tif}
5
+ module MediaOrganizer
7
6
 
8
- def Image.getJpegData(file)
9
- meta = EXIFR::JPEG.new(file)
10
- return meta.to_hash
11
- #!!! Rescue from common file-related and exifr-related errors here
12
- end
7
+ module Image
8
+ SUPPORTED_FILETYPES = %w{.jpg .tif}
13
9
 
14
- def Image.getTiffData(file)
15
- meta = EXIFR::TIFF.new(file)
16
- return meta.to_hash
17
- #!!! Rescue from common file-related and exifr-related errors here
18
- end
10
+ def Image.getJpegData(file)
11
+ meta = EXIFR::JPEG.new(file)
12
+ return meta.to_hash
13
+ #!!! Rescue from common file-related and exifr-related errors here
14
+ end
19
15
 
20
- def Image.supported_filetypes
21
- return SUPPORTED_FILETYPES
22
- end
16
+ def Image.getTiffData(file)
17
+ meta = EXIFR::TIFF.new(file)
18
+ return meta.to_hash
19
+ #!!! Rescue from common file-related and exifr-related errors here
20
+ end
23
21
 
24
- def Image.is_image?(uri)
25
- unless !uri.nil? && uri.is_a?(String) && File.exists?(uri)
26
- raise FileNotFoundError, "Directory given (#{uri}) could not be accessed."
22
+ def Image.supported_filetypes
23
+ return SUPPORTED_FILETYPES
27
24
  end
28
25
 
29
- if SUPPORTED_FILETYPES.include?(File.extname(uri).downcase)
30
- return true
31
- else
26
+ def Image.is_image?(uri)
27
+ unless !uri.nil? && uri.is_a?(String) && File.exists?(uri)
28
+ raise FileNotFoundError, "Directory given (#{uri}) could not be accessed."
29
+ end
30
+
31
+ if SUPPORTED_FILETYPES.include?(File.extname(uri).downcase)
32
+ return true
33
+ else
34
+ return false
35
+ end
36
+
37
+ rescue FileNotFoundError => e
38
+ puts e.message
39
+ puts e.backtrace.inspect
32
40
  return false
33
41
  end
34
42
 
35
- rescue FileNotFoundError => e
36
- puts e.message
37
- puts e.backtrace.inspect
38
- return false
39
43
  end
40
-
41
44
  end
@@ -1,59 +1,116 @@
1
1
  require 'taglib'
2
2
 
3
- class FileNotFoundError < StandardError ; end
4
-
5
- module Music
6
-
7
- SUPPORTED_FILETYPES = %w{.mp3 .m4a .mp4 .flac .m4a .ogg .aiff .asf .wav}
8
-
9
- def Music.getMusicData(file)
10
- attributes = {}
11
- TagLib::FileRef.open(file) do |fileref|
12
- unless fileref.null?
13
- #sign tags to local variables
14
- tag = fileref.tag
15
- properties = fileref.audio_properties
16
-
17
- #load tags into attributes attribute
18
- attributes[:track_name] = tag.title
19
- attributes[:track_number] = tag.track
20
- attributes[:track_genre] = tag.genre
21
- attributes[:track_release_date] = tag.year
22
- attributes[:album_name] = tag.album
23
- attributes[:artist_name] = tag.artist
24
- attributes[:comment] = tag.comment
25
-
26
- attributes[:track_length] = properties.length
27
- attributes[:track_bitrate] = properties.bitrate
28
- attributes[:track_channels] = properties.channels
29
- attributes[:track_sample_rate] = properties.sample_rate
30
-
31
- end
32
- end
33
- return attributes
34
- end
3
+ module MediaOrganizer
35
4
 
36
- def Music.supported_filetypes
37
- reutrn SUPPORTED_FILETYPES
38
- end
5
+ class FileNotFoundError < StandardError ; end
6
+
7
+ module Music
8
+
9
+ SUPPORTED_FILETYPES = %w{.mp3 .m4a .mp4 .flac .m4a .ogg .aiff .asf .wav}
39
10
 
40
- def Music.is_music?(uri)
41
- unless !uri.nil? && uri.is_a?(String) && File.exists?(uri)
42
- raise FileNotFoundError, "Directory given (#{uri}) could not be accessed."
11
+ def Music.getMusicData(file)
12
+ attributes = {}
13
+ TagLib::FileRef.open(file) do |fileref|
14
+ unless fileref.null?
15
+ #sign tags to local variables
16
+ tag = fileref.tag
17
+ properties = fileref.audio_properties
18
+
19
+ #load tags into attributes attribute
20
+ attributes[:title] = tag.title
21
+ attributes[:track] = tag.track
22
+ attributes[:genre] = tag.genre
23
+ attributes[:year] = tag.year
24
+ attributes[:album] = tag.album
25
+ attributes[:artist] = tag.artist
26
+ attributes[:comment] = tag.comment
27
+
28
+ attributes[:length] = properties.length
29
+ attributes[:bitrate] = properties.bitrate
30
+ attributes[:channels] = properties.channels
31
+ attributes[:sample_rate] = properties.sample_rate
32
+
33
+ end
34
+ end
35
+ return attributes
43
36
  end
44
37
 
45
- if SUPPORTED_FILETYPES.include?(File.extname(uri).downcase)
46
- return true
47
- else
38
+ def Music.supported_filetypes
39
+ reutrn SUPPORTED_FILETYPES
40
+ end
41
+
42
+ def Music.is_music?(uri)
43
+ unless !uri.nil? && uri.is_a?(String) && File.exists?(uri)
44
+ raise FileNotFoundError, "Directory given (#{uri}) could not be accessed."
45
+ end
46
+
47
+ if SUPPORTED_FILETYPES.include?(File.extname(uri).downcase)
48
+ return true
49
+ else
50
+ return false
51
+ end
52
+
53
+ rescue FileNotFoundError => e
54
+ puts e.message
55
+ puts e.backtrace.inspect
48
56
  return false
49
57
  end
50
58
 
51
- rescue FileNotFoundError => e
52
- puts e.message
53
- puts e.backtrace.inspect
54
- return false
55
- end
59
+ #
60
+ #availableMetadata(file, args): returns list of fields available as metadata for the given file.
61
+ #
62
+ #===Inputs
63
+ # *(1) filepath: full/absolute URI of the file to be analyzed. Required input.
64
+ # *(2) args: optional arguments passed as hash. Set ":include_null" to false to only return populated metadata fields.
65
+ #
66
+ def Music.availableMetadata(filepath = "", args = {})
67
+ attrs = getMusicData(filepath)
68
+
69
+ unless args[:include_null] == false
70
+ attrs.each do |field, value|
71
+ if value == nil || value == ""
72
+ attrs.delete(field)
73
+ end
74
+ end
75
+ end
76
+ return attrs
77
+ end
56
78
 
79
+ #
80
+ #writeMetadata(file = "", meta = {}): returns list of fields available as metadata for the given file.
81
+ #
82
+ #===Inputs
83
+ # *(1) filepath: full/absolute URI of the file to be analyzed. Required input.
84
+ # *(2) meta: metadata to be written, passed as a hash in the format :metadata_field => metadata_value
85
+ #
86
+ #===Outputs
87
+ #Returns true if the file was successfully saved. Note: true status does not necessarily indicate each field was successfully written.
88
+ #
89
+ #===Examples
90
+ #Music.writeMetadata("/absolute/path/to/file.mp3", {:artist => "NewArtistName", :year => "2019"})
91
+ #
92
+ def Music.writeMetadata(filepath, meta = {})
93
+ attributes = {}
94
+ successflag = false
95
+ TagLib::FileRef.open(filepath) do |fileref|
96
+ unless fileref.null?
97
+ #sign tags to local variables
98
+ tag = fileref.tag
99
+ properties = fileref.audio_properties
57
100
 
58
- end
101
+ meta.each do |field, value|
102
+ if tag.respond_to?(field)
103
+ tag.send("#{field.to_s}=", value)
104
+ elsif properties.respond_to?(field)
105
+ properties.send("#{field.to_s}=", value)
106
+ end
107
+ end
108
+ successflag = fileref.save
109
+ end
110
+ end
111
+ return successflag
59
112
 
113
+ end
114
+
115
+ end
116
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: media-organizer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2015-03-01 00:00:00.000000000 Z
12
+ date: 2015-03-14 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: taglib-ruby