1 /*****************************************************************************
2 * ml_item.cpp: the media library's result item
3 *****************************************************************************
4 * Copyright (C) 2008-2011 the VideoLAN Team and AUTHORS
7 * Authors: Antoine Lejeune <phytos@videolan.org>
8 * Jean-Philippe André <jpeg@videolan.org>
9 * Rémi Duraffort <ivoire@videolan.org>
10 * Adrien Maglo <magsoft@videolan.org>
11 * Srikanth Raju <srikiraju#gmail#com>
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
26 *****************************************************************************/
37 #include "ml_item.hpp"
42 * @brief Compare the attribute 'meta' between medias a and b.
46 * @note If a->meta < b->meta, return -1
47 * If a->meta == b->meta, return 0
48 * If a->meta > b->meta, return +1
49 * @note If a->meta == NULL and b->meta != NULL (strings), then b>a
51 static int compareMeta( const ml_media_t
*a
, const ml_media_t
*b
,
54 # define scomp(c) ((a->c&&b->c&&*a->c&&*b->c) ? strcasecmp(a->c,b->c) : \
55 (a->c&&*a->c?-1:(b->c&&*b->c?1:0)))
56 # define icomp(c) (a->c<b->c?-1:(a->c==b->c?0:1))
59 case ML_ALBUM
: return scomp( psz_album
);
60 case ML_ALBUM_ID
: return icomp( i_album_id
);
61 //case ML_ARTIST: return scomp( psz_artist );
62 //case ML_ARTIST_ID: return icomp( i_artist_id );
63 case ML_COVER
: return scomp( psz_cover
);
64 case ML_DURATION
: return icomp( i_duration
);
65 case ML_EXTRA
: return scomp( psz_extra
);
66 case ML_GENRE
: return scomp( psz_genre
);
67 case ML_ID
: return icomp( i_id
);
68 case ML_LAST_PLAYED
: return icomp( i_last_played
);
69 case ML_ORIGINAL_TITLE
: return scomp( psz_orig_title
);
70 case ML_PLAYED_COUNT
: return icomp( i_played_count
);
71 // case ML_ROLE: return 0;
72 case ML_SCORE
: return icomp( i_score
);
73 case ML_TITLE
: return scomp( psz_title
);
74 case ML_TRACK_NUMBER
: return icomp( i_track_number
);
75 case ML_TYPE
: return icomp( i_type
);
76 case ML_URI
: return scomp( psz_uri
);
77 case ML_VOTE
: return icomp( i_vote
);
78 case ML_YEAR
: return icomp( i_year
);
86 MLItem::MLItem( const MLModel
*p_model
,
87 intf_thread_t
* _p_intf
,
90 : p_intf( _p_intf
), model( p_model
), children(), parentItem( p_parent
)
93 ml_gc_incref( p_media
);
94 this->media
= p_media
;
95 p_ml
= ml_Get( _p_intf
);
102 ml_gc_decref( this->media
);
103 if( !children
.isEmpty() )
108 * @brief recursively delete all children of this node
109 * @note must be entered after the appropriate beginRemoveRows()
111 void MLItem::clearChildren()
113 // Recursively delete all children
114 qDeleteAll( children
);
118 MLItem
* MLItem::child( int row
) const
120 if( row
< 0 || row
>= childCount() ) return NULL
;
121 else return children
.at( row
);
124 void MLItem::addChild( MLItem
*child
, int row
)
127 children
.insert( row
==-1 ? children
.count() : row
, child
);
130 void MLItem::delChild( int row
)
132 if( !childCount() ) return; // assert ?
134 children
.takeAt( ( row
!=-1 ) ? row
: ( children
.count()-1 ) );
139 int MLItem::rowOfChild( MLItem
*item
) const
141 return children
.indexOf( item
);
144 int MLItem::childCount() const
146 return children
.count();
149 MLItem
* MLItem::parent() const
155 * @brief Get a QVariant representing the data on a column
157 * @return The QVariant may be formed of a int, QString
158 * Use toString() to print it on the screen, except for pixmaps
160 QVariant
MLItem::data( int column
) const
162 ml_select_e type
= model
->columnType( column
);
163 ml_person_t
*p_people
= NULL
, *p_person
= NULL
;
165 #define sreturn(a) if(media->a) return qfu(media->a); break
168 case ML_ALBUM
: sreturn( psz_album
);
169 case ML_ALBUM_ID
: return media
->i_album_id
;
171 p_people
= ml_GetPersonsFromMedia( p_ml
, media
, ML_PERSON_ARTIST
);
175 if( !EMPTY_STR( p_person
->psz_name
) )
177 qsz_return
.isEmpty() ? qsz_return
= qfu( p_person
->psz_name
) :
178 qsz_return
.append( "," ).append( qfu( p_person
->psz_name
) );
180 p_person
= p_person
->p_next
;
182 ml_FreePeople( p_people
);
185 case ML_COVER
: sreturn( psz_cover
);
187 return QTime().addSecs( media
->i_duration
/1000000 ).toString( "HH:mm:ss" );
188 case ML_EXTRA
: sreturn( psz_extra
);
189 case ML_GENRE
: sreturn( psz_genre
);
190 case ML_ID
: return media
->i_id
;
193 if( media
->i_last_played
> 0 )
195 QDateTime
time( QDate(1970,1,1) );
196 return time
.addSecs( qint64( media
->i_last_played
) );
201 case ML_ORIGINAL_TITLE
: sreturn( psz_orig_title
);
202 case ML_PLAYED_COUNT
: return media
->i_played_count
;
203 // case ML_ROLE: return qtr( "Role" );
204 case ML_SCORE
: return media
->i_score
? media
->i_score
: QVariant();
207 /* If no title, return filename */
208 if( !EMPTY_STR( media
->psz_title
) )
209 return qfu( media
->psz_title
);
212 QFileInfo p_file
= QFileInfo( qfu( media
->psz_uri
) );
213 return p_file
.fileName().isEmpty() ? p_file
.absoluteFilePath()
217 case ML_TRACK_NUMBER
: return media
->i_track_number
? media
->i_track_number
: QVariant();
221 if( media
->i_type
& ML_AUDIO
)
223 if( media
->i_type
& ML_VIDEO
)
225 if( media
->i_type
& ML_STREAM
)
227 if( txt
.isEmpty() ) txt
= "Stream";
228 else txt
+= " stream";
230 if( media
->i_type
& ML_REMOVABLE
)
232 if( txt
.isEmpty() ) txt
= "Removable media";
233 else txt
+= " (removable media)";
235 if( media
->i_type
& ML_NODE
)
237 if( txt
.isEmpty() ) txt
= "Playlist";
238 else txt
+= " (Playlist)";
241 txt
= qtr( "Unknown" );
244 case ML_URI
: sreturn( psz_uri
);
245 case ML_VOTE
: return media
->i_vote
? media
->i_vote
: QVariant();
246 case ML_YEAR
: return media
->i_year
? media
->i_year
: QVariant();
247 default: return QVariant();
253 bool MLItem::setData( ml_select_e meta
, const QVariant
&data
)
255 # define setmeta(a) ml_LockMedia(media); free(media->a); \
256 media->a = strdup( qtu(data.toString()) ); ml_UnlockMedia( media ); \
261 case ML_ALBUM
: setmeta( psz_album
);
262 case ML_ARTIST
: ml_DeletePersonTypeFromMedia( media
, ML_PERSON_ARTIST
);
263 ml_CreateAppendPersonAdv( &media
->p_people
,
264 ML_PERSON_ARTIST
, (char*)qtu(data
.toString()), 0 );
265 return ml_UpdateSimple( p_ml
, ML_MEDIA
, NULL
, id(),
266 ML_PEOPLE
, ML_PERSON_ARTIST
, qtu( data
.toString() ) ) == VLC_SUCCESS
;
267 case ML_EXTRA
: setmeta( psz_extra
);
268 case ML_GENRE
: setmeta( psz_genre
);
269 case ML_ORIGINAL_TITLE
: setmeta( psz_orig_title
);
270 case ML_TITLE
: setmeta( psz_title
);
272 return ml_UpdateSimple( p_ml
, ML_MEDIA
, NULL
, id(),
273 meta
, qtu( data
.toString() ) ) == VLC_SUCCESS
;
275 /* Modifiable integers */
276 case ML_TRACK_NUMBER
:
278 return ml_UpdateSimple( p_ml
, ML_MEDIA
, NULL
, id(),
279 meta
, data
.toInt() ) == VLC_SUCCESS
;
281 // TODO case ML_VOTE:
283 /* Non modifiable meta */
290 int MLItem::id() const
295 ml_media_t
* MLItem::getMedia() const
300 QUrl
MLItem::getUri() const
302 if( !media
->psz_uri
) return QUrl(); // This should be rootItem
303 QString uri
= qfu( media
->psz_uri
);
304 if( uri
.contains( "://" ) )
307 return QUrl( "file://" + uri
);
310 bool MLItem::operator<( MLItem
* item
)
312 int ret
= compareMeta( getMedia(), item
->getMedia(), ML_ALBUM
);