info_panels.cpp 19.7 KB
Newer Older
1 2 3
/*****************************************************************************
 * infopanels.cpp : Panels for the information dialogs
 ****************************************************************************
4
 * Copyright (C) 2006-2007 the VideoLAN team
5
 * $Id$
6 7
 *
 * Authors: Clément Stenac <zorglub@videolan.org>
8
 *          Jean-Baptiste Kempf <jb@videolan.org>
9
 *          Ilkka Ollakka <ileoo@videolan.org>
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
 *
 * 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.
 *****************************************************************************/
25

26 27 28
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
29 30

#include "qt4.hpp"
31
#include "components/info_panels.hpp"
32
#include "components/interface_widgets.hpp"
33

34 35
#include <assert.h>

36
#include <QTreeWidget>
37 38
#include <QHeaderView>
#include <QList>
39
#include <QStringList>
40
#include <QGridLayout>
41 42 43
#include <QLineEdit>
#include <QLabel>
#include <QSpinBox>
44

45 46 47 48
/************************************************************************
 * Single panels
 ************************************************************************/

49 50 51 52 53 54 55
/**
 * First Panel - Meta Info
 * All the usual MetaData are displayed and can be changed.
 **/
MetaPanel::MetaPanel( QWidget *parent,
                      intf_thread_t *_p_intf )
                      : QWidget( parent ), p_intf( _p_intf )
56
{
57
    QGridLayout *metaLayout = new QGridLayout( this );
58

59
    int line = 0; /* Counter for GridLayout */
60
    p_input = NULL;
61

62
#define ADD_META( string, widget ) {                                      \
63
    metaLayout->addWidget( new QLabel( qtr( string ) + " :" ), line, 0 ); \
64
    widget = new QLineEdit;                                               \
65
    metaLayout->addWidget( widget, line, 1, 1, 9 );                       \
66
    line++;            }
67

68
    /* Title, artist and album*/
69 70
    ADD_META( VLC_META_TITLE, title_text ); /* OK */
    ADD_META( VLC_META_ARTIST, artist_text ); /* OK */
Rafaël Carré's avatar
Rafaël Carré committed
71
    ADD_META( VLC_META_ALBUM, collection_text ); /* OK */
72

73
    /* Genre Name */
74
    /* TODO List id3genres.h is not includable yet ? */
75
    genre_text = new QLineEdit;
76
    metaLayout->addWidget( new QLabel( qtr( VLC_META_GENRE ) + " :" ), line, 0 );
77
    metaLayout->addWidget( genre_text, line, 1, 1, 3 );
78

79
    /* Number - on the same line */
Rafaël Carré's avatar
Rafaël Carré committed
80
    metaLayout->addWidget( new QLabel( qtr( VLC_META_TRACK_NUMBER )  + " :" ),
81
                  line, 5, 1, 2  );
82 83 84
    seqnum_text = new QLineEdit;
    seqnum_text->setInputMask("0000");
    seqnum_text->setAlignment( Qt::AlignRight );
85
    metaLayout->addWidget( seqnum_text, line, 7, 1, 3 );
86
    line++;
87

88
    /* Date (Should be in years) */
89 90 91
    date_text = new QLineEdit;
    date_text->setInputMask("0000");
    date_text->setAlignment( Qt::AlignRight );
92
    metaLayout->addWidget( new QLabel( qtr( VLC_META_DATE ) + " :" ), line, 0 );
93
    metaLayout->addWidget( date_text, line, 1, 1, 3 );
94

95
    /* Rating - on the same line */
96
    /*
97
    metaLayout->addWidget( new QLabel( qtr( VLC_META_RATING ) + " :" ), line, 4, 1, 2 );
98
    rating_text = new QSpinBox; setSpinBounds( rating_text );
99
    metaLayout->addWidget( rating_text, line, 6, 1, 1 );
100
    */
101
    /* Language on the same line */
102
    metaLayout->addWidget( new QLabel( qfu( VLC_META_LANGUAGE ) + " :" ), line, 5, 1, 2 );
103
    language_text = new QLineEdit;
104
    language_text->setReadOnly( true );
105
    metaLayout->addWidget( language_text, line,  7, 1, 3 );
106
    line++;
107

