got_mp3 0.3.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.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/lib/got_mp3.rb +145 -31
- data.tar.gz.sig +0 -0
- metadata +42 -2
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a109d9369982eb251b2439256a7ab8ecb0494f8b693efeb869ed6e29329d23e4
|
4
|
+
data.tar.gz: 960ba30e1ab1178b77280f9f6068248cb82616040caa2fca2880dcccc78c1af0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8777628c7ec8d16460fe3ff59199b98bf34bf10494ffdb22afd432cb1f7110591bd48370998f4bc4757f9564d3b4a190ec03537e03d2f9c7cecd01b0ddafe744
|
7
|
+
data.tar.gz: 7c9b29dc4e6e889644c2cfef6464fcb09fb34ead8101670a7f08942344132994099444a144b5ee5a24e9f76d1c176f595837845accd9a6ef8efb1ff269994e80
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data/lib/got_mp3.rb
CHANGED
@@ -4,11 +4,15 @@
|
|
4
4
|
|
5
5
|
require 'dxlite'
|
6
6
|
require 'ostruct'
|
7
|
-
require
|
7
|
+
require 'mp3info'
|
8
|
+
require 'ogginfo'
|
9
|
+
require 'playlist_creator'
|
8
10
|
|
9
11
|
|
10
12
|
class GotMP3
|
11
13
|
|
14
|
+
attr_accessor :dir
|
15
|
+
|
12
16
|
def initialize(dir: '.', debug: false)
|
13
17
|
@dir, @debug = dir, debug
|
14
18
|
end
|
@@ -44,7 +48,58 @@ class GotMP3
|
|
44
48
|
|
45
49
|
end
|
46
50
|
|
47
|
-
#
|
51
|
+
# Adds an XSPF playlist file to each file directory containing MP3s
|
52
|
+
#
|
53
|
+
def add_playlist(dir: @dir)
|
54
|
+
|
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.
|
48
103
|
#
|
49
104
|
def compile(source_directory: '', target_directory: '')
|
50
105
|
|
@@ -72,6 +127,8 @@ class GotMP3
|
|
72
127
|
|
73
128
|
end
|
74
129
|
|
130
|
+
# copy the .txt file from each mp3 directory into a central file directory
|
131
|
+
#
|
75
132
|
def consolidate_txt(target_directory: '')
|
76
133
|
|
77
134
|
raise 'target_directory cannot be empty' if target_directory.empty?
|
@@ -90,19 +147,19 @@ class GotMP3
|
|
90
147
|
|
91
148
|
end
|
92
149
|
|
93
|
-
def
|
150
|
+
def each_media_file(directory=@dir, &blk)
|
94
151
|
|
95
|
-
puts '
|
96
|
-
found = Dir[File.join(directory, "*.mp3")].sort_by { |x| File.mtime(x) }
|
97
|
-
puts '
|
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
|
98
155
|
|
99
|
-
found.
|
156
|
+
found.each.with_index do |media_filepath, i|
|
100
157
|
|
101
|
-
puts '
|
158
|
+
puts 'each_medi... - media_filepath: ' + media_filepath.inspect if @debug
|
102
159
|
|
103
|
-
next unless File.exists?
|
160
|
+
next unless File.exists? media_filepath
|
104
161
|
|
105
|
-
blk.call(
|
162
|
+
blk.call(media_filepath, i )
|
106
163
|
|
107
164
|
end
|
108
165
|
|
@@ -136,7 +193,7 @@ class GotMP3
|
|
136
193
|
#
|
137
194
|
def rename()
|
138
195
|
|
139
|
-
|
196
|
+
each_media_file do |mp3_filepath|
|
140
197
|
|
141
198
|
mp3_directory = File.dirname(mp3_filepath)
|
142
199
|
mp3_filename = File.basename(mp3_filepath)
|
@@ -148,11 +205,28 @@ class GotMP3
|
|
148
205
|
|
149
206
|
end
|
150
207
|
|
208
|
+
# sort MP3 or OGG by track number in the filename
|
209
|
+
#
|
210
|
+
def sort_by_tracknum!()
|
211
|
+
|
212
|
+
each_media_file do |filepath|
|
213
|
+
|
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
|
+
#
|
151
225
|
def write_titles(format: 'txt')
|
152
226
|
|
153
227
|
puts 'inside write_titles()' if @debug
|
154
228
|
|
155
|
-
find_by_ext('.mp3').each do |directory, _ |
|
229
|
+
find_by_ext('.{mp3,ogg}').each do |directory, _ |
|
156
230
|
|
157
231
|
puts 'write_titles() - directory: ' + directory.inspect if @debug
|
158
232
|
txt_filename = Dir[File.join(directory, '*.txt')].first
|
@@ -161,17 +235,17 @@ class GotMP3
|
|
161
235
|
|
162
236
|
tracks = []
|
163
237
|
|
164
|
-
|
238
|
+
each_media_track(directory) do |media, trackno, media_filepath|
|
165
239
|
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
240
|
+
info = case File.extname(media_filepath)
|
241
|
+
when '.mp3'
|
242
|
+
mp3info(media)
|
243
|
+
when '.ogg'
|
244
|
+
ogginfo(media)
|
245
|
+
end
|
246
|
+
|
247
|
+
info[:filename] = File.basename(media_filepath)
|
248
|
+
tracks << OpenStruct.new(info)
|
175
249
|
|
176
250
|
end
|
177
251
|
|
@@ -180,11 +254,12 @@ class GotMP3
|
|
180
254
|
heading = tracks[0].album_artist + ' - ' + tracks[0].album
|
181
255
|
|
182
256
|
s = "# %s\n\n" % [heading]
|
183
|
-
h = tracks.group_by(&:disc)
|
184
257
|
|
185
258
|
|
186
259
|
if format.to_sym == :txt then
|
187
260
|
|
261
|
+
h = tracks.group_by(&:disc)
|
262
|
+
|
188
263
|
body = if h.length == 1 then
|
189
264
|
|
190
265
|
list(tracks)
|
@@ -207,13 +282,16 @@ class GotMP3
|
|
207
282
|
dx = DxLite.new('album[album_artist, album]/track(tracknum, title, ' +
|
208
283
|
'artist, disc, album_artist)')
|
209
284
|
|
210
|
-
h.each {|_,x| puts x.inspect } if @debug
|
211
|
-
h.each {|_,x| x.each {|track| dx.create(track.to_h) } }
|
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) }
|
212
288
|
|
213
289
|
dx.album_artist = dx.all[0].album_artist
|
214
290
|
dx.album = dx.all[0].album
|
215
291
|
dx.save File.join(directory, 'playlist.dx')
|
216
292
|
|
293
|
+
yield(directory) if block_given?
|
294
|
+
|
217
295
|
end
|
218
296
|
|
219
297
|
end
|
@@ -231,7 +309,7 @@ class GotMP3
|
|
231
309
|
image_file = File.new(File.join(directory, img_filename),'rb')
|
232
310
|
img = image_file.read
|
233
311
|
|
234
|
-
|
312
|
+
each_media_track(directory) do |mp3, _, _|
|
235
313
|
|
236
314
|
mp3.tag2.remove_pictures
|
237
315
|
mp3.tag2.add_picture img
|
@@ -240,14 +318,16 @@ class GotMP3
|
|
240
318
|
|
241
319
|
end
|
242
320
|
|
321
|
+
# Modifies the MP3s' tags using the track titles in the .txt file
|
322
|
+
#
|
243
323
|
def add_tracktitles(directory, txt_filename)
|
244
324
|
|
245
325
|
txt_file = File.join(directory, txt_filename)
|
246
326
|
track_titles = File.read(txt_file).lines[1..-1].map(&:strip)
|
247
327
|
|
248
|
-
|
328
|
+
each_media_track(directory) do |media, trackno, _|
|
249
329
|
|
250
|
-
|
330
|
+
media.tag.title = track_titles[trackno-1]
|
251
331
|
|
252
332
|
end
|
253
333
|
end
|
@@ -285,11 +365,16 @@ class GotMP3
|
|
285
365
|
|
286
366
|
end
|
287
367
|
|
288
|
-
def
|
368
|
+
def each_media_track(directory, &blk)
|
289
369
|
|
290
|
-
|
370
|
+
each_media_file(directory) do |filepath, i|
|
291
371
|
|
292
|
-
|
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
|
293
378
|
|
294
379
|
end
|
295
380
|
|
@@ -309,6 +394,8 @@ class GotMP3
|
|
309
394
|
end
|
310
395
|
end
|
311
396
|
|
397
|
+
# used by public method *write_titles* to list the tracks in plain text
|
398
|
+
#
|
312
399
|
def list(tracks)
|
313
400
|
|
314
401
|
a = if tracks.map(&:artist).uniq.length < 2 then
|
@@ -321,6 +408,33 @@ class GotMP3
|
|
321
408
|
|
322
409
|
end
|
323
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
|
+
|
324
438
|
end
|
325
439
|
|
326
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.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- James Robertson
|
@@ -35,7 +35,7 @@ cert_chain:
|
|
35
35
|
RFrZsrDO1Cwk4v03qCUvuZ8H/nCojYYJGMrJE1JhBBJNJXCAULivh/zlOYcDhG69
|
36
36
|
uPtZOD7YKrG45OftX8aNxlNv
|
37
37
|
-----END CERTIFICATE-----
|
38
|
-
date: 2021-11-
|
38
|
+
date: 2021-11-28 00:00:00.000000000 Z
|
39
39
|
dependencies:
|
40
40
|
- !ruby/object:Gem::Dependency
|
41
41
|
name: dxlite
|
@@ -77,6 +77,46 @@ dependencies:
|
|
77
77
|
- - ">="
|
78
78
|
- !ruby/object:Gem::Version
|
79
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'
|
80
120
|
description:
|
81
121
|
email: digital.robertson@gmail.com
|
82
122
|
executables: []
|
metadata.gz.sig
CHANGED
Binary file
|