id3taginator 0.8

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 (150) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +13 -0
  3. data/.idea/.gitignore +8 -0
  4. data/.idea/ID3Taginator.iml +73 -0
  5. data/.idea/misc.xml +4 -0
  6. data/.idea/modules.xml +8 -0
  7. data/.idea/vcs.xml +6 -0
  8. data/.rspec +3 -0
  9. data/.rubocop.yml +26 -0
  10. data/CHANGELOG.md +5 -0
  11. data/CODE_OF_CONDUCT.md +84 -0
  12. data/Gemfile +12 -0
  13. data/LICENSE.txt +21 -0
  14. data/README.md +408 -0
  15. data/Rakefile +12 -0
  16. data/bin/console +15 -0
  17. data/bin/setup +8 -0
  18. data/id3taginator.gemspec +37 -0
  19. data/lib/id3taginator/audio_file.rb +136 -0
  20. data/lib/id3taginator/errors/id3_tag_error.rb +12 -0
  21. data/lib/id3taginator/extensions/argument_check.rb +88 -0
  22. data/lib/id3taginator/extensions/comparable.rb +28 -0
  23. data/lib/id3taginator/extensions/encodable.rb +215 -0
  24. data/lib/id3taginator/extensions/optionable.rb +73 -0
  25. data/lib/id3taginator/frames/buffer/entities/buffer.rb +26 -0
  26. data/lib/id3taginator/frames/buffer/rbuf_recommended_buffer_size_frame.rb +59 -0
  27. data/lib/id3taginator/frames/buffer_frames.rb +32 -0
  28. data/lib/id3taginator/frames/comment/comm_comment_frame.rb +56 -0
  29. data/lib/id3taginator/frames/comment/entities/comment.rb +26 -0
  30. data/lib/id3taginator/frames/comment_frames.rb +42 -0
  31. data/lib/id3taginator/frames/count/entities/popularimeter.rb +26 -0
  32. data/lib/id3taginator/frames/count/pcnt_play_counter_frame.rb +40 -0
  33. data/lib/id3taginator/frames/count/popm_popularimeter_frame.rb +52 -0
  34. data/lib/id3taginator/frames/count_frames.rb +51 -0
  35. data/lib/id3taginator/frames/custom_frame.rb +39 -0
  36. data/lib/id3taginator/frames/custom_frames.rb +54 -0
  37. data/lib/id3taginator/frames/encryption/aenc_audio_encryption.rb +54 -0
  38. data/lib/id3taginator/frames/encryption/encr_encryption_method_frame.rb +49 -0
  39. data/lib/id3taginator/frames/encryption/entities/audio_encryption.rb +28 -0
  40. data/lib/id3taginator/frames/encryption/entities/encryption_method.rb +26 -0
  41. data/lib/id3taginator/frames/encryption_frames.rb +77 -0
  42. data/lib/id3taginator/frames/frameable.rb +75 -0
  43. data/lib/id3taginator/frames/geo/entities/encapsulated_object.rb +28 -0
  44. data/lib/id3taginator/frames/geo/geob_general_encapsulated_object_frame.rb +59 -0
  45. data/lib/id3taginator/frames/geo_frames.rb +41 -0
  46. data/lib/id3taginator/frames/grouping/entities/group_identification.rb +26 -0
  47. data/lib/id3taginator/frames/grouping/grid_group_identification_frame.rb +49 -0
  48. data/lib/id3taginator/frames/grouping/grp1_grouping_frame.rb +40 -0
  49. data/lib/id3taginator/frames/grouping_frames.rb +61 -0
  50. data/lib/id3taginator/frames/has_id.rb +51 -0
  51. data/lib/id3taginator/frames/id3v23_frame_flags.rb +64 -0
  52. data/lib/id3taginator/frames/id3v24_frame_flags.rb +80 -0
  53. data/lib/id3taginator/frames/id3v2_frame.rb +249 -0
  54. data/lib/id3taginator/frames/id3v2_frame_factory.rb +98 -0
  55. data/lib/id3taginator/frames/ipl/entities/involved_person.rb +24 -0
  56. data/lib/id3taginator/frames/ipl/ipls_involved_people_frame.rb +48 -0
  57. data/lib/id3taginator/frames/ipl_frames.rb +31 -0
  58. data/lib/id3taginator/frames/lyrics/entities/unsync_lyrics.rb +26 -0
  59. data/lib/id3taginator/frames/lyrics/uslt_unsync_lyrics_frame.rb +56 -0
  60. data/lib/id3taginator/frames/lyrics_frames.rb +42 -0
  61. data/lib/id3taginator/frames/mcdi/mcdi_music_cd_identifier_frame.rb +40 -0
  62. data/lib/id3taginator/frames/mcdi_frames.rb +28 -0
  63. data/lib/id3taginator/frames/picture/apic_picture_frame.rb +106 -0
  64. data/lib/id3taginator/frames/picture/entities/picture.rb +32 -0
  65. data/lib/id3taginator/frames/picture_frames.rb +51 -0
  66. data/lib/id3taginator/frames/private/entities/private_frame.rb +24 -0
  67. data/lib/id3taginator/frames/private/priv_private_frame.rb +45 -0
  68. data/lib/id3taginator/frames/private_frames.rb +40 -0
  69. data/lib/id3taginator/frames/text/entities/copyright.rb +24 -0
  70. data/lib/id3taginator/frames/text/entities/date.rb +24 -0
  71. data/lib/id3taginator/frames/text/entities/part_of_set.rb +24 -0
  72. data/lib/id3taginator/frames/text/entities/time.rb +24 -0
  73. data/lib/id3taginator/frames/text/entities/track_number.rb +24 -0
  74. data/lib/id3taginator/frames/text/entities/user_info.rb +24 -0
  75. data/lib/id3taginator/frames/text/talb_album_frame.rb +40 -0
  76. data/lib/id3taginator/frames/text/tbpm_bpm_frame.rb +40 -0
  77. data/lib/id3taginator/frames/text/tcom_composer_frame.rb +42 -0
  78. data/lib/id3taginator/frames/text/tcon_genre_frame.rb +104 -0
  79. data/lib/id3taginator/frames/text/tcop_copyright_frame.rb +55 -0
  80. data/lib/id3taginator/frames/text/tdat_date_frame.rb +60 -0
  81. data/lib/id3taginator/frames/text/tdly_playlist_delay_frame.rb +40 -0
  82. data/lib/id3taginator/frames/text/tenc_encoded_by_frame.rb +40 -0
  83. data/lib/id3taginator/frames/text/text_writers_frame.rb +43 -0
  84. data/lib/id3taginator/frames/text/tflt_file_type_frame.rb +71 -0
  85. data/lib/id3taginator/frames/text/time_time_frame.rb +60 -0
  86. data/lib/id3taginator/frames/text/tit1_content_group_description_frame.rb +40 -0
  87. data/lib/id3taginator/frames/text/tit2_title_frame.rb +40 -0
  88. data/lib/id3taginator/frames/text/tit3_subtitle_frame.rb +40 -0
  89. data/lib/id3taginator/frames/text/tkey_initial_key_frame.rb +40 -0
  90. data/lib/id3taginator/frames/text/tlan_language_frame.rb +48 -0
  91. data/lib/id3taginator/frames/text/tlen_length_frame.rb +40 -0
  92. data/lib/id3taginator/frames/text/tmed_media_type_frame.rb +40 -0
  93. data/lib/id3taginator/frames/text/toal_original_album_frame.rb +40 -0
  94. data/lib/id3taginator/frames/text/tofn_original_filename_frame.rb +40 -0
  95. data/lib/id3taginator/frames/text/toly_original_writers_frame.rb +43 -0
  96. data/lib/id3taginator/frames/text/tope_original_artists_frame.rb +43 -0
  97. data/lib/id3taginator/frames/text/tory_original_release_year_frame.rb +42 -0
  98. data/lib/id3taginator/frames/text/town_file_owner_frame.rb +40 -0
  99. data/lib/id3taginator/frames/text/tpe1_artist_frame.rb +43 -0
  100. data/lib/id3taginator/frames/text/tpe2_album_artist_frame.rb +40 -0
  101. data/lib/id3taginator/frames/text/tpe3_conductor_frame.rb +40 -0
  102. data/lib/id3taginator/frames/text/tpe4_modified_by_frame.rb +40 -0
  103. data/lib/id3taginator/frames/text/tpos_part_of_set_frame.rb +50 -0
  104. data/lib/id3taginator/frames/text/tpub_publisher_frame.rb +40 -0
  105. data/lib/id3taginator/frames/text/trck_track_number_frame.rb +50 -0
  106. data/lib/id3taginator/frames/text/trda_recording_dates_frame.rb +42 -0
  107. data/lib/id3taginator/frames/text/trsn_internet_radio_station_frame.rb +40 -0
  108. data/lib/id3taginator/frames/text/tsiz_size_frame.rb +41 -0
  109. data/lib/id3taginator/frames/text/tsoa_album_sort_order_frame.rb +40 -0
  110. data/lib/id3taginator/frames/text/tsop_performer_sort_order_frame.rb +40 -0
  111. data/lib/id3taginator/frames/text/tsot_title_sort_order_frame.rb +40 -0
  112. data/lib/id3taginator/frames/text/tsrc_isrc_frame.rb +40 -0
  113. data/lib/id3taginator/frames/text/tsse_encoder_frame.rb +40 -0
  114. data/lib/id3taginator/frames/text/txxx_user_text_info_frame.rb +51 -0
  115. data/lib/id3taginator/frames/text/tyer_year_frame.rb +42 -0
  116. data/lib/id3taginator/frames/text_frames.rb +840 -0
  117. data/lib/id3taginator/frames/tos/entities/ownership.rb +26 -0
  118. data/lib/id3taginator/frames/tos/entities/terms_of_use.rb +24 -0
  119. data/lib/id3taginator/frames/tos/owne_ownership_frame.rb +53 -0
  120. data/lib/id3taginator/frames/tos/user_terms_of_use_frame.rb +49 -0
  121. data/lib/id3taginator/frames/tos_frames.rb +54 -0
  122. data/lib/id3taginator/frames/ufid/entities/ufid_info.rb +24 -0
  123. data/lib/id3taginator/frames/ufid/ufid_unique_file_identifier_frame.rb +47 -0
  124. data/lib/id3taginator/frames/ufid_frames.rb +40 -0
  125. data/lib/id3taginator/frames/url/entities/user_info.rb +24 -0
  126. data/lib/id3taginator/frames/url/wcom_commercial_url_frame.rb +40 -0
  127. data/lib/id3taginator/frames/url/wcop_copyright_url_frame.rb +40 -0
  128. data/lib/id3taginator/frames/url/woaf_official_file_webpage_frame.rb +40 -0
  129. data/lib/id3taginator/frames/url/woar_official_artist_webpage_frame.rb +40 -0
  130. data/lib/id3taginator/frames/url/woas_official_source_webpage_frame.rb +40 -0
  131. data/lib/id3taginator/frames/url/wors_official_radio_station_homepage_frame.rb +40 -0
  132. data/lib/id3taginator/frames/url/wpay_payment_url_frame.rb +40 -0
  133. data/lib/id3taginator/frames/url/wpub_official_publisher_webpage_frame.rb +40 -0
  134. data/lib/id3taginator/frames/url/wxxx_user_url_link_frame.rb +50 -0
  135. data/lib/id3taginator/frames/url_frames.rb +195 -0
  136. data/lib/id3taginator/genres.rb +168 -0
  137. data/lib/id3taginator/header/id3v23_extended_header.rb +37 -0
  138. data/lib/id3taginator/header/id3v24_extended_header.rb +100 -0
  139. data/lib/id3taginator/header/id3v2_flags.rb +64 -0
  140. data/lib/id3taginator/id3v1_tag.rb +156 -0
  141. data/lib/id3taginator/id3v22_tag.rb +30 -0
  142. data/lib/id3taginator/id3v23_tag.rb +63 -0
  143. data/lib/id3taginator/id3v24_tag.rb +75 -0
  144. data/lib/id3taginator/id3v2_tag.rb +241 -0
  145. data/lib/id3taginator/options/options.rb +33 -0
  146. data/lib/id3taginator/util/compress_util.rb +25 -0
  147. data/lib/id3taginator/util/math_util.rb +68 -0
  148. data/lib/id3taginator/util/sync_util.rb +65 -0
  149. data/lib/id3taginator.rb +449 -0
  150. 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