c - qmmp - Qmmp with Jyrki's patches
aboutsummaryrefslogblamecommitdiff
path: root/src/plugins/Transports/http/httpstreamreader.cpp
blob: 29fccc4a683e4c8cabe30ef99337b210eb85d87e (plain) (tree)
1
2
3
                                                                            
                                                                            
                                                                            













                                                                            
                                                                            
                                                                             
                       
                      
               

                     
                   
                   
                              

                              
                             
                            
                             
 

                                           



                                                                    
                                                                    









                                                                                            
                                    





                                                                                                   
                                                                                                            











                                                                        
                                        
                          
                      





                                                                
                                                                    

                                    


                              
                         
     

                                                  


                                                
     
                                                    

                                   
                                            
     
                                                              
                                             
     
        
     
                                                                                                
                                                                                           
                                                
                                                                                        
 
                                 

                                                      
                                               
         



                                               

                          
                     



                                                                                            



                      
                                                                    







                                         


                                                                                                    
 
                                      
                                        
                                                                 
                                
                                                                                              
                                                                        



                                                                  

                                                     
                
                                                  
                                                                                                 

                                             

                        

 
                                     

            
                          
                            
                          
                          
                     
                           
 
                           



                                       

 




















                                              
                                          
 






                                              











                                                       
 





                                                            
 

                   
                   




                              
                                  

                                       
     

                                                                   
         
                                                                                              













                                                           

                     
               

 
                                          



                     
                                 



                    
                                       
 
                                                 

                                                               

 
                              

                   
                    




                         
                            
                     

                             


                                    
                           
     
                       

 
                                               
 
                                                           

 
                            
 
                                                         
                                      
                                                
                                
           
                                                   
     
                                                 


                                                                                              



                                                                               
        
     
                                                         
     
 
                                                 
                                                        

                                                                                     
                                                           
 
                          
                                                                                  





                                                                       
                  
                                                              
                                                          
                            
                                                      



                                                                        
                                                   



                                                          

                                                       
                 
                                                                           
                                                                            

                                                                 
 

                                                                                    


                                                                        


                           
                               
     
                          

                                                                      
                             
                            
                     
                    
                                                 

                                              


                                                                                                 
                                                            
                     
                           
     
 
 
                                                              








                                                                     



                              

 
                                    
 
                                   
               
 
                                             
     
                        
                                          
                        

                                                   



                                                                                 
                                                
                                                                                      
             
                                    
         
                     
     
        
     
                                                                                             

                              

 
                                        
 
                            

                    







                                                          
                         
     
                                       
                          
                                                                 




                                  
                                            
                                                             
                                    

                     
 
 
                                                                










                                                                                                       
                                                            


                                                                             

                                 
         

                                


                                                   

                                                                    




                                                                             
                                                   
                                   









                                                           
                

                                                                                                  
                                            
                                  
                               



                  
 


                                                        
                                                    





                                                                       










                                                                          
/***************************************************************************
 *   Copyright (C) 2006-2020 by Ilya Kotov                                 *
 *   forkotov02@ya.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.,                                       *
 *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.         *
 ***************************************************************************/
#include <QApplication>
#include <QStringList>
#include <QDir>
#include <QSettings>
#include <QTextCodec>
#include <stdint.h>
#include <stdlib.h>
#include <qmmp/qmmpsettings.h>
#include <qmmp/qmmp.h>
#include <qmmp/statehandler.h>
#include <qmmp/inputsource.h>
#include "httpinputsource.h"
#include "httpstreamreader.h"

#define MAX_BUFFER_SIZE 150000000UL //bytes

//curl callbacks
static size_t curl_write_data(void *data, size_t size, size_t nmemb,
                              void *pointer)
{
    HttpStreamReader *dl = static_cast<HttpStreamReader *>(pointer);
    dl->mutex()->lock();

    if(dl->stream()->buf_fill > MAX_BUFFER_SIZE)
    {
        qWarning("HttpStreamReader: buffer has reached the maximum size, disconnecting...");
        dl->stream()->aborted = true;
        dl->mutex()->unlock();
        return 0;
    }

    size_t data_size = size * nmemb;
    if(dl->stream()->buf_fill + data_size > dl->stream()->buf_size)
    {
        char *prev = dl->stream()->buf;
        dl->stream()->buf = (char *)realloc(dl->stream()->buf, dl->stream()->buf_fill + data_size);
        if(!dl->stream()->buf)
        {
            qWarning("HttpStreamReader: unable to allocate %zu bytes",  dl->stream()->buf_fill + data_size);
            if(prev)
                free(prev);

            dl->stream()->buf_fill = 0;
            dl->stream()->buf_size = 0;
            dl->stream()->aborted = true;
            dl->mutex()->unlock();
            return 0;
        }
        dl->stream()->buf_size = dl->stream()->buf_fill + data_size;
    }
    memcpy(dl->stream()->buf + dl->stream()->buf_fill, data, data_size);
    dl->stream()->buf_fill += data_size;
    dl->mutex()->unlock();
    dl->checkBuffer();
    return data_size;
}

