rmff.cpp
来自「Amarok是一款在LINUX或其他类UNIX操作系统中运行的音频播放器软件。 」· C++ 代码 · 共 999 行 · 第 1/3 页
CPP
999 行
/*************************************************************************** copyright : (C) 2005 by Paul Cifarelli email : paulc2@optonline.net ***************************************************************************//*************************************************************************** * 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 * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * 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 St, 5th fl, Boston, MA 02110-1301, * * USA, or check http://www.fsf.org/about/contact.html * * * * Note that no RealNetworks code appears or is duplicated, copied, or * + used as a template in this code. The code was written from scratch * * using the reference documentation found at: * * * * https://common.helixcommunity.org/nonav/2003/HCS_SDK_r5/helixsdk.htm * * * ***************************************************************************/#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <unistd.h>#include <netinet/in.h>#include <taglib.h>#include <id3v1tag.h>#include <id3v2tag.h>#include <tfile.h>#include <fileref.h>#include <iostream>#include <string.h>#include "rmff.h"#define UNPACK4(a, buf, i) memcpy((void *)&a, (void *) &buf[i], 4),i+=4,a=ntohl(a)#define UNPACK2(a, buf, i) memcpy((void *)&a, (void *) &buf[i], 2),i+=2,a=ntohs(a)using namespace TagLib;using namespace TagLib::RealMedia;RMFFile::RMFFile(const char *filename) : File(filename), m_id3tag(0) { if (isOpen()) m_id3tag = new ID3v1::Tag(this, length() - 128); } RMFFile::~RMFFile() { delete m_id3tag; }bool RMFFile::save() { ByteVector bv = m_id3tag->render(); //TODO finish this return false; } String RealMediaFF::title () const{ return !m_err && m_id3v1tag ? m_id3v1tag->tag()->title() : "";}String RealMediaFF::artist () const{ return !m_err && m_id3v1tag ? m_id3v1tag->tag()->artist() : "";}String RealMediaFF::album () const{ return !m_err && m_id3v1tag ? m_id3v1tag->tag()->album() : "";}String RealMediaFF::comment() const{ return !m_err && m_id3v1tag ? m_id3v1tag->tag()->comment() : "";}String RealMediaFF::genre() const{ return !m_err && m_id3v1tag ? m_id3v1tag->tag()->genre() : "";}TagLib::uint RealMediaFF::year() const{ return !m_err && m_id3v1tag ? m_id3v1tag->tag()->year() : 0;}TagLib::uint RealMediaFF::track() const{ return !m_err && m_id3v1tag ? m_id3v1tag->tag()->track() : 0;}// propertiesint RealMediaFF::length () const{ return m_readProperties && !m_err && m_props ? m_props->duration : 0;}int RealMediaFF::bitrate () const{ return m_readProperties && !m_err && m_props ? m_props->avg_bit_rate : 0;}int RealMediaFF::sampleRate () const{ return 0;}int RealMediaFF::channels () const{ return 0; }RealMediaFF::RealMediaFF(const char *file, bool readProperties, AudioProperties::ReadStyle /*propertiesStyle*/): m_filename(0), m_head(0), m_tail(0), m_err(0), m_hdr(0), m_props(0), media_hdrs(0), m_contenthdr(0), m_md(0), m_title(0), m_author(0), m_copyright(0), m_comment(0), m_id3v1tag(0), m_flipYearInMetadataSection(0), m_readProperties(readProperties){ m_filename = strdup(file); m_fd = open(m_filename, O_RDONLY); if (m_fd < 0) { m_err = -1; return; } // ok, for RM files, the properties are embedded, so we ignore propertiesStyle if (m_readProperties) { init(); // and now for the really complicated stuff... if (initMetadataSection()) std::cerr << "ERROR reading Metadata\n"; } // now get the ID3v1 tag at the end of this file m_id3v1tag = new RMFFile(m_filename);}RealMediaFF::RealMediaFF(RealMediaFF &src): m_filename(0), m_head(0), m_tail(0), m_err(0), m_hdr(0), m_props(0), media_hdrs(0), m_contenthdr(0), m_md(0), m_title(0), m_author(0), m_copyright(0), m_comment(0), m_id3v1tag(0), m_flipYearInMetadataSection(0), m_readProperties(src.m_readProperties){ m_filename=strdup(src.m_filename); m_fd = open(m_filename, O_RDONLY); if (m_fd < 0) { m_err = -1; return; } // ok, for RM files, the properties are embedded, so we ignore propertiesStyle if (m_readProperties) { init(); // and now for the really complicated stuff... if (initMetadataSection()) std::cerr << "ERROR reading Metadata\n"; } // now get the ID3v1 tag at the end of this file m_id3v1tag = new RMFFile(m_filename);}RealMediaFF::~RealMediaFF(){ ::free(m_filename); Collectable *hdr = m_head, *next; while (hdr) { next = hdr->fwd; delete hdr; hdr = next; } delete m_id3v1tag; delete m_md; close(m_fd);}bool RealMediaFF::isEmpty() const { return m_id3v1tag->tag()->isEmpty(); } void RealMediaFF::saveHeader(Collectable *hdr){ hdr->fwd = 0; if (!m_head) m_head = m_tail = hdr; else { m_tail->fwd = hdr; m_tail = hdr; }}int RealMediaFF::init(){ int nbytes; unsigned char buf[65536]; UINT32 object_id; UINT32 sz; UINT32 consumed = 0; off_t s; if ( (s = lseek(m_fd, 0, SEEK_SET)) ) { m_err = -1; return m_err; } m_hdr = new File_Header_v0_v1; nbytes = getChunk(buf, 65536, m_hdr->s.object_id, m_hdr->s.size, consumed); if (nbytes < 0 || m_hdr->s.size != consumed || memcmp((void *)&m_hdr->s.object_id, ".RMF", 4)) { //std::cerr << "SERIOUS ERROR - not likely a RealMedia file\n"; m_err = -1; return m_err; } if (!getRealFileHeader(m_hdr, buf, m_hdr->s.object_id, m_hdr->s.size)) { saveHeader(m_hdr); consumed = 0; nbytes = getChunk(buf, 65536, object_id, sz, consumed); if (nbytes < 0 || sz != consumed) { m_err = -1; return m_err; } while (!m_err && memcmp((void *)&object_id, "DATA", 4)) { char oid[5]; memcpy((void *)oid, (void *)&object_id, 4); oid[4] = 0; if (!memcmp((void *)&object_id, "PROP", 4)) { m_props = new RMProperties; getRealPropertyHeader(m_props, buf, object_id, sz); saveHeader(m_props); } if (!memcmp((void *)&object_id, "MDPR", 4)) { media_hdrs = new MediaProperties; getMediaPropHeader(media_hdrs, buf, object_id, sz); saveHeader(media_hdrs); } if (!memcmp((void *)&object_id, "CONT", 4)) { m_contenthdr = new ContentDescription; getContentDescription(m_contenthdr, buf, object_id, sz); saveHeader(m_contenthdr); } consumed = 0; do { nbytes = getChunk(buf, 65536, object_id, sz, consumed); } while ( !m_err && memcmp((void *)&object_id, "DATA", 4) && (consumed < sz) ); } } return 0;}int RealMediaFF::getHdr(unsigned char *buf, size_t sz, UINT32 &fourcc, UINT32 &csz){ int nbytes = 0, i = 0; if (sz < (size_t)RMFF_HDR_SIZE) return 0; if ( (nbytes = read(m_fd, (void *) buf, RMFF_HDR_SIZE)) != RMFF_HDR_SIZE ) { m_err = -1; return (nbytes); } memcpy((void *)&fourcc, buf, 4); i+=4; UNPACK4(csz,buf,i);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?