id3taginator 0.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +13 -0
- data/.idea/.gitignore +8 -0
- data/.idea/ID3Taginator.iml +73 -0
- data/.idea/misc.xml +4 -0
- data/.idea/modules.xml +8 -0
- data/.idea/vcs.xml +6 -0
- data/.rspec +3 -0
- data/.rubocop.yml +26 -0
- data/CHANGELOG.md +5 -0
- data/CODE_OF_CONDUCT.md +84 -0
- data/Gemfile +12 -0
- data/LICENSE.txt +21 -0
- data/README.md +408 -0
- data/Rakefile +12 -0
- data/bin/console +15 -0
- data/bin/setup +8 -0
- data/id3taginator.gemspec +37 -0
- data/lib/id3taginator/audio_file.rb +136 -0
- data/lib/id3taginator/errors/id3_tag_error.rb +12 -0
- data/lib/id3taginator/extensions/argument_check.rb +88 -0
- data/lib/id3taginator/extensions/comparable.rb +28 -0
- data/lib/id3taginator/extensions/encodable.rb +215 -0
- data/lib/id3taginator/extensions/optionable.rb +73 -0
- data/lib/id3taginator/frames/buffer/entities/buffer.rb +26 -0
- data/lib/id3taginator/frames/buffer/rbuf_recommended_buffer_size_frame.rb +59 -0
- data/lib/id3taginator/frames/buffer_frames.rb +32 -0
- data/lib/id3taginator/frames/comment/comm_comment_frame.rb +56 -0
- data/lib/id3taginator/frames/comment/entities/comment.rb +26 -0
- data/lib/id3taginator/frames/comment_frames.rb +42 -0
- data/lib/id3taginator/frames/count/entities/popularimeter.rb +26 -0
- data/lib/id3taginator/frames/count/pcnt_play_counter_frame.rb +40 -0
- data/lib/id3taginator/frames/count/popm_popularimeter_frame.rb +52 -0
- data/lib/id3taginator/frames/count_frames.rb +51 -0
- data/lib/id3taginator/frames/custom_frame.rb +39 -0
- data/lib/id3taginator/frames/custom_frames.rb +54 -0
- data/lib/id3taginator/frames/encryption/aenc_audio_encryption.rb +54 -0
- data/lib/id3taginator/frames/encryption/encr_encryption_method_frame.rb +49 -0
- data/lib/id3taginator/frames/encryption/entities/audio_encryption.rb +28 -0
- data/lib/id3taginator/frames/encryption/entities/encryption_method.rb +26 -0
- data/lib/id3taginator/frames/encryption_frames.rb +77 -0
- data/lib/id3taginator/frames/frameable.rb +75 -0
- data/lib/id3taginator/frames/geo/entities/encapsulated_object.rb +28 -0
- data/lib/id3taginator/frames/geo/geob_general_encapsulated_object_frame.rb +59 -0
- data/lib/id3taginator/frames/geo_frames.rb +41 -0
- data/lib/id3taginator/frames/grouping/entities/group_identification.rb +26 -0
- data/lib/id3taginator/frames/grouping/grid_group_identification_frame.rb +49 -0
- data/lib/id3taginator/frames/grouping/grp1_grouping_frame.rb +40 -0
- data/lib/id3taginator/frames/grouping_frames.rb +61 -0
- data/lib/id3taginator/frames/has_id.rb +51 -0
- data/lib/id3taginator/frames/id3v23_frame_flags.rb +64 -0
- data/lib/id3taginator/frames/id3v24_frame_flags.rb +80 -0
- data/lib/id3taginator/frames/id3v2_frame.rb +249 -0
- data/lib/id3taginator/frames/id3v2_frame_factory.rb +98 -0
- data/lib/id3taginator/frames/ipl/entities/involved_person.rb +24 -0
- data/lib/id3taginator/frames/ipl/ipls_involved_people_frame.rb +48 -0
- data/lib/id3taginator/frames/ipl_frames.rb +31 -0
- data/lib/id3taginator/frames/lyrics/entities/unsync_lyrics.rb +26 -0
- data/lib/id3taginator/frames/lyrics/uslt_unsync_lyrics_frame.rb +56 -0
- data/lib/id3taginator/frames/lyrics_frames.rb +42 -0
- data/lib/id3taginator/frames/mcdi/mcdi_music_cd_identifier_frame.rb +40 -0
- data/lib/id3taginator/frames/mcdi_frames.rb +28 -0
- data/lib/id3taginator/frames/picture/apic_picture_frame.rb +106 -0
- data/lib/id3taginator/frames/picture/entities/picture.rb +32 -0
- data/lib/id3taginator/frames/picture_frames.rb +51 -0
- data/lib/id3taginator/frames/private/entities/private_frame.rb +24 -0
- data/lib/id3taginator/frames/private/priv_private_frame.rb +45 -0
- data/lib/id3taginator/frames/private_frames.rb +40 -0
- data/lib/id3taginator/frames/text/entities/copyright.rb +24 -0
- data/lib/id3taginator/frames/text/entities/date.rb +24 -0
- data/lib/id3taginator/frames/text/entities/part_of_set.rb +24 -0
- data/lib/id3taginator/frames/text/entities/time.rb +24 -0
- data/lib/id3taginator/frames/text/entities/track_number.rb +24 -0
- data/lib/id3taginator/frames/text/entities/user_info.rb +24 -0
- data/lib/id3taginator/frames/text/talb_album_frame.rb +40 -0
- data/lib/id3taginator/frames/text/tbpm_bpm_frame.rb +40 -0
- data/lib/id3taginator/frames/text/tcom_composer_frame.rb +42 -0
- data/lib/id3taginator/frames/text/tcon_genre_frame.rb +104 -0
- data/lib/id3taginator/frames/text/tcop_copyright_frame.rb +55 -0
- data/lib/id3taginator/frames/text/tdat_date_frame.rb +60 -0
- data/lib/id3taginator/frames/text/tdly_playlist_delay_frame.rb +40 -0
- data/lib/id3taginator/frames/text/tenc_encoded_by_frame.rb +40 -0
- data/lib/id3taginator/frames/text/text_writers_frame.rb +43 -0
- data/lib/id3taginator/frames/text/tflt_file_type_frame.rb +71 -0
- data/lib/id3taginator/frames/text/time_time_frame.rb +60 -0
- data/lib/id3taginator/frames/text/tit1_content_group_description_frame.rb +40 -0
- data/lib/id3taginator/frames/text/tit2_title_frame.rb +40 -0
- data/lib/id3taginator/frames/text/tit3_subtitle_frame.rb +40 -0
- data/lib/id3taginator/frames/text/tkey_initial_key_frame.rb +40 -0
- data/lib/id3taginator/frames/text/tlan_language_frame.rb +48 -0
- data/lib/id3taginator/frames/text/tlen_length_frame.rb +40 -0
- data/lib/id3taginator/frames/text/tmed_media_type_frame.rb +40 -0
- data/lib/id3taginator/frames/text/toal_original_album_frame.rb +40 -0
- data/lib/id3taginator/frames/text/tofn_original_filename_frame.rb +40 -0
- data/lib/id3taginator/frames/text/toly_original_writers_frame.rb +43 -0
- data/lib/id3taginator/frames/text/tope_original_artists_frame.rb +43 -0
- data/lib/id3taginator/frames/text/tory_original_release_year_frame.rb +42 -0
- data/lib/id3taginator/frames/text/town_file_owner_frame.rb +40 -0
- data/lib/id3taginator/frames/text/tpe1_artist_frame.rb +43 -0
- data/lib/id3taginator/frames/text/tpe2_album_artist_frame.rb +40 -0
- data/lib/id3taginator/frames/text/tpe3_conductor_frame.rb +40 -0
- data/lib/id3taginator/frames/text/tpe4_modified_by_frame.rb +40 -0
- data/lib/id3taginator/frames/text/tpos_part_of_set_frame.rb +50 -0
- data/lib/id3taginator/frames/text/tpub_publisher_frame.rb +40 -0
- data/lib/id3taginator/frames/text/trck_track_number_frame.rb +50 -0
- data/lib/id3taginator/frames/text/trda_recording_dates_frame.rb +42 -0
- data/lib/id3taginator/frames/text/trsn_internet_radio_station_frame.rb +40 -0
- data/lib/id3taginator/frames/text/tsiz_size_frame.rb +41 -0
- data/lib/id3taginator/frames/text/tsoa_album_sort_order_frame.rb +40 -0
- data/lib/id3taginator/frames/text/tsop_performer_sort_order_frame.rb +40 -0
- data/lib/id3taginator/frames/text/tsot_title_sort_order_frame.rb +40 -0
- data/lib/id3taginator/frames/text/tsrc_isrc_frame.rb +40 -0
- data/lib/id3taginator/frames/text/tsse_encoder_frame.rb +40 -0
- data/lib/id3taginator/frames/text/txxx_user_text_info_frame.rb +51 -0
- data/lib/id3taginator/frames/text/tyer_year_frame.rb +42 -0
- data/lib/id3taginator/frames/text_frames.rb +840 -0
- data/lib/id3taginator/frames/tos/entities/ownership.rb +26 -0
- data/lib/id3taginator/frames/tos/entities/terms_of_use.rb +24 -0
- data/lib/id3taginator/frames/tos/owne_ownership_frame.rb +53 -0
- data/lib/id3taginator/frames/tos/user_terms_of_use_frame.rb +49 -0
- data/lib/id3taginator/frames/tos_frames.rb +54 -0
- data/lib/id3taginator/frames/ufid/entities/ufid_info.rb +24 -0
- data/lib/id3taginator/frames/ufid/ufid_unique_file_identifier_frame.rb +47 -0
- data/lib/id3taginator/frames/ufid_frames.rb +40 -0
- data/lib/id3taginator/frames/url/entities/user_info.rb +24 -0
- data/lib/id3taginator/frames/url/wcom_commercial_url_frame.rb +40 -0
- data/lib/id3taginator/frames/url/wcop_copyright_url_frame.rb +40 -0
- data/lib/id3taginator/frames/url/woaf_official_file_webpage_frame.rb +40 -0
- data/lib/id3taginator/frames/url/woar_official_artist_webpage_frame.rb +40 -0
- data/lib/id3taginator/frames/url/woas_official_source_webpage_frame.rb +40 -0
- data/lib/id3taginator/frames/url/wors_official_radio_station_homepage_frame.rb +40 -0
- data/lib/id3taginator/frames/url/wpay_payment_url_frame.rb +40 -0
- data/lib/id3taginator/frames/url/wpub_official_publisher_webpage_frame.rb +40 -0
- data/lib/id3taginator/frames/url/wxxx_user_url_link_frame.rb +50 -0
- data/lib/id3taginator/frames/url_frames.rb +195 -0
- data/lib/id3taginator/genres.rb +168 -0
- data/lib/id3taginator/header/id3v23_extended_header.rb +37 -0
- data/lib/id3taginator/header/id3v24_extended_header.rb +100 -0
- data/lib/id3taginator/header/id3v2_flags.rb +64 -0
- data/lib/id3taginator/id3v1_tag.rb +156 -0
- data/lib/id3taginator/id3v22_tag.rb +30 -0
- data/lib/id3taginator/id3v23_tag.rb +63 -0
- data/lib/id3taginator/id3v24_tag.rb +75 -0
- data/lib/id3taginator/id3v2_tag.rb +241 -0
- data/lib/id3taginator/options/options.rb +33 -0
- data/lib/id3taginator/util/compress_util.rb +25 -0
- data/lib/id3taginator/util/math_util.rb +68 -0
- data/lib/id3taginator/util/sync_util.rb +65 -0
- data/lib/id3taginator.rb +449 -0
- metadata +198 -0
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Id3Taginator
|
4
|
+
module Frames
|
5
|
+
module Url
|
6
|
+
class UserUrlLinkFrame < Id3v2Frame
|
7
|
+
include HasId
|
8
|
+
|
9
|
+
frame_info :WXX, :WXXX, :WXXX
|
10
|
+
|
11
|
+
attr_accessor :description, :url
|
12
|
+
|
13
|
+
# builds the custom user url link frame
|
14
|
+
#
|
15
|
+
# @param description [String] the description
|
16
|
+
# @param url [String] the url
|
17
|
+
# @param options [Options::Options] options to use
|
18
|
+
# @param id3_version [Integer] the id3 version to build the frame for
|
19
|
+
#
|
20
|
+
# @return [Id3v2Frame] the resulting id3v2 frame
|
21
|
+
def self.build_frame(description, url, options = nil, id3_version: 3)
|
22
|
+
supported?('WXXX', id3_version, options)
|
23
|
+
|
24
|
+
argument_not_nil(description, 'description')
|
25
|
+
argument_not_nil(url, 'url')
|
26
|
+
|
27
|
+
frame = new(frame_id(id3_version, options), 0, build_id3_flags(id3_version), '')
|
28
|
+
frame.description = description
|
29
|
+
frame.url = url
|
30
|
+
frame
|
31
|
+
end
|
32
|
+
|
33
|
+
def process_content(content)
|
34
|
+
content_io = StringIO.new(content)
|
35
|
+
encoding_byte = content_io.getbyte
|
36
|
+
encoding = find_encoding(encoding_byte)
|
37
|
+
|
38
|
+
encoded_description = read_stream_until(content_io, zero_byte(encoding))
|
39
|
+
@description = decode(encoded_description, encoding)
|
40
|
+
@url = content_io.read
|
41
|
+
end
|
42
|
+
|
43
|
+
def content_to_bytes
|
44
|
+
encoded_description = encode(@description, null_terminated: true)
|
45
|
+
merge(default_encoding_destination_byte, encoded_description, @url)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,195 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Id3Taginator
|
4
|
+
module Frames
|
5
|
+
module UrlFrames
|
6
|
+
include Frames::Frameable
|
7
|
+
|
8
|
+
# extracts the commercial information url (WCOM/WCM)
|
9
|
+
#
|
10
|
+
# @return [String, nil] returns the URL
|
11
|
+
def commercial_information_url
|
12
|
+
find_frame(Url::CommercialUrlFrame.frame_id(@major_version, @options))&.url
|
13
|
+
end
|
14
|
+
|
15
|
+
# sets the commercial information url (WCOM/WCM)
|
16
|
+
#
|
17
|
+
# @param url [String] the url
|
18
|
+
def commercial_information_url=(url)
|
19
|
+
set_frame_fields(Url::CommercialUrlFrame, [:@url], url)
|
20
|
+
end
|
21
|
+
|
22
|
+
# removes the commercial information url frame
|
23
|
+
def remove_commercial_information_url
|
24
|
+
@frames.delete_if { |f| f.frame_id == Url::CommercialUrlFrame.frame_id(@major_version, @options) }
|
25
|
+
end
|
26
|
+
|
27
|
+
# extracts the copyright information url (WCOP/WCP)
|
28
|
+
#
|
29
|
+
# @return [String, nil] returns the URL
|
30
|
+
def copyright_information_url
|
31
|
+
find_frame(Url::CopyrightUrlFrame.frame_id(@major_version, @options))&.url
|
32
|
+
end
|
33
|
+
|
34
|
+
# sets the copyright information url (WCOP/WCP)
|
35
|
+
#
|
36
|
+
# @param url [String] the url
|
37
|
+
def copyright_information_url=(url)
|
38
|
+
set_frame_fields(Url::CopyrightUrlFrame, [:@url], url)
|
39
|
+
end
|
40
|
+
|
41
|
+
# removes the copyright information url frame
|
42
|
+
def remove_copyright_information_url
|
43
|
+
@frames.delete_if { |f| f.frame_id == Url::CopyrightUrlFrame.frame_id(@major_version, @options) }
|
44
|
+
end
|
45
|
+
|
46
|
+
# extracts the official audio file url (WOAF/WAF)
|
47
|
+
#
|
48
|
+
# @return [String, nil] returns the URL
|
49
|
+
def official_audio_file_url
|
50
|
+
find_frame(Url::OfficialFileWebpageFrame.frame_id(@major_version, @options))&.url
|
51
|
+
end
|
52
|
+
|
53
|
+
# sets the official audio file url (WOAF/WAF)
|
54
|
+
#
|
55
|
+
# @param url [String] the url
|
56
|
+
def official_audio_file_url=(url)
|
57
|
+
set_frame_fields(Url::OfficialFileWebpageFrame, [:@url], url)
|
58
|
+
end
|
59
|
+
|
60
|
+
# removes the official audio file url frame
|
61
|
+
def remove_official_audio_file_url
|
62
|
+
@frames.delete_if { |f| f.frame_id == Url::OfficialFileWebpageFrame.frame_id(@major_version, @options) }
|
63
|
+
end
|
64
|
+
|
65
|
+
# extracts the official artist url (WOAR/WAR)
|
66
|
+
#
|
67
|
+
# @return [String, nil] returns the URL
|
68
|
+
def official_artist_url
|
69
|
+
find_frame(Url::OfficialArtistWebpageFrame.frame_id(@major_version, @options))&.url
|
70
|
+
end
|
71
|
+
|
72
|
+
# sets the official artist url (WOAR/WAR)
|
73
|
+
#
|
74
|
+
# @param url [String] the url
|
75
|
+
def official_artist_url=(url)
|
76
|
+
set_frame_fields(Url::OfficialArtistWebpageFrame, [:@url], url)
|
77
|
+
end
|
78
|
+
|
79
|
+
# removes the official artist url frame
|
80
|
+
def remove_official_artist_url
|
81
|
+
@frames.delete_if { |f| f.frame_id == Url::OfficialArtistWebpageFrame.frame_id(@major_version, @options) }
|
82
|
+
end
|
83
|
+
|
84
|
+
# extracts the official source url (WOAS/WAS)
|
85
|
+
#
|
86
|
+
# @return [String, nil] returns the URL
|
87
|
+
def official_source_url
|
88
|
+
find_frame(Url::OfficialSourceWebpageFrame.frame_id(@major_version, @options))&.url
|
89
|
+
end
|
90
|
+
|
91
|
+
# sets the official source url (WOAS/WAS)
|
92
|
+
#
|
93
|
+
# @param url [String] the url
|
94
|
+
def official_source_url=(url)
|
95
|
+
set_frame_fields(Url::OfficialSourceWebpageFrame, [:@url], url)
|
96
|
+
end
|
97
|
+
|
98
|
+
# removes the official source url frame
|
99
|
+
def remove_official_source_url
|
100
|
+
@frames.delete_if { |f| f.frame_id == Url::OfficialSourceWebpageFrame.frame_id(@major_version, @options) }
|
101
|
+
end
|
102
|
+
|
103
|
+
# extracts the official radio station url (WORS)
|
104
|
+
#
|
105
|
+
# @return [String, nil] returns the URL
|
106
|
+
def official_radio_station_homepage
|
107
|
+
find_frame(Url::OfficialAudioRadioStationHomepageFrame.frame_id(@major_version, @options))&.url
|
108
|
+
end
|
109
|
+
|
110
|
+
# sets the official radio station url (WORS)
|
111
|
+
#
|
112
|
+
# @param url [String] the url
|
113
|
+
def official_radio_station_homepage=(url)
|
114
|
+
set_frame_fields(Url::OfficialAudioRadioStationHomepageFrame, [:@url], url)
|
115
|
+
end
|
116
|
+
|
117
|
+
# removes the official radio station homepage frame
|
118
|
+
def remove_official_radio_station_homepage
|
119
|
+
@frames.delete_if do |f|
|
120
|
+
f.frame_id == Url::OfficialAudioRadioStationHomepageFrame.frame_id(@major_version, @options)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
# extracts the official radio station url (WPAY)
|
125
|
+
#
|
126
|
+
# @return [String, nil] returns the URL
|
127
|
+
def payment_url
|
128
|
+
find_frame(Url::PaymentUrlFrame.frame_id(@major_version, @options))&.url
|
129
|
+
end
|
130
|
+
|
131
|
+
# sets the payment url (WPAY)
|
132
|
+
#
|
133
|
+
# @param url [String] the url
|
134
|
+
def payment_url=(url)
|
135
|
+
set_frame_fields(Url::PaymentUrlFrame, [:@url], url)
|
136
|
+
end
|
137
|
+
|
138
|
+
# removes the payment frame
|
139
|
+
def remove_payment_url
|
140
|
+
@frames.delete_if { |f| f.frame_id == Url::PaymentUrlFrame.frame_id(@major_version, @options) }
|
141
|
+
end
|
142
|
+
|
143
|
+
# extracts the official publisher url (WPUB/WPB)
|
144
|
+
#
|
145
|
+
# @return [String, nil] returns the URL
|
146
|
+
def official_publisher_webpage
|
147
|
+
find_frame(Url::OfficialPublisherWebpageFrame.frame_id(@major_version, @options))&.url
|
148
|
+
end
|
149
|
+
|
150
|
+
# sets the official publisher url (WPUB/WPB)
|
151
|
+
#
|
152
|
+
# @param url [String] the url
|
153
|
+
def official_publisher_webpage=(url)
|
154
|
+
set_frame_fields(Url::OfficialPublisherWebpageFrame, [:@url], url)
|
155
|
+
end
|
156
|
+
|
157
|
+
# removes the official publisher webpage frame
|
158
|
+
def remove_official_publisher_webpage
|
159
|
+
@frames.delete_if { |f| f.frame_id == Url::OfficialPublisherWebpageFrame.frame_id(@major_version, @options) }
|
160
|
+
end
|
161
|
+
|
162
|
+
# extracts the user custom url links (WXXX/WXX)
|
163
|
+
#
|
164
|
+
# @return [Array<Frames::Url::Entities::UserInfo>] returns the custom URL links
|
165
|
+
def user_custom_url_links
|
166
|
+
frame = find_frames(Url::UserUrlLinkFrame.frame_id(@major_version, @options))
|
167
|
+
return [] if frame.nil? || frame.empty?
|
168
|
+
|
169
|
+
frame.map { |f| Url::Entities::UserInfo.new(f.description, f.url) }
|
170
|
+
end
|
171
|
+
|
172
|
+
# adds a user custom url link (WXXX/WXX)
|
173
|
+
# Multiple ones can be added, as long as they have different description
|
174
|
+
#
|
175
|
+
# @param custom_url [Frames::Url::Entities::UserInfo] the custom url link to add
|
176
|
+
def user_custom_url_link=(custom_url)
|
177
|
+
set_frame_fields_by_selector(Url::UserUrlLinkFrame, %i[@description @url],
|
178
|
+
->(f) { f.description == custom_url.description },
|
179
|
+
custom_url.description, custom_url.url)
|
180
|
+
end
|
181
|
+
|
182
|
+
alias add_user_custom_url_link user_custom_url_link=
|
183
|
+
|
184
|
+
# removes a user custom url link for the specific description (WXXX/WXX)
|
185
|
+
#
|
186
|
+
# @param description [String] the description
|
187
|
+
def remove_user_custom_url_link(description)
|
188
|
+
@frames.delete_if do |f|
|
189
|
+
f.frame_id == Url::UserUrlLinkFrame.frame_id(@major_version, @options) &&
|
190
|
+
f.description == description
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|
@@ -0,0 +1,168 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Id3Taginator
|
4
|
+
module Genres
|
5
|
+
BLUES = 0
|
6
|
+
CLASSIC_ROCK = 1
|
7
|
+
COUNTRY = 2
|
8
|
+
DANCE = 3
|
9
|
+
DISCO = 4
|
10
|
+
FUNK = 5
|
11
|
+
GRUNGE = 6
|
12
|
+
HIP_HOP = 7
|
13
|
+
JAZZ = 8
|
14
|
+
METAL = 9
|
15
|
+
NEW_AGE = 10
|
16
|
+
OLDIES = 11
|
17
|
+
OTHER = 12
|
18
|
+
POP = 13
|
19
|
+
RNB = 14
|
20
|
+
RAP = 15
|
21
|
+
REGGAE = 16
|
22
|
+
ROCK = 17
|
23
|
+
TECHNO = 18
|
24
|
+
INDUSTRIAL = 19
|
25
|
+
ALTERNATIVE = 20
|
26
|
+
SKA = 21
|
27
|
+
DEATH_METAL = 22
|
28
|
+
PRANKS = 23
|
29
|
+
SOUNDTRACK = 24
|
30
|
+
EURO_TECHNO = 25
|
31
|
+
AMBIENT = 26
|
32
|
+
TRIP_HOP = 27
|
33
|
+
VOCAL = 28
|
34
|
+
JAZZ_FUNK = 29
|
35
|
+
FUSION = 30
|
36
|
+
TRANCE = 31
|
37
|
+
CLASSICAL = 32
|
38
|
+
INSTRUMENTAL = 33
|
39
|
+
ACID = 34
|
40
|
+
HOUSE = 35
|
41
|
+
GAME = 36
|
42
|
+
SOUND_CLIP = 37
|
43
|
+
GOSPEL = 38
|
44
|
+
NOISE = 39
|
45
|
+
ALT_ROCK = 40
|
46
|
+
BASS = 41
|
47
|
+
SOUL = 42
|
48
|
+
PUNK = 43
|
49
|
+
SPACE = 44
|
50
|
+
MEDITATIVE = 45
|
51
|
+
INSTRUMENTAL_POP = 46
|
52
|
+
INSTRUMENTAL_ROCK = 47
|
53
|
+
ETHNIC = 48
|
54
|
+
GOTHIC = 49
|
55
|
+
DARKWAVE = 50
|
56
|
+
TECHNO_INDUSTRIAL = 51
|
57
|
+
ELECTRONIC = 52
|
58
|
+
POP_FOLK = 53
|
59
|
+
EURODANCE = 54
|
60
|
+
DREAM = 55
|
61
|
+
SOUTHERN_ROCK = 56
|
62
|
+
COMEDY = 57
|
63
|
+
CULT = 58
|
64
|
+
GANGSTA = 59
|
65
|
+
TOP_40 = 60
|
66
|
+
CHRISTIAN_RAP = 61
|
67
|
+
POP_FUNK = 62
|
68
|
+
JUNGLE = 63
|
69
|
+
NATIVE_AMERICAN = 64
|
70
|
+
CABARET = 65
|
71
|
+
NEW_WAVE = 66
|
72
|
+
PSYCHEDELIC = 67
|
73
|
+
RAVE = 68
|
74
|
+
SHOWTUNES = 69
|
75
|
+
TRAILER = 70
|
76
|
+
LO_FI = 71
|
77
|
+
TRIBAL = 72
|
78
|
+
ACID_PUNK = 73
|
79
|
+
ACID_JAZZ = 74
|
80
|
+
POLKA = 75
|
81
|
+
RETRO = 76
|
82
|
+
MUSICAL = 77
|
83
|
+
ROCK_N_ROLL = 78
|
84
|
+
HARD_ROCK = 79
|
85
|
+
FOLK = 80
|
86
|
+
FOLK_ROCK = 81
|
87
|
+
NATIONAL_FOLK = 82
|
88
|
+
SWING = 83
|
89
|
+
FAST_FUSION = 84
|
90
|
+
BEBOB = 85
|
91
|
+
LATIN = 86
|
92
|
+
REVIVAL = 87
|
93
|
+
CELTIC = 88
|
94
|
+
BLUEGRASS = 89
|
95
|
+
AVANTGARDE = 90
|
96
|
+
GOTHIC_ROCK = 91
|
97
|
+
PROGRESSIVE_ROCK = 92
|
98
|
+
PSYCHEDELIC_ROCK = 93
|
99
|
+
SYMPHONIC_ROCK = 94
|
100
|
+
SLOW_ROCK = 95
|
101
|
+
BIG_BAND = 96
|
102
|
+
CHORUS = 97
|
103
|
+
EASY_LISTENING = 98
|
104
|
+
ACOUSTIC = 99
|
105
|
+
HUMOUR = 100
|
106
|
+
SPEECH = 101
|
107
|
+
CHANSON = 102
|
108
|
+
OPERA = 103
|
109
|
+
CHAMBER_MUSIC = 104
|
110
|
+
SONATA = 105
|
111
|
+
SYMPHONY = 106
|
112
|
+
BOOTY_BASS = 107
|
113
|
+
PRIMUS = 108
|
114
|
+
PORN_GROOVE = 109
|
115
|
+
SATIRE_PARODY = 110
|
116
|
+
SLOW_JAM = 111
|
117
|
+
CLUB = 112
|
118
|
+
TANGO = 113
|
119
|
+
SAMBA = 114
|
120
|
+
FOLKLORE = 115
|
121
|
+
BALLAD = 116
|
122
|
+
POWER_BALLAD = 117
|
123
|
+
RHYTHMIC_SOUL = 118
|
124
|
+
FREESTYLE = 119
|
125
|
+
DUET = 120
|
126
|
+
PUNK_ROCK = 121
|
127
|
+
DRUM_SOLO = 122
|
128
|
+
ACAPELLA = 123
|
129
|
+
EURO_HOUSE = 124
|
130
|
+
DANCE_HALL = 125
|
131
|
+
GOA = 126
|
132
|
+
DRUM_N_BASS = 127
|
133
|
+
CLUB_HOUSE = 128
|
134
|
+
HARDCORE = 129
|
135
|
+
TERROR = 130
|
136
|
+
INDIE = 131
|
137
|
+
BRITPOP = 132
|
138
|
+
NEGERPUNK = 133
|
139
|
+
POLSK_PUNK = 134
|
140
|
+
BEAT = 135
|
141
|
+
CHRISTIAN_GANGSTA = 136
|
142
|
+
HEAVY_METAL = 137
|
143
|
+
THRASH_METAL = 138
|
144
|
+
ANIME = 139
|
145
|
+
JPOP = 140
|
146
|
+
SYNTHPOP = 141
|
147
|
+
INVALID = 255
|
148
|
+
|
149
|
+
def self.genre(id)
|
150
|
+
return nil if id.nil?
|
151
|
+
|
152
|
+
result = constants.find { |genre| const_get(genre) == id }
|
153
|
+
return :INVALID if result.nil?
|
154
|
+
|
155
|
+
result
|
156
|
+
end
|
157
|
+
|
158
|
+
def self.genre_by_name(name)
|
159
|
+
return INVALID if name.nil?
|
160
|
+
|
161
|
+
begin
|
162
|
+
const_get(name)
|
163
|
+
rescue NameError
|
164
|
+
name
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Id3Taginator
|
4
|
+
module Header
|
5
|
+
class Id3v23ExtendedHeader
|
6
|
+
|
7
|
+
attr_accessor :size, :flags, :padding, :crc_data
|
8
|
+
|
9
|
+
# constructor
|
10
|
+
#
|
11
|
+
# @param size [Integer] the size of the extended header
|
12
|
+
# @param flags [String] 2 byte Array as a String representing the flags
|
13
|
+
# @param padding [Integer] the number of padding of the extended header
|
14
|
+
# @param crc_data [String] the crc data if present
|
15
|
+
def initialize(size, flags, padding, crc_data = nil)
|
16
|
+
@size = size
|
17
|
+
@flags = flags
|
18
|
+
@padding = padding
|
19
|
+
@crc_data = crc_data
|
20
|
+
end
|
21
|
+
|
22
|
+
# returns the CRC data if present
|
23
|
+
#
|
24
|
+
# @return [String, nil] the CRC data
|
25
|
+
def crc
|
26
|
+
@crc_data
|
27
|
+
end
|
28
|
+
|
29
|
+
# determined if the crc is present
|
30
|
+
#
|
31
|
+
# @return [Boolean] true if crc is present, else false
|
32
|
+
def crc?
|
33
|
+
(@flags[0] & 0b10000000) == 0b10000000
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Id3Taginator
|
4
|
+
module Header
|
5
|
+
class Id3v24ExtendedHeader
|
6
|
+
|
7
|
+
attr_accessor :size, :flags
|
8
|
+
|
9
|
+
# constructor
|
10
|
+
#
|
11
|
+
# @param size [Integer] the size of the extended header
|
12
|
+
# @param flags [String] 2 byte Array as a String representing the flags
|
13
|
+
def initialize(size, flags)
|
14
|
+
@size = size
|
15
|
+
@flags = flags
|
16
|
+
@tag_is_update = false
|
17
|
+
@crc_data = nil
|
18
|
+
@restrictions = 0b00000000
|
19
|
+
|
20
|
+
flags_stream = StringIO.new(flags)
|
21
|
+
ext_flag = flags_stream.readbyte
|
22
|
+
# tag is update
|
23
|
+
if bit_set?(ext_flag, 0b01000000)
|
24
|
+
@tag_is_update = true
|
25
|
+
flags_stream.readbyte
|
26
|
+
end
|
27
|
+
|
28
|
+
# crc data
|
29
|
+
if bit_set?(ext_flag, 0b00100000)
|
30
|
+
length = ext_flag.readbyte
|
31
|
+
@crc_data = flags_stream.read(length)
|
32
|
+
end
|
33
|
+
|
34
|
+
ext_flag.readbyte if bit_set?(ext_flag, 0b00010000)
|
35
|
+
@restrictions = ext_flag.readbyte if bit_set?(ext_flag, 0b00010000)
|
36
|
+
end
|
37
|
+
|
38
|
+
# determined if the tag is an update
|
39
|
+
#
|
40
|
+
# @return [Boolean] true if it is an update, else false
|
41
|
+
def tag_is_an_update?
|
42
|
+
@tag_is_update
|
43
|
+
end
|
44
|
+
|
45
|
+
# returns the CRC data if present
|
46
|
+
#
|
47
|
+
# @return [String, nil] the CRC data
|
48
|
+
def crc
|
49
|
+
@crc_data
|
50
|
+
end
|
51
|
+
|
52
|
+
# determined if the tag is size restricted
|
53
|
+
#
|
54
|
+
# @return [Boolean] true if it restricted, else false
|
55
|
+
def tag_size_restrictions?
|
56
|
+
(@restrictions & 0b11000000) == 0b11000000
|
57
|
+
end
|
58
|
+
|
59
|
+
# determined if the tag is text encoding restricted
|
60
|
+
#
|
61
|
+
# @return [Boolean] true if text encoding restricted, else false
|
62
|
+
def text_encoding_restrictions?
|
63
|
+
(@restrictions & 0b00100000) == 0b00100000
|
64
|
+
end
|
65
|
+
|
66
|
+
# determined if the tag is fields size restricted
|
67
|
+
#
|
68
|
+
# @return [Boolean] true if fields size restricted, else false
|
69
|
+
def text_fields_size_restrictions?
|
70
|
+
(@restrictions & 0b00011000) == 0b00011000
|
71
|
+
end
|
72
|
+
|
73
|
+
# determined if the tag is encoding restricted
|
74
|
+
#
|
75
|
+
# @return [Boolean] true if encoding restricted, else false
|
76
|
+
def image_encoding_restrictions?
|
77
|
+
(@restrictions & 0b00000100) == 0b00000100
|
78
|
+
end
|
79
|
+
|
80
|
+
# determined if the tag is image encoding restricted
|
81
|
+
#
|
82
|
+
# @return [Boolean] true if image encoding restricted, else false
|
83
|
+
def image_size_restrictions?
|
84
|
+
(@restrictions & 0b00000011) == 0b00000011
|
85
|
+
end
|
86
|
+
|
87
|
+
# checks if the given bit of the given byte is set
|
88
|
+
#
|
89
|
+
# @param byte [Integer] the byte to check if a specific bit is set
|
90
|
+
# @param set [Byte] the Byte where the bit is set that should be checked
|
91
|
+
#
|
92
|
+
# @return [Boolean] true if the bit is set, else false
|
93
|
+
def bit_set?(byte, set)
|
94
|
+
(byte & set) == set
|
95
|
+
end
|
96
|
+
|
97
|
+
private :bit_set?
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Id3Taginator
|
4
|
+
module Header
|
5
|
+
class Id3v2Flags
|
6
|
+
|
7
|
+
# constructor
|
8
|
+
#
|
9
|
+
# @param flags [Integer] the 1 byte header flag
|
10
|
+
def initialize(flags)
|
11
|
+
@flags = flags
|
12
|
+
end
|
13
|
+
|
14
|
+
# determined if the tag is unsynchronized
|
15
|
+
#
|
16
|
+
# @return [Boolean] true if unsynchronized, else false
|
17
|
+
def unsynchronized?
|
18
|
+
(@flags & 0b1000_0000) == 0b1000_0000
|
19
|
+
end
|
20
|
+
|
21
|
+
# enables or synchronization for the tag
|
22
|
+
#
|
23
|
+
# @param enabled [Boolean] true, if tag should be synchronized, else false
|
24
|
+
def unsynchronized=(enabled)
|
25
|
+
@flags = enabled ? @flags | 0b1000_0000 : @flags & 0b0111_1111
|
26
|
+
end
|
27
|
+
|
28
|
+
# determines if an extended header is present
|
29
|
+
#
|
30
|
+
# @return [Boolean] true if header is present, else false
|
31
|
+
def extended_header?
|
32
|
+
(@flags & 0b0100_0000) == 0b0100_0000
|
33
|
+
end
|
34
|
+
|
35
|
+
# determines if experimental tags are present
|
36
|
+
#
|
37
|
+
# @return [Boolean] true if experimental tags present, else false
|
38
|
+
def experimental?
|
39
|
+
(@flags & 0b0010_0000) == 0b0010_0000
|
40
|
+
end
|
41
|
+
|
42
|
+
# determines if a footer is present
|
43
|
+
#
|
44
|
+
# @return [Boolean] true if a footer is present, else false
|
45
|
+
def footer?
|
46
|
+
(@flags & 0b0001_0000) == 0b0001_0000
|
47
|
+
end
|
48
|
+
|
49
|
+
# enables or disables a footer
|
50
|
+
#
|
51
|
+
# @param enabled [Boolean] true, if the footer should be set to the tag, else false
|
52
|
+
def footer=(enabled)
|
53
|
+
@flags = enabled ? @flags | 0b0001_0000 : @flags & 0b1110_1111
|
54
|
+
end
|
55
|
+
|
56
|
+
# dumps the flags to a byte string
|
57
|
+
#
|
58
|
+
# @return [String] the String representing the flags
|
59
|
+
def to_bytes
|
60
|
+
@flags.chr
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|