Skip to content

Commit

Permalink
frame flags half done
Browse files Browse the repository at this point in the history
  • Loading branch information
Krists authored and Krists committed Oct 18, 2013
1 parent 0962ff7 commit a81cf13
Show file tree
Hide file tree
Showing 4 changed files with 246 additions and 49 deletions.
12 changes: 8 additions & 4 deletions lib/id3tag/frames/v2/basic_frame.rb
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,6 @@ def group_id
end
end

def inspect
"<#{self.class.name} #{id}: #{inspect_content}>"
end

def decompressed_size
if compressed?
raw_content_io.rewind
Expand Down Expand Up @@ -81,6 +77,14 @@ def data_length_indicator?
frame_flags.data_length_indicator?
end

def additional_info_byte_count
frame_flags.additional_info_byte_count
end

def inspect
"<#{self.class.name} #{id}: #{inspect_content}>"
end

private

def frame_flags
Expand Down
118 changes: 74 additions & 44 deletions lib/id3tag/frames/v2/frame_flags.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,53 +2,27 @@ module ID3Tag
module Frames
module V2
class FrameFlags
FLAG_INDEXES_BY_VERSION = {
EXCLUDE_END_TRUE = true
FLAG_MAP_IN_APPEARANCE_ORDER_BY_VERSION = {
3 => {
:status_flags => [
:preserve_on_tag_alteration,
:preserve_on_file_alteration,
:read_only,
nil,
nil,
nil,
nil,
nil
],
:format_flags => [
:compressed,
:encrypted,
:grouped,
nil,
nil,
nil,
nil,
nil
]
:status_flags => [ :preserve_on_tag_alteration, :preserve_on_file_alteration, :read_only, nil, nil, nil, nil, nil ],
:format_flags => [ :compressed, :encrypted, :grouped, nil, nil, nil, nil, nil ]
},
4 => {
:status_flags => [
nil,
:preserve_on_tag_alteration,
:preserve_on_file_alteration,
:read_only,
nil,
nil,
nil,
nil
],
:format_flags => [
nil,
:grouped,
nil,
nil,
:compressed,
:encrypted,
:unsynchronised,
:data_length_indicator
]
:status_flags => [ nil, :preserve_on_tag_alteration, :preserve_on_file_alteration, :read_only, nil, nil, nil, nil ],
:format_flags => [ nil, :grouped, nil, nil, :compressed, :encrypted, :unsynchronised, :data_length_indicator ]
}
}

ADDITIONAL_INFO_BYTES_IN_APPEARANCE_ORDER_BY_VERSION = {
3 => [
[:compressed?, 4], [:encrypted?, 1], [:grouped?, 1]
],
4 => [
[:grouped?, 1], [:encrypted?, 1], [:data_length_indicator?, 4]
]
}

def initialize(flag_bytes, major_version_number)
@flag_bytes = flag_bytes
@major_version_number = major_version_number
Expand Down Expand Up @@ -86,6 +60,58 @@ def data_length_indicator?
flag(:format_flags, :data_length_indicator) == 1
end

def additional_info_byte_count
current_additional_info_map.inject(0) do |total, query|
total += query.last if self.send(query.first)
total
end
end

def range_of_data_length_bytes
if data_length_indicator?
cursor = 0
length = 0
current_additional_info_map.reject { |q| !self.send(q.first) }.map do |q|
cursor += q.last if q.first != :data_length_indicator?
if q.first == :data_length_indicator?
length = q.last
break
end
end
Range.new(cursor,cursor + length, EXCLUDE_END_TRUE)
end
end

def range_of_group_id
if grouped?
cursor = 0
length = 0
current_additional_info_map.reject { |q| !self.send(q.first) }.map do |q|
cursor += q.last if q.first != :grouped?
if q.first == :grouped?
length = q.last
break
end
end
Range.new(cursor, cursor + length, EXCLUDE_END_TRUE)
end
end

def range_of_encryption_id
if encrypted?
cursor = 0
length = 0
current_additional_info_map.reject { |q| !self.send(q.first) }.map do |q|
cursor += q.last if q.first != :encrypted?
if q.first == :encrypted?
length = q.last
break
end
end
Range.new(cursor, cursor + length, EXCLUDE_END_TRUE)
end
end

private

def flag(scope, name)
Expand All @@ -107,14 +133,18 @@ def flags_for_scope(scope)
end

def index_of_flag(scope, name)
current_version_map[scope].find_index(name)
current_flag_map[scope].find_index(name)
end

def current_version_map
FLAG_INDEXES_BY_VERSION.fetch(@major_version_number) do
def current_flag_map
FLAG_MAP_IN_APPEARANCE_ORDER_BY_VERSION.fetch(@major_version_number) do
{ :status_flags => [], :format_flags => [] }
end
end

def current_additional_info_map
ADDITIONAL_INFO_BYTES_IN_APPEARANCE_ORDER_BY_VERSION.fetch(@major_version_number) { [] }
end
end
end
end
Expand Down
157 changes: 157 additions & 0 deletions spec/lib/id3tag/frames/v2/frame_flags_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
require 'spec_helper'

describe ID3Tag::Frames::V2::FrameFlags do
subject { described_class.new(flag_bytes, version) }

context "When major version is 2" do
let(:flag_bytes) { nil }
let(:version) { 2 }

its(:preserve_on_tag_alteration?) { should be_true }
its(:preserve_on_file_alteration?) { should be_true }
its(:read_only?) { should be_false }
its(:compressed?) { should be_false }
its(:encrypted?) { should be_false }
its(:grouped?) { should be_false }
its(:unsynchronised?) { should be_false }
its(:data_length_indicator?) { should be_false }
its(:additional_info_byte_count) { should eq 0 }
its(:range_of_data_length_bytes) { should eq nil }
its(:range_of_group_id) { should eq nil }
its(:range_of_encryption_id) { should eq nil }
end

context "when major version is 3" do
let(:version) { 3 }
context "when all flags are nulled" do
let(:flag_bytes) { [0b00000000, 0b00000000].pack("C2") }
its(:preserve_on_tag_alteration?) { should be_true }
its(:preserve_on_file_alteration?) { should be_true }
its(:read_only?) { should be_false }
its(:compressed?) { should be_false }
its(:encrypted?) { should be_false }
its(:grouped?) { should be_false }
its(:unsynchronised?) { should be_false }
its(:data_length_indicator?) { should be_false }
its(:additional_info_byte_count) { should eq 0 }
its(:range_of_data_length_bytes) { should eq nil }
its(:range_of_group_id) { should eq nil }
its(:range_of_encryption_id) { should eq nil }
end

context "when compression is on" do
let(:flag_bytes) { [0b00000000, 0b10000000].pack("C2") }
its(:preserve_on_tag_alteration?) { should be_true }
its(:preserve_on_file_alteration?) { should be_true }
its(:read_only?) { should be_false }
its(:compressed?) { should be_true }
its(:encrypted?) { should be_false }
its(:grouped?) { should be_false }
its(:unsynchronised?) { should be_false }
its(:data_length_indicator?) { should be_false }
its(:additional_info_byte_count) { should eq 4 }
its(:range_of_data_length_bytes) { should eq 0...4 }
its(:range_of_group_id) { should eq nil }
its(:range_of_encryption_id) { should eq nil }
end

context "when compression and group id is on" do
let(:flag_bytes) { [0b00000000, 0b10100000].pack("C2") }
its(:preserve_on_tag_alteration?) { should be_true }
its(:preserve_on_file_alteration?) { should be_true }
its(:read_only?) { should be_false }
its(:compressed?) { should be_true }
its(:encrypted?) { should be_false }
its(:grouped?) { should be_true }
its(:unsynchronised?) { should be_false }
its(:data_length_indicator?) { should be_false }
its(:additional_info_byte_count) { should eq 5 }
its(:range_of_data_length_bytes) { should eq 0...4 }
its(:range_of_group_id) { should eq 3...4 }
its(:range_of_encryption_id) { should eq nil }
end

context "when all flags are 1" do
let(:flag_bytes) { [0b11100000, 0b11100000].pack("C2") }
its(:preserve_on_tag_alteration?) { should be_false }
its(:preserve_on_file_alteration?) { should be_false }
its(:read_only?) { should be_true }
its(:compressed?) { should be_true }
its(:encrypted?) { should be_true }
its(:grouped?) { should be_true }
its(:unsynchronised?) { should be_false }
its(:data_length_indicator?) { should be_false }
its(:additional_info_byte_count) { should eq 6 }
its(:range_of_data_length_bytes) { should eq 0...4 }
its(:range_of_group_id) { should eq 3...4 }
its(:range_of_encryption_id) { should eq 4...5 }
end
end

context "when major version is 4" do
let(:version) { 4 }
context "when all flags are nulled" do
let(:flag_bytes) { [0b00000000, 0b00000000].pack("C2") }
its(:preserve_on_tag_alteration?) { should be_true }
its(:preserve_on_file_alteration?) { should be_true }
its(:read_only?) { should be_false }
its(:compressed?) { should be_false }
its(:encrypted?) { should be_false }
its(:grouped?) { should be_false }
its(:unsynchronised?) { should be_false }
its(:data_length_indicator?) { should be_false }
its(:additional_info_byte_count) { should eq 0 }
its(:range_of_data_length_bytes) { should eq nil }
its(:range_of_group_id) { should eq nil }
its(:range_of_encryption_id) { should eq nil }
end

context "when compression is on" do
let(:flag_bytes) { [0b00000000, 0b10001001].pack("C2") }
its(:preserve_on_tag_alteration?) { should be_true }
its(:preserve_on_file_alteration?) { should be_true }
its(:read_only?) { should be_false }
its(:compressed?) { should be_true }
its(:encrypted?) { should be_false }
its(:grouped?) { should be_false }
its(:unsynchronised?) { should be_false }
its(:data_length_indicator?) { should be_true }
its(:additional_info_byte_count) { should eq 4 }
its(:range_of_data_length_bytes) { should eq 0...4 }
its(:range_of_group_id) { should eq nil }
its(:range_of_encryption_id) { should eq nil }
end

context "when compression and group id is on" do
let(:flag_bytes) { [0b00000000, 0b01001001].pack("C2") }
its(:preserve_on_tag_alteration?) { should be_true }
its(:preserve_on_file_alteration?) { should be_true }
its(:read_only?) { should be_false }
its(:compressed?) { should be_true }
its(:encrypted?) { should be_false }
its(:grouped?) { should be_true }
its(:unsynchronised?) { should be_false }
its(:data_length_indicator?) { should be_true }
its(:additional_info_byte_count) { should eq 5 }
its(:range_of_data_length_bytes) { should eq 1...5 }
its(:range_of_group_id) { should eq 0...1 }
its(:range_of_encryption_id) { should eq nil }
end

context "when all flags are 1" do
let(:flag_bytes) { [0b01110000, 0b01001111].pack("C2") }
its(:preserve_on_tag_alteration?) { should be_false }
its(:preserve_on_file_alteration?) { should be_false }
its(:read_only?) { should be_true }
its(:compressed?) { should be_true }
its(:encrypted?) { should be_true }
its(:grouped?) { should be_true }
its(:unsynchronised?) { should be_true }
its(:data_length_indicator?) { should be_true }
its(:additional_info_byte_count) { should eq 6 }
its(:range_of_data_length_bytes) { should eq 2...6 }
its(:range_of_group_id) { should eq 0...1 }
its(:range_of_encryption_id) { should eq 1...2 }
end
end
end
8 changes: 7 additions & 1 deletion tags
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ V2 lib/id3tag/frames/v2/genre_frame/genre_parser_24.rb /^ module V2$/;" m cl
V2 lib/id3tag/frames/v2/genre_frame/genre_parser_pre_24.rb /^ module V2$/;" m class:ID3Tag.Frames
V2 lib/id3tag/frames/v2/text_frame.rb /^ module V2$/;" m class:ID3Tag.Frames
V2 lib/id3tag/frames/v2/unique_file_id_frame.rb /^ module V2$/;" m class:ID3Tag.Frames
additional_info_byte_count lib/id3tag/frames/v2/basic_frame.rb /^ def additional_info_byte_count$/;" f class:ID3Tag.Frames.V2.BasicFrame
additional_info_byte_count lib/id3tag/frames/v2/frame_flags.rb /^ def additional_info_byte_count$/;" f class:ID3Tag.Frames.V2.FrameFlags
advise lib/id3tag/frame_id_advisor.rb /^ def advise(frame_name)$/;" f class:ID3Tag.FrameIdAdvisor
album lib/id3tag/tag.rb /^ def album$/;" f class:ID3Tag
album_frame lib/id3tag/id3_v1_frame_parser.rb /^ def album_frame$/;" f class:ID3Tag.ID3V1FrameParser
Expand All @@ -120,7 +122,8 @@ content_split_apart_by_null_byte lib/id3tag/frames/v2/unique_file_id_frame.rb /^
content_without_encoding_byte lib/id3tag/frames/v2/text_frame.rb /^ def content_without_encoding_byte$/;" f class:ID3Tag.Frames.V2.TextFrame
convert_32bit_integer_to_string lib/id3tag/number_util.rb /^ def self.convert_32bit_integer_to_string(integer)$/;" F class:ID3Tag.NumberUtil
convert_string_to_32bit_integer lib/id3tag/number_util.rb /^ def self.convert_string_to_32bit_integer(string)$/;" F class:ID3Tag.NumberUtil
current_version_map lib/id3tag/frames/v2/frame_flags.rb /^ def current_version_map$/;" f class:ID3Tag.Frames.V2.FrameFlags
current_additional_info_map lib/id3tag/frames/v2/frame_flags.rb /^ def current_additional_info_map$/;" f class:ID3Tag.Frames.V2.FrameFlags
current_flag_map lib/id3tag/frames/v2/frame_flags.rb /^ def current_flag_map$/;" f class:ID3Tag.Frames.V2.FrameFlags
data_length_indicator? lib/id3tag/frames/v2/basic_frame.rb /^ def data_length_indicator?$/;" f class:ID3Tag.Frames.V2.BasicFrame
data_length_indicator? lib/id3tag/frames/v2/frame_flags.rb /^ def data_length_indicator?$/;" f class:ID3Tag.Frames.V2.FrameFlags
decode lib/id3tag/synchsafe_integer.rb /^ def decode(synchsafe_int)$/;" f class:ID3Tag.SynchsafeInteger.encode
Expand Down Expand Up @@ -220,6 +223,9 @@ preserve_on_file_alteration? lib/id3tag/frames/v2/frame_header_flags.rb /^
preserve_on_tag_alteration? lib/id3tag/frames/v2/basic_frame.rb /^ def preserve_on_tag_alteration?$/;" f class:ID3Tag.Frames.V2.BasicFrame
preserve_on_tag_alteration? lib/id3tag/frames/v2/frame_flags.rb /^ def preserve_on_tag_alteration?$/;" f class:ID3Tag.Frames.V2.FrameFlags
preserve_on_tag_alteration? lib/id3tag/frames/v2/frame_header_flags.rb /^ def preserve_on_tag_alteration?$/;" f class:ID3Tag.Frames.V2.FrameFlags
range_of_data_length_bytes lib/id3tag/frames/v2/frame_flags.rb /^ def range_of_data_length_bytes$/;" f class:ID3Tag.Frames.V2.FrameFlags
range_of_encryption_id lib/id3tag/frames/v2/frame_flags.rb /^ def range_of_encryption_id$/;" f class:ID3Tag.Frames.V2.FrameFlags
range_of_group_id lib/id3tag/frames/v2/frame_flags.rb /^ def range_of_group_id$/;" f class:ID3Tag.Frames.V2.FrameFlags
raw_content_io lib/id3tag/frames/v2/basic_frame.rb /^ def raw_content_io$/;" f class:ID3Tag.Frames.V2.BasicFrame
raw_text_and_content lib/id3tag/frames/v2/comments_frame.rb /^ def raw_text_and_content$/;" f class:ID3Tag.Frames.V2.CommentsFrame
read lib/id3tag.rb /^ def self.read(source, version = :all)$/;" F class:ID3Tag
Expand Down

0 comments on commit a81cf13

Please sign in to comment.