X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fgui%2Fmacosx%2Fplaylistinfo.m;h=83c11b375b7b62c2faffbb3016ce1788f1922b97;hb=f0dc54ba5d8a5219692b5fac17fe26a4eb11eadd;hp=1dbade792449ab0b4abc8ea0e7ce496f6eeac599;hpb=48ad6e8d7529ff1c3b4ceb4416b1a0b547ea91ac;p=vlc diff --git a/modules/gui/macosx/playlistinfo.m b/modules/gui/macosx/playlistinfo.m index 1dbade7924..83c11b375b 100644 --- a/modules/gui/macosx/playlistinfo.m +++ b/modules/gui/macosx/playlistinfo.m @@ -1,10 +1,11 @@ /***************************************************************************** r playlistinfo.m: MacOS X interface module ***************************************************************************** - * Copyright (C) 2002-2004 VideoLAN + * Copyright (C) 2002-2007 the VideoLAN team * $Id$ * * Authors: Benjamin Pracht + * Felix Kühne * * 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 @@ -18,7 +19,7 @@ * * 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, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ /***************************************************************************** @@ -41,41 +42,95 @@ if( self != nil ) { - i_item = -1; - o_selected = NULL; + p_item = NULL; + o_statUpdateTimer = nil; } return( self ); } -- (void)dealloc -{ - [o_selected release]; - [super dealloc]; -} - - (void)awakeFromNib { [o_info_window setExcludedFromWindowsMenu: TRUE]; - [o_info_window setTitle: _NS("Properties")]; + [o_info_window setTitle: _NS("Information")]; [o_uri_lbl setStringValue: _NS("URI")]; [o_title_lbl setStringValue: _NS("Title")]; [o_author_lbl setStringValue: _NS("Author")]; [o_btn_ok setTitle: _NS("OK")]; [o_btn_cancel setTitle: _NS("Cancel")]; + + [[o_tab_view tabViewItemAtIndex: 0] setLabel: _NS("General")]; + [[o_tab_view tabViewItemAtIndex: 1] setLabel: _NS("Advanced Information")]; + [[o_tab_view tabViewItemAtIndex: 2] setLabel: _NS("Statistics")]; + [o_tab_view selectTabViewItemAtIndex: 0]; + + /* constants defined in vlc_meta.h */ + [o_genre_lbl setStringValue: _NS(VLC_META_GENRE)]; + [o_copyright_lbl setStringValue: _NS(VLC_META_COPYRIGHT)]; + [o_collection_lbl setStringValue: _NS(VLC_META_COLLECTION)]; + [o_seqNum_lbl setStringValue: _NS(VLC_META_SEQ_NUM)]; + [o_description_lbl setStringValue: _NS(VLC_META_DESCRIPTION)]; + [o_rating_lbl setStringValue: _NS(VLC_META_RATING)]; + [o_date_lbl setStringValue: _NS(VLC_META_DATE)]; + [o_language_lbl setStringValue: _NS(VLC_META_LANGUAGE)]; + [o_nowPlaying_lbl setStringValue: _NS(VLC_META_NOW_PLAYING)]; + [o_publisher_lbl setStringValue: _NS(VLC_META_PUBLISHER)]; + + /* statistics */ + [o_input_box setTitle: _NS("Input")]; + [o_read_bytes_lbl setStringValue: _NS("Read at media")]; + [o_input_bitrate_lbl setStringValue: _NS("Input bitrate")]; + [o_demux_bytes_lbl setStringValue: _NS("Demuxed")]; + [o_demux_bitrate_lbl setStringValue: _NS("Stream bitrate")]; + + [o_video_box setTitle: _NS("Video")]; + [o_video_decoded_lbl setStringValue: _NS("Decoded blocks")]; + [o_displayed_lbl setStringValue: _NS("Displayed frames")]; + [o_lost_frames_lbl setStringValue: _NS("Lost frames")]; + + [o_sout_box setTitle: _NS("Streaming")]; + [o_sent_packets_lbl setStringValue: _NS("Sent packets")]; + [o_sent_bytes_lbl setStringValue: _NS("Sent bytes")]; + [o_sent_bitrate_lbl setStringValue: _NS("Send rate")]; + + [o_audio_box setTitle: _NS("Audio")]; + [o_audio_decoded_lbl setStringValue: _NS("Decoded blocks")]; + [o_played_abuffers_lbl setStringValue: _NS("Played buffers")]; + [o_lost_abuffers_lbl setStringValue: _NS("Lost buffers")]; +} + +- (void)dealloc +{ + /* make sure that the timer is released in any case */ + if( [o_statUpdateTimer isValid] ) + [o_statUpdateTimer invalidate]; + + if ( o_statUpdateTimer ) + [o_statUpdateTimer release]; + + [super dealloc]; } +#if GC_ENABLED +- (void)finalize +{ + /* since dealloc isn't called with enabled GC on 10.5, we need this to prevent core crashes */ + if( [o_statUpdateTimer isValid] ) + [o_statUpdateTimer invalidate]; + [super finalize]; +} +#endif + - (IBAction)togglePlaylistInfoPanel:(id)sender { if( [o_info_window isVisible] ) { + [self windowShouldClose: nil]; [o_info_window orderOut: sender]; } else { - i_item = [[[VLCMain sharedInstance] getPlaylist] selectedPlaylistItem]; - o_selected = [[[VLCMain sharedInstance] getPlaylist] selectedPlaylistItemsList]; - [o_selected retain]; + p_item = [[[VLCMain sharedInstance] getPlaylist] selectedPlaylistItem]; [self initPanel:sender]; } } @@ -84,104 +139,208 @@ { if( [o_info_window isVisible] ) { + [self windowShouldClose: nil]; [o_info_window orderOut: sender]; } else { intf_thread_t * p_intf = VLCIntf; - playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, - FIND_ANYWHERE ); + playlist_t * p_playlist = pl_Yield( p_intf ); - if (p_playlist) - { - i_item = p_playlist->i_index; - o_selected = [NSMutableArray arrayWithObject: - [NSNumber numberWithInt:i_item]]; - [o_selected retain]; - vlc_object_release(p_playlist); - } + p_item = p_playlist->status.p_item; + vlc_object_release( p_playlist ); + [self initPanel:sender]; } } - (void)initPanel:(id)sender { + BOOL b_stats = config_GetInt(VLCIntf, "stats"); + if( b_stats ) + { + o_statUpdateTimer = [NSTimer scheduledTimerWithTimeInterval: 1 + target: self selector: @selector(updateStatistics:) + userInfo: nil repeats: YES]; + [o_statUpdateTimer fire]; + [o_statUpdateTimer retain]; + } + else + { + if( [o_tab_view numberOfTabViewItems] > 2 ) + [o_tab_view removeTabViewItem: [o_tab_view tabViewItemAtIndex: 2]]; + } + + [self updatePanel]; + [o_info_window makeKeyAndOrderFront: sender]; +} + +- (void)updatePanel +{ + /* make sure that we got the current item and not an outdated one */ intf_thread_t * p_intf = VLCIntf; - playlist_t * p_playlist; + playlist_t * p_playlist = pl_Yield( p_intf ); - p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, - FIND_ANYWHERE ); + p_item = p_playlist->status.p_item; + vlc_object_release( p_playlist ); + /* check whether our item is valid, because we would crash if not */ + if(! [self isItemInPlaylist: p_item] ) return; - if( p_playlist ) - { - char *psz_temp; + vlc_mutex_lock( &p_item->p_input->lock ); - /*fill uri / title / author info */ + /* fill uri info */ + if( p_item->p_input->psz_uri ) + { [o_uri_txt setStringValue: - ([NSString stringWithUTF8String:p_playlist-> - pp_items[i_item]->input.psz_uri] == nil ) ? - [NSString stringWithCString:p_playlist-> - pp_items[i_item]->input.psz_uri] : - [NSString stringWithUTF8String:p_playlist-> - pp_items[i_item]->input.psz_uri]]; - - [o_title_txt setStringValue: - ([NSString stringWithUTF8String:p_playlist-> - pp_items[i_item]->input.psz_name] == nil ) ? - [NSString stringWithCString:p_playlist-> - pp_items[i_item]->input.psz_name] : - [NSString stringWithUTF8String:p_playlist-> - pp_items[i_item]->input.psz_name]]; - - psz_temp = playlist_GetInfo( p_playlist, i_item ,_("General"),_("Author") ); - [o_author_txt setStringValue: [NSString stringWithUTF8String: psz_temp]]; - free( psz_temp ); - - [[VLCInfoTreeItem rootItem] refresh]; - [o_outline_view reloadData]; + ([NSString stringWithUTF8String:p_item->p_input->psz_uri] == nil ) ? + [NSString stringWithCString:p_item->p_input->psz_uri] : + [NSString stringWithUTF8String:p_item->p_input->psz_uri]]; + } - vlc_object_release( p_playlist ); + /* fill the other fields */ +#define p_m p_item->p_input->p_meta + [self setMeta: p_m->psz_title forLabel: o_title_txt]; + [self setMeta: p_m->psz_artist forLabel: o_author_txt]; + [self setMeta: p_m->psz_album forLabel: o_collection_txt]; + [self setMeta: p_m->psz_tracknum forLabel: o_seqNum_txt]; + [self setMeta: p_m->psz_genre forLabel: o_genre_txt]; + [self setMeta: p_m->psz_copyright forLabel: o_copyright_txt]; + [self setMeta: p_m->psz_rating forLabel: o_rating_txt]; + [self setMeta: p_m->psz_publisher forLabel: o_publisher_txt]; + [self setMeta: p_m->psz_nowplaying forLabel: o_nowPlaying_txt]; + [self setMeta: p_m->psz_language forLabel: o_language_txt]; + [self setMeta: p_m->psz_date forLabel: o_date_txt]; +#undef p_m + vlc_mutex_unlock( &p_item->p_input->lock ); + + /* reload the advanced table */ + [[VLCInfoTreeItem rootItem] refresh]; + [o_outline_view reloadData]; + + /* update the stats once to display p_item change faster */ + [self updateStatistics: nil]; +} + +- (void)setMeta: (char *)psz_meta forLabel: (id)theItem +{ + if( psz_meta != NULL && *psz_meta) + [theItem setStringValue: + ([NSString stringWithUTF8String:psz_meta] == nil ) ? + [NSString stringWithCString:psz_meta] : + [NSString stringWithUTF8String:psz_meta]]; + else + [theItem setStringValue: @"-"]; +} + +- (void)updateStatistics:(NSTimer*)theTimer +{ + if( [self isItemInPlaylist: p_item] ) + { + /* we can only do that if there's a valid input around */ + + vlc_mutex_lock( &p_item->p_input->p_stats->lock ); + + /* input */ + [o_read_bytes_txt setStringValue: [NSString stringWithFormat: + @"%8.0f kB", (float)(p_item->p_input->p_stats->i_read_bytes)/1000]]; + [o_input_bitrate_txt setStringValue: [NSString stringWithFormat: + @"%6.0f kb/s", (float)(p_item->p_input->p_stats->f_input_bitrate)*8000]]; + [o_demux_bytes_txt setStringValue: [NSString stringWithFormat: + @"%8.0f kB", (float)(p_item->p_input->p_stats->i_demux_read_bytes)/1000]]; + [o_demux_bitrate_txt setStringValue: [NSString stringWithFormat: + @"%6.0f kb/s", (float)(p_item->p_input->p_stats->f_demux_bitrate)*8000]]; + + /* Video */ + [o_video_decoded_txt setStringValue: [NSString stringWithFormat: @"%5i", + p_item->p_input->p_stats->i_decoded_video]]; + [o_displayed_txt setStringValue: [NSString stringWithFormat: @"%5i", + p_item->p_input->p_stats->i_displayed_pictures]]; + [o_lost_frames_txt setStringValue: [NSString stringWithFormat: @"%5i", + p_item->p_input->p_stats->i_lost_pictures]]; + + /* Sout */ + [o_sent_packets_txt setStringValue: [NSString stringWithFormat: @"%5i", + p_item->p_input->p_stats->i_sent_packets]]; + [o_sent_bytes_txt setStringValue: [NSString stringWithFormat: @"%8.0f kB", + (float)(p_item->p_input->p_stats->i_sent_bytes)/1000]]; + [o_sent_bitrate_txt setStringValue: [NSString stringWithFormat: + @"%6.0f kb/s", (float)(p_item->p_input->p_stats->f_send_bitrate*8)*1000]]; + + /* Audio */ + [o_audio_decoded_txt setStringValue: [NSString stringWithFormat: @"%5i", + p_item->p_input->p_stats->i_decoded_audio]]; + [o_played_abuffers_txt setStringValue: [NSString stringWithFormat: @"%5i", + p_item->p_input->p_stats->i_played_abuffers]]; + [o_lost_abuffers_txt setStringValue: [NSString stringWithFormat: @"%5i", + p_item->p_input->p_stats->i_lost_abuffers]]; + + vlc_mutex_unlock( &p_item->p_input->p_stats->lock ); } - [o_info_window makeKeyAndOrderFront: sender]; } - (IBAction)infoCancel:(id)sender { + [self windowShouldClose: nil]; [o_info_window orderOut: self]; } - (IBAction)infoOk:(id)sender { - int c; intf_thread_t * p_intf = VLCIntf; - playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, - FIND_ANYWHERE ); + playlist_t * p_playlist = pl_Yield( p_intf ); vlc_value_t val; - if (p_playlist) + if( [self isItemInPlaylist: p_item] ) { - vlc_mutex_lock(&p_playlist->pp_items[i_item]->input.lock); + vlc_mutex_lock( &p_item->p_input->lock ); - p_playlist->pp_items[i_item]->input.psz_uri = - strdup([[o_uri_txt stringValue] cString]); - p_playlist->pp_items[i_item]->input.psz_name = - strdup([[o_title_txt stringValue] cString]); - playlist_ItemAddInfo(p_playlist->pp_items[i_item],_("General"),_("Author"), [[o_author_txt stringValue] cString]); + p_item->p_input->psz_uri = strdup( [[o_uri_txt stringValue] UTF8String] ); + p_item->p_input->psz_name = strdup( [[o_title_txt stringValue] UTF8String] ); + vlc_meta_SetArtist( p_item->p_input->p_meta, [[o_author_txt stringValue] UTF8String] ) + vlc_mutex_unlock( &p_item->p_input->lock ); - c = (int)[o_selected count]; - vlc_mutex_unlock(&p_playlist->pp_items[i_item]->input.lock); val.b_bool = VLC_TRUE; - var_Set( p_playlist,"intf-change",val ); - vlc_object_release ( p_playlist ); + var_Set( p_playlist, "intf-change", val ); } + vlc_object_release( p_playlist ); + [self windowShouldClose: nil]; [o_info_window orderOut: self]; } -- (int)getItem +- (playlist_item_t *)getItem { - return i_item; + return p_item; +} + +- (BOOL)isItemInPlaylist:(playlist_item_t *)p_local_item +{ + intf_thread_t * p_intf = VLCIntf; + playlist_t * p_playlist = pl_Yield( p_intf ); + int i; + + for( i = 0 ; i < p_playlist->all_items.i_size ; i++ ) + { + if( ARRAY_VAL( p_playlist->all_items, i ) == p_local_item ) + { + vlc_object_release( p_playlist ); + return YES; + } + } + vlc_object_release( p_playlist ); + return NO; +} + +- (BOOL)windowShouldClose:(id)sender +{ + if( [o_statUpdateTimer isValid] ) + [o_statUpdateTimer invalidate]; + + if( o_statUpdateTimer ) + [o_statUpdateTimer release]; + + return YES; } @end @@ -196,7 +355,7 @@ input_thread_t * p_input = vlc_object_find( p_intf, VLC_OBJECT_INPUT, FIND_ANYWHERE ); - if( [[o_mi title] isEqualToString: _NS("Info")] ) + if( [[o_mi title] isEqualToString: _NS("Information")] ) { if( p_input == NULL ) { @@ -223,7 +382,7 @@ - (id)outlineView:(NSOutlineView *)outlineView child:(int)index ofItem:(id)item { - return (item == nil) ? [[VLCInfoTreeItem rootItem] childAtIndex:index] : [item childAtIndex:index]; + return (item == nil) ? [[VLCInfoTreeItem rootItem] childAtIndex:index] : (id)[item childAtIndex:index]; } - (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item @@ -257,19 +416,23 @@ static VLCInfoTreeItem *o_root_item = nil; o_value = [o_item_value copy]; i_object_id = i_id; o_parent = o_parent_item; - i_item = [[[VLCMain sharedInstance] getInfo] getItem]; + if( [[VLCMain sharedInstance] getInfo] != nil ) + p_item = [[[VLCMain sharedInstance] getInfo] getItem]; + else + p_item = NULL; } return( self ); } + (VLCInfoTreeItem *)rootItem { - if (o_root_item == nil) o_root_item = [[VLCInfoTreeItem alloc] initWithName:@"main" value: @"" ID: 0 parent:nil]; + if( o_root_item == nil ) + o_root_item = [[VLCInfoTreeItem alloc] initWithName:@"main" value: @"" ID: 0 parent:nil]; return o_root_item; } - (void)dealloc { - if (o_children != IsALeafNode) [o_children release]; + if( o_children != IsALeafNode ) [o_children release]; [o_name release]; [super dealloc]; } @@ -280,56 +443,48 @@ static VLCInfoTreeItem *o_root_item = nil; { if (o_children == NULL) { - intf_thread_t * p_intf = VLCIntf; - playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, - FIND_ANYWHERE ); int i; - if (p_playlist) + if( [[[VLCMain sharedInstance] getInfo] isItemInPlaylist: p_item] ) { - if (i_item > -1) + if( self == o_root_item ) { - if (self == o_root_item) + vlc_mutex_lock( &p_item->p_input->lock ); + o_children = [[NSMutableArray alloc] initWithCapacity: + p_item->p_input->i_categories]; + for (i = 0 ; i < p_item->p_input->i_categories ; i++) { - o_children = [[NSMutableArray alloc] initWithCapacity:p_playlist->pp_items[i_item]->input.i_categories]; - for (i = 0 ; ipp_items[i_item]->input.i_categories ; i++) - { - [o_children addObject:[[VLCInfoTreeItem alloc] - initWithName: [NSString stringWithUTF8String: - p_playlist->pp_items[i_item]->input. - pp_categories[i]->psz_name] - value: @"" - ID: i - parent: self]]; - } - } - else if (o_parent == o_root_item) - { - o_children = [[NSMutableArray alloc] initWithCapacity: - p_playlist->pp_items[i_item]->input. - pp_categories[i_object_id]->i_infos]; - for (i = 0 ; ipp_items[i_item]->input. - pp_categories[i_object_id]->i_infos ; i++) - { - [o_children addObject:[[VLCInfoTreeItem alloc] + [o_children addObject:[[VLCInfoTreeItem alloc] initWithName: [NSString stringWithUTF8String: - p_playlist->pp_items[i_item]->input. - pp_categories[i_object_id]-> - pp_infos[i]->psz_name] - value: [NSString stringWithUTF8String: - p_playlist->pp_items[i_item]->input. - pp_categories[i_object_id]-> - pp_infos[i]->psz_value] - ID: i - parent: self]]; - } + p_item->p_input->pp_categories[i]->psz_name] + value: @"" + ID: i + parent: self]]; } - else + vlc_mutex_unlock( &p_item->p_input->lock ); + } + else if( o_parent == o_root_item ) + { + vlc_mutex_lock( &p_item->p_input->lock ); + o_children = [[NSMutableArray alloc] initWithCapacity: + p_item->p_input->pp_categories[i_object_id]->i_infos]; + + for (i = 0 ; i < p_item->p_input->pp_categories[i_object_id]->i_infos ; i++) { - o_children = IsALeafNode; + [o_children addObject:[[VLCInfoTreeItem alloc] + initWithName: [NSString stringWithUTF8String: + p_item->p_input->pp_categories[i_object_id]->pp_infos[i]->psz_name] + value: [NSString stringWithUTF8String: + p_item->p_input->pp_categories[i_object_id]->pp_infos[i]->psz_value] + ID: i + parent: self]]; } + vlc_mutex_unlock( &p_item->p_input->lock ); + } + else + { + o_children = IsALeafNode; } - vlc_object_release(p_playlist); } } return o_children; @@ -351,7 +506,7 @@ static VLCInfoTreeItem *o_root_item = nil; - (int)numberOfChildren { id i_tmp = [self children]; - return (i_tmp == IsALeafNode) ? (-1) : (int)[i_tmp count]; + return ( i_tmp == IsALeafNode ) ? (-1) : (int)[i_tmp count]; } /*- (int)selectedPlaylistItem @@ -361,8 +516,8 @@ static VLCInfoTreeItem *o_root_item = nil; */ - (void)refresh { - i_item = [[[VLCMain sharedInstance] getInfo] getItem]; - if (o_children != NULL) + p_item = [[[VLCMain sharedInstance] getInfo] getItem]; + if( o_children != NULL ) { [o_children release]; o_children = NULL;