108
    /* ART_URL */
109
    art_cover = new CoverArtLabel( this, p_intf );
110
    metaLayout->addWidget( art_cover, line, 8, 4, 2, Qt::AlignRight );
111

112
/* Settings is unused */
113
/*    l->addWidget( new QLabel( qtr( VLC_META_SETTING ) + " :" ), line, 5 );
114
    setting_text = new QLineEdit;
115
    l->addWidget( setting_text, line, 6, 1, 4 ); */
116

117
/* Less used metadata */
118
#define ADD_META_2( string, widget ) {                                    \
119
    metaLayout->addWidget( new QLabel( qtr( string ) + " :" ), line, 0 ); \
120
    widget = new QLineEdit;                                               \
121
    metaLayout->addWidget( widget, line, 1, 1, 7 );                       \
122
    line++;            }
123

124 125 126
    /* Now Playing - Useful for live feeds (HTTP, DVB, ETC...) */
    ADD_META_2( VLC_META_NOW_PLAYING, nowplaying_text );
    nowplaying_text->setReadOnly( true );
127
    ADD_META_2( VLC_META_PUBLISHER, publisher_text );
128
    ADD_META_2( VLC_META_COPYRIGHT, copyright_text );
Christophe Mutricy's avatar
Christophe Mutricy committed
129
    ADD_META_2( N_("Comments"), description_text );
130

131 132 133
/* useless metadata */

    //ADD_META_2( VLC_META_ENCODED_BY, encodedby_text );
134
    /*  ADD_META( TRACKID )  Useless ? */
135
    /*  ADD_URI - DO not show it, done outside */
136

137 138
    metaLayout->setColumnStretch( 1, 2 );
    metaLayout->setColumnMinimumWidth ( 1, 80 );
139
#undef ADD_META
140 141 142 143 144 145 146
#undef ADD_META_2

    CONNECT( title_text, textEdited( QString ), this, enterEditMode() );
    CONNECT( artist_text, textEdited( QString ), this, enterEditMode() );
    CONNECT( collection_text, textEdited( QString ), this, enterEditMode() );
    CONNECT( genre_text, textEdited( QString ), this, enterEditMode() );
    CONNECT( seqnum_text, textEdited( QString ), this, enterEditMode() );
147

148 149
    CONNECT( date_text, textEdited( QString ), this, enterEditMode() );
    CONNECT( description_text, textEdited( QString ), this, enterEditMode() );
150 151 152 153
/*    CONNECT( rating_text, valueChanged( QString ), this, enterEditMode( QString ) );*/

    /* We are not yet in Edit Mode */
    b_inEditMode = false;
154
}
155

156 157 158
/**
 * Update all the MetaData and art on an "item-changed" event
 **/
159
void MetaPanel::update( input_item_t *p_item )
160
{
161 162 163 164 165
    if( !p_item )
    {
        clear();
        return;
    }
166

167 168
    /* Don't update if you are in edit mode */
    if( b_inEditMode ) return;
169
    else p_input = p_item;
170

171
    char *psz_meta;
172
#define UPDATE_META( meta, widget ) {               \
173
    psz_meta = input_item_Get##meta( p_item );      \
174 175 176
    if( !EMPTY_STR( psz_meta ) )                    \
        widget->setText( qfu( psz_meta ) );         \
    else                                            \
177 178
        widget->setText( "" ); }                    \
    free( psz_meta );
179

180
#define UPDATE_META_INT( meta, widget ) {           \
181
    psz_meta = input_item_Get##meta( p_item );      \
182
    if( !EMPTY_STR( psz_meta ) )                    \
183 184 185
        widget->setValue( atoi( psz_meta ) ); }     \
    free( psz_meta );

186
    /* Name / Title */
187
    psz_meta = input_item_GetTitle( p_item );
188
    char *psz_name = input_item_GetName( p_item );
189 190
    if( !EMPTY_STR( psz_meta ) )
        title_text->setText( qfu( psz_meta ) );
191 192
    else if( !EMPTY_STR( psz_name ) )
        title_text->setText( qfu( psz_name ) );
193
    else title_text->setText( "" );
194
    free( psz_meta );
195
    free( psz_name );
196

197
    /* URL / URI */
