Unbewohnte
3 years ago
12 changed files with 304 additions and 159 deletions
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1,113 +1,221 @@ |
|||||||
package v2 |
package v2 |
||||||
|
|
||||||
// // Writes ID3v2Tag to ws
|
import ( |
||||||
// func (tag *ID3v2Tag) write(ws io.WriteSeeker) error {
|
"fmt" |
||||||
// _, err := ws.Seek(0, io.SeekStart)
|
"io" |
||||||
// if err != nil {
|
"os" |
||||||
// return fmt.Errorf("could not seek: %s", err)
|
"path/filepath" |
||||||
// }
|
|
||||||
|
"github.com/Unbewohnte/id3ed/util" |
||||||
// // write header
|
) |
||||||
// _, err = ws.Write(tag.Header.toBytes())
|
|
||||||
// if err != nil {
|
// Writes ID3v2Tag to ws
|
||||||
// return fmt.Errorf("could not write to writer: %s", err)
|
func (tag *ID3v2Tag) write(ws io.WriteSeeker) error { |
||||||
// }
|
_, err := ws.Seek(0, io.SeekStart) |
||||||
|
if err != nil { |
||||||
// // write frames
|
return fmt.Errorf("could not seek: %s", err) |
||||||
// for _, frame := range tag.Frames {
|
} |
||||||
// _, err = ws.Write(frame.toBytes())
|
|
||||||
// if err != nil {
|
// write header
|
||||||
// return fmt.Errorf("could not write to writer: %s", err)
|
_, err = ws.Write(tag.Header.toBytes()) |
||||||
// }
|
if err != nil { |
||||||
// }
|
return fmt.Errorf("could not write to writer: %s", err) |
||||||
|
} |
||||||
// return nil
|
|
||||||
// }
|
// write frames
|
||||||
|
for _, frame := range tag.Frames { |
||||||
// // Writes ID3v2Tag to file, removing already existing tag if found
|
_, err = ws.Write(frame.toBytes()) |
||||||
// func (tag *ID3v2Tag) WriteToFile(f *os.File) error {
|
if err != nil { |
||||||
// defer f.Close()
|
return fmt.Errorf("could not write to writer: %s", err) |
||||||
|
} |
||||||
// _, err := f.Seek(0, io.SeekStart)
|
} |
||||||
// if err != nil {
|
|
||||||
// return fmt.Errorf("could not seek: %s", err)
|
// write padding if has any
|
||||||
// }
|
if tag.Padding != 0 { |
||||||
|
util.WriteToExtent(ws, []byte{0}, int(tag.Padding)) |
||||||
// // check for existing tag
|
} |
||||||
// possibleHeaderID, err := util.ReadToString(f, 3)
|
|
||||||
// if err != nil {
|
return nil |
||||||
// return err
|
} |
||||||
// }
|
|
||||||
|
// Writes ID3v2Tag to file, removing already existing tag if found
|
||||||
// if possibleHeaderID != HEADERIDENTIFIER {
|
func (tag *ID3v2Tag) WriteToFile(f *os.File) error { |
||||||
// // No existing tag, just write what we have
|
defer f.Close() |
||||||
// // and exit
|
|
||||||
// tag.write(f)
|
_, err := f.Seek(0, io.SeekStart) |
||||||
|
if err != nil { |
||||||
// return nil
|
return fmt.Errorf("could not seek: %s", err) |
||||||
// }
|
} |
||||||
// // there is an existing tag, remove it
|
|
||||||
// // and write a new one
|
// check if there`s content at all
|
||||||
|
fStats, err := f.Stat() |
||||||
// // get size of the existing tag
|
if err != nil { |
||||||
// existingHeader, err := readHeader(f)
|
return err |
||||||
// if err != nil {
|
} |
||||||
// return err
|
|
||||||
// }
|
if fStats.Size() < 3 { |
||||||
// existingHSize := existingHeader.Size()
|
// there`s no way that the file can contain TAG,
|
||||||
|
// just write and exit
|
||||||
// // cannot truncate just the existing tag with f.Truncate(),
|
|
||||||
// // so we need to improvise and have a temporary copy of the mp3,
|
// `write` for some reason removes all contents if there`s no tag, so
|
||||||
// // wipe the original file, write our tag and place the actual
|
// we need forcefully store already existing data and
|
||||||
// // music without the old tag from the temporary copy.
|
// write it again afterwards
|
||||||
|
|
||||||
// // create a temporary file
|
_, err := f.Seek(0, io.SeekStart) |
||||||
// temporaryDir := os.TempDir()
|
if err != nil { |
||||||
// tmpF, err := os.CreateTemp(temporaryDir, fmt.Sprintf("%s_TEMP", filepath.Base(f.Name())))
|
return fmt.Errorf("could not seek: %s", err) |
||||||
// if err != nil {
|
} |
||||||
// return err
|
|
||||||
// }
|
contents, err := util.Read(f, uint64(fStats.Size())) |
||||||
|
if err != nil { |
||||||
// defer tmpF.Close()
|
return err |
||||||
// // remove it afterwards
|
} |
||||||
// defer os.Remove(filepath.Join(temporaryDir, tmpF.Name()))
|
|
||||||
|
err = tag.write(f) |
||||||
// tmpFStats, err := tmpF.Stat()
|
if err != nil { |
||||||
// if err != nil {
|
return err |
||||||
// return err
|
} |
||||||
// }
|
|
||||||
|
_, err = f.Write(contents) |
||||||
// // copy contents from the original mp3 to a temporary one
|
if err != nil { |
||||||
// _, err = io.Copy(tmpF, f)
|
return err |
||||||
// if err != nil {
|
} |
||||||
// return err
|
|
||||||
// }
|
// apparently, there are 3 zerobytes
|
||||||
|
// that appear after writing the contents for some
|
||||||
// // fully remove contents from the original file
|
// alien-like reason so we need to remove them.
|
||||||
// err = f.Truncate(0)
|
fStats, err = f.Stat() |
||||||
// if err != nil {
|
if err != nil { |
||||||
// return err
|
return err |
||||||
// }
|
} |
||||||
|
|
||||||
// // write our tag
|
err = f.Truncate(fStats.Size() - 3) |
||||||
// tag.write(f)
|
if err != nil { |
||||||
|
return err |
||||||
// // read all contents of the temporary file, except the existing tag
|
} |
||||||
// tmpF.Seek(int64(existingHSize), io.SeekStart)
|
|
||||||
|
return nil |
||||||
// musicDataSize := uint64(tmpFStats.Size() - int64(existingHSize))
|
} |
||||||
|
|
||||||
// musicData, err := util.Read(tmpF, musicDataSize)
|
// check for an existing tag
|
||||||
// if err != nil {
|
possibleHeaderID, err := util.ReadToString(f, 3) |
||||||
// return err
|
if err != nil { |
||||||
// }
|
return err |
||||||
|
} |
||||||
// // and write them into the original file, which
|
|
||||||
// // contains only the new tag
|
if possibleHeaderID != HEADERIDENTIFIER { |
||||||
// _, err = f.Write(musicData)
|
// No existing tag, just write what we have
|
||||||
// if err != nil {
|
// and exit
|
||||||
// return err
|
|
||||||
// }
|
// `write` for some reason removes all contents if there`s no tag, so
|
||||||
|
// we need forcefully store already existing data and
|
||||||
// return nil
|
// write it again afterwards
|
||||||
// }
|
|
||||||
|
_, err := f.Seek(0, io.SeekStart) |
||||||
|
if err != nil { |
||||||
|
return fmt.Errorf("could not seek: %s", err) |
||||||
|
} |
||||||
|
|
||||||
|
contents, err := util.Read(f, uint64(fStats.Size())) |
||||||
|
if err != nil { |
||||||
|
return err |
||||||
|
} |
||||||
|
|
||||||
|
err = tag.write(f) |
||||||
|
if err != nil { |
||||||
|
return err |
||||||
|
} |
||||||
|
|
||||||
|
_, err = f.Write(contents) |
||||||
|
if err != nil { |
||||||
|
return err |
||||||
|
} |
||||||
|
|
||||||
|
// apparently, there are 3 zerobytes
|
||||||
|
// that appear after writing the contents for some
|
||||||
|
// alien-like reason so we need to remove them.
|
||||||
|
fStats, err = f.Stat() |
||||||
|
if err != nil { |
||||||
|
return err |
||||||
|
} |
||||||
|
|
||||||
|
err = f.Truncate(fStats.Size() - 3) |
||||||
|
if err != nil { |
||||||
|
return err |
||||||
|
} |
||||||
|
|
||||||
|
return nil |
||||||
|
} |
||||||
|
// there is an existing tag, remove it
|
||||||
|
// and write a new one
|
||||||
|
|
||||||
|
// get size of the existing tag
|
||||||
|
existingHeader, err := readHeader(f) |
||||||
|
if err != nil { |
||||||
|
return err |
||||||
|
} |
||||||
|
existingHeaderSize := existingHeader.Size() |
||||||
|
|
||||||
|
// cannot truncate just the existing tag with f.Truncate(),
|
||||||
|
// so we need to improvise and have a temporary copy of the mp3,
|
||||||
|
// wipe the original file, write our tag and place the actual
|
||||||
|
// music without the old tag from the temporary copy.
|
||||||
|
|
||||||
|
// create a temporary file
|
||||||
|
temporaryDir := os.TempDir() |
||||||
|
tmpF, err := os.CreateTemp(temporaryDir, fmt.Sprintf("%s_TEMP", filepath.Base(f.Name()))) |
||||||
|
if err != nil { |
||||||
|
return err |
||||||
|
} |
||||||
|
|
||||||
|
defer tmpF.Close() |
||||||
|
// remove it afterwards
|
||||||
|
defer os.Remove(filepath.Join(temporaryDir, tmpF.Name())) |
||||||
|
|
||||||
|
// copy contents of the original mp3 to a temporary one
|
||||||
|
_, err = io.Copy(tmpF, f) |
||||||
|
if err != nil { |
||||||
|
return err |
||||||
|
} |
||||||
|
|
||||||
|
// fully remove contents of the original file
|
||||||
|
err = f.Truncate(0) |
||||||
|
if err != nil { |
||||||
|
return err |
||||||
|
} |
||||||
|
|
||||||
|
// write our tag to the original file, which is at that moment is
|
||||||
|
// empty
|
||||||
|
err = tag.write(f) |
||||||
|
if err != nil { |
||||||
|
return err |
||||||
|
} |
||||||
|
|
||||||
|
tmpFStats, err := tmpF.Stat() |
||||||
|
if err != nil { |
||||||
|
return err |
||||||
|
} |
||||||
|
|
||||||
|
// read all contents of the temporary file, except the existing tag
|
||||||
|
|
||||||
|
musicDataSize := int64(tmpFStats.Size() - int64(existingHeaderSize)) |
||||||
|
|
||||||
|
_, err = tmpF.Seek(int64(existingHeaderSize), io.SeekStart) |
||||||
|
if err != nil { |
||||||
|
return fmt.Errorf("could not seek: %s", err) |
||||||
|
} |
||||||
|
|
||||||
|
musicData, err := util.Read(tmpF, uint64(musicDataSize)) |
||||||
|
if err != nil { |
||||||
|
return err |
||||||
|
} |
||||||
|
|
||||||
|
// and write them into the original file, which
|
||||||
|
// contains only the new tag
|
||||||
|
_, err = f.Write(musicData) |
||||||
|
if err != nil { |
||||||
|
return err |
||||||
|
} |
||||||
|
|
||||||
|
return nil |
||||||
|
} |
||||||
|
@ -1,27 +1,33 @@ |
|||||||
package v2 |
package v2 |
||||||
|
|
||||||
// func TestWrite(t *testing.T) {
|
import ( |
||||||
// f, err := os.Open(filepath.Join(TESTDATAPATH, "testreadv2.mp3"))
|
"os" |
||||||
// if err != nil {
|
"path/filepath" |
||||||
// t.Errorf("%s", err)
|
"testing" |
||||||
// }
|
) |
||||||
// defer f.Close()
|
|
||||||
|
|
||||||
// testTag, err := ReadV2Tag(f)
|
func TestWrite(t *testing.T) { |
||||||
// if err != nil {
|
f, err := os.Open(filepath.Join(TESTDATAPATH, "testreadv2.mp3")) |
||||||
// t.Errorf("%s", err)
|
if err != nil { |
||||||
// }
|
t.Errorf("%s", err) |
||||||
|
} |
||||||
|
defer f.Close() |
||||||
|
|
||||||
// ff, err := os.OpenFile(filepath.Join(TESTDATAPATH, "testwritev2.mp3"),
|
testTag, err := ReadV2Tag(f) |
||||||
// os.O_CREATE|os.O_RDWR, os.ModePerm)
|
if err != nil { |
||||||
// if err != nil {
|
t.Errorf("%s", err) |
||||||
// t.Errorf("%s", err)
|
} |
||||||
// }
|
|
||||||
// defer ff.Close()
|
|
||||||
|
|
||||||
// // WRITING
|
ff, err := os.OpenFile(filepath.Join(TESTDATAPATH, "testwritev2.mp3"), |
||||||
// err = testTag.WriteToFile(ff)
|
os.O_CREATE|os.O_RDWR, os.ModePerm) |
||||||
// if err != nil {
|
if err != nil { |
||||||
// t.Errorf("WriteToFile failed: %s", err)
|
t.Errorf("%s", err) |
||||||
// }
|
} |
||||||
// }
|
defer ff.Close() |
||||||
|
|
||||||
|
// write testTag to the ff
|
||||||
|
err = testTag.WriteToFile(ff) |
||||||
|
if err != nil { |
||||||
|
t.Errorf("WriteToFile failed: %s", err) |
||||||
|
} |
||||||
|
} |
||||||
|
Loading…
Reference in new issue