1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE TS> <TS version="2.0" language="ru_RU" sourcelanguage="ru_RU"> <context> <name>CoverManager</name> <message> <location filename="../covermanager.cpp" line="36"/> <source>Show Cover</source> <translation>Показать обложку</translation> </message> <message> <location filename="../covermanager.cpp" line="37"/> <source>Ctrl+M</source> <translation type="unfinished"></translation> </message> </context> <context> <name>CoverManagerFactory</name> <message> <location filename="../covermanagerfactory.cpp" line="29"/> <source>Cover Manager Plugin</source> <translation>Модуль упр. обложками</translation> </message/*************************************************************************** * Copyright (C) 2006-2011 by Ilya Kotov * * forkotov02@hotmail.ru * * * * 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 program 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 General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include <QApplication> #include <QSettings> #include <stdint.h> #include <stdlib.h> #include <qmmp/qmmp.h> #include <qmmp/statehandler.h> #include <qmmp/inputsource.h> #include "mmsstreamreader.h" MMSStreamReader::MMSStreamReader(const QString &url, QObject *parent) : QIODevice(parent) { m_url = url; m_handle = 0; m_aborted = false; QSettings settings(Qmmp::configFile(), QSettings::IniFormat); m_prebuf_size = settings.value("MMS/buffer_size",128).toInt() * 1024; m_buffer_size = m_prebuf_size; m_buffer = (char *)malloc(m_buffer_size); m_ready = false; m_buffer_at = 0; m_thread = new DownloadThread(this); } MMSStreamReader::~MMSStreamReader() { qDebug("%s", Q_FUNC_INFO); abort(); free(m_buffer); m_buffer = 0; m_buffer_at = 0; m_buffer_size = 0; } bool MMSStreamReader::atEnd () const { return false; } qint64 MMSStreamReader::bytesToWrite () const { return -1; } void MMSStreamReader::close () { abort(); QIODevice::close(); } bool MMSStreamReader::isSequential () const { return true; } bool MMSStreamReader::open (OpenMode mode) { if (mode != QIODevice::ReadOnly) return false; QIODevice::open(mode); return m_ready; } bool MMSStreamReader::seek (qint64 pos) { Q_UNUSED(pos); return false; } qint64 MMSStreamReader::writeData(const char*, qint64) { return -1; } qint64 MMSStreamReader::readData(char* data, qint64 maxlen) { m_mutex.lock(); qint64 len = qMin<qint64>(m_buffer_at, maxlen); memmove(data, m_buffer, len); m_buffer_at -= len; memmove(m_buffer, m_buffer + len, m_buffer_at); m_mutex.unlock(); return len; } void MMSStreamReader::downloadFile() { m_thread->start(); } QMutex *MMSStreamReader::mutex() { return &m_mutex; } void MMSStreamReader::abort() { m_mutex.lock(); if (m_aborted) { m_mutex.unlock(); return; } m_aborted = true; m_mutex.unlock(); m_thread->wait(); m_ready = false; if (m_handle) mmsx_close(m_handle); m_handle = 0; } qint64 MMSStreamReader::bytesAvailable() const { return QIODevice::bytesAvailable() + m_buffer_at; } void MMSStreamReader::run() { int to_read = 1024; char prebuf[to_read]; m_handle = mmsx_connect (0, 0, m_url.toLocal8Bit().constData(), 128 * 1024); if(!m_handle) { qWarning("MMSStreamReader: connection failed"); setErrorString("connection failed"); emit error(); return; } m_mutex.lock(); if(m_aborted) { m_mutex.unlock(); qDebug("MMSStreamReader: aborted"); return; } m_mutex.unlock(); qint64 len = 0; forever { m_mutex.lock(); if(m_buffer_at + to_read > m_buffer_size) { m_buffer_size = m_buffer_at + to_read; m_buffer = (char *)realloc(m_buffer, m_buffer_size); } m_mutex.unlock(); len = mmsx_read (0, m_handle, prebuf, to_read); m_mutex.lock(); if(len < 0) { m_mutex.unlock(); qWarning("MMSStreamReader: mms thread funished with code %lld (%s)", len, strerror(len)); if(!m_aborted && !m_ready) { setErrorString(strerror(len)); emit error(); } break; } memcpy(m_buffer + m_buffer_at, prebuf, len); m_buffer_at += len; if(!m_ready) checkBuffer(); m_mutex.unlock(); if(m_aborted) break; usleep(5000); } } void MMSStreamReader::checkBuffer() { if (m_buffer_at > m_prebuf_size && !m_ready) { m_ready = true; qDebug("MMSStreamReader: ready"); QMap<Qmmp::MetaData, QString> metaData; metaData.insert(Qmmp::URL, m_url); (qobject_cast<InputSource *>(parent()))->addMetaData(metaData); emit ready(); } else if (!m_ready) { StateHandler::instance()->dispatchBuffer(100 * m_buffer_at / m_buffer_size); qApp->processEvents(); } } DownloadThread::DownloadThread(MMSStreamReader *parent) : QThread(parent) { m_parent = parent; } DownloadThread::~DownloadThread (){} void DownloadThread::run() { m_parent->run(); }