Main Page | Modules | Class Hierarchy | Class List | Directories | File List | Class Members | File Members | Related Pages

view.c

00001 /*****************************************************************************
00002  * view.c : Playlist views functions
00003  *****************************************************************************
00004  * Copyright (C) 1999-2004 the VideoLAN team
00005  * $Id: item.c 7997 2004-06-18 11:35:45Z sigmunau $
00006  *
00007  * Authors: Clément Stenac <[email protected]>
00008  *
00009  * This program is free software; you can redistribute it and/or modify
00010  * it under the terms of the GNU General Public License as published by
00011  * the Free Software Foundation; either version 2 of the License, or
00012  * (at your option) any later version.
00013  *
00014  * This program is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  * GNU General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU General Public License
00020  * along with this program; if not, write to the Free Software
00021  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
00022  *****************************************************************************/
00023 #include <stdlib.h>                                      /* free(), strtol() */
00024 #include <stdio.h>                                              /* sprintf() */
00025 #include <string.h>                                            /* strerror() */
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  * Local prototypes
00036  ************************************************************************/
00037 
00038 /* TODO: inline */
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  * Exported View management functions
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     /* Handle update of sorted views here */
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  * Exported Nodes management functions
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     /* Create the item */
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; /* Default behaviour */
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     /* Delete the children */
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             /* Delete the item here */
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     /* Delete the children */
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             /* Delete the item here */
00395             playlist_Delete( p_playlist, p_root->pp_children[i]->input.i_id );
00396         }
00397     }
00398     /* Delete the node */
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    /* Add the parent to the array */
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    /* Let the interface know this has been updated */
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    /* Let the interface know this has been updated */
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  * Tree functions
00621  **********************************************************************/
00622 
00633 playlist_item_t *playlist_FindNextFromParent( playlist_t *p_playlist,
00634                                         int i_view, /* FIXME: useless */
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     /* Find the parent node of the item */
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     /* Now, go up the tree until we find a suitable next item */
00678     p_next = playlist_RecursiveFindNext( p_playlist,i_view,
00679                                          p_node, p_item, p_search );
00680 
00681     /* Not found, do we go past p_node ? */
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             /* OK, we could continue, so set our current node to the root */
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     /* Find the parent node of the item */
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     /* Now, go up the tree until we find a suitable next item */
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             /* OK, we could continue, so set our current node to the root */
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  * Following functions are local
00788  ***********************************************************************/
00789 
00790 
00791 /* Recursively search the tree for next item */
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             /* We found our item */
00814             if( i+1 >= p_parent->i_children )
00815             {
00816                 /* Too far... */
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                     /* Hmm, seems it's the end for you, guy ! */
00828                     return NULL;
00829                 }
00830 
00831                 /* Go up one level */
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                     /* Cool, we have found a real item to play */
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                     /* Select the first child of this node */
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                         /* first child is a node ! */
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                     /* This node has no child... We must continue */
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     /* Just in case :) */
00884     return NULL;
00885 }
00886 
00887 /* Recursively search the tree for previous item */
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             /* We found our item */
00910             if( i < 1 )
00911             {
00912                 /* Too far... */
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                     /* Hmm, seems it's the end for you, guy ! */
00924                     return NULL;
00925                 }
00926                 /* Go up one level */
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                     /* Cool, we have found a real item to play */
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                     /* Select the last child of this node */
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                         /* Last child is a node */
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                     /* This node has no child... We must continue */
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 /* This function returns the parent of an item in a view */
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 /* This function dumps a node : to be used only for debug*/
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

Generated on Tue Dec 20 10:15:01 2005 for vlc-0.8.4a by  doxygen 1.4.2