198
    psz_meta = input_item_GetURL( p_item );
199
    if( !EMPTY_STR( psz_meta ) )
200
        emit uriSet( psz_meta );
201 202 203 204 205
    else
    {
        free( psz_meta );
        psz_meta = input_item_GetURI( p_item );
        if( !EMPTY_STR( psz_meta ) )
206
            emit uriSet( psz_meta );
207
    }
Rémi Duraffort's avatar
Rémi Duraffort committed
208
    free( psz_meta );
209

210
    /* Other classic though */
211 212
    UPDATE_META( Artist, artist_text );
    UPDATE_META( Genre, genre_text );
213
    UPDATE_META( Copyright, copyright_text );
214
    UPDATE_META( Album, collection_text );
215
    UPDATE_META( Description, description_text );
216
    UPDATE_META( Language, language_text );
217 218
    UPDATE_META( NowPlaying, nowplaying_text );
    UPDATE_META( Publisher, publisher_text );
219 220
//    UPDATE_META( Setting, setting_text );
//    UPDATE_META( EncodedBy, encodedby_text );
221

222 223
    UPDATE_META( Date, date_text );
    UPDATE_META( TrackNum, seqnum_text );
224
//    UPDATE_META_INT( Rating, rating_text );
225 226

#undef UPDATE_META_INT
227
#undef UPDATE_META
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
/**
 * Save the MetaData, triggered by parent->save Button
 **/
void MetaPanel::saveMeta()
{
    playlist_t *p_playlist;

    meta_export_t p_export;
    p_export.p_item = p_input;

    if( p_input == NULL )
        return;

    /* we can write meta data only in a file */
    vlc_mutex_lock( &p_input->lock );
    int i_type = p_input->i_type;
    vlc_mutex_unlock( &p_input->lock );
    if( i_type == ITEM_TYPE_FILE )
    {
        char *psz_uri_orig = input_item_GetURI( p_input );
        char *psz_uri = psz_uri_orig;
        if( !strncmp( psz_uri, "file://", 7 ) )
            psz_uri += 7; /* strlen("file://") = 7 */

        p_export.psz_file = strndup( psz_uri, PATH_MAX );
        free( psz_uri_orig );
    }
    else
        return;

    /* now we read the modified meta data */
262
    input_item_SetTitle(  p_input, qtu( title_text->text() ) );
263 264 265 266
    input_item_SetArtist( p_input, qtu( artist_text->text() ) );
    input_item_SetAlbum(  p_input, qtu( collection_text->text() ) );
    input_item_SetGenre(  p_input, qtu( genre_text->text() ) );
    input_item_SetTrackNum(  p_input, qtu( seqnum_text->text() ) );
267
    input_item_SetDate(  p_input, qtu( date_text->text() ) );
268

269 270 271
    input_item_SetCopyright( p_input, qtu( copyright_text->text() ) );
    input_item_SetPublisher( p_input, qtu( publisher_text->text() ) );
    input_item_SetDescription( p_input, qtu( description_text->text() ) );
272

Antoine Cellerier's avatar
Antoine Cellerier committed
273
    p_playlist = pl_Hold( p_intf );
274 275 276
    PL_LOCK;
    p_playlist->p_private = &p_export;

277
    module_t *p_mod = module_need( p_playlist, "meta writer", NULL, false );
278
    if( p_mod )
279
        module_unneed( p_playlist, p_mod );
280
    PL_UNLOCK;
281
    pl_Release( p_intf );
282

283 284
    /* Reset the status of the mode. No need to emit any signal because parent
       is the only caller */
285 286 287 288 289 290 291 292 293 294 295
    b_inEditMode = false;
}


bool MetaPanel::isInEditMode()
{
    return b_inEditMode;
}

void MetaPanel::enterEditMode()
{
296
    msg_Dbg( p_intf, "Entering Edit MetaData Mode" );
297 298 299 300 301 302 303 304 305
    setEditMode( true );
}

void MetaPanel::setEditMode( bool b_editing )
{
    b_inEditMode = b_editing;
    if( b_editing )emit editing();
}

306 307 308
/*
 * Clear all the metadata widgets
 */
309 310 311 312 313 314 315 316 317 318 319 320 321 322
void MetaPanel::clear()
{
    title_text->clear();
    artist_text->clear();
    genre_text->clear();
    copyright_text->clear();
    collection_text->clear();
    seqnum_text->clear();
    description_text->clear();
    date_text->clear();
    language_text->clear();
    nowplaying_text->clear();
    publisher_text->clear();

323
    setEditMode( false );
324
    emit uriSet( "" );
325
}
326

327 328 329 330 331 332
/**
 * Second Panel - Shows the extra metadata in a tree, non editable.
 **/
ExtraMetaPanel::ExtraMetaPanel( QWidget *parent,
                                intf_thread_t *_p_intf )
                                : QWidget( parent ), p_intf( _p_intf )
333 334
{
     QGridLayout *layout = new QGridLayout(this);
335

336
     QLabel *topLabel = new QLabel( qtr( "Extra metadata and other information"
337
                 " are shown in this panel.\n" ) );
338 339 340 341 342 343
     topLabel->setWordWrap( true );
     layout->addWidget( topLabel, 0, 0 );

     extraMetaTree = new QTreeWidget( this );
     extraMetaTree->setAlternatingRowColors( true );
     extraMetaTree->setColumnCount( 2 );
344
     extraMetaTree->resizeColumnToContents( 0 );
345
     extraMetaTree->header()->hide();
346 347 348 349
/*     QStringList headerList = ( QStringList() << qtr( "Type" )
 *                                             << qtr( "Value" ) );
 * Useless, add this header if you think it would help the user          **
 */
350 351 352 353

     layout->addWidget( extraMetaTree, 1, 0 );
}

354
/**
355
 * Update the Extra Metadata from p_meta->i_extras
356
 **/
357
void ExtraMetaPanel::update( input_item_t *p_item )
358
{
359 360 361 362 363
    if( !p_item )
    {
        clear();
        return;
    }
364

365 366 367 368
    QList<QTreeWidgetItem *> items;

    extraMetaTree->clear();

369
    vlc_mutex_lock( &p_item->lock );
370
    vlc_meta_t *p_meta = p_item->p_meta;
371
    if( !p_meta )
372 373
    {
        vlc_mutex_unlock( &p_item->lock );
374
        return;
375
    }
376

377 378
    vlc_dictionary_t * p_dict = &p_meta->extra_tags;
    char ** ppsz_allkey = vlc_dictionary_all_keys( p_dict );
379 380

    for( int i = 0; ppsz_allkey[i] ; i++ )
381
    {
382 383
        const char * psz_value = (const char *)vlc_dictionary_value_for_key(
                p_dict, ppsz_allkey[i] );
384
        QStringList tempItem;
385
        tempItem.append( qfu( ppsz_allkey[i] ) + " : ");
386
        tempItem.append( qfu( psz_value ) );
387
        items.append( new QTreeWidgetItem ( extraMetaTree, tempItem ) );
388
        free( ppsz_allkey[i] );
389
    }
390
    vlc_mutex_unlock( &p_item->lock );
391
    free( ppsz_allkey );
392

393
    extraMetaTree->addTopLevelItems( items );
394
    extraMetaTree->resizeColumnToContents( 0 );
395 396
}

397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417
/**
 * Clear the ExtraMetaData Tree
 **/
void ExtraMetaPanel::clear()
{
    extraMetaTree->clear();
}

/**
 * Third panel - Stream info
 * Display all codecs and muxers info that we could gather.
 **/
InfoPanel::InfoPanel( QWidget *parent,
                      intf_thread_t *_p_intf )
                      : QWidget( parent ), p_intf( _p_intf )
{
     QGridLayout *layout = new QGridLayout(this);

     QList<QTreeWidgetItem *> items;

     QLabel *topLabel = new QLabel( qtr( "Information about what your media or"
418
              " stream is made of.\nMuxer, Audio and Video Codecs, Subtitles "
419 420 421 422 423 424 425 426 427 428 429 430 431 432 433
              "are shown." ) );
     topLabel->setWordWrap( true );
     layout->addWidget( topLabel, 0, 0 );

     InfoTree = new QTreeWidget(this);
     InfoTree->setColumnCount( 1 );
     InfoTree->header()->hide();
     layout->addWidget(InfoTree, 1, 0 );
}

/**
 * Update the Codecs information on parent->update()
 **/
void InfoPanel::update( input_item_t *p_item)
{
434 435 436 437 438
    if( !p_item )
    {
        clear();
        return;
    }
439

440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456
    InfoTree->clear();
    QTreeWidgetItem *current_item = NULL;
    QTreeWidgetItem *child_item = NULL;

    for( int i = 0; i< p_item->i_categories ; i++)
    {
        current_item = new QTreeWidgetItem();
        current_item->setText( 0, qfu(p_item->pp_categories[i]->psz_name) );
        InfoTree->addTopLevelItem( current_item );

        for( int j = 0 ; j < p_item->pp_categories[i]->i_infos ; j++ )
        {
            child_item = new QTreeWidgetItem ();
            child_item->setText( 0,
                    qfu(p_item->pp_categories[i]->pp_infos[j]->psz_name)
                    + ": "
                    + qfu(p_item->pp_categories[i]->pp_infos[j]->psz_value));
457

458 459 460 461 462
            current_item->addChild(child_item);
        }
         InfoTree->setItemExpanded( current_item, true);
    }
}
463

464 465 466 467 468 469 470 471 472 473 474 475 476 477
/**
 * Clear the tree
 **/
void InfoPanel::clear()
{
    InfoTree->clear();
}

/**
 * Save all the information to a file
 * Not yet implemented.
 **/
/*
void InfoPanel::saveCodecsInfo()
478
{}
479 480 481 482 483 484 485 486 487
*/

/**
 * Fourth Panel - Stats
 * Displays the Statistics for reading/streaming/encoding/displaying in a tree
 */
InputStatsPanel::InputStatsPanel( QWidget *parent,
                                  intf_thread_t *_p_intf )
                                  : QWidget( parent ), p_intf( _p_intf )
488 489
{
     QGridLayout *layout = new QGridLayout(this);
490

491
     QList<QTreeWidgetItem *> items;
492

493 494
     QLabel *topLabel = new QLabel( qtr( "Statistics about the currently "
                 "playing media or stream." ) );
495 496
     topLabel->setWordWrap( true );
     layout->addWidget( topLabel, 0, 0 );
497

498
     StatsTree = new QTreeWidget(this);
499 500 501 502
     StatsTree->setColumnCount( 3 );
     StatsTree->header()->hide();

#define CREATE_TREE_ITEM( itemName, itemText, itemValue, unit ) {              \
503 504
    itemName =                                                                 \
      new QTreeWidgetItem((QStringList () << itemText << itemValue << unit )); \
505 506 507 508 509 510 511
    itemName->setTextAlignment( 1 , Qt::AlignRight ) ; }

#define CREATE_CATEGORY( catName, itemText ) {                           \
    CREATE_TREE_ITEM( catName, itemText , "", "" );                      \
    catName->setExpanded( true );                                        \
    StatsTree->addTopLevelItem( catName );    }

512 513
#define CREATE_AND_ADD_TO_CAT( itemName, itemText, itemValue, catName, unit ){ \
    CREATE_TREE_ITEM( itemName, itemText, itemValue, unit );                   \
514 515
    catName->addChild( itemName ); }

516
    /* Create the main categories */
517
    CREATE_CATEGORY( audio, qtr("Audio") );
518
    CREATE_CATEGORY( video, qtr("Video") );
519
    CREATE_CATEGORY( input, qtr("Input") );
520 521
    CREATE_CATEGORY( streaming, qtr("Streaming") );

522 523 524 525
    CREATE_AND_ADD_TO_CAT( read_media_stat, qtr("Read at media"),
                           "0", input , "kB" );
    CREATE_AND_ADD_TO_CAT( input_bitrate_stat, qtr("Input bitrate"),
                           "0", input, "kb/s" );
526
    CREATE_AND_ADD_TO_CAT( demuxed_stat, qtr("Demuxed"), "0", input, "kB") ;
527 528
    CREATE_AND_ADD_TO_CAT( stream_bitrate_stat, qtr("Stream bitrate"),
                           "0", input, "kb/s" );
