aboutsummaryrefslogblamecommitdiff
path: root/src/plugins/Effect/crossfade/crossfadeplugin.h
blob: 340e10f832453552e19b185507833249532e4f97 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
















                                                                            
                                                                            



























                                                                             
                 



                   



                                                                             










                            
/***************************************************************************
 *   Copyright (C) 2010 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.,                                       *
 *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.         *
 ***************************************************************************/
#ifndef CROSSFADEPLUGIN_H
#define CROSSFADEPLUGIN_H

#include <QMutex>
#include <qmmp/effect.h>

class SoundCore;
class StateHandler;

/**
    @author Ilya Kotov <forkotov02@hotmail.ru>
*/

class CrossfadePlugin : public Effect
{
public:
    CrossfadePlugin();

    virtual ~CrossfadePlugin();

    void applyEffect(Buffer *b);
    void configure(quint32 freq, int chan, Qmmp::AudioFormat format);

private:
    enum State
    {
        WAITING = 0,
        CHECKING,
        PREPARING,
        PROCESSING,
    };

    void mix8(uchar *cur_buf, uchar *prev_buf, uint samples, double volume);
    void mix16(uchar *cur_buf, uchar *prev_buf, uint samples, double volume);
    void mix32(uchar *cur_buf, uchar *prev_buf, uint samples, double volume);

    uchar *m_buffer;
    ulong  m_buffer_at;
    ulong  m_buffer_size;
    qint64 m_overlap;
    int m_state;
    SoundCore *m_core;
    StateHandler *m_handler;

};

#endif
+0000 committer trialuser02 <trialuser02@90c681e8-e032-0410-971d-27865f9a5e38> 2012-12-22 10:46:29 +0000 playlist format api cleanup' href='/qmmp/commit/src/qmmpui/playlistparser.cpp?id=954146ff9b69591f0cf3895e96922bb55ad88502'>954146ff9
70339a551
954146ff9

70339a551
cd52bf36b











b2576ddc1

81170fffe
b2576ddc1

aecf85927

b2576ddc1
6cf6bc2f6


aecf85927

954146ff9

b2576ddc1
1e31fe896
a4da0eb5e
81170fffe

a4da0eb5e
b917024aa
a4da0eb5e

aecf85927

845322411
aecf85927


b67a746b1









b2576ddc1
b67a746b1





b2576ddc1
b67a746b1
b67a746b1
b2576ddc1
b67a746b1

b2576ddc1
b67a746b1




b2576ddc1
b67a746b1

463f4e95c
b2576ddc1


b67a746b1
b2576ddc1

b67a746b1
9bdd208bb
1e31fe896
b67a746b1
9bdd208bb
b2576ddc1
9bdd208bb
b67a746b1

9bdd208bb

7bd9c314a
9bdd208bb


b2576ddc1



fc595e1a3
b2576ddc1
6cf6bc2f6


b67a746b1

b2576ddc1
a4da0eb5e
0e9d21145
a4da0eb5e
0e9d21145

1e31fe896
a4da0eb5e
2d7eebdbf
a4da0eb5e

2d7eebdbf
a4da0eb5e
c7848bc54
a4da0eb5e
b917024aa
a4da0eb5e
596a532c6
a4da0eb5e

0e9d21145
a4da0eb5e

da6b743dd







