static size_t curl_header(void *data, size_t size, size_t nmemb,
                          void *pointer)
{
    HttpStreamReader *dl = static_cast<HttpStreamReader *>(pointer);
    dl->mutex()->lock ();
    size_t data_size = size * nmemb;
    if (data_size < 3)
    {
        dl->mutex()->unlock();
        return data_size;
    }

    //qDebug("header received: %s", (char*) data);
    QByteArray header((char *) data, data_size);
    header = header.trimmed ();
    if (header.left(4).contains("HTTP"))
    {
        qDebug("HttpStreamReader: header received");
        //TODO open metadata socket
    }
    else if (header.left(4).contains("ICY"))
    {
        qDebug("HttpStreamReader: shoutcast header received");
        //dl->stream()->icy_meta_data = true;
    }
    else
    {
        QString key = QString::fromLatin1(header.left(header.indexOf(":")).trimmed().toLower());
        QByteArray value = header.right(header.size() - header.indexOf(":") - 1).trimmed();
        dl->stream()->header.insert(key, value);
        qDebug("HttpStreamReader: key=%s, value=%s",qPrintable(key), value.constData());

        if (key == "icy-metaint")
        {
            dl->stream()->icy_metaint = value.toInt();
            dl->stream()->icy_meta_data = true;
        }
        else if(key == "icy-name")
        {
            dl->stream()->icy_meta_data = true;
        }
    }
    dl->mutex()->unlock();
    return data_size;
}

int curl_progress(void *pointer, double dltotal, double dlnow, double ultotal, double ulnow)
{
    Q_UNUSED(dltotal);
    Q_UNUSED(dlnow);
    Q_UNUSED(ultotal);
    Q_UNUSED(ulnow);
    HttpStreamReader *dl = static_cast<HttpStreamReader *>(pointer);
    dl->mutex()->lock ();
    bool aborted = dl->stream()->aborted;
    dl->mutex()->unlock();
    if (aborted)
        return -1;
    return 0;
}

HttpStreamReader::HttpStreamReader(const QString &url, HTTPInputSource *parent) : QIODevice(parent),
    m_url(url),
    m_parent(parent)
{
    curl_global_init(CURL_GLOBAL_ALL);
    m_thread = new DownloadThread(this);
    QSettings settings(Qmmp::configFile(), QSettings::IniFormat);
    settings.beginGroup("HTTP");
    m_codec = QTextCodec::codecForName(settings.value("icy_encoding","UTF-8").toByteArray ());
    m_prebuffer_size = settings.value("buffer_size",384).toInt() * 1000;
    if(settings.value("override_user_agent",false).toBool())
        m_userAgent = settings.value("user_agent").toString();
    if(m_userAgent.isEmpty())
        m_userAgent = QString("qmmp/%1").arg(Qmmp::strVersion());;
    if (!m_codec)
        m_codec = QTextCodec::codecForName ("UTF-8");
#ifdef WITH_ENCA
    if(settings.value("use_enca", false).toBool())
        m_analyser = enca_analyser_alloc(settings.value("enca_lang").toByteArray ().constData());
    if(m_analyser)
        enca_set_threshold(m_analyser, 1.38);
#endif
    settings.endGroup();
}

HttpStreamReader::~HttpStreamReader()
{
    abort();
    curl_global_cleanup();
    m_stream.aborted = true;
    m_stream.buf_fill = 0;
    m_stream.buf_size = 0;
    if (m_stream.buf)
        free(m_stream.buf);

    m_stream.buf = nullptr;
#ifdef WITH_ENCA
    if(m_analyser)
        enca_analyser_free(m_analyser);
#endif
}

bool HttpStreamReader::atEnd () const
{
    return false;
}

qint64 HttpStreamReader::bytesToWrite () const
{
    return -1;
}

void HttpStreamReader::close ()
{
    abort();
    QIODevice::close();
}

bool HttpStreamReader::isSequential () const
{
    return true;
}

bool HttpStreamReader::open(OpenMode mode)
{
    if(m_ready && mode == QIODevice::ReadOnly)
    {
        QIODevice::open(mode);
        return true;
    }

    return false;
}

bool HttpStreamReader::seek (qint64 pos)
{
    Q_UNUSED(pos);