got_mp3 0.2.0 → 0.4.0

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.
Files changed (6) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/lib/got_mp3.rb +235 -32
  4. data.tar.gz.sig +0 -0
  5. metadata +63 -3
  6. metadata.gz.sig +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 94d8fc924be742f45265ce5ced2836859ad920e2813294107861e9530ce00ab0
4
- data.tar.gz: c60a80063c720c5a97a6cd0dc994688e9c6227c462c4bd857dc51307af2143c4
3
+ metadata.gz: a109d9369982eb251b2439256a7ab8ecb0494f8b693efeb869ed6e29329d23e4
4
+ data.tar.gz: 960ba30e1ab1178b77280f9f6068248cb82616040caa2fca2880dcccc78c1af0
5
5
  SHA512:
6
- metadata.gz: dc555a1313236f60e25892afbee007b6a2953b35c7a7c36ceeb0acf36865315b181a70d748c243b3c7385e2d5bb547a36742884465877bfc3796bd16a11b00af
7
- data.tar.gz: e07d01081c5002073e8f147559cc19022ce326d438698808d004eaff62bd35c1095139e3ccd0a91971caeade73993b6f5505ed967561458e3d660fed2edc0f86
6
+ metadata.gz: 8777628c7ec8d16460fe3ff59199b98bf34bf10494ffdb22afd432cb1f7110591bd48370998f4bc4757f9564d3b4a190ec03537e03d2f9c7cecd01b0ddafe744
7
+ data.tar.gz: 7c9b29dc4e6e889644c2cfef6464fcb09fb34ead8101670a7f08942344132994099444a144b5ee5a24e9f76d1c176f595837845accd9a6ef8efb1ff269994e80
checksums.yaml.gz.sig CHANGED
Binary file
data/lib/got_mp3.rb CHANGED
@@ -2,12 +2,17 @@
2
2
 
3
3
  # file: got_mp3.rb
4
4
 
5
+ require 'dxlite'
5
6
  require 'ostruct'
6
- require "mp3info"
7
+ require 'mp3info'
8
+ require 'ogginfo'
9
+ require 'playlist_creator'
7
10
 
8
11
 
9
12
  class GotMP3
10
13
 
14
+ attr_accessor :dir
15
+
11
16
  def initialize(dir: '.', debug: false)
12
17
  @dir, @debug = dir, debug
13
18
  end
@@ -22,6 +27,8 @@ class GotMP3
22
27
  def add_jpg()
23
28
 
24
29
  find_by_ext('.jpg').each do |directory, img_filename|
30
+
31
+ puts 'add_jpg to directory: ' + directory.inspect if @debug
25
32
  add_image directory, img_filename
26
33
  end
27
34
 
@@ -41,12 +48,118 @@ class GotMP3
41
48
 
42
49
  end
43
50
 
44
- def each_mp3_file(directory='.', &blk)
51
+ # Adds an XSPF playlist file to each file directory containing MP3s
52
+ #
53
+ def add_playlist(dir: @dir)
45
54
 
46
- found = Dir[File.join(directory, "*.mp3")].sort_by { |x| File.mtime(x) }
47
- found.each.with_index do |mp3_filepath, i|
55
+ # .new('/home/james/Music2/Christmas)
56
+ #mp3s = Dir[File.join(@dir, '*.mp3')].sort_by {|x| File.mtime(x)}.reverse
57
+ a = Dir.glob(File.join(dir, '*')).select {|f| File.directory? f}
58
+
59
+ tracks = []
60
+
61
+ a.each do |dir|
62
+
63
+ tracks += add_playlist(dir: dir)
64
+
65
+ each_media_track(dir) do |media, trackno, filepath|
66
+
67
+ info = case File.extname(filepath)
68
+ when '.mp3'
69
+ mp3info(media)
70
+ when '.ogg'
71
+ ogginfo(media)
72
+ end
73
+
74
+ h = {
75
+ title: info[:title],
76
+ location: File.join(File.basename(dir), File.basename(filepath)),
77
+ album: info[:album]
78
+ }
79
+
80
+ tracks << h
81
+
82
+ end
83
+
84
+ end
85
+
86
+
87
+
88
+ pc = PlaylistCreator.new()
89
+
90
+ tracks.each do |x|
91
+ pc.add title: x[:title], location: x[:location], album: x[:album]
92
+ end
93
+
94
+ File.write File.join(dir,'playlist.xspf'), pc.to_xspf
95
+
96
+ return tracks
97
+
98
+ end
99
+
100
+ # Copies all MP3 directories through the category file-directory stucture.
101
+ # To accomplish this, it need a reference (source) directory containing the
102
+ # .txt for each album.
103
+ #
104
+ def compile(source_directory: '', target_directory: '')
105
+
106
+ raise 'target_directory cannot be empty' if target_directory.empty?
48
107
 