4ebc220be
da6b743dd




























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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
                                                                            
                                                                            
                                                                            













                                                                            
                                                                            

                                                                             
                        
                
               
                       


                        
                    
                      
                           

                           
                                                            
 























                                                                         
                                                 
 
                  
                      

 
                                         
 
                  
                        
                                                            
     
                                                
     

                   
 











                                                                                                                      

                                                   
                                                                   

 

                                                               
                  


                                                                                                                         

 

                                                                   
                  
                                                      
     

                                                                                       
     
                   

 

                                                          
                                                


                            









                                                                                       
                                                                               





                                                                                                       
                                                                          
 
                              
                                        

                                                             
                                        




                                                                                                       
                                        

     
                                                                     


                        
                                                                        

                      
 
                 
                                            
     
                         
 
                                

                     

                                                                   
 


                               



                  
                                                                                                  
 


                                                                                                             

 
                                  
 
                  
               

                                             
                                                                       
     
                                       

                                            
                                                                                                   
            
                                                                              
 
                                      
                   
                                                         

                
                                   

     







































                                                                                                                                
                                                                                         




























                                                                                                            
/***************************************************************************
 *   Copyright (C) 2008-2021 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 <QPluginLoader>
#include <QList>
#include <QDir>
#include <QApplication>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <algorithm>
#include <qmmp/qmmp.h>
#include "playlistformat.h"
#include "playlistparser.h"

QList<PlayListFormat*> *PlayListParser::m_formats = nullptr;

//key names
const QHash<QString, Qmmp::MetaData>  PlayListParser::m_metaKeys = {
    { "title", Qmmp::TITLE },
    { "artist", Qmmp::ARTIST },
    { "albumArtist", Qmmp::ALBUMARTIST },
    { "album", Qmmp::ALBUM },
    { "comment", Qmmp::COMMENT },
    { "genre", Qmmp::GENRE },
    { "composer", Qmmp::COMPOSER },
    { "year", Qmmp::YEAR },
    { "track", Qmmp::TRACK },
    { "disk", Qmmp::DISCNUMBER }
};

const QHash<QString, Qmmp::TrackProperty>  PlayListParser::m_propKeys = {
    { "bitrate", Qmmp::BITRATE },
    { "samplerate", Qmmp::SAMPLERATE },
    { "channels", Qmmp::CHANNELS },
    { "bitsPerSample", Qmmp::BITS_PER_SAMPLE },
    { "formatName", Qmmp::FORMAT_NAME },
    { "decoder", Qmmp::DECODER },
    { "fileSize", Qmmp::FILE_SIZE }
};

QList<PlayListFormat *> PlayListParser::formats()
{
    loadFormats();
    return *m_formats;
}

QStringList PlayListParser::nameFilters()
{
    loadFormats();
    QStringList filters;
    for(const PlayListFormat *format : qAsConst(*m_formats))
    {
        filters << format->properties().filters;
    }
    return filters;
}

QStringList PlayListParser::filters()
{
    loadFormats();
    QStringList filters;
    for(const PlayListFormat *format : qAsConst(*m_formats))
    {
        if (!format->properties().filters.isEmpty())
            filters << format->properties().shortName.toUpper() + " (" + format->properties().filters.join(" ") + ")";
    }
    return filters;
}

bool PlayListParser::isPlayList(const QString &url)
{
    return QDir::match(nameFilters(), url.section(QChar('/'), -1));
}

PlayListFormat *PlayListParser::findByMime(const QString &mime)
{
    loadFormats();
    auto it = std::find_if(m_formats->cbegin(), m_formats->cend(),
                           [mime](PlayListFormat *format) { return format->properties().contentTypes.contains(mime); } );
    return it == m_formats->cend() ? nullptr : *it;
}

PlayListFormat *PlayListParser::findByPath(const QString &filePath)
{
    loadFormats();
    for(PlayListFormat *format : qAsConst(*m_formats))
    {
        if(QDir::match(format->properties().filters, filePath.section(QChar('/'), -1)))
            return format;
    }
    return nullptr;
}

PlayListFormat *PlayListParser::findByUrl(const QUrl &url)
{
    QString path = url.path(QUrl::FullyEncoded);
    return findByPath(path);
}

void PlayListParser::savePlayList(QList<PlayListTrack *> tracks, const QString &f_name)
{
    if(tracks.isEmpty())
        return;
    PlayListFormat* prs = PlayListParser::findByPath(f_name);
    if (!prs)
        return;
    QFile file(f_name);
    if (file.open(QIODevice::WriteOnly))
    {
        file.write(prs->encode(tracks, QFileInfo(f_name).canonicalFilePath()));
        file.close();
    }
    else
        qWarning("PlayListParser: unable to save playlist, error: %s", qPrintable(file.errorString()));
}

QList<PlayListTrack *> PlayListParser::loadPlaylist(const QString &f_name)
{
    if(!QFile::exists(f_name))
        return QList<PlayListTrack *>();
    PlayListFormat* prs = PlayListParser::findByPath(f_name);
    if(!prs)
        return QList<PlayListTrack *>();

    QFile file(f_name);
    if (!file.open(QIODevice::ReadOnly))
    {
        qWarning("PlayListParser: unable to open playlist, error: %s", qPrintable(file.errorString()));
        return QList<PlayListTrack *>();
    }

    const QList<PlayListTrack*> tracks = prs->decode(file.readAll());

    if(tracks.isEmpty())
    {
        qWarning("PlayListParser: error opening %s",qPrintable(f_name));
        return tracks;
    }

    QString path;
    for(PlayListTrack *t : qAsConst(tracks))
    {
        path = t->path();

        if(path.contains("://"))
            continue;

        if(QFileInfo(path).isRelative())
            path.prepend(QFileInfo(f_name).canonicalPath () + "/");

        path.replace("\\","/");
        path.replace("//","/");
        t->setPath(path);
    }
    return tracks;
}

QList<PlayListTrack *> PlayListParser::loadPlaylist(const QString &fmt, const QByteArray &content)
{
    auto it = std::find_if(m_formats->cbegin(), m_formats->cend(),
                           [fmt](PlayListFormat *format) { return format->properties().shortName == fmt; } );
    return it == m_formats->cend() ? QList<PlayListTrack *>() : (*it)->decode(content);
}

void PlayListParser::loadFormats()
{
    if (m_formats)
        return;

    m_formats = new QList<PlayListFormat*>();
    for(const QString &filePath : Qmmp::findPlugins("PlayListFormats"))
    {
        QPluginLoader loader(filePath);
        QObject *plugin = loader.instance();
        if (loader.isLoaded())
            qDebug("PlayListParser: loaded plugin %s", qPrintable(QFileInfo(filePath).filePath()));
        else
            qWarning("PlayListParser: %s", qPrintable(loader.errorString ()));

        PlayListFormat *fmt = nullptr;
        if (plugin)
            fmt = qobject_cast<PlayListFormat *>(plugin);

        if (fmt)
            m_formats->append(fmt);
    }
}

QByteArray PlayListParser::serialize(const QList<PlayListTrack *> &tracks)
{
    QJsonArray array;
    for(const PlayListTrack *t : qAsConst(tracks))
    {
        QJsonObject obj;
        QString value;
        for(QHash<QString, Qmmp::MetaData>::const_iterator it = m_metaKeys.constBegin(); it != m_metaKeys.constEnd(); ++it)
        {
            if(!(value = t->value(it.value())).isEmpty())
                obj.insert(it.key(), value);
        }

        for(QHash<QString, Qmmp::TrackProperty>::const_iterator it = m_propKeys.constBegin(); it != m_propKeys.constEnd(); ++it)
        {
            if(!(value = t->value(it.value())).isEmpty())
                obj.insert(it.key(), value);
        }

        obj.insert("path", t->path());
        obj.insert("duration", t->duration());
        array.append(obj);
    }

    return QJsonDocument(array).toJson(QJsonDocument::Compact);
}

QList<PlayListTrack *> PlayListParser::deserialize(const QByteArray &json)
{
    QList<PlayListTrack *> out;

    QJsonDocument document = QJsonDocument::fromJson(json);
    if(!document.isArray())
    {
        qWarning("PlayListParser: invalid JSON array");
        return out;
    }

    QJsonArray array = document.array();
    for(QJsonArray::const_iterator it = array.constBegin(); it != array.constEnd(); ++it)
    {
        if(!(*it).isObject())
            continue;

        QJsonObject obj = (*it).toObject();

        if(obj.value("path").isNull())
            continue;

        PlayListTrack *t = new PlayListTrack();
        t->setPath(obj.value("path").toString());
        t->setDuration(obj.value("duration").toDouble());

        Qmmp::MetaData metaKey;
        Qmmp::TrackProperty propKey;

        for(QJsonObject::const_iterator i = obj.constBegin(); i != obj.constEnd(); ++i)
        {
            if((metaKey = m_metaKeys.value(i.key(), Qmmp::UNKNOWN)) != Qmmp::UNKNOWN)
                t->setValue(metaKey, i.value().toString());
            else if((propKey = m_propKeys.value(i.key(), Qmmp::UNKNOWN_PROPERTY)) != Qmmp::UNKNOWN_PROPERTY)
                t->setValue(propKey, i.value().toString());
        }

        out << t;
    }

    return out;
}