Merge pull request #4875 from koying/fixdroidremotekeyboard
[vuplus_xbmc] / xbmc / music / tags / TagLibVFSStream.cpp
index f910956..e2abcd5 100644 (file)
@@ -1,6 +1,6 @@
 /*
- *      Copyright (C) 2005-2008 Team XBMC
- *      http://www.xbmc.org
+ *      Copyright (C) 2005-2013 Team XBMC
+ *      http://xbmc.org
  *
  *  This Program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -13,9 +13,8 @@
  *  GNU General Public License for more details.
  *
  *  You should have received a copy of the GNU General Public License
- *  along with XBMC; see the file COPYING.  If not, write to
- *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
- *  http://www.gnu.org/copyleft/gpl.html
+ *  along with XBMC; see the file COPYING.  If not, see
+ *  <http://www.gnu.org/licenses/>.
  *
  */
 #include "limits.h"
@@ -52,6 +51,7 @@ TagLibVFSStream::TagLibVFSStream(const string& strFileName, bool readOnly)
       m_bIsOpen = false;
   }
   m_strFileName = strFileName;
+  m_bIsReadOnly = readOnly || !m_bIsOpen;
 }
 
 /*!
@@ -73,7 +73,7 @@ FileName TagLibVFSStream::name() const
 /*!
  * Reads a block of size \a length at the current get pointer.
  */
-ByteVector TagLibVFSStream::readBlock(ulong length)
+ByteVector TagLibVFSStream::readBlock(TagLib::ulong length)
 {
   ByteVector byteVector(static_cast<TagLib::uint>(length));
   byteVector.resize(m_file.Read(byteVector.data(), length));
@@ -101,7 +101,7 @@ void TagLibVFSStream::writeBlock(const ByteVector &data)
  * \note This method is slow since it requires rewriting all of the file
  * after the insertion point.
  */
-void TagLibVFSStream::insert(const ByteVector &data, ulong start, ulong replace)
+void TagLibVFSStream::insert(const ByteVector &data, TagLib::ulong start, TagLib::ulong replace)
 {
   if (data.size() == replace)
   {
@@ -125,7 +125,7 @@ void TagLibVFSStream::insert(const ByteVector &data, ulong start, ulong replace)
   // First, make sure that we're working with a buffer that is longer than
   // the *differnce* in the tag sizes.  We want to avoid overwriting parts
   // that aren't yet in memory, so this is necessary.
-  ulong bufferLength = bufferSize();
+  TagLib::ulong bufferLength = bufferSize();
 
   while (data.size() - replace > bufferLength)
     bufferLength += bufferSize();
@@ -165,7 +165,7 @@ void TagLibVFSStream::insert(const ByteVector &data, ulong start, ulong replace)
 
     // Check to see if we just read the last block.  We need to call clear()
     // if we did so that the last write succeeds.
-    if (ulong(bytesRead) < bufferLength)
+    if (TagLib::ulong(bytesRead) < bufferLength)
       clear();
 
     // Seek to the write position and write our buffer.  Increment the
@@ -186,16 +186,16 @@ void TagLibVFSStream::insert(const ByteVector &data, ulong start, ulong replace)
  * \note This method is slow since it involves rewriting all of the file
  * after the removed portion.
  */
-void TagLibVFSStream::removeBlock(ulong start, ulong length)
+void TagLibVFSStream::removeBlock(TagLib::ulong start, TagLib::ulong length)
 {
-  ulong bufferLength = bufferSize();
+  TagLib::ulong bufferLength = bufferSize();
 
   long readPosition = start + length;
   long writePosition = start;
 
   ByteVector buffer(static_cast<TagLib::uint>(bufferLength));
 
-  ulong bytesRead = 1;
+  TagLib::ulong bytesRead = 1;
 
   while(bytesRead != 0)
   {
@@ -240,6 +240,38 @@ bool TagLibVFSStream::isOpen() const
  */
 void TagLibVFSStream::seek(long offset, Position p)
 {
+  const long fileLen = length();
+  if (m_bIsReadOnly && fileLen > 0)
+  {
+    long startPos;
+    if (p == Beginning)
+      startPos = 0;
+    else if (p == Current)
+      startPos = tell();
+    else if (p == End)
+      startPos = fileLen;
+    else
+      return; // wrong Position value
+    
+    // When parsing some broken files, taglib may try to seek above end of file.
+    // If underlying VFS does not move I/O pointer in this case, taglib will parse
+    // same part of file several times and ends with error. To prevent this
+    // situation, force seek to last valid position so VFS move I/O pointer.
+    if (startPos >= 0)
+    {
+      if (offset < 0 && startPos + offset < 0)
+      {
+        m_file.Seek(0, SEEK_SET);
+        return;
+      }
+      if (offset > 0 && startPos + offset > fileLen)
+      {
+        m_file.Seek(fileLen, SEEK_SET);
+        return;
+      }
+    }
+  }
+
   switch(p)
   {
     case Beginning:
@@ -278,7 +310,7 @@ long TagLibVFSStream::tell() const
  */
 long TagLibVFSStream::length()
 {
-  return m_file.GetLength();
+  return (long)m_file.GetLength();
 }
 
 /*!