49
- blk.call(mp3_filepath, i )
108
+ find_by_ext('.txt').each do |directory, _ |
109
+
110
+ Dir[File.join(directory, '*.txt')].each do |txt_filename|
111
+
112
+ album = File.join(source_directory,
113
+ File.basename(txt_filename).sub(/\.txt$/,''))
114
+ library_dir = File.join(target_directory, File.basename(directory))
115
+ FileUtils.mkdir_p library_dir
116
+
117
+ if @debug then
118
+ puts 'copying from:' + album.inspect
119
+ puts 'copying to: ' + library_dir.inspect
120
+ end
121
+
122
+ puts 'copying ' + album + ' ...'
123
+ FileUtils.cp_r album, library_dir, remove_destination: true
124
+
125
+ end
126
+ end
127
+
128
+ end
129
+
130
+ # copy the .txt file from each mp3 directory into a central file directory
131
+ #
132
+ def consolidate_txt(target_directory: '')
133
+
134
+ raise 'target_directory cannot be empty' if target_directory.empty?
135
+
136
+ find_by_ext('.mp3').each do |directory, _ |
137
+
138
+ txt_filename = Dir[File.join(directory, '*.txt')].first
139
+
140
+ next unless txt_filename
141
+
142
+ target_file = File.basename(directory)
143
+ FileUtils.cp txt_filename, File.join(target_directory,
144
+ target_file + '.txt')
145
+
146
+ end
147
+
148
+ end
149
+
150
+ def each_media_file(directory=@dir, &blk)
151
+
152
+ puts 'each_media_file - directory: ' + directory.inspect if @debug
153
+ found = Dir[File.join(directory, "*.{mp3,ogg}")].sort_by { |x| File.mtime(x) }
154
+ puts 'each_nedia_file - found: ' + found.inspect if @debug
155
+
156
+ found.each.with_index do |media_filepath, i|
157
+
158
+ puts 'each_medi... - media_filepath: ' + media_filepath.inspect if @debug
159
+
160
+ next unless File.exists? media_filepath
161
+
162
+ blk.call(media_filepath, i )
50
163
 
51
164
  end
52
165
 
@@ -60,6 +173,7 @@ class GotMP3
60
173
 
61
174
  # find the image file
62
175
  img_filename = Dir[File.join(directory, '*.jpg')].first
176
+ puts 'img_filename: ' + img_filename.inspect if @debug
63
177
 
64
178
  # find the text file
65
179
  txt_filename = Dir[File.join(directory, '*.txt')].first
@@ -79,7 +193,7 @@ class GotMP3
79
193
  #
80
194
  def rename()
81
195
 
82
- each_mp3_file do |mp3_filepath|
196
+ each_media_file do |mp3_filepath|
83
197
 
84
198
  mp3_directory = File.dirname(mp3_filepath)
85
199
  mp3_filename = File.basename(mp3_filepath)
@@ -91,43 +205,94 @@ class GotMP3
91
205
 
92
206
  end
93
207
 
94
- def write_titles()
208
+ # sort MP3 or OGG by track number in the filename
209
+ #
210
+ def sort_by_tracknum!()
211
+
212
+ each_media_file do |filepath|
95
213
 
96
- find_by_ext('.mp3').each do |directory, _ |
214
+ directory = File.dirname(filepath)
215
+ a = Dir[File.join(directory, '*.{mp3,ogg}')]
216
+ a.sort_by {|x| x[/^\d+/]}.each {|file| FileUtils.touch file}
217
+
218
+ end
219
+
220
+ end
221
+
222
+ # write either a track listing into the media filepath, either in
223
+ # plain text or XML format.
224
+ #
225
+ def write_titles(format: 'txt')
226
+
227
+ puts 'inside write_titles()' if @debug
228
+
229
+ find_by_ext('.{mp3,ogg}').each do |directory, _ |
230
+
231
+ puts 'write_titles() - directory: ' + directory.inspect if @debug
232
+ txt_filename = Dir[File.join(directory, '*.txt')].first
233
+
234
+ next if txt_filename and format.to_sym == :txt
97
235
 
98
236
  tracks = []
99
237
 
100
- each_mp3_track(directory) do |mp3, trackno, mp3_filepath|
238
+ each_media_track(directory) do |media, trackno, media_filepath|
239
+
240
+ info = case File.extname(media_filepath)
241
+ when '.mp3'
242
+ mp3info(media)
243
+ when '.ogg'
244
+ ogginfo(media)
245
+ end
101
246
 
