00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <stdlib.h>
00024 #include <stdio.h>
00025 #include <string.h>
00026
00027 #include <vlc/vlc.h>
00028 #include <vlc/input.h>
00029
00030 #include "vlc_playlist.h"
00031
00032 #undef PLAYLIST_DEBUG
00033
00034
00035
00036
00037
00038
00039 playlist_item_t *playlist_FindDirectParent( playlist_t *p_playlist,
00040 playlist_item_t *, int );
00041
00042 playlist_item_t *playlist_RecursiveFindNext( playlist_t *p_playlist,
00043 int i_view,
00044 playlist_item_t *p_root,
00045 playlist_item_t *p_item,
00046 playlist_item_t *p_parent );
00047
00048 playlist_item_t *playlist_RecursiveFindPrev( playlist_t *p_playlist,
00049 int i_view,
00050 playlist_item_t *p_root,
00051 playlist_item_t *p_item,
00052 playlist_item_t *p_parent );
00053
00054 void playlist_NodeDump( playlist_t *p_playlist, playlist_item_t *p_item,
00055 int i_level );
00056
00057
00058
00059
00060
00068 playlist_view_t * playlist_ViewCreate( playlist_t *p_playlist, int i_id,
00069 char *psz_name )
00070 {
00071 playlist_view_t * p_view;
00072
00073 p_view = malloc( sizeof( playlist_view_t ) );
00074
00075 memset( p_view, 0, sizeof( playlist_view_t ) );
00076
00077 p_view->p_root = playlist_NodeCreate( p_playlist, i_id, NULL, NULL );
00078 p_view->i_id = i_id;
00079 p_view->psz_name = psz_name ? strdup( psz_name ) : strdup(_("Undefined") );
00080
00081 return p_view;
00082 }
00083
00093 int playlist_ViewInsert( playlist_t *p_playlist, int i_id, char *psz_name )
00094 {
00095 playlist_view_t *p_view =
00096 playlist_ViewCreate( p_playlist, i_id , psz_name );
00097 if( !p_view )
00098 {
00099 msg_Err( p_playlist, "Creation failed" );
00100 return VLC_EGENERIC;
00101 }
00102
00103 vlc_mutex_lock( &p_playlist->object_lock );
00104
00105 INSERT_ELEM( p_playlist->pp_views, p_playlist->i_views,
00106 p_playlist->i_views, p_view );
00107
00108 vlc_mutex_unlock( &p_playlist->object_lock );
00109 return VLC_SUCCESS;
00110 }
00111
00112
00121 int playlist_ViewDelete( playlist_t *p_playlist,playlist_view_t *p_view )
00122 {
00123 playlist_NodeDelete( p_playlist, p_view->p_root, VLC_TRUE, VLC_TRUE );
00124 REMOVE_ELEM( p_playlist->pp_views, p_playlist->i_views, 0 );
00125 return VLC_SUCCESS;
00126 }
00127
00128
00136 int playlist_ViewDump( playlist_t *p_playlist, playlist_view_t *p_view )
00137 {
00138 #ifdef PLAYLIST_DEBUG
00139 msg_Dbg( p_playlist, "dumping view %i",p_view->i_id );
00140 playlist_NodeDump( p_playlist,p_view->p_root, 1 );
00141 #endif
00142 return VLC_SUCCESS;
00143 }
00144
00152 int playlist_ViewItemCount( playlist_t *p_playlist,
00153 playlist_view_t *p_view )
00154 {
00155 return playlist_NodeChildrenCount( p_playlist, p_view->p_root );
00156 }
00157
00158
00166 int playlist_ViewUpdate( playlist_t *p_playlist, int i_view)
00167 {
00168 playlist_view_t *p_view = playlist_ViewFind( p_playlist, i_view );
00169
00170 if( p_view == NULL )
00171 {
00172 return VLC_EGENERIC;
00173 }
00174
00175 if( i_view == VIEW_ALL )
00176 {
00177 p_view->p_root->i_children = p_playlist->i_size;
00178 p_view->p_root->pp_children = p_playlist->pp_items;
00179 }
00180
00181
00182 if( i_view >= VIEW_FIRST_SORTED )
00183 {
00184 int i_sort_type;
00185 playlist_ViewEmpty( p_playlist, i_view, VLC_FALSE );
00186
00187 switch( i_view )
00188 {
00189 case VIEW_S_AUTHOR: i_sort_type = SORT_AUTHOR;break;
00190 case VIEW_S_ALBUM: i_sort_type = SORT_ALBUM;break;
00191 case VIEW_S_GENRE: i_sort_type = SORT_GENRE;break;
00192 default: i_sort_type = SORT_AUTHOR;
00193 }
00194 playlist_NodeGroup( p_playlist, i_view, p_view->p_root,
00195 p_playlist->pp_items,p_playlist->i_size,
00196 i_sort_type, ORDER_NORMAL );
00197 }
00198
00199
00200 return VLC_SUCCESS;
00201 }
00202
00203
00211 playlist_view_t *playlist_ViewFind( playlist_t *p_playlist, int i_id )
00212 {
00213 int i;
00214 for( i=0 ; i< p_playlist->i_views ; i++ )
00215 {
00216 if( p_playlist->pp_views[i]->i_id == i_id )
00217 {
00218 return p_playlist->pp_views[i];
00219 }
00220 }
00221 return NULL;
00222 }
00223
00224
00225 int playlist_ViewEmpty( playlist_t *p_playlist, int i_view,
00226 vlc_bool_t b_delete_items )
00227 {
00228 playlist_view_t *p_view = playlist_ViewFind( p_playlist, i_view );
00229
00230 if( p_view == NULL )
00231 {
00232 return VLC_EGENERIC;
00233 }
00234
00235 return playlist_NodeEmpty( p_playlist, p_view->p_root, b_delete_items );
00236 }
00237
00238
00239
00240
00241
00242
00243
00252 playlist_item_t * playlist_NodeCreate( playlist_t *p_playlist, int i_view,
00253 char *psz_name,
00254 playlist_item_t *p_parent )
00255 {
00256
00257 playlist_item_t *p_item = (playlist_item_t *)malloc(
00258 sizeof( playlist_item_t ) );
00259 vlc_value_t val;
00260 playlist_add_t *p_add;
00261
00262 if( p_item == NULL )
00263 {
00264 return NULL;
00265 }
00266 p_add = (playlist_add_t*)malloc( sizeof(playlist_add_t) );
00267 if( p_add == NULL )
00268 {
00269 free( p_item );
00270 return NULL;
00271 }
00272 vlc_input_item_Init( VLC_OBJECT(p_playlist), &p_item->input );
00273
00274 if( psz_name != NULL )
00275 {
00276 p_item->input.psz_name = strdup( psz_name );
00277 }
00278 else
00279 {
00280 p_item->input.psz_name = strdup( _("Undefined") );
00281 }
00282
00283 p_item->input.psz_uri = NULL;
00284
00285 p_item->b_enabled = VLC_TRUE;
00286 p_item->i_nb_played = 0;
00287
00288 p_item->i_flags = 0;
00289
00290 p_item->i_children = 0;
00291 p_item->pp_children = NULL;
00292
00293 p_item->input.i_duration = -1;
00294 p_item->input.ppsz_options = NULL;
00295 p_item->input.i_options = 0;
00296 p_item->input.i_categories = 0;
00297 p_item->input.pp_categories = NULL;
00298 p_item->input.i_id = ++p_playlist->i_last_id;
00299
00300 p_item->input.i_type = ITEM_TYPE_NODE;
00301
00302 p_item->pp_parents = NULL;
00303 p_item->i_parents = 0;
00304 p_item->i_serial = 0;
00305
00306 p_item->i_flags |= PLAYLIST_SKIP_FLAG;
00307
00308 vlc_mutex_init( p_playlist, &p_item->input.lock );
00309
00310 INSERT_ELEM( p_playlist->pp_all_items,
00311 p_playlist->i_all_size,
00312 p_playlist->i_all_size,
00313 p_item );
00314
00315 if( p_parent != NULL )
00316 {
00317 playlist_NodeAppend( p_playlist, i_view, p_item, p_parent );
00318 }
00319
00320 p_add->i_node = p_parent ? p_parent->input.i_id : -1;
00321 p_add->i_item = p_item->input.i_id;
00322 p_add->i_view = i_view;
00323 val.p_address = p_add;
00324 var_Set( p_playlist, "item-append", val);
00325
00326 free( p_add );
00327
00328 return p_item;
00329 }
00330
00341 int playlist_NodeEmpty( playlist_t *p_playlist, playlist_item_t *p_root,
00342 vlc_bool_t b_delete_items )
00343 {
00344 int i;
00345 if( p_root->i_children == -1 )
00346 {
00347 return VLC_EGENERIC;
00348 }
00349
00350
00351 for( i = p_root->i_children-1 ; i >= 0 ;i-- )
00352 {
00353 if( p_root->pp_children[i]->i_children > -1 )
00354 {
00355 playlist_NodeDelete( p_playlist, p_root->pp_children[i],
00356 b_delete_items , VLC_FALSE );
00357 }
00358 else if( b_delete_items )
00359 {
00360
00361 playlist_Delete( p_playlist, p_root->pp_children[i]->input.i_id );
00362 }
00363 }
00364 return VLC_SUCCESS;
00365 }
00366
00375 int playlist_NodeDelete( playlist_t *p_playlist, playlist_item_t *p_root,
00376 vlc_bool_t b_delete_items, vlc_bool_t b_force )
00377 {
00378 int i, i_top, i_bottom;
00379 if( p_root->i_children == -1 )
00380 {
00381 return VLC_EGENERIC;
00382 }
00383
00384
00385 for( i = p_root->i_children - 1 ; i >= 0; i-- )
00386 {
00387 if( p_root->pp_children[i]->i_children > -1 )
00388 {
00389 playlist_NodeDelete( p_playlist, p_root->pp_children[i],
00390 b_delete_items , b_force );
00391 }
00392 else if( b_delete_items )
00393 {
00394
00395 playlist_Delete( p_playlist, p_root->pp_children[i]->input.i_id );
00396 }
00397 }
00398
00399 if( p_root->i_flags & PLAYLIST_RO_FLAG && !b_force )
00400 {
00401 }
00402 else
00403 {
00404 for( i = 0 ; i< p_root->i_parents; i++ )
00405 {
00406 playlist_NodeRemoveItem( p_playlist, p_root,
00407 p_root->pp_parents[i]->p_parent );
00408 }
00409 var_SetInteger( p_playlist, "item-deleted", p_root->input.i_id );
00410
00411 i_bottom = 0; i_top = p_playlist->i_all_size - 1;
00412 i = i_top / 2;
00413 while( p_playlist->pp_all_items[i]->input.i_id != p_root->input.i_id &&
00414 i_top > i_bottom )
00415 {
00416 if( p_playlist->pp_all_items[i]->input.i_id < p_root->input.i_id )
00417 {
00418 i_bottom = i + 1;
00419 }
00420 else
00421 {
00422 i_top = i - 1;
00423 }
00424 i = i_bottom + ( i_top - i_bottom ) / 2;
00425 }
00426 if( p_playlist->pp_all_items[i]->input.i_id == p_root->input.i_id )
00427 {
00428 REMOVE_ELEM( p_playlist->pp_all_items, p_playlist->i_all_size, i );
00429 }
00430 playlist_ItemDelete( p_root );
00431 }
00432 return VLC_SUCCESS;
00433 }
00434
00435
00445 int playlist_NodeAppend( playlist_t *p_playlist,
00446 int i_view,
00447 playlist_item_t *p_item,
00448 playlist_item_t *p_parent )
00449 {
00450 return playlist_NodeInsert( p_playlist, i_view, p_item, p_parent, -1 );
00451 }
00452
00453 int playlist_NodeInsert( playlist_t *p_playlist,
00454 int i_view,
00455 playlist_item_t *p_item,
00456 playlist_item_t *p_parent,
00457 int i_position )
00458 {
00459 int i;
00460 vlc_bool_t b_found = VLC_FALSE;
00461 if( !p_parent || p_parent->i_children == -1 )
00462 {
00463 msg_Err( p_playlist, "invalid node" );
00464 return VLC_EGENERIC;
00465 }
00466
00467 if( i_position == -1 ) i_position = p_parent->i_children ;
00468
00469 INSERT_ELEM( p_parent->pp_children,
00470 p_parent->i_children,
00471 i_position,
00472 p_item );
00473
00474
00475 for( i= 0; i< p_item->i_parents ; i++ )
00476 {
00477 if( p_item->pp_parents[i]->i_view == i_view )
00478 {
00479 b_found = VLC_TRUE;
00480 break;
00481 }
00482 }
00483 if( b_found == VLC_FALSE )
00484 {
00485 struct item_parent_t *p_ip = (struct item_parent_t *)
00486 malloc(sizeof(struct item_parent_t) );
00487 p_ip->i_view = i_view;
00488 p_ip->p_parent = p_parent;
00489
00490 INSERT_ELEM( p_item->pp_parents,
00491 p_item->i_parents, p_item->i_parents,
00492 p_ip );
00493 }
00494
00495
00496 p_parent->i_serial++;
00497 return VLC_SUCCESS;
00498 }
00499
00508 int playlist_NodeRemoveParent( playlist_t *p_playlist,
00509 playlist_item_t *p_item,
00510 playlist_item_t *p_parent )
00511 {
00512 int i;
00513 if( !p_parent || p_parent->i_children == -1 )
00514 {
00515 msg_Err( p_playlist, "invalid node" );
00516 }
00517
00518 for( i = 0; i < p_item->i_parents; i++ )
00519 {
00520 if( p_item->pp_parents[i]->p_parent == p_parent )
00521 {
00522 if( p_item->pp_parents[i] )
00523 {
00524 free( p_item->pp_parents[i] );
00525 }
00526 REMOVE_ELEM( p_item->pp_parents, p_item->i_parents, i );
00527 }
00528 }
00529 p_item->i_serial++;
00530 return VLC_SUCCESS;
00531 }
00532
00541 int playlist_NodeRemoveItem( playlist_t *p_playlist,
00542 playlist_item_t *p_item,
00543 playlist_item_t *p_parent )
00544 {
00545 int i;
00546 for( i= 0; i< p_parent->i_children ; i++ )
00547 {
00548 if( p_parent->pp_children[i] == p_item )
00549 {
00550 REMOVE_ELEM( p_parent->pp_children, p_parent->i_children, i );
00551 }
00552 }
00553
00554
00555 p_parent->i_serial++;
00556
00557 return VLC_SUCCESS;
00558 }
00559
00560
00568 int playlist_NodeChildrenCount( playlist_t *p_playlist, playlist_item_t*p_node)
00569 {
00570 int i;
00571 int i_nb = 0;
00572 if( p_node->i_children == -1 )
00573 {
00574 return 0;
00575 }
00576
00577 for( i=0 ; i< p_node->i_children;i++ )
00578 {
00579 if( p_node->pp_children[i]->i_children == -1 )
00580 {
00581 i_nb++;
00582 }
00583 else
00584 {
00585 i_nb += playlist_NodeChildrenCount( p_playlist,
00586 p_node->pp_children[i] );
00587 }
00588 }
00589 return i_nb;
00590 }
00591
00599 playlist_item_t *playlist_ChildSearchName( playlist_item_t *p_node,
00600 const char *psz_search )
00601 {
00602 int i;
00603
00604 if( p_node->i_children < 0 )
00605 {
00606 return NULL;
00607 }
00608 for( i = 0 ; i< p_node->i_children; i++ )
00609 {
00610 if( !strcmp( p_node->pp_children[i]->input.psz_name, psz_search ) )
00611 {
00612 return p_node->pp_children[i];
00613 }
00614 }
00615 return NULL;
00616 }
00617
00618
00619
00620
00621
00622
00633 playlist_item_t *playlist_FindNextFromParent( playlist_t *p_playlist,
00634 int i_view,
00635 playlist_item_t *p_root,
00636 playlist_item_t *p_node,
00637 playlist_item_t *p_item )
00638 {
00639 playlist_item_t *p_search, *p_next;
00640
00641 #ifdef PLAYLIST_DEBUG
00642 if( p_item != NULL )
00643 {
00644 msg_Dbg( p_playlist, "finding next of %s within %s - root %s",
00645 p_item->input.psz_name, p_node->input.psz_name,
00646 p_root->input.psz_name );
00647 }
00648 else
00649 {
00650 msg_Dbg( p_playlist, "finding something to play within %s -root %s",
00651 p_node->input.psz_name, p_root->input.psz_name );
00652
00653 }
00654 #endif
00655
00656 if( !p_node || p_node->i_children == -1 )
00657 {
00658 msg_Err( p_playlist,"invalid arguments for FindNextFromParent" );
00659 return NULL;
00660 }
00661
00662
00663 if( p_item != NULL )
00664 {
00665 p_search = playlist_FindDirectParent( p_playlist, p_item, i_view );
00666 if( p_search == NULL )
00667 {
00668 msg_Err( p_playlist, "parent node not found" );
00669 return NULL;
00670 }
00671 }
00672 else
00673 {
00674 p_search = p_node;
00675 }
00676
00677
00678 p_next = playlist_RecursiveFindNext( p_playlist,i_view,
00679 p_node, p_item, p_search );
00680
00681
00682 if( p_next == NULL )
00683 {
00684 if( p_playlist->b_go_next )
00685 {
00686 #ifdef PLAYLIST_DEBUG
00687 msg_Dbg( p_playlist, "Moving on to next node: search from %s",
00688 p_root->input.psz_name );
00689 #endif
00690 p_next = playlist_RecursiveFindNext( p_playlist, i_view,
00691 p_root, p_item, p_search );
00692 if( p_next == NULL )
00693 {
00694 return NULL;
00695 }
00696
00697 p_playlist->status.p_node = p_root;
00698 }
00699 else
00700 {
00701 #ifdef PLAYLIST_DEBUG
00702 msg_Dbg( p_playlist, "Not moving on to next node: you loose" );
00703 #endif
00704 return NULL;
00705 }
00706 }
00707 return p_next;
00708 }
00709
00720 playlist_item_t *playlist_FindPrevFromParent( playlist_t *p_playlist,
00721 int i_view,
00722 playlist_item_t *p_root,
00723 playlist_item_t *p_node,
00724 playlist_item_t *p_item )
00725 {
00726 playlist_item_t *p_search, *p_next;
00727
00728 #ifdef PLAYLIST_DEBUG
00729 if( p_item != NULL )
00730 {
00731 msg_Dbg( p_playlist, "Finding prev of %s within %s",
00732 p_item->input.psz_name, p_node->input.psz_name );
00733 }
00734 else
00735 {
00736 msg_Dbg( p_playlist, "Finding prev from %s",p_node->input.psz_name );
00737 }
00738 #endif
00739
00740 if( !p_node || p_node->i_children == -1 )
00741 {
00742 msg_Err( p_playlist,"invalid arguments for FindPrevFromParent" );
00743 return NULL;
00744 }
00745
00746
00747 if( p_item != NULL )
00748 {
00749 p_search = playlist_FindDirectParent( p_playlist, p_item, i_view );
00750 if( p_search == NULL )
00751 {
00752 msg_Err( p_playlist, "parent node not found" );
00753 return NULL;
00754 }
00755 }
00756 else
00757 {
00758 p_search = p_node;
00759 }
00760
00761
00762 p_next = playlist_RecursiveFindPrev( p_playlist,i_view,
00763 p_node, p_item, p_search );
00764
00765 if( p_next == NULL )
00766 {
00767 if( p_playlist->b_go_next )
00768 {
00769 p_next = playlist_RecursiveFindPrev( p_playlist, i_view,
00770 p_root, p_item, p_search );
00771 if( p_next == NULL )
00772 {
00773 return NULL;
00774 }
00775
00776 p_playlist->status.p_node = p_root;
00777 }
00778 else
00779 {
00780 return NULL;
00781 }
00782 }
00783 return p_next;
00784 }
00785
00786
00787
00788
00789
00790
00791
00792 playlist_item_t *playlist_RecursiveFindNext( playlist_t *p_playlist,
00793 int i_view,
00794 playlist_item_t *p_root,
00795 playlist_item_t *p_item,
00796 playlist_item_t *p_parent )
00797 {
00798 int i;
00799 playlist_item_t *p_parent_parent;
00800
00801 for( i= 0 ; i < p_parent->i_children ; i++ )
00802 {
00803 if( p_parent->pp_children[i] == p_item || p_item == NULL )
00804 {
00805 if( p_item == NULL )
00806 {
00807 i = -1;
00808 }
00809 #ifdef PLAYLIST_DEBUG
00810 msg_Dbg( p_playlist,"Current item found, child %i of %s",
00811 i , p_parent->input.psz_name );
00812 #endif
00813
00814 if( i+1 >= p_parent->i_children )
00815 {
00816
00817 #ifdef PLAYLIST_DEBUG
00818 msg_Dbg( p_playlist, "Going up the tree,at parent of %s",
00819 p_parent->input.psz_name );
00820 #endif
00821 if( p_parent == p_root )
00822 {
00823 #ifdef PLAYLIST_DEBUG
00824 msg_Dbg( p_playlist, "At root item (%s)",
00825 p_root->input.psz_name );
00826 #endif
00827
00828 return NULL;
00829 }
00830
00831
00832 p_parent_parent = playlist_FindDirectParent( p_playlist,
00833 p_parent, i_view );
00834 if( p_parent_parent == NULL )
00835 {
00836 msg_Warn( p_playlist, "Unable to find parent !");
00837 return NULL;
00838 }
00839 return playlist_RecursiveFindNext( p_playlist, i_view,p_root,
00840 p_parent, p_parent_parent );
00841 }
00842 else
00843 {
00844 if( p_parent->pp_children[i+1]->i_children == -1 )
00845 {
00846
00847 #ifdef PLAYLIST_DEBUG
00848 msg_Dbg( p_playlist, "Playing child %i of %s",
00849 i+1 , p_parent->input.psz_name );
00850 #endif
00851 return p_parent->pp_children[i+1];
00852 }
00853 else if( p_parent->pp_children[i+1]->i_children > 0 )
00854 {
00855
00856 #ifdef PLAYLIST_DEBUG
00857 msg_Dbg( p_playlist, "%s is a node with children, "
00858 "playing the first",
00859 p_parent->pp_children[i+1]->input.psz_name);
00860 #endif
00861 if( p_parent->pp_children[i+1]->pp_children[0]
00862 ->i_children >= 0 )
00863 {
00864
00865 return playlist_RecursiveFindNext( p_playlist, i_view,
00866 p_root, NULL ,
00867 p_parent->pp_children[i+1]->pp_children[0]);
00868 }
00869 return p_parent->pp_children[i+1]->pp_children[0];
00870 }
00871 else
00872 {
00873
00874 #ifdef PLAYLIST_DEBUG
00875 msg_Dbg( p_playlist, "%s is a node with no children",
00876 p_parent->pp_children[i+1]->input.psz_name);
00877 #endif
00878 p_item = p_parent->pp_children[i+1];
00879 }
00880 }
00881 }
00882 }
00883
00884 return NULL;
00885 }
00886
00887
00888 playlist_item_t *playlist_RecursiveFindPrev( playlist_t *p_playlist,
00889 int i_view,
00890 playlist_item_t *p_root,
00891 playlist_item_t *p_item,
00892 playlist_item_t *p_parent )
00893 {
00894 int i;
00895 playlist_item_t *p_parent_parent;
00896
00897 for( i= p_parent->i_children - 1 ; i >= 0 ; i-- )
00898 {
00899 if( p_parent->pp_children[i] == p_item || p_item == NULL )
00900 {
00901 if( p_item == NULL )
00902 {
00903 i = -1;
00904 }
00905 #ifdef PLAYLIST_DEBUG
00906 msg_Dbg( p_playlist,"Current item found, child %i of %s",
00907 i , p_parent->input.psz_name );
00908 #endif
00909
00910 if( i < 1 )
00911 {
00912
00913 #ifdef PLAYLIST_DEBUG
00914 msg_Dbg( p_playlist, "Going up the tree,at parent of %s",
00915 p_parent->input.psz_name );
00916 #endif
00917 if( p_parent == p_root )
00918 {
00919 #ifdef PLAYLIST_DEBUG
00920 msg_Dbg( p_playlist, "At root item (%s)",
00921 p_root->input.psz_name );
00922 #endif
00923
00924 return NULL;
00925 }
00926
00927 p_parent_parent = playlist_FindDirectParent( p_playlist,
00928 p_parent, i_view );
00929 if( p_parent_parent == NULL )
00930 {
00931 #ifdef PLAYLIST_DEBUG
00932 msg_Dbg( p_playlist, "Mmmh, couldn't find parent" );
00933 #endif
00934 return NULL;
00935 }
00936 return playlist_RecursiveFindPrev( p_playlist, i_view,p_root,
00937 p_parent, p_parent_parent );
00938 }
00939 else
00940 {
00941 if( p_parent->pp_children[i-1]->i_children == -1 )
00942 {
00943
00944 #ifdef PLAYLIST_DEBUG
00945 msg_Dbg( p_playlist, "Playing child %i of %s",
00946 i-1, p_parent->input.psz_name );
00947 #endif
00948 return p_parent->pp_children[i-1];
00949 }
00950 else if( p_parent->pp_children[i-1]->i_children > 0 )
00951 {
00952
00953 #ifdef PLAYLIST_DEBUG
00954 msg_Dbg( p_playlist, "%s is a node with children,"
00955 " playing the last",
00956 p_parent->pp_children[i-1]->input.psz_name);
00957 #endif
00958 if( p_parent->pp_children[i-1]->pp_children[p_parent->
00959 pp_children[i-1]->i_children-1]->i_children >= 0 )
00960 {
00961
00962 return playlist_RecursiveFindPrev( p_playlist, i_view,
00963 p_root,NULL,
00964 p_parent->pp_children[i-1]->pp_children[
00965 p_parent->pp_children[i-1]->i_children-1]);
00966 }
00967 return p_parent->pp_children[i-1]->pp_children[
00968 p_parent->pp_children[i-1]->i_children-1];
00969 }
00970 else
00971 {
00972
00973 #ifdef PLAYLIST_DEBUG
00974 msg_Dbg( p_playlist, "%s is a node with no children",
00975 p_parent->pp_children[i-1]->input.psz_name);
00976 #endif
00977 p_item = p_parent->pp_children[i-1];
00978 }
00979 }
00980 }
00981 }
00982 return NULL;
00983 }
00984
00985
00986 playlist_item_t *playlist_FindDirectParent( playlist_t *p_playlist,
00987 playlist_item_t *p_item,
00988 int i_view )
00989 {
00990 int i = 0;
00991 for( i= 0; i< p_item->i_parents ; i++ )
00992 {
00993 if( p_item->pp_parents[i]->i_view == i_view )
00994 {
00995 return p_item->pp_parents[i]->p_parent;
00996 }
00997 }
00998 return NULL;
00999 }
01000
01001
01002 #ifdef PLAYLIST_DEBUG
01003
01004 void playlist_NodeDump( playlist_t *p_playlist, playlist_item_t *p_item,
01005 int i_level )
01006 {
01007 char str[512];
01008 int i;
01009
01010 if( i_level == 1 )
01011 {
01012 msg_Dbg( p_playlist, "%s (%i)",
01013 p_item->input.psz_name, p_item->i_children );
01014 }
01015
01016 if( p_item->i_children == -1 )
01017 {
01018 return;
01019 }
01020
01021 for( i = 0; i< p_item->i_children; i++ )
01022 {
01023 memset( str, 32, 512 );
01024 sprintf( str + 2 * i_level , "%s (%i)",
01025 p_item->pp_children[i]->input.psz_name,
01026 p_item->pp_children[i]->i_children );
01027 msg_Dbg( p_playlist, "%s",str );
01028 if( p_item->pp_children[i]->i_children >= 0 )
01029 {
01030 playlist_NodeDump( p_playlist, p_item->pp_children[i],
01031 i_level + 1 );
01032 }
01033 }
01034 return;
01035 }
01036 #endif