Commit 7cf99d81 authored by Pierre d'Herbemont's avatar Pierre d'Herbemont

macosx: Fix the info panel. Remove the use of maybe-freed-ptr. Make it display...

macosx: Fix the info panel. Remove the use of maybe-freed-ptr. Make it display currently selected item.
parent fcc30d46
......@@ -1752,8 +1752,11 @@ end:
[o_bookmarks release];
if( nib_info_loaded )
{
[o_info stop];
[o_info release];
}
if( nib_wizard_loaded )
[o_wizard release];
......
......@@ -123,6 +123,8 @@
- (void)sortNode:(int)i_mode;
- (void)updateRowSelection;
- (BOOL)isSelectionEmpty;
- (IBAction)servicesChange:(id)sender;
- (IBAction)playItem:(id)sender;
- (IBAction)preparseItem:(id)sender;
......
......@@ -497,11 +497,29 @@
vlc_object_release( p_playlist );
}
- (void)outlineViewSelectionDidChange:(NSNotification *)notification
{
// FIXME: unsafe
playlist_item_t * p_item = [[o_outline_view itemAtRow:[o_outline_view selectedRow]] pointerValue];
if( p_item )
{
/* update our info-panel to reflect the new item */
[[[VLCMain sharedInstance] getInfo] updatePanelWithItem:p_item->p_input];
}
}
- (BOOL)isSelectionEmpty
{
return [o_outline_view selectedRow] == -1;
}
- (void)updateRowSelection
{
int i_row;
unsigned int j;
// FIXME: unsafe
playlist_t *p_playlist = pl_Yield( VLCIntf );
playlist_item_t *p_item, *p_temp_item;
NSMutableArray *o_array = [NSMutableArray array];
......@@ -532,10 +550,11 @@
}
/* update our info-panel to reflect the new item */
[[[VLCMain sharedInstance] getInfo] updatePanelWithItem:p_item->p_input];
vlc_object_release( p_playlist );
/* update our info-panel to reflect the new item */
[[[VLCMain sharedInstance] getInfo] updatePanel];
}
/* Check if p_item is a child of p_node recursively. We need to check the item
......
......@@ -26,6 +26,7 @@
* VLCPlaylistInfo interface
*****************************************************************************/
@class VLCInfoTreeItem;
@interface VLCInfo : NSObject
{
......@@ -94,7 +95,9 @@
IBOutlet id o_fps_lbl;
IBOutlet id o_fps_txt;
playlist_item_t * p_item;
VLCInfoTreeItem * rootItem;
input_item_t * p_item;
NSTimer * o_statUpdateTimer;
}
......@@ -102,10 +105,8 @@
- (IBAction)metaFieldChanged:(id)sender;
- (IBAction)saveMetaData:(id)sender;
- (void)initMediaPanelStats;
- (void)updatePanel;
- (playlist_item_t *)getItem;
- (BOOL)isItemInPlaylist:(playlist_item_t *)p_item;
- (void)updatePanelWithItem:(input_item_t *)_p_item;
- (input_item_t *)item;
- (void)setMeta: (char *)meta forLabel: (id)theItem;
- (void)updateStatistics: (NSTimer*)theTimer;
......@@ -117,16 +118,15 @@
NSString *o_name;
NSString *o_value;
int i_object_id;
playlist_item_t * p_item;
input_item_t * p_item;
VLCInfoTreeItem *o_parent;
NSMutableArray *o_children;
}
+ (VLCInfoTreeItem *)rootItem;
- (int)numberOfChildren;
- (VLCInfoTreeItem *)childAtIndex:(int)i_index;
- (NSString *)getName;
- (NSString *)getValue;
- (NSString *)name;
- (NSString *)value;
- (void)refresh;
@end
......
......@@ -54,6 +54,8 @@ static VLCInfo *_o_sharedInstance = nil;
{
p_item = NULL;
o_statUpdateTimer = nil;
[self updatePanelWithItem: NULL];
rootItem = [[VLCInfoTreeItem alloc] init];
}
}
......@@ -110,39 +112,78 @@ static VLCInfo *_o_sharedInstance = nil;
[o_lost_abuffers_lbl setStringValue: _NS("Lost buffers")];
[o_info_window setInitialFirstResponder: o_uri_txt];
[o_info_window setDelegate: self];
/* We may be awoken from nib way after initialiwation
* Update ourselves */
[self updatePanelWithItem:p_item];
}
- (void)stop
{
/* make sure that the timer is released in any case */
if( o_statUpdateTimer && [o_statUpdateTimer isValid] )
[o_statUpdateTimer invalidate];
[rootItem release];
[o_statUpdateTimer release];
o_statUpdateTimer = nil;
}
- (void)dealloc
{
/* make sure that the timer is released in any case */
if( [o_statUpdateTimer isValid] )
if( o_statUpdateTimer && [o_statUpdateTimer isValid] )
[o_statUpdateTimer invalidate];
if ( o_statUpdateTimer )
[o_statUpdateTimer release];
[o_statUpdateTimer release];
if( p_item ) vlc_gc_decref( p_item );
[super dealloc];
}
- (void)initPanel
- (void)windowDidBecomeKey:(NSNotification *)notification
{
BOOL b_stats = config_GetInt(VLCIntf, "stats");
[self initMediaPanelStats];
if( b_stats )
{
if( o_statUpdateTimer )
{
[o_statUpdateTimer invalidate];
[o_statUpdateTimer release];
o_statUpdateTimer = nil;
}
o_statUpdateTimer = [NSTimer scheduledTimerWithTimeInterval: 1
target: self selector: @selector(updateStatistics:)
userInfo: nil repeats: YES];
[o_statUpdateTimer fire];
[o_statUpdateTimer retain];
}
else
}
- (BOOL)windowShouldClose:(id)sender
{
if( [o_statUpdateTimer isValid] )
[o_statUpdateTimer invalidate];
if( o_statUpdateTimer )
[o_statUpdateTimer release];
o_statUpdateTimer = nil;
return YES;
}
- (void)initPanel
{
BOOL b_stats = config_GetInt(VLCIntf, "stats");
if( !b_stats )
{
if( [o_tab_view numberOfTabViewItems] > 2 )
[o_tab_view removeTabViewItem: [o_tab_view tabViewItemAtIndex: 2]];
}
[self updatePanel];
[self initMediaPanelStats];
[o_info_window makeKeyAndOrderFront: self];
}
......@@ -172,61 +213,89 @@ static VLCInfo *_o_sharedInstance = nil;
}
- (void)updatePanel
- (void)updatePanelWithItem:(input_item_t *)_p_item;
{
/* make sure that we got the current item and not an outdated one */
intf_thread_t * p_intf = VLCIntf;
playlist_t * p_playlist = pl_Yield( p_intf );
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;
/* fill uri info */
if( input_item_GetURI( p_item->p_input ) != NULL )
if( _p_item != p_item )
{
[o_uri_txt setStringValue: [NSString stringWithUTF8String: input_item_GetURI( p_item->p_input ) ]];
if( p_item ) vlc_gc_decref( p_item );
if( _p_item ) vlc_gc_incref( _p_item );
p_item = _p_item;
}
#define SET( foo, bar ) \
char *psz_##foo = input_item_Get##bar ( p_item->p_input ); \
[self setMeta: psz_##foo forLabel: o_##foo##_txt]; \
FREENULL( psz_##foo );
/* fill the other fields */
SET( title, Title );
SET( author, Artist );
SET( collection, Album );
SET( seqNum, TrackNum );
SET( genre, Genre );
SET( copyright, Copyright );
SET( publisher, Publisher );
SET( nowPlaying, NowPlaying );
SET( language, Language );
SET( date, Date );
SET( description, Description );
#undef SET
char *psz_meta;
NSImage *o_image;
psz_meta = input_item_GetArtURL( p_item->p_input );
if( psz_meta && !strncmp( psz_meta, "file://", 7 ) )
o_image = [[NSImage alloc] initWithContentsOfURL: [NSURL URLWithString: [NSString stringWithUTF8String: psz_meta]]];
if( !p_item )
{
/* Erase */
#define SET( foo ) \
[self setMeta: "" forLabel: o_##foo##_txt];
SET( uri );
SET( title );
SET( author );
SET( collection );
SET( seqNum );
SET( genre );
SET( copyright );
SET( publisher );
SET( nowPlaying );
SET( language );
SET( date );
SET( description );
#undef SET
[o_image_well setImage: [NSImage imageNamed: @"noart.png"]];
}
else
o_image = [[NSImage imageNamed: @"noart.png"] retain];
[o_image_well setImage: o_image];
[o_image release];
FREENULL( psz_meta );
{
/* fill uri info */
char * psz_url = input_item_GetURI( p_item );
[o_uri_txt setStringValue: [NSString stringWithUTF8String: psz_url ? psz_url : "" ]];
if( !input_item_IsPreparsed( p_item ) )
{
playlist_t * p_playlist = pl_Yield( VLCIntf );
playlist_PreparseEnqueue( p_playlist, p_item );
pl_Release( VLCIntf );
}
free( psz_url );
#define SET( foo, bar ) \
char *psz_##foo = input_item_Get##bar ( p_item ); \
[self setMeta: psz_##foo forLabel: o_##foo##_txt]; \
FREENULL( psz_##foo );
/* fill the other fields */
SET( title, Title );
SET( author, Artist );
SET( collection, Album );
SET( seqNum, TrackNum );
SET( genre, Genre );
SET( copyright, Copyright );
SET( publisher, Publisher );
SET( nowPlaying, NowPlaying );
SET( language, Language );
SET( date, Date );
SET( description, Description );
#undef SET
char *psz_meta;
NSImage *o_image;
psz_meta = input_item_GetArtURL( p_item );
if( psz_meta && !strncmp( psz_meta, "file://", 7 ) )
o_image = [[NSImage alloc] initWithContentsOfURL: [NSURL URLWithString: [NSString stringWithUTF8String: psz_meta]]];
else
o_image = [[NSImage imageNamed: @"noart.png"] retain];
[o_image_well setImage: o_image];
[o_image release];
FREENULL( psz_meta );
}
/* reload the advanced table */
[[VLCInfoTreeItem rootItem] refresh];
[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
......@@ -239,42 +308,45 @@ static VLCInfo *_o_sharedInstance = nil;
- (void)updateStatistics:(NSTimer*)theTimer
{
if( [self isItemInPlaylist: p_item] )
if( !p_item || !p_item->p_stats )
{
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 setIntValue: p_item->p_input->p_stats->i_decoded_video];
[o_displayed_txt setIntValue: p_item->p_input->p_stats->i_displayed_pictures];
[o_lost_frames_txt setIntValue: p_item->p_input->p_stats->i_lost_pictures];
float f_fps = 0;
/* FIXME: input_Control( p_item->p_input, INPUT_GET_VIDEO_FPS, &f_fps ); */
[o_fps_txt setFloatValue: f_fps];
/* Sout */
[o_sent_packets_txt setIntValue: 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 setIntValue: p_item->p_input->p_stats->i_decoded_audio];
[o_played_abuffers_txt setIntValue: p_item->p_input->p_stats->i_played_abuffers];
[o_lost_abuffers_txt setIntValue: p_item->p_input->p_stats->i_lost_abuffers];
vlc_mutex_unlock( &p_item->p_input->p_stats->lock );
[self initMediaPanelStats];
return;
}
vlc_mutex_lock( &p_item->p_stats->lock );
/* input */
[o_read_bytes_txt setStringValue: [NSString stringWithFormat:
@"%8.0f kB", (float)(p_item->p_stats->i_read_bytes)/1000]];
[o_input_bitrate_txt setStringValue: [NSString stringWithFormat:
@"%6.0f kb/s", (float)(p_item->p_stats->f_input_bitrate)*8000]];
[o_demux_bytes_txt setStringValue: [NSString stringWithFormat:
@"%8.0f kB", (float)(p_item->p_stats->i_demux_read_bytes)/1000]];
[o_demux_bitrate_txt setStringValue: [NSString stringWithFormat:
@"%6.0f kb/s", (float)(p_item->p_stats->f_demux_bitrate)*8000]];
/* Video */
[o_video_decoded_txt setIntValue: p_item->p_stats->i_decoded_video];
[o_displayed_txt setIntValue: p_item->p_stats->i_displayed_pictures];
[o_lost_frames_txt setIntValue: p_item->p_stats->i_lost_pictures];
float f_fps = 0;
/* FIXME: input_Control( p_item, INPUT_GET_VIDEO_FPS, &f_fps ); */
[o_fps_txt setFloatValue: f_fps];
/* Sout */
[o_sent_packets_txt setIntValue: p_item->p_stats->i_sent_packets];
[o_sent_bytes_txt setStringValue: [NSString stringWithFormat: @"%8.0f kB",
(float)(p_item->p_stats->i_sent_bytes)/1000]];
[o_sent_bitrate_txt setStringValue: [NSString stringWithFormat:
@"%6.0f kb/s", (float)(p_item->p_stats->f_send_bitrate*8)*1000]];
/* Audio */
[o_audio_decoded_txt setIntValue: p_item->p_stats->i_decoded_audio];
[o_played_abuffers_txt setIntValue: p_item->p_stats->i_played_abuffers];
[o_lost_abuffers_txt setIntValue: p_item->p_stats->i_lost_abuffers];
vlc_mutex_unlock( &p_item->p_stats->lock );
}
- (IBAction)metaFieldChanged:(id)sender
......@@ -284,100 +356,72 @@ static VLCInfo *_o_sharedInstance = nil;
- (IBAction)saveMetaData:(id)sender
{
intf_thread_t * p_intf = VLCIntf;
playlist_t * p_playlist = pl_Yield( p_intf );
playlist_t * p_playlist = pl_Yield( VLCIntf );
vlc_value_t val;
if( [self isItemInPlaylist: p_item] )
{
meta_export_t p_export;
p_export.p_item = p_item->p_input;
if( !p_item ) goto error;
if( p_item->p_input == NULL )
goto end;
meta_export_t p_export;
p_export.p_item = p_item;
/* we can write meta data only in a file */
vlc_mutex_lock( &p_item->p_input->lock );
int i_type = p_item->p_input->i_type;
vlc_mutex_unlock( &p_item->p_input->lock );
if( i_type == ITEM_TYPE_FILE )
{
char *psz_uri_orig = input_item_GetURI( p_item->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
goto end;
#define utf8( o_blub ) \
[[o_blub stringValue] UTF8String]
input_item_SetName( p_item->p_input, utf8( o_title_txt ) );
input_item_SetTitle( p_item->p_input, utf8( o_title_txt ) );
input_item_SetArtist( p_item->p_input, utf8( o_author_txt ) );
input_item_SetAlbum( p_item->p_input, utf8( o_collection_txt ) );
input_item_SetGenre( p_item->p_input, utf8( o_genre_txt ) );
input_item_SetTrackNum( p_item->p_input, utf8( o_seqNum_txt ) );
input_item_SetDate( p_item->p_input, utf8( o_date_txt ) );
input_item_SetCopyright( p_item->p_input, utf8( o_copyright_txt ) );
input_item_SetPublisher( p_item->p_input, utf8( o_publisher_txt ) );
input_item_SetDescription( p_item->p_input, utf8( o_description_txt ) );
input_item_SetLanguage( p_item->p_input, utf8( o_language_txt ) );
PL_LOCK;
p_playlist->p_private = &p_export;
module_t *p_mod = module_Need( p_playlist, "meta writer", NULL, 0 );
if( p_mod )
module_Unneed( p_playlist, p_mod );
PL_UNLOCK;
val.b_bool = true;
var_Set( p_playlist, "intf-change", val );
[self updatePanel];
}
/* we can write meta data only in a file */
vlc_mutex_lock( &p_item->lock );
int i_type = p_item->i_type;
vlc_mutex_unlock( &p_item->lock );
end:
vlc_object_release( p_playlist );
[o_saveMetaData_btn setEnabled: NO];
}
if( i_type != ITEM_TYPE_FILE )
goto error;
- (playlist_item_t *)getItem
{
return p_item;
}
char *psz_uri_orig = input_item_GetURI( p_item );
char *psz_uri = psz_uri_orig;
if( !strncmp( psz_uri, "file://", 7 ) )
psz_uri += 7; /* strlen("file://") = 7 */
- (BOOL)isItemInPlaylist:(playlist_item_t *)p_local_item
{
intf_thread_t * p_intf = VLCIntf;
playlist_t * p_playlist = pl_Yield( p_intf );
int i;
p_export.psz_file = strndup( psz_uri, PATH_MAX );
free( psz_uri_orig );
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;
}
#define utf8( o_blub ) \
[[o_blub stringValue] UTF8String]
- (BOOL)windowShouldClose:(id)sender
{
if( [o_statUpdateTimer isValid] )
[o_statUpdateTimer invalidate];
input_item_SetName( p_item, utf8( o_title_txt ) );
input_item_SetTitle( p_item, utf8( o_title_txt ) );
input_item_SetArtist( p_item, utf8( o_author_txt ) );
input_item_SetAlbum( p_item, utf8( o_collection_txt ) );
input_item_SetGenre( p_item, utf8( o_genre_txt ) );
input_item_SetTrackNum( p_item, utf8( o_seqNum_txt ) );
input_item_SetDate( p_item, utf8( o_date_txt ) );
input_item_SetCopyright( p_item, utf8( o_copyright_txt ) );
input_item_SetPublisher( p_item, utf8( o_publisher_txt ) );
input_item_SetDescription( p_item, utf8( o_description_txt ) );
input_item_SetLanguage( p_item, utf8( o_language_txt ) );
if( o_statUpdateTimer )
[o_statUpdateTimer release];
PL_LOCK;
p_playlist->p_private = &p_export;
return YES;
module_t *p_mod = module_Need( p_playlist, "meta writer", NULL, 0 );
if( p_mod )
module_Unneed( p_playlist, p_mod );
PL_UNLOCK;
val.b_bool = true;
var_Set( p_playlist, "intf-change", val );
[self updatePanelWithItem: p_item];
pl_Release( VLCIntf );
[o_saveMetaData_btn setEnabled: NO];
return;
error:
pl_Release( VLCIntf );
NSRunAlertPanel(_NS("Error while saving meta"),
_NS("Impossible to save the meta data."),
_NS("OK"), nil, nil);
}
- (input_item_t *)item
{
vlc_gc_incref( p_item );
return p_item;
}
@end
......@@ -388,20 +432,12 @@ static VLCInfo *_o_sharedInstance = nil;
{
BOOL bEnabled = TRUE;
intf_thread_t * p_intf = VLCIntf;
input_thread_t * p_input = vlc_object_find( p_intf, VLC_OBJECT_INPUT,
FIND_ANYWHERE );
if( [[o_mi title] isEqualToString: _NS("Information")] )
{
if( p_input == NULL )
{
bEnabled = FALSE;
}
return ![[[VLCMain sharedInstance] getPlaylist] isSelectionEmpty];
}
if( p_input ) vlc_object_release( p_input );
return( bEnabled );
return TRUE;
}
@end
......@@ -410,7 +446,7 @@ static VLCInfo *_o_sharedInstance = nil;
- (int)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item
{
return (item == nil) ? [[VLCInfoTreeItem rootItem] numberOfChildren] : [item numberOfChildren];
return (item == nil) ? [rootItem numberOfChildren] : [item numberOfChildren];
}
- (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item {
......@@ -419,18 +455,18 @@ static VLCInfo *_o_sharedInstance = nil;
- (id)outlineView:(NSOutlineView *)outlineView child:(int)index ofItem:(id)item
{
return (item == nil) ? [[VLCInfoTreeItem rootItem] childAtIndex:index] : (id)[item childAtIndex:index];
return (item == nil) ? [rootItem childAtIndex:index] : (id)[item childAtIndex:index];
}
- (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item
{
if ([[tableColumn identifier] isEqualToString:@"0"])
{
return (item == nil) ? @"" : (id)[item getName];
return (item == nil) ? @"" : (id)[item name];
}
else
{
return (item == nil) ? @"" : (id)[item getValue];
return (item == nil) ? @"" : (id)[item value];
}
}
......@@ -439,11 +475,10 @@ static VLCInfo *_o_sharedInstance = nil;
@implementation VLCInfoTreeItem
static VLCInfoTreeItem *o_root_item = nil;
#define IsALeafNode ((id)-1)
- (id)initWithName: (NSString *)o_item_name value: (NSString *)o_item_value ID: (int)i_id parent:(VLCInfoTreeItem *)o_parent_item
- (id)initWithName: (NSString *)o_item_name value: (NSString *)o_item_value ID: (int)i_id
parent:(VLCInfoTreeItem *)o_parent_item
{
self = [super init];
......@@ -453,24 +488,23 @@ static VLCInfoTreeItem *o_root_item = nil;
o_value = [o_item_value copy];
i_object_id = i_id;
o_parent = o_parent_item;
if( [[VLCMain sharedInstance] getInfo] != nil )
p_item = [[[VLCMain sharedInstance] getInfo] getItem];
else
p_item = NULL;
p_item = [[[VLCMain sharedInstance] getInfo] item];
o_children = nil;
}
return( self );
}
+ (VLCInfoTreeItem *)rootItem {
if( o_root_item == nil )
o_root_item = [[VLCInfoTreeItem alloc] initWithName:@"main" value: @"" ID: 0 parent:nil];
return o_root_item;
- (id)init
{
return [self initWithName:@"main" value:@"" ID:-1 parent:nil];
}
- (void)dealloc
{
if( o_children != IsALeafNode ) [o_children release];
[o_name release];
[o_value release];
if( p_item ) vlc_gc_decref( p_item );
[super dealloc];
}
......@@ -478,77 +512,62 @@ static VLCInfoTreeItem *o_root_item = nil;
* Loads children incrementally */
- (NSArray *)children
{
if( !p_item ) return nil;
if (o_children == NULL)
{
int i;
if( [[[VLCMain sharedInstance] getInfo] isItemInPlaylist: p_item] )
if( i_object_id == -1 )
{
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 addObject:[[VLCInfoTreeItem alloc]
initWithName: [NSString stringWithUTF8String: