2 * Copyright (C) 2005-2018 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
14 #include "XBTFReader.h"
15 #include "guilib/XBTF.h"
16 #include "utils/EndianSwap.h"
19 #include "filesystem/SpecialProtocol.h"
20 #include "utils/CharsetConverter.h"
21 #include "platform/win32/PlatformDefs.h"
24 static bool ReadString(FILE* file
, char* str
, size_t max_length
)
26 if (file
== nullptr || str
== nullptr || max_length
<= 0)
29 return (fread(str
, max_length
, 1, file
) == 1);
32 static bool ReadChar(FILE* file
, char& value
)
37 if (fread(&value
, sizeof(char), 1, file
) != 1)
43 static bool ReadUInt32(FILE* file
, uint32_t& value
)
48 if (fread(&value
, sizeof(uint32_t), 1, file
) != 1)
51 value
= Endian_SwapLE32(value
);
55 static bool ReadUInt64(FILE* file
, uint64_t& value
)
60 if (fread(&value
, sizeof(uint64_t), 1, file
) != 1)
63 value
= Endian_SwapLE64(value
);
67 CXBTFReader::CXBTFReader()
72 CXBTFReader::~CXBTFReader()
77 bool CXBTFReader::Open(const std::string
& path
)
85 std::wstring strPathW
;
86 g_charsetConverter
.utf8ToW(CSpecialProtocol::TranslatePath(m_path
), strPathW
, false);
87 m_file
= _wfopen(strPathW
.c_str(), L
"rb");
89 m_file
= fopen(m_path
.c_str(), "rb");
91 if (m_file
== nullptr)
94 // read the magic word
96 if (!ReadString(m_file
, magic
, sizeof(magic
)))
99 if (strncmp(XBTF_MAGIC
.c_str(), magic
, sizeof(magic
)) != 0)
104 if (!ReadChar(m_file
, version
))
107 if (version
< XBTF_VERSION_MIN
)
110 unsigned int nofFiles
;
111 if (!ReadUInt32(m_file
, nofFiles
))
114 for (uint32_t i
= 0; i
< nofFiles
; i
++)
120 // one extra char to null terminate the string
121 char path
[CXBTFFile::MaximumPathLength
+ 1] = {};
122 if (!ReadString(m_file
, path
, sizeof(path
) - 1))
124 xbtfFile
.SetPath(path
);
126 if (!ReadUInt32(m_file
, u32
))
128 xbtfFile
.SetLoop(u32
);
130 unsigned int nofFrames
;
131 if (!ReadUInt32(m_file
, nofFrames
))
134 for (uint32_t j
= 0; j
< nofFrames
; j
++)
138 if (!ReadUInt32(m_file
, u32
))
142 if (!ReadUInt32(m_file
, u32
))
144 frame
.SetHeight(u32
);
146 if (!ReadUInt32(m_file
, u32
))
148 frame
.SetFormat(static_cast<XB_FMT
>(u32
));
150 if (!ReadUInt64(m_file
, u64
))
152 frame
.SetPackedSize(u64
);
154 if (!ReadUInt64(m_file
, u64
))
156 frame
.SetUnpackedSize(u64
);
158 if (!ReadUInt32(m_file
, u32
))
160 frame
.SetDuration(u32
);
162 if (!ReadUInt64(m_file
, u64
))
164 frame
.SetOffset(u64
);
166 xbtfFile
.GetFrames().push_back(frame
);
173 uint64_t pos
= static_cast<uint64_t>(ftell(m_file
));
174 if (pos
!= GetHeaderSize())
180 bool CXBTFReader::IsOpen() const
182 return m_file
!= nullptr;
185 void CXBTFReader::Close()
187 if (m_file
!= nullptr)
197 time_t CXBTFReader::GetLastModificationTimestamp() const
199 if (m_file
== nullptr)
202 struct stat fileStat
;
203 if (fstat(fileno(m_file
), &fileStat
) == -1)
206 return fileStat
.st_mtime
;
209 bool CXBTFReader::Load(const CXBTFFrame
& frame
, unsigned char* buffer
) const
211 if (m_file
== nullptr)
214 #if defined(TARGET_DARWIN) || defined(TARGET_FREEBSD)
215 if (fseeko(m_file
, static_cast<off_t
>(frame
.GetOffset()), SEEK_SET
) == -1)
216 #elif defined(TARGET_ANDROID)
217 if (fseek(m_file
, static_cast<long>(frame
.GetOffset()), SEEK_SET
) == -1) // No fseeko64 before N
219 if (fseeko64(m_file
, static_cast<off_t
>(frame
.GetOffset()), SEEK_SET
) == -1)
223 if (fread(buffer
, 1, static_cast<size_t>(frame
.GetPackedSize()), m_file
) != frame
.GetPackedSize())