| Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
| AsfFileWriter |
|
| 3.6666666666666665;3.667 |
| 1 | /* | |
| 2 | * Entagged Audio Tag library | |
| 3 | * Copyright (c) 2004-2005 Christian Laireiter <liree@web.de> | |
| 4 | * | |
| 5 | * This library is free software; you can redistribute it and/or | |
| 6 | * modify it under the terms of the GNU Lesser General Public | |
| 7 | * License as published by the Free Software Foundation; either | |
| 8 | * version 2.1 of the License, or (at your option) any later version. | |
| 9 | * | |
| 10 | * This library is distributed in the hope that it will be useful, | |
| 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| 13 | * Lesser General Public License for more details. | |
| 14 | * | |
| 15 | * You should have received a copy of the GNU Lesser General Public | |
| 16 | * License along with this library; if not, write to the Free Software | |
| 17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |
| 18 | */ | |
| 19 | package org.jaudiotagger.audio.asf; | |
| 20 | ||
| 21 | import org.jaudiotagger.audio.asf.data.AsfHeader; | |
| 22 | import org.jaudiotagger.audio.asf.data.ChunkContainer; | |
| 23 | import org.jaudiotagger.audio.asf.data.MetadataContainer; | |
| 24 | import org.jaudiotagger.audio.asf.io.*; | |
| 25 | import org.jaudiotagger.tag.asf.AsfTag; | |
| 26 | import org.jaudiotagger.audio.asf.util.TagConverter; | |
| 27 | import org.jaudiotagger.audio.exceptions.CannotWriteException; | |
| 28 | import org.jaudiotagger.audio.generic.AudioFileWriter; | |
| 29 | import org.jaudiotagger.tag.Tag; | |
| 30 | ||
| 31 | import java.io.IOException; | |
| 32 | import java.io.RandomAccessFile; | |
| 33 | import java.util.ArrayList; | |
| 34 | import java.util.List; | |
| 35 | ||
| 36 | /** | |
| 37 | * This class writes given tags to ASF files containing WMA content. <br> | |
| 38 | * <br> | |
| 39 | * | |
| 40 | * @author Christian Laireiter | |
| 41 | */ | |
| 42 | 8 | public class AsfFileWriter extends AudioFileWriter { |
| 43 | ||
| 44 | /** | |
| 45 | * {@inheritDoc} | |
| 46 | */ | |
| 47 | @Override | |
| 48 | protected void deleteTag(final RandomAccessFile raf, | |
| 49 | final RandomAccessFile tempRaf) throws CannotWriteException, | |
| 50 | IOException { | |
| 51 | 52 | writeTag(new AsfTag(true), raf, tempRaf); |
| 52 | 52 | } |
| 53 | ||
| 54 | private boolean[] searchExistence(final ChunkContainer container, | |
| 55 | final MetadataContainer[] metaContainers) { | |
| 56 | 266 | assert container != null; |
| 57 | 266 | assert metaContainers != null; |
| 58 | 266 | final boolean[] result = new boolean[metaContainers.length]; |
| 59 | 1596 | for (int i = 0; i < result.length; i++) { |
| 60 | 1330 | result[i] = container.hasChunkByGUID(metaContainers[i] |
| 61 | .getContainerType().getContainerGUID()); | |
| 62 | } | |
| 63 | 266 | return result; |
| 64 | } | |
| 65 | ||
| 66 | /** | |
| 67 | * {@inheritDoc} | |
| 68 | */ | |
| 69 | @Override | |
| 70 | protected void writeTag(final Tag tag, final RandomAccessFile raf, | |
| 71 | final RandomAccessFile rafTemp) throws CannotWriteException, | |
| 72 | IOException { | |
| 73 | /* | |
| 74 | * Since this implementation should not change the structure of the ASF | |
| 75 | * file (locations of content description chunks), we need to read the | |
| 76 | * content description chunk and the extended content description chunk | |
| 77 | * from the source file. In the second step we need to determine which | |
| 78 | * modifier (asf header or asf extended header) gets the appropriate | |
| 79 | * modifiers. The following policies are applied: if the source does not | |
| 80 | * contain any descriptor, the necessary descriptors are appended to the | |
| 81 | * header object. | |
| 82 | * | |
| 83 | * if the source contains only one descriptor in the header extension | |
| 84 | * object, and the other type is needed as well, the other one will be | |
| 85 | * put into the header extension object. | |
| 86 | * | |
| 87 | * for each descriptor type, if an object is found, an updater will be | |
| 88 | * configured. | |
| 89 | */ | |
| 90 | 133 | final AsfHeader sourceHeader = AsfHeaderReader.readTagHeader(raf); |
| 91 | 133 | raf.seek(0); // Reset for the streamer |
| 92 | /* | |
| 93 | * Now createField modifiers for metadata descriptor and extended content | |
| 94 | * descriptor as implied by the given Tag. | |
| 95 | */ | |
| 96 | // TODO not convinced that we need to copy fields here | |
| 97 | 133 | final AsfTag copy = new AsfTag(tag, true); |
| 98 | 133 | final MetadataContainer[] distribution = TagConverter |
| 99 | .distributeMetadata(copy); | |
| 100 | 133 | final boolean[] existHeader = searchExistence(sourceHeader, |
| 101 | distribution); | |
| 102 | 133 | final boolean[] existExtHeader = searchExistence(sourceHeader |
| 103 | .getExtendedHeader(), distribution); | |
| 104 | // Modifiers for the asf header object | |
| 105 | 133 | final List<ChunkModifier> headerModifier = new ArrayList<ChunkModifier>(); |
| 106 | // Modifiers for the asf header extension object | |
| 107 | 133 | final List<ChunkModifier> extHeaderModifier = new ArrayList<ChunkModifier>(); |
| 108 | 798 | for (int i = 0; i < distribution.length; i++) { |
| 109 | 665 | final WriteableChunkModifer modifier = new WriteableChunkModifer( |
| 110 | distribution[i]); | |
| 111 | 665 | if (existHeader[i]) { |
| 112 | // Will remove or modify chunks in ASF header | |
| 113 | 158 | headerModifier.add(modifier); |
| 114 | 507 | } else if (existExtHeader[i]) { |
| 115 | // Will remove or modify chunks in extended header | |
| 116 | 66 | extHeaderModifier.add(modifier); |
| 117 | } else { | |
| 118 | // Objects (chunks) will be added here. | |
| 119 | 441 | if (i == 0 || i == 2 || i == 1) { |
| 120 | // Add content description and extended content description | |
| 121 | // at header for maximum compatibility | |
| 122 | 241 | headerModifier.add(modifier); |
| 123 | } else { | |
| 124 | // For now, the rest should be created at extended header | |
| 125 | // since other positions aren't known. | |
| 126 | 200 | extHeaderModifier.add(modifier); |
| 127 | } | |
| 128 | } | |
| 129 | } | |
| 130 | // only addField an AsfExtHeaderModifier, if there is actually something to | |
| 131 | // change (performance) | |
| 132 | 133 | if (!extHeaderModifier.isEmpty()) { |
| 133 | 133 | headerModifier.add(new AsfExtHeaderModifier(extHeaderModifier)); |
| 134 | } | |
| 135 | 133 | new AsfStreamer() |
| 136 | .createModifiedCopy(new RandomAccessFileInputstream(raf), | |
| 137 | new RandomAccessFileOutputStream(rafTemp), | |
| 138 | headerModifier); | |
| 139 | 133 | } |
| 140 | ||
| 141 | } |