UWP平台Taglib编译(2)
此文已由作者郑博授权网易云社区发布。
欢迎访问网易云社区,了解更多网易技术产品运营经验
#endif // _WIN32
} class FileStream::FileStreamPrivate
{
public:
FileStreamPrivate(const FileName &fileName)
: file(InvalidFileHandle)
, name(fileName)
, readOnly(true)
{
} FileHandle file;
FileNameHandle name;
bool readOnly;
}; ////////////////////////////////////////////////////////////////////////////////
// public members
//////////////////////////////////////////////////////////////////////////////// FileStream::FileStream(FileName fileName, bool openReadOnly)
: d(new FileStreamPrivate(fileName))
{
// First try with read / write mode, if that fails, fall back to read only. if(!openReadOnly)
d->file = openFile(fileName, false); if(d->file != InvalidFileHandle)
d->readOnly = false;
else
d->file = openFile(fileName, true); if(d->file == InvalidFileHandle)
{
# ifdef _WIN32
debug("Could not open file " + fileName.toString());
# else
debug("Could not open file " + String(static_cast(d->name)));
# endif
}
} FileStream::~FileStream()
{
if(isOpen())
closeFile(d->file); delete d;
} FileName FileStream::name() const
{
return d->name;
} ByteVector FileStream::readBlock(ulong length)
{
if(!isOpen()) {
debug("FileStream::readBlock() -- invalid file.");
return ByteVector::null;
} if(length == 0)
return ByteVector::null; const ulong streamLength = static_cast(FileStream::length());
if(length > bufferSize() && length > streamLength)
length = streamLength; ByteVector buffer(static_cast(length)); const size_t count = readFile(d->file, buffer);
buffer.resize(static_cast(count)); return buffer;
} void FileStream::writeBlock(const ByteVector &data)
{
if(!isOpen()) {
debug("FileStream::writeBlock() -- invalid file.");
return;
} if(readOnly()) {
debug("FileStream::writeBlock() -- read only file.");
return;
} writeFile(d->file, data);
} void FileStream::insert(const ByteVector &data, ulong start, ulong replace)
{
if(!isOpen()) {
debug("FileStream::insert() -- invalid file.");
return;
} if(readOnly()) {
debug("FileStream::insert() -- read only file.");
return;
} if(data.size() == replace) {
seek(start);
writeBlock(data);
return;
}
else if(data.size() < replace) {
seek(start);
writeBlock(data);
removeBlock(start + data.size(), replace - data.size());
return;
} // Woohoo! Faster (about 20%) than id3lib at last. I had to get hardcore
// and avoid TagLib's high level API for rendering just copying parts of
// the file that don't contain tag data.
//
// Now I'll explain the steps in this ugliness: // 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(); while(data.size() - replace > bufferLength)
bufferLength += bufferSize(); // Set where to start the reading and writing. long readPosition = start + replace;
long writePosition = start; ByteVector buffer = data;
ByteVector aboutToOverwrite(static_cast(bufferLength)); while(true)
{
// Seek to the current read position and read the data that we're about
// to overwrite. Appropriately increment the readPosition. seek(readPosition);
const size_t bytesRead = readFile(d->file, aboutToOverwrite);
aboutToOverwrite.resize(bytesRead);
readPosition += bufferLength; // 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(bytesRead < bufferLength)
clear(); // Seek to the write position and write our buffer. Increment the
// writePosition. seek(writePosition);
writeBlock(buffer); // We hit the end of the file. if(bytesRead == 0)
break; writePosition += buffer.size(); // Make the current buffer the data that we read in the beginning. buffer = aboutToOverwrite;
}
} void FileStream::removeBlock(ulong start, ulong length)
{
if(!isOpen()) {
debug("FileStream::removeBlock() -- invalid file.");
return;
} ulong bufferLength = bufferSize(); long readPosition = start + length;
long writePosition = start; ByteVector buffer(static_cast(bufferLength)); for(size_t bytesRead = -1; bytesRead != 0;)
{
seek(readPosition);
bytesRead = readFile(d->file, buffer);
readPosition += bytesRead; // 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(bytesRead < buffer.size()) {
clear();
buffer.resize(bytesRead);
} seek(writePosition);
writeFile(d->file, buffer); writePosition += bytesRead;
} truncate(writePosition);
} bool FileStream::readOnly() const
{
return d->readOnly;
} bool FileStream::isOpen() const
{
return (d->file != InvalidFileHandle);
} void FileStream::seek(long offset, Position p)
{
if(!isOpen()) {
debug("FileStream::seek() -- invalid file.");
return;
} #ifdef _WIN32 DWORD whence;
switch(p) {
case Beginning:
whence = FILE_BEGIN;
break;
case Current:
whence = FILE_CURRENT;
break;
case End:
whence = FILE_END;
break;
default:
debug("FileStream::seek() -- Invalid Position value.");
return;
} #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_SYSTEM)
LARGE_INTEGER distance = { 0 };
distance.QuadPart = offset; if (!SetFilePointerEx(d->file, distance, NULL, whence))
#else
SetLastError(NO_ERROR);
SetFilePointer(d->file, offset, NULL, whence); const int lastError = GetLastError();
if(lastError != NO_ERROR && lastError != ERROR_NEGATIVE_SEEK)
#endif
debug("FileStream::seek() -- Failed to set the file pointer."); #else int whence;
switch(p) {
case Beginning:
whence = SEEK_SET;
break;
case Current:
whence = SEEK_CUR;
break;
case End:
whence = SEEK_END;
break;
default:
debug("FileStream::seek() -- Invalid Position value.");
return;
} fseek(d->file, offset, whence); #endif
} void FileStream::clear()
{
#ifdef _WIN32 // NOP #else clearerr(d->file); #endif
} long FileStream::tell() const
{
#ifdef _WIN32 #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_SYSTEM)
LARGE_INTEGER distance = { 0 };
LARGE_INTEGER position = { 0 };
if (SetFilePointerEx(d->file, distance, &position, FILE_CURRENT)) {
return static_cast(position.QuadPart);
}
#else
SetLastError(NO_ERROR);
const DWORD position = SetFilePointer(d->file, 0, NULL, FILE_CURRENT);
if(GetLastError() == NO_ERROR) {
return static_cast(position);
}
#endif
else {
debug("FileStream::tell() -- Failed to get the file pointer.");
return 0;
} #else return ftell(d->file); #endif
} long FileStream::length()
{
if(!isOpen()) {
debug("FileStream::length() -- invalid file.");
return 0;
} #ifdef _WIN32 #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_SYSTEM)
LARGE_INTEGER fileSize = { 0 }; if (GetFileSizeEx(d->file, &fileSize)) {
return static_cast(fileSize.QuadPart);
}
#else
SetLastError(NO_ERROR);
const DWORD fileSize = GetFileSize(d->file, NULL); if (GetLastError() == NO_ERROR) {
return static_cast(fileSize);
}
#endif
else {
debug("FileStream::length() -- Failed to get the file size.");
return 0;
} #else const long curpos = tell(); seek(0, End);
const long endpos = tell(); seek(curpos, Beginning); return endpos; #endif
} ////////////////////////////////////////////////////////////////////////////////
// protected members
//////////////////////////////////////////////////////////////////////////////// void FileStream::truncate(long length)
{
#ifdef _WIN32 const long currentPos = tell(); seek(length); SetLastError(NO_ERROR);
SetEndOfFile(d->file);
if(GetLastError() != NO_ERROR) {
debug("FileStream::truncate() -- Failed to truncate the file.");
} seek(currentPos); #else const int error = ftruncate(fileno(d->file), length);
if(error != 0) {
debug("FileStream::truncate() -- Coundn't truncate the file.");
} #endif
} TagLib::uint FileStream::bufferSize()
{
return 1024;
}
为了便于调试,还需要修改taglib\toolkit\tdebuglistener.cpp,以便在调试直接在Output窗口输出调试信息,完整代码如下:
/***************************************************************************
copyright : (C) 2013 by Tsuda Kageyu
email : tsuda.kageyu@gmail.com
***************************************************************************/ /***************************************************************************
* This library is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License version *
* 2.1 as published by the Free Software Foundation. *
* *
* This library is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the Free Software *
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA *
* 02110-1301 USA *
* *
* Alternatively, this file is available under the Mozilla Public *
* License Version 1.1. You may obtain a copy of the License at *
* http://www.mozilla.org/MPL/ *
***************************************************************************/ #include "tdebuglistener.h" #include
#include #ifdef _WIN32
# include
#endif using namespace TagLib; namespace
{
class DefaultListener : public DebugListener
{
public:
virtual void printMessage(const String &msg)
{
#ifdef _WIN32 const wstring wstr = msg.toWString();
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_SYSTEM)
OutputDebugStringW(wstr.c_str());
#else
const int len = WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), -1, NULL, 0, NULL, NULL);
if(len != 0) {
std::vector buf(len);
WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), -1, &buf[0], len, NULL, NULL); std::cerr << std::string(&buf[0]);
}
#endif #else std::cerr << msg; #endif
}
}; DefaultListener defaultListener;
} namespace TagLib
{
DebugListener *debugListener = &defaultListener; DebugListener::DebugListener()
{
} DebugListener::~DebugListener()
{
} void setDebugListener(DebugListener *listener)
{
if(listener)
debugListener = listener;
else
debugListener = &defaultListener;
}
}
最后,编译吧,骚年!!!
免费领取验证码、内容安全、短信发送、直播点播体验包及云服务器等套餐
更多网易技术、产品、运营经验分享请点击。
相关文章:
【推荐】 Docker容器的原理与实践 (下)
【推荐】 Shadowsocks原理详解(上篇)
UWP平台Taglib编译(2)的更多相关文章
- UWP平台Taglib编译(1)
此文已由作者郑博授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验 最近开始开发UWP平台的App,项目需要用到Taglib进行音视频文件的标签信息读写,Google并没有现成的B ...
- xamarin UWP平台线程交互问题
先吐槽一下,xamarin到现在为止,虽然开发一下应用尚可,对于一些简单的app开发使用xamarin-forms方式开发,虽然有一些优势,可以省下开发三个平台共同功能的时间,但是当我们随着项目深入的 ...
- QT全平台设置图标,全平台静态编译 good
1. 概述 当我们用QT写好了一个软件,要把你的程序分享出去的时候,不可能把编译的目录拷贝给别人去运行.编译好的程序应该是一个主程序,加一些资源文件,再加一些动态链接库,高大上一些的还可以做一个安装 ...
- [UWP]在UWP平台中使用Lottie动画
最近QQ影音久违的更新了,因为记得QQ影音之前体验还算不错(FFmepg的事另说),我也第一时间去官网下载体验了一下,结果发现一些有趣的事情. 是的,你没看错,QQ影音主界面上这个动画效果是使用Lot ...
- Unity3d依赖于平台的编译
Unity的这一功能被命名为"依赖于平台的编译". 这包括了一些预编译处理指令,让你能够专门的针对不同的平台分开编译和运行一段代码. 此外,你能够在编辑器下运行一些代码用于測试而不 ...
- webrtc所有平台下载编译步骤详细说明
webrtc所有平台下载编译步骤详细说明 1.安装depot tools Windows:国外下载:https://storage.googleapis.com/chrome-infra/depot_ ...
- DevEco Device Tool 2.1 Beta1 的Hi3861在Windows平台的编译体验
DevEco Device Tool迎来了2.1 Beta1,其中的亮点之一是:支持Hi3861开发板的源码在Windows平台编译.带着浓厚的兴趣,第一时间做了一次体验. 首先在官网下载" ...
- qml支持多平台的编译--尤其对于需要支持xp的情况
http://www.oschina.net/p/deepin-boot-maker 系统支持: Windows平台: Windows 7/ Windows 8 需要安装显卡驱动 Windows XP ...
- Lichee(两) 在sun4i_crane该平台下编译
让我们先来回顾一下编译命令 $ cd workdir/lichee $ ./build.sh -p sun4i_crane -k 3.0 lichee文件夹下的build.sh #!/bin/bas ...
随机推荐
- sudo:must be setuid root 解决方法 <转>
http://walkerqt.blog.51cto.com/1310630/1354103
- TrinityCore3.3.5编译过程-官方指导-踩坑总结
官方指导:主页->how to compile -> windows 指导文档写得很详细,但有不少细节点没提到,这里把过程简化总结,说明重点,及易坑点 1,安装需求 编译工具:cmake, ...
- 【原】Coursera—Andrew Ng机器学习—课程笔记 Lecture 17—Large Scale Machine Learning 大规模机器学习
Lecture17 Large Scale Machine Learning大规模机器学习 17.1 大型数据集的学习 Learning With Large Datasets 如果有一个低方差的模型 ...
- MyBatis 体系结构
- CString 成员函数用法大全
CString的构造函数CString( );例:CString csStr; CString( const CString& stringSrc );例:CString csStr(&quo ...
- 06.Lucen入门程序-Field
需求: 实现一个歌词搜索系统,通过关键字搜索,凡是文件名或文件内容包括关键字的文件都要找出来. 注意:该入门程序只对文本文件(.txt)搜索. Lucene中包含两个重要的类: IndexWriter ...
- KVC的底层实现原理
KVC是OC特有的,本质是在运行时动态的给对象发送setValue:forKey 消息,设置数值 -调用super.init 保证对象已经被创建完成 .当给对象发送setValue:forKey 消息 ...
- 大话CNN
这几年深度学习快速发展,在图像识别.语音识别.物体识别等各种场景上取得了巨大的成功,例如AlphaGo击败世界围棋冠军,iPhone X内置了人脸识别解锁功能等等,很多AI产品在世界上引起了很大的轰动 ...
- 523. Continuous Subarray Sum是否有连续和是某数的几倍
[抄题]: Given a list of non-negative numbers and a target integer k, write a function to check if the ...
- libpcap编程实例
#include <stdio.h> #include <stdlib.h> #include <pcap.h> #include <errno.h> ...