playlistinfo.m
上传用户:kjfoods
上传日期:2020-07-06
资源大小:29949k
文件大小:18k
源码类别:

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  r playlistinfo.m: MacOS X interface module
  3.  *****************************************************************************
  4.  * Copyright (C) 2002-2009 the VideoLAN team
  5.  * $Id: 151bda9f0d8d4de88422a584785bcf73a292b80c $
  6.  *
  7.  * Authors: Benjamin Pracht <bigben at videolan dot org>
  8.  *          Felix Paul Kühne <fkuehne at videolan dot org>
  9.  *
  10.  * This program is free software; you can redistribute it and/or modify
  11.  * it under the terms of the GNU General Public License as published by
  12.  * the Free Software Foundation; either version 2 of the License, or
  13.  * (at your option) any later version.
  14.  *
  15.  * This program is distributed in the hope that it will be useful,
  16.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18.  * GNU General Public License for more details.
  19.  *
  20.  * You should have received a copy of the GNU General Public License
  21.  * along with this program; if not, write to the Free Software
  22.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  23.  *****************************************************************************/
  24. /*****************************************************************************
  25.  * Preamble
  26.  *****************************************************************************/
  27. #include "intf.h"
  28. #include "playlistinfo.h"
  29. #include "playlist.h"
  30. #include <vlc_url.h>
  31. /*****************************************************************************
  32.  * VLCPlaylistInfo Implementation
  33.  *****************************************************************************/
  34. @implementation VLCInfo
  35. static VLCInfo *_o_sharedInstance = nil;
  36. + (VLCInfo *)sharedInstance
  37. {
  38.     return _o_sharedInstance ? _o_sharedInstance : [[self alloc] init];
  39. }
  40. - (id)init
  41. {
  42.     if( _o_sharedInstance )
  43.     {
  44.         [self dealloc];
  45.     }
  46.     else
  47.     {
  48.         _o_sharedInstance = [super init];
  49.         
  50.         if( _o_sharedInstance != nil )
  51.         {
  52.             p_item = NULL;
  53.             o_statUpdateTimer = nil;
  54.             [self updatePanelWithItem: NULL];
  55.             rootItem = [[VLCInfoTreeItem alloc] init];
  56.         }
  57.     }
  58.     return _o_sharedInstance;
  59. }
  60. - (void)awakeFromNib
  61. {
  62.     [o_info_window setExcludedFromWindowsMenu: YES];
  63.     [o_info_window setFloatingPanel: NO];
  64.     [o_info_window setTitle: _NS("Media Information")];
  65.     [o_uri_lbl setStringValue: _NS("Location")];
  66.     [o_title_lbl setStringValue: _NS("Title")];
  67.     [o_author_lbl setStringValue: _NS("Artist")];
  68.     [o_saveMetaData_btn setStringValue: _NS("Save Metadata" )];
  69.     [[o_tab_view tabViewItemAtIndex: 0] setLabel: _NS("General")];
  70.     [[o_tab_view tabViewItemAtIndex: 1] setLabel: _NS("Codec Details")];
  71.     [[o_tab_view tabViewItemAtIndex: 2] setLabel: _NS("Statistics")];
  72.     [o_tab_view selectTabViewItemAtIndex: 0];
  73.     /* constants defined in vlc_meta.h */
  74.     [o_genre_lbl setStringValue: _NS(VLC_META_GENRE)];
  75.     [o_copyright_lbl setStringValue: _NS(VLC_META_COPYRIGHT)];
  76.     [o_collection_lbl setStringValue: _NS(VLC_META_ALBUM)];
  77.     [o_seqNum_lbl setStringValue: _NS(VLC_META_TRACK_NUMBER)];
  78.     [o_description_lbl setStringValue: _NS(VLC_META_DESCRIPTION)];
  79.     [o_date_lbl setStringValue: _NS(VLC_META_DATE)];
  80.     [o_language_lbl setStringValue: _NS(VLC_META_LANGUAGE)];
  81.     [o_nowPlaying_lbl setStringValue: _NS(VLC_META_NOW_PLAYING)];
  82.     [o_publisher_lbl setStringValue: _NS(VLC_META_PUBLISHER)];
  83.     /* statistics */
  84.     [o_input_box setTitle: _NS("Input")];
  85.     [o_read_bytes_lbl setStringValue: _NS("Read at media")];
  86.     [o_input_bitrate_lbl setStringValue: _NS("Input bitrate")];
  87.     [o_demux_bytes_lbl setStringValue: _NS("Demuxed")];
  88.     [o_demux_bitrate_lbl setStringValue: _NS("Stream bitrate")];
  89.     [o_video_box setTitle: _NS("Video")];
  90.     [o_video_decoded_lbl setStringValue: _NS("Decoded blocks")];
  91.     [o_displayed_lbl setStringValue: _NS("Displayed frames")];
  92.     [o_lost_frames_lbl setStringValue: _NS("Lost frames")];
  93. [o_fps_lbl setStringValue: _NS("Frames per Second")];
  94.     [o_sout_box setTitle: _NS("Streaming")];
  95.     [o_sent_packets_lbl setStringValue: _NS("Sent packets")];
  96.     [o_sent_bytes_lbl setStringValue: _NS("Sent bytes")];
  97.     [o_sent_bitrate_lbl setStringValue: _NS("Send rate")];
  98.     [o_audio_box setTitle: _NS("Audio")];
  99.     [o_audio_decoded_lbl setStringValue: _NS("Decoded blocks")];
  100.     [o_played_abuffers_lbl setStringValue: _NS("Played buffers")];
  101.     [o_lost_abuffers_lbl setStringValue: _NS("Lost buffers")];
  102.     [o_info_window setInitialFirstResponder: o_uri_txt];
  103.     [o_info_window setDelegate: self];
  104.     /* We may be awoken from nib way after initialisation
  105.      * Update ourselves */
  106.     [self updatePanelWithItem:p_item];
  107. }
  108. - (void)stopTimers
  109. {
  110.     /* make sure that the timer is released in any case */
  111.     if( o_statUpdateTimer && [o_statUpdateTimer isValid] )
  112.         [o_statUpdateTimer invalidate];
  113.     [rootItem release];
  114.     [o_statUpdateTimer release];
  115.     o_statUpdateTimer = nil;
  116. }
  117. - (void)dealloc
  118. {
  119.     /* make sure that the timer is released in any case */
  120.     if( o_statUpdateTimer && [o_statUpdateTimer isValid] )
  121.         [o_statUpdateTimer invalidate];
  122.     [o_statUpdateTimer release];
  123.     if( p_item ) vlc_gc_decref( p_item );
  124.     [super dealloc];
  125. }
  126. - (void)windowDidBecomeKey:(NSNotification *)notification
  127. {
  128.     BOOL b_stats = config_GetInt(VLCIntf, "stats");
  129.     if( b_stats )
  130.     {
  131.         if( o_statUpdateTimer )
  132.         {
  133.             [o_statUpdateTimer invalidate];
  134.             [o_statUpdateTimer release];
  135.             o_statUpdateTimer = nil;
  136.         }
  137.         o_statUpdateTimer = [NSTimer scheduledTimerWithTimeInterval: 1
  138.             target: self selector: @selector(updateStatistics:)
  139.             userInfo: nil repeats: YES];
  140.         [o_statUpdateTimer fire];
  141.         [o_statUpdateTimer retain];
  142.     }
  143. }
  144. - (BOOL)windowShouldClose:(id)sender
  145. {
  146.     if( [o_statUpdateTimer isValid] )
  147.         [o_statUpdateTimer invalidate];
  148.     if( o_statUpdateTimer )
  149.         [o_statUpdateTimer release];
  150.     o_statUpdateTimer = nil;
  151.     return YES;
  152. }
  153. - (void)initPanel
  154. {
  155.     BOOL b_stats = config_GetInt(VLCIntf, "stats");
  156.     if( !b_stats )
  157.     {
  158.         if( [o_tab_view numberOfTabViewItems] > 2 )
  159.             [o_tab_view removeTabViewItem: [o_tab_view tabViewItemAtIndex: 2]];
  160.     }
  161.     [self initMediaPanelStats];
  162.     [o_info_window makeKeyAndOrderFront: self];
  163. }
  164. - (void)initMediaPanelStats
  165. {
  166.     //Initializing Input Variables
  167.     [o_read_bytes_txt setStringValue: [NSString stringWithFormat:@"%8.0f kB", (float)0]];
  168.     [o_input_bitrate_txt setStringValue: [NSString stringWithFormat:@"%6.0f kb/s", (float)0]];
  169.     [o_demux_bytes_txt setStringValue: [NSString stringWithFormat:@"%8.0f kB", (float)0]];
  170.     [o_demux_bitrate_txt setStringValue: [NSString stringWithFormat:@"%6.0f kb/s", (float)0]];
  171.     
  172.     //Initializing Video Variables
  173.     [o_video_decoded_txt setIntValue:0];
  174.     [o_displayed_txt setIntValue:0];
  175.     [o_lost_frames_txt setIntValue:0];
  176.     [o_fps_txt setFloatValue:0];
  177.     //Initializing Output Variables
  178.     [o_sent_packets_txt setIntValue: 0];
  179.     [o_sent_bytes_txt setStringValue: [NSString stringWithFormat:@"%8.0f kB", (float)0]];
  180.     [o_sent_bitrate_txt setStringValue: [NSString stringWithFormat:@"%6.0f kb/s", (float)0]];
  181.     //Initializing Audio Variables
  182.     [o_audio_decoded_txt setIntValue:0];
  183.     [o_played_abuffers_txt setIntValue: 0];
  184.     [o_lost_abuffers_txt setIntValue: 0];
  185. }
  186. - (void)updatePanelWithItem:(input_item_t *)_p_item;
  187. {
  188.     if( _p_item != p_item )
  189.     {
  190.         if( p_item ) vlc_gc_decref( p_item );
  191.         [o_saveMetaData_btn setEnabled: NO];
  192.         if( _p_item ) vlc_gc_incref( _p_item );
  193.         p_item = _p_item;
  194.     }
  195.     if( !p_item )
  196.     {
  197.         /* Erase */
  198.     #define SET( foo ) 
  199.         [self setMeta: "" forLabel: o_##foo##_txt];
  200.         SET( uri );
  201.         SET( title );
  202.         SET( author );
  203.         SET( collection );
  204.         SET( seqNum );
  205.         SET( genre );
  206.         SET( copyright );
  207.         SET( publisher );
  208.         SET( nowPlaying );
  209.         SET( language );
  210.         SET( date );
  211.         SET( description );
  212.     #undef SET
  213.         [o_image_well setImage: [NSImage imageNamed: @"noart.png"]];
  214.     }
  215.     else
  216.     {
  217.         if( !input_item_IsPreparsed( p_item ) )
  218.         {
  219.             playlist_t * p_playlist = pl_Hold( VLCIntf );
  220.             PL_LOCK;
  221.             playlist_PreparseEnqueue( p_playlist, p_item, pl_Locked );
  222.             PL_UNLOCK;
  223.             pl_Release( VLCIntf );
  224.         }
  225.         /* fill uri info */
  226.         char * psz_url = input_item_GetURI( p_item );
  227.         [o_uri_txt setStringValue: [NSString stringWithUTF8String: psz_url ? psz_url : ""  ]];
  228.         free( psz_url );
  229.         /* fill title info */
  230.         char * psz_title = input_item_GetTitle( p_item );
  231.         if( !psz_title )
  232.             psz_title = input_item_GetName( p_item );
  233.         [o_title_txt setStringValue: [NSString stringWithUTF8String: psz_title ? : ""  ]];
  234.         free( psz_title );
  235.     #define SET( foo, bar ) 
  236.         char *psz_##foo = input_item_Get##bar ( p_item ); 
  237.         [self setMeta: psz_##foo forLabel: o_##foo##_txt]; 
  238.         FREENULL( psz_##foo );
  239.         /* fill the other fields */
  240.         SET( author, Artist );
  241.         SET( collection, Album );
  242.         SET( seqNum, TrackNum );
  243.         SET( genre, Genre );
  244.         SET( copyright, Copyright );
  245.         SET( publisher, Publisher );
  246.         SET( nowPlaying, NowPlaying );
  247.         SET( language, Language );
  248.         SET( date, Date );
  249.         SET( description, Description );
  250.     #undef SET
  251.         char *psz_meta;
  252.         NSImage *o_image;
  253.         psz_meta = input_item_GetArtURL( p_item );
  254.         if( psz_meta && !strncmp( psz_meta, "file://", 7 ) && decode_URI( psz_meta + 7 ) )
  255.             o_image = [[NSImage alloc] initWithContentsOfFile: [NSString stringWithUTF8String: psz_meta+7]];
  256.         else
  257.             o_image = [[NSImage imageNamed: @"noart.png"] retain];
  258.         [o_image_well setImage: o_image];
  259.         [o_image release];
  260.         FREENULL( psz_meta );
  261.     }
  262.     /* reload the advanced table */
  263.     [rootItem refresh];
  264.     [o_outline_view reloadData];
  265.     /* update the stats once to display p_item change faster */
  266.     [self updateStatistics: nil];
  267. }
  268. - (void)setMeta: (char *)psz_meta forLabel: (id)theItem
  269. {
  270.     if( psz_meta != NULL && *psz_meta)
  271.         [theItem setStringValue: [NSString stringWithUTF8String:psz_meta]];
  272.     else
  273.         [theItem setStringValue: @""];
  274. }
  275. - (void)updateStatistics:(NSTimer*)theTimer
  276. {
  277.     if( !p_item || !p_item->p_stats )
  278.     {
  279.         [self initMediaPanelStats];
  280.         return;
  281.     }
  282.     vlc_mutex_lock( &p_item->p_stats->lock );
  283.     /* input */
  284.     [o_read_bytes_txt setStringValue: [NSString stringWithFormat:
  285.         @"%8.0f kB", (float)(p_item->p_stats->i_read_bytes)/1000]];
  286.     [o_input_bitrate_txt setStringValue: [NSString stringWithFormat:
  287.         @"%6.0f kb/s", (float)(p_item->p_stats->f_input_bitrate)*8000]];
  288.     [o_demux_bytes_txt setStringValue: [NSString stringWithFormat:
  289.         @"%8.0f kB", (float)(p_item->p_stats->i_demux_read_bytes)/1000]];
  290.     [o_demux_bitrate_txt setStringValue: [NSString stringWithFormat:
  291.         @"%6.0f kb/s", (float)(p_item->p_stats->f_demux_bitrate)*8000]];
  292.     /* Video */
  293.     [o_video_decoded_txt setIntValue: p_item->p_stats->i_decoded_video];
  294.     [o_displayed_txt setIntValue: p_item->p_stats->i_displayed_pictures];
  295.     [o_lost_frames_txt setIntValue: p_item->p_stats->i_lost_pictures];
  296.     float f_fps = 0;
  297.     /* FIXME: input_Control( p_item, INPUT_GET_VIDEO_FPS, &f_fps ); */
  298.     [o_fps_txt setFloatValue: f_fps];
  299.     /* Sout */
  300.     [o_sent_packets_txt setIntValue: p_item->p_stats->i_sent_packets];
  301.     [o_sent_bytes_txt setStringValue: [NSString stringWithFormat: @"%8.0f kB",
  302.         (float)(p_item->p_stats->i_sent_bytes)/1000]];
  303.     [o_sent_bitrate_txt setStringValue: [NSString stringWithFormat:
  304.         @"%6.0f kb/s", (float)(p_item->p_stats->f_send_bitrate*8)*1000]];
  305.     /* Audio */
  306.     [o_audio_decoded_txt setIntValue: p_item->p_stats->i_decoded_audio];
  307.     [o_played_abuffers_txt setIntValue: p_item->p_stats->i_played_abuffers];
  308.     [o_lost_abuffers_txt setIntValue: p_item->p_stats->i_lost_abuffers];
  309.     vlc_mutex_unlock( &p_item->p_stats->lock );
  310. }
  311. - (IBAction)metaFieldChanged:(id)sender
  312. {
  313.     [o_saveMetaData_btn setEnabled: YES];
  314. }
  315. - (IBAction)saveMetaData:(id)sender
  316. {
  317.     playlist_t * p_playlist = pl_Hold( VLCIntf );
  318.     vlc_value_t val;
  319.     if( !p_item ) goto error;
  320.     meta_export_t p_export;
  321.     p_export.p_item = p_item;
  322.     /* we can write meta data only in a file */
  323.     vlc_mutex_lock( &p_item->lock );
  324.     int i_type = p_item->i_type;
  325.     vlc_mutex_unlock( &p_item->lock );
  326.     if( i_type != ITEM_TYPE_FILE )
  327.         goto error;
  328.     char *psz_uri_orig = input_item_GetURI( p_item );
  329.     char *psz_uri = psz_uri_orig;
  330.     if( !strncmp( psz_uri, "file://", 7 ) )
  331.         psz_uri += 7; /* strlen("file://") = 7 */
  332.     p_export.psz_file = strndup( psz_uri, PATH_MAX );
  333.     free( psz_uri_orig );
  334.     #define utf8( o_blub ) 
  335.         [[o_blub stringValue] UTF8String]
  336.     input_item_SetName( p_item, utf8( o_title_txt ) );
  337.     input_item_SetTitle( p_item, utf8( o_title_txt ) );
  338.     input_item_SetArtist( p_item, utf8( o_author_txt ) );
  339.     input_item_SetAlbum( p_item, utf8( o_collection_txt ) );
  340.     input_item_SetGenre( p_item, utf8( o_genre_txt ) );
  341.     input_item_SetTrackNum( p_item, utf8( o_seqNum_txt ) );
  342.     input_item_SetDate( p_item, utf8( o_date_txt ) );
  343.     input_item_SetCopyright( p_item, utf8( o_copyright_txt ) );
  344.     input_item_SetPublisher( p_item, utf8( o_publisher_txt ) );
  345.     input_item_SetDescription( p_item, utf8( o_description_txt ) );
  346.     input_item_SetLanguage( p_item, utf8( o_language_txt ) );
  347.     PL_LOCK;
  348.     p_playlist->p_private = &p_export;
  349.     module_t *p_mod = module_need( p_playlist, "meta writer", NULL, false );
  350.     if( p_mod )
  351.         module_unneed( p_playlist, p_mod );
  352.     PL_UNLOCK;
  353.     val.b_bool = true;
  354.     var_Set( p_playlist, "intf-change", val );
  355.     [self updatePanelWithItem: p_item];
  356.     pl_Release( VLCIntf );
  357.     [o_saveMetaData_btn setEnabled: NO];
  358.     return;
  359. error:
  360.     pl_Release( VLCIntf );
  361.     NSRunAlertPanel(_NS("Error while saving meta"),
  362.         _NS("VLC was unable to save the meta data."),
  363.         _NS("OK"), nil, nil);
  364. }
  365. - (IBAction)downloadCoverArt:(id)sender
  366. {
  367.     playlist_t * p_playlist = pl_Hold( VLCIntf );
  368.     if( p_item) playlist_AskForArtEnqueue( p_playlist, p_item, pl_Unlocked );
  369.     pl_Release( VLCIntf );
  370. }
  371. - (input_item_t *)item
  372. {
  373.     if( p_item ) vlc_gc_incref( p_item );
  374.     return p_item;
  375. }
  376. @end
  377. @implementation VLCInfo (NSMenuValidation)
  378. - (BOOL)validateMenuItem:(NSMenuItem *)o_mi
  379. {
  380.     BOOL bEnabled = TRUE;
  381.     if( [[o_mi title] isEqualToString: _NS("Information")] )
  382.     {
  383.         return ![[[VLCMain sharedInstance] playlist] isSelectionEmpty];
  384.     }
  385.     return TRUE;
  386. }
  387. @end
  388. @implementation VLCInfo (NSTableDataSource)
  389. - (NSInteger)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item
  390. {
  391.     return (item == nil) ? [rootItem numberOfChildren] : [item numberOfChildren];
  392. }
  393. - (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item {
  394.     return ([item numberOfChildren] > 0);
  395. }
  396. - (id)outlineView:(NSOutlineView *)outlineView child:(NSInteger)index ofItem:(id)item
  397. {
  398.     return (item == nil) ? [rootItem childAtIndex:index] : (id)[item childAtIndex:index];
  399. }
  400. - (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item
  401. {
  402.     if ([[tableColumn identifier] isEqualToString:@"0"])
  403.     {
  404.         return (item == nil) ? @"" : (id)[item name];
  405.     }
  406.     else
  407.     {
  408.         return (item == nil) ? @"" : (id)[item value];
  409.     }
  410. }
  411. @end
  412. @implementation VLCInfoTreeItem
  413. #define IsALeafNode ((id)-1)
  414. - (id)initWithName: (NSString *)o_item_name value: (NSString *)o_item_value ID: (int)i_id
  415.        parent:(VLCInfoTreeItem *)o_parent_item
  416. {
  417.     self = [super init];
  418.     if( self != nil )
  419.     {
  420.         o_name = [o_item_name copy];
  421.         o_value = [o_item_value copy];
  422.         i_object_id = i_id;
  423.         o_parent = o_parent_item;
  424.         p_item = [[[VLCMain sharedInstance] info] item];
  425.         o_children = nil;
  426.     }
  427.     return( self );
  428. }
  429. - (id)init
  430. {
  431.     return [self initWithName:@"main" value:@"" ID:-1 parent:nil];
  432. }
  433. - (void)dealloc
  434. {
  435.     if( o_children != IsALeafNode ) [o_children release];
  436.     [o_name release];
  437.     [o_value release];
  438.     if( p_item ) vlc_gc_decref( p_item );
  439.     [super dealloc];
  440. }
  441. /* Creates and returns the array of children
  442.  * Loads children incrementally */
  443. - (NSArray *)children
  444. {
  445.     if( !p_item ) return nil;
  446.     if (o_children == NULL)
  447.     {
  448.         int i;
  449.         if( i_object_id == -1 )
  450.         {
  451.             vlc_mutex_lock( &p_item->lock );
  452.             o_children = [[NSMutableArray alloc] initWithCapacity: p_item->i_categories];
  453.             for (i = 0 ; i < p_item->i_categories ; i++)
  454.             {
  455.                 NSString * name = [NSString stringWithUTF8String: p_item->pp_categories[i]->psz_name];
  456.                 VLCInfoTreeItem * item = [[VLCInfoTreeItem alloc] initWithName:name value:@"" ID:i parent:self];
  457.                 [item autorelease];
  458.                 [o_children addObject:item];
  459.             }
  460.             vlc_mutex_unlock( &p_item->lock );
  461.         }
  462.         else if( o_parent->i_object_id == -1 )
  463.         {
  464.             vlc_mutex_lock( &p_item->lock );
  465.             info_category_t * cat = p_item->pp_categories[i_object_id];
  466.             o_children = [[NSMutableArray alloc] initWithCapacity: cat->i_infos];
  467.             for (i = 0 ; i < cat->i_infos ; i++)
  468.             {
  469.                 NSString * name = [NSString stringWithUTF8String: cat->pp_infos[i]->psz_name];
  470.                 NSString * value = [NSString stringWithUTF8String: cat->pp_infos[i]->psz_value ? : ""];
  471.                 VLCInfoTreeItem * item = [[VLCInfoTreeItem alloc] initWithName:name value:value ID:i parent:self];
  472.                 [item autorelease];
  473.                 [o_children addObject:item];
  474.             }
  475.             vlc_mutex_unlock( &p_item->lock );
  476.         }
  477.         else
  478.         {
  479.             o_children = IsALeafNode;
  480.         }
  481.     }
  482.     return o_children;
  483. }
  484. - (NSString *)name
  485. {
  486.     return [[o_name retain] autorelease];
  487. }
  488. - (NSString *)value
  489. {
  490.     return [[o_value retain] autorelease];
  491. }
  492. - (void)refresh
  493. {
  494.     input_item_t * oldItem = p_item;
  495.     p_item = [[[VLCMain sharedInstance] info] item];
  496.     if( oldItem && oldItem != p_item ) vlc_gc_decref( oldItem );
  497.     [o_children release];
  498.     o_children = nil;
  499. }
  500. - (VLCInfoTreeItem *)childAtIndex:(NSUInteger)i_index {
  501.     return [[self children] objectAtIndex:i_index];
  502. }
  503. - (NSInteger)numberOfChildren {
  504.     id i_tmp = [self children];
  505.     return ( i_tmp == IsALeafNode ) ? (-1) : (int)[i_tmp count];
  506. }
  507. @end