102
- tracks << OpenStruct.new({
103
- title: mp3.tag.title,
104
- artist: mp3.tag.artist,
105
- album: mp3.tag.album,
106
- album_artist: mp3.tag2['TPE2'],
107
- disc: mp3.tag2['TPOS'],
108
- tracknum: mp3.tag.tracknum,
109
- filename: File.basename(mp3_filepath)
110
- })
247
+ info[:filename] = File.basename(media_filepath)
248
+ tracks << OpenStruct.new(info)
111
249
 
112
250
  end
113
251
 
252
+ puts 'tracks: ' + tracks.inspect if @debug
253
+
114
254
  heading = tracks[0].album_artist + ' - ' + tracks[0].album
255
+
115
256
  s = "# %s\n\n" % [heading]
116
- h = tracks.group_by(&:disc)
117
257
 
118
- body = if h.length == 1 then
119
258
 
120
- list(tracks)
259
+ if format.to_sym == :txt then
260
+
261
+ h = tracks.group_by(&:disc)
262
+
263
+ body = if h.length == 1 then
264
+
265
+ list(tracks)
266
+
267
+ else
268
+
269
+ "\n" + h.map do |disc, tracks2|
270
+ ("## Disc %d\n\n" % disc) + list(tracks2) + "\n\n"
271
+ end.join("\n")
272
+
273
+ end
274
+
275
+ File.write File.join(directory, heading + '.txt'), s + body
121
276
 
122
277
  else
123
278
 
124
- "\n" + h.map do |disc, tracks2|
125
- ("## Disc %d\n\n" % disc) + list(tracks2) + "\n\n"
126
- end.join("\n")
279
+ # :xml
280
+ puts 'xml' if @debug
127
281
 
128
- end
282
+ dx = DxLite.new('album[album_artist, album]/track(tracknum, title, ' +
283
+ 'artist, disc, album_artist)')
284
+
285
+ #h.each {|_,x| puts x.inspect } if @debug
286
+ #h.each {|_,x| x.each {|track| dx.create(track.to_h) } }
287
+ tracks.each {|track| dx.create(track.to_h) }
129
288
 
130
- File.write File.join(directory, heading + '.txt'), s + body
289
+ dx.album_artist = dx.all[0].album_artist
290
+ dx.album = dx.all[0].album
291
+ dx.save File.join(directory, 'playlist.dx')
292
+
293
+ yield(directory) if block_given?
294
+
295
+ end
131
296
 
132
297
  end
133
298
 
@@ -139,11 +304,12 @@ class GotMP3
139
304
  #
140
305
  def add_image(directory, img_filename)
141
306
 
307
+ puts 'inside add_image - directory: ' + directory.inspect if @debug
142
308
  puts 'img_filename: ' + img_filename.inspect if @debug
143
309
  image_file = File.new(File.join(directory, img_filename),'rb')
144
310
  img = image_file.read
145
311
 
146
- each_mp3_track(directory) do |mp3, _, _|
312
+ each_media_track(directory) do |mp3, _, _|
147
313
 
148
314
  mp3.tag2.remove_pictures
149
315
  mp3.tag2.add_picture img
@@ -152,14 +318,16 @@ class GotMP3
152
318
 
153
319
  end
154
320
 
321
+ # Modifies the MP3s' tags using the track titles in the .txt file
322
+ #
155
323
  def add_tracktitles(directory, txt_filename)
156
324
 
157
325
  txt_file = File.join(directory, txt_filename)
158
326
  track_titles = File.read(txt_file).lines[1..-1].map(&:strip)
159
327
 
160
- each_mp3_track(directory) do |mp3, trackno, _|
328
+ each_media_track(directory) do |media, trackno, _|
161
329
 
162
- mp3.tag.title = track_titles[trackno-1]
330
+ media.tag.title = track_titles[trackno-1]
163
331
 
164
332
  end
165
333
  end
@@ -197,11 +365,16 @@ class GotMP3
197
365
 
198
366
  end
199
367
 
200
- def each_mp3_track(directory, &blk)
368
+ def each_media_track(directory, &blk)
201
369
 
202
- each_mp3_file do |mp3_filepath, i|
370
+ each_media_file(directory) do |filepath, i|
203
371
 
204
- Mp3Info.open(mp3_filepath) {|mp3| blk.call(mp3, i+1, mp3_filepath) }
372
+ case File.extname(filepath)
373
+ when '.mp3'
374
+ Mp3Info.open(filepath) {|mp3| blk.call(mp3, i+1, filepath) }
375
+ when '.ogg'
376
+ OggInfo.open(filepath) {|ogg| blk.call(ogg, i+1, filepath) }
377
+ end
205
378
 
206
379
  end
207
380
 
@@ -209,6 +382,7 @@ class GotMP3
209
382
 
210
383
  def find_by_ext(extension)
211
384
 
385
+ puts 'find_by_ext() - @dir' + @dir.inspect if @debug
212
386
  a = Dir[File.join(@dir, "**", "*" + extension)]
213
387
  puts 'a: ' + a.inspect if @debug
214
388
 
@@ -220,6 +394,8 @@ class GotMP3
220
394
  end
221
395
  end
222
396
 
397
+ # used by public method *write_titles* to list the tracks in plain text
398
+ #
223
399
  def list(tracks)
224
400
 
225
401
  a = if tracks.map(&:artist).uniq.length < 2 then
@@ -232,6 +408,33 @@ class GotMP3
232
408
 
233
409
  end
234
410
 
411
+ def mp3info(mp3)
412
+ {
413
+ title: mp3.tag.title.sub(/^\d+\. */,''),
414
+ artist: mp3.tag.artist,
415
+ album: mp3.tag.album,
416
+ album_artist: mp3.tag2['TPE2'] || mp3.tag.artist,
417
+ disc: mp3.tag2['TPOS'] || 1,
418
+ tracknum: mp3.tag.tracknum,
419
+ }
420
+ end
421
+
422
+ def ogginfo(ogg)
423
+
424
+ # options
425
+ # ["title", "artist", "tracknumber", "tracktotal", "album", "albumartist",
426
+ # "genre", "discid", "musicbrainz_discid"]
427
+
428
+ {
429
+ title: ogg.tag.title.sub(/^\d+\. */,''),
430
+ artist: ogg.tag.artist,
431
+ album: ogg.tag.album,
432
+ album_artist: ogg.tag.albumartist || ogg.tag.artist,
433
+ disc: ogg.tag.discid || 1,
434
+ tracknum: ogg.tag.tracknumber,
435
+ }
436
+ end
437
+
235
438
  end
236
439
 
237
440
  class Titles
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: got_mp3
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - James Robertson
@@ -35,8 +35,28 @@ cert_chain:
35
35
  RFrZsrDO1Cwk4v03qCUvuZ8H/nCojYYJGMrJE1JhBBJNJXCAULivh/zlOYcDhG69
36
36
  uPtZOD7YKrG45OftX8aNxlNv
37
37
  -----END CERTIFICATE-----
38
- date: 2021-11-25 00:00:00.000000000 Z
38
+ date: 2021-11-28 00:00:00.000000000 Z
39
39
  dependencies:
40
+ - !ruby/object:Gem::Dependency
41
+ name: dxlite
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '0.3'
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: 0.3.5
50
+ type: :runtime
51
+ prerelease: false
52
+ version_requirements: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - "~>"
55
+ - !ruby/object:Gem::Version
56
+ version: '0.3'
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ version: 0.3.5
40
60
  - !ruby/object:Gem::Dependency
41
61
  name: ruby-mp3info
42
62
  requirement: !ruby/object:Gem::Requirement
@@ -57,6 +77,46 @@ dependencies:
57
77
  - - ">="
58
78
  - !ruby/object:Gem::Version
59
79
  version: 0.8.10
80
+ - !ruby/object:Gem::Dependency
81
+ name: ruby-ogginfo
82
+ requirement: !ruby/object:Gem::Requirement
83
+ requirements:
84
+ - - "~>"
85
+ - !ruby/object:Gem::Version
86
+ version: '0.7'
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: 0.7.2
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '0.7'
97
+ - - ">="
98
+ - !ruby/object:Gem::Version
99
+ version: 0.7.2
100
+ - !ruby/object:Gem::Dependency
101
+ name: playlist_creator
102
+ requirement: !ruby/object:Gem::Requirement
103
+ requirements:
104
+ - - ">="
105
+ - !ruby/object:Gem::Version
106
+ version: 0.2.0
107
+ - - "~>"
108
+ - !ruby/object:Gem::Version
109
+ version: '0.2'
110
+ type: :runtime
111
+ prerelease: false
112
+ version_requirements: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - ">="
115
+ - !ruby/object:Gem::Version
116
+ version: 0.2.0
117
+ - - "~>"
118
+ - !ruby/object:Gem::Version
119
+ version: '0.2'
60
120
  description:
61
121
  email: digital.robertson@gmail.com
62
122
  executables: []
@@ -88,5 +148,5 @@ rubygems_version: 2.7.10
88
148
  signing_key:
89
149
  specification_version: 4
90
150
  summary: A ruby-mp3info wrapper to make it convenient to update the album art and
91
- track titles of multiple MP3 files as a batch process.
151
+ track titles of multiple MP3 files in a batch process.
92
152
  test_files: []
metadata.gz.sig CHANGED
Binary file