529 530 531 532
    CREATE_AND_ADD_TO_CAT( corrupted_stat, qtr("Corrupted"),
                           "0", input, "" );
    CREATE_AND_ADD_TO_CAT( discontinuity_stat, qtr("Discontinuities"),
                           "0", input, "" );
533 534 535 536 537 538 539 540 541 542 543

    CREATE_AND_ADD_TO_CAT( vdecoded_stat, qtr("Decoded blocks"),
                           "0", video, "" );
    CREATE_AND_ADD_TO_CAT( vdisplayed_stat, qtr("Displayed frames"),
                           "0", video, "" );
    CREATE_AND_ADD_TO_CAT( vlost_frames_stat, qtr("Lost frames"),
                           "0", video, "" );

    CREATE_AND_ADD_TO_CAT( send_stat, qtr("Sent packets"), "0", streaming, "" );
    CREATE_AND_ADD_TO_CAT( send_bytes_stat, qtr("Sent bytes"),
                           "0", streaming, "kB" );
544
    CREATE_AND_ADD_TO_CAT( send_bitrate_stat, qtr("Sent bitrate"),
545 546 547 548 549 550 551
                           "0", streaming, "kb/s" );

    CREATE_AND_ADD_TO_CAT( adecoded_stat, qtr("Decoded blocks"),
                           "0", audio, "" );
    CREATE_AND_ADD_TO_CAT( aplayed_stat, qtr("Played buffers"),
                           "0", audio, "" );
    CREATE_AND_ADD_TO_CAT( alost_stat, qtr("Lost buffers"), "0", audio, "" );
552 553 554 555 556 557 558

    input->setExpanded( true );
    video->setExpanded( true );
    streaming->setExpanded( true );
    audio->setExpanded( true );

    StatsTree->resizeColumnToContents( 0 );
559
    StatsTree->setColumnWidth( 1 , 200 );
560 561

    layout->addWidget(StatsTree, 1, 0 );
562 563
}

564 565 566
/**
 * Update the Statistics
 **/
567 568
void InputStatsPanel::update( input_item_t *p_item )
{
569
    assert( p_item );
570 571 572 573 574
    vlc_mutex_lock( &p_item->p_stats->lock );

#define UPDATE( widget, format, calc... ) \
    { QString str; widget->setText( 1 , str.sprintf( format, ## calc ) );  }

575 576
    UPDATE( read_media_stat, "%8.0f",
            (float)(p_item->p_stats->i_read_bytes)/1000);
577 578 579 580 581 582
    UPDATE( input_bitrate_stat, "%6.0f",
                    (float)(p_item->p_stats->f_input_bitrate * 8000 ));
    UPDATE( demuxed_stat, "%8.0f",
                    (float)(p_item->p_stats->i_demux_read_bytes)/1000 );
    UPDATE( stream_bitrate_stat, "%6.0f",
                    (float)(p_item->p_stats->f_demux_bitrate * 8000 ));
583 584
    UPDATE( corrupted_stat, "%5i", p_item->p_stats->i_demux_corrupted );
    UPDATE( discontinuity_stat, "%5i", p_item->p_stats->i_demux_discontinuity );
585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608

    /* Video */
    UPDATE( vdecoded_stat, "%5i", p_item->p_stats->i_decoded_video );
    UPDATE( vdisplayed_stat, "%5i", p_item->p_stats->i_displayed_pictures );
    UPDATE( vlost_frames_stat, "%5i", p_item->p_stats->i_lost_pictures );

    /* Sout */
    UPDATE( send_stat, "%5i", p_item->p_stats->i_sent_packets );
    UPDATE( send_bytes_stat, "%8.0f",
            (float)(p_item->p_stats->i_sent_bytes)/1000 );
    UPDATE( send_bitrate_stat, "%6.0f",
            (float)(p_item->p_stats->f_send_bitrate*8)*1000 );

    /* Audio*/
    UPDATE( adecoded_stat, "%5i", p_item->p_stats->i_decoded_audio );
    UPDATE( aplayed_stat, "%5i", p_item->p_stats->i_played_abuffers );
    UPDATE( alost_stat, "%5i", p_item->p_stats->i_lost_abuffers );

    vlc_mutex_unlock(& p_item->p_stats->lock );
}

void InputStatsPanel::clear()
{
}
609