diff -NurwbBE main/Gui/app.c main.dev/Gui/app.c --- main/Gui/app.c 2003-03-20 15:41:32.000000000 +0300 +++ main.dev/Gui/app.c 2004-09-12 13:16:03.000000000 +0400 @@ -26,6 +26,7 @@ { evEqualizer, "evEqualizer" }, { evEqualizer, "evEqualeaser" }, { evPlayList, "evPlaylist" }, + { evShuffle, "evShuffle" }, { evExit, "evExit" }, { evIconify, "evIconify" }, { evIncBalance, "evIncBalance" }, diff -NurwbBE main/Gui/app.h main.dev/Gui/app.h --- main/Gui/app.h 2003-03-20 15:41:32.000000000 +0300 +++ main.dev/Gui/app.h 2004-09-12 13:16:03.000000000 +0400 @@ -59,7 +59,8 @@ #define evSetAspect 44 #define evSetAudio 45 #define evSetVideo 46 -// 47 ... +#define evShuffle 47 +// 48 ... #define evExit 1000 diff -NurwbBE main/Gui/cfg.c main.dev/Gui/cfg.c --- main/Gui/cfg.c 2004-07-30 19:58:36.000000000 +0400 +++ main.dev/Gui/cfg.c 2004-09-12 13:16:03.000000000 +0400 @@ -72,6 +72,8 @@ int gui_main_pos_y = -2; int gui_sub_pos_x = -1; int gui_sub_pos_y = -1; + +int gui_shuffle_playlist = 0; // --- extern char * get_path( char * filename ); @@ -163,6 +165,8 @@ { "gui_skin",&skinName,CONF_TYPE_STRING,0,0,0,NULL }, + { "gui_shuffle",&gui_shuffle_playlist,CONF_TYPE_FLAG,0,0,1,NULL }, + { "gui_save_pos", &gui_save_pos, CONF_TYPE_FLAG,0,0,1,NULL}, { "gui_main_pos_x", &gui_main_pos_x, CONF_TYPE_INT,0,0,0,NULL}, { "gui_main_pos_y", &gui_main_pos_y, CONF_TYPE_INT,0,0,0,NULL}, diff -NurwbBE main/Gui/interface.c main.dev/Gui/interface.c --- main/Gui/interface.c 2004-07-30 19:58:36.000000000 +0400 +++ main.dev/Gui/interface.c 2004-09-12 13:16:03.000000000 +0400 @@ -43,6 +43,12 @@ #include "../m_option.h" extern mixer_t mixer; // mixer from mplayer.c +extern int gui_shuffle_playlist; // gui_shuffle config variable from cfg.c +/* a "shuffle window" keeps track of recent prev/next jumps + in order to allow for more sensible prev/next operation */ +#define GUI_SHUFFLE_WINDOW_SIZE 16 +int shuffle_window[GUI_SHUFFLE_WINDOW_SIZE]; +int swi = -1; /* shuffle window index - current position in the shuffle window */ guiInterface_t guiIntfStruct; int guiWinID=-1; @@ -903,6 +909,9 @@ URLItem * url_item = (URLItem *)vparam; int is_added = True; + int next_pl_pos = -1, current_pl_pos = 0, pl_size, i; + plItem * it; + switch ( cmd ) { // --- handle playlist @@ -914,6 +923,8 @@ next->next=item; item->prev=next; } else { item->prev=item->next=NULL; plCurrent=plList=item; } list(); + /* any alteration of playlist invalidates current shuffle window */ + swi = -1; return NULL; case gtkInsertPlItem: // add item into playlist after current if ( plCurrent ) @@ -929,28 +940,111 @@ } else return gtkSet(gtkAddPlItem,0,(void*)item); + swi = -1; /* invalidate shuffle window */ return NULL; - case gtkGetNextPlItem: // get current item from playlist - if ( plCurrent && plCurrent->next) - { - plCurrent=plCurrent->next; - /*if ( !plCurrent && plList ) - { - plItem * next = plList; - while ( next->next ) { if ( !next->next ) break; next=next->next; } - plCurrent=next; - }*/ - return plCurrent; + case gtkGetNextPlItem: + case gtkGetPrevPlItem: + if ( plCurrent ) { + /* count current pl size. note the position of current entry. */ + for (pl_size = 0, it = plList; it; it = it->next, pl_size++) { + if (it == plCurrent) + current_pl_pos = pl_size; + } + /* initialize shuffle window, if needed */ + if (-1 == swi) { + for (i = 0; i < GUI_SHUFFLE_WINDOW_SIZE; i++) { + shuffle_window[i] = -1; + } + shuffle_window[(swi=0)] = current_pl_pos; + } else { + switch (cmd) { + case gtkGetNextPlItem: + if ((swi < GUI_SHUFFLE_WINDOW_SIZE - 1) + && (-1 != shuffle_window[swi+1])) { + /* just move on to the next item in window */ + next_pl_pos = shuffle_window[++swi]; } - return NULL; + break; case gtkGetPrevPlItem: - if ( plCurrent && plCurrent->prev) - { - plCurrent=plCurrent->prev; - //if ( !plCurrent && plList ) plCurrent=plList; - return plCurrent; + if ((swi > 0) + && (-1 != shuffle_window[swi-1])) { + /* move one step left in the window */ + next_pl_pos = shuffle_window[--swi]; + } + break; + } /* switch cmd */ + } + /* no items to the right of window index - determine the next entry to be played */ + if (next_pl_pos == -1) { + if (gui_shuffle_playlist) { + /* select random entry, avoiding dupes if possible. + (only do this on sufficiently big playlists) */ + do { + next_pl_pos = rand() % (pl_size + 1); + for (i = 0; + i < GUI_SHUFFLE_WINDOW_SIZE + && shuffle_window[i] != next_pl_pos; + i++); + } while (pl_size > GUI_SHUFFLE_WINDOW_SIZE * 2 + && i < GUI_SHUFFLE_WINDOW_SIZE); + } else { + switch (cmd) { + case gtkGetNextPlItem: + if (plCurrent->next) + next_pl_pos = current_pl_pos + 1; + break; + case gtkGetPrevPlItem: + if (plCurrent->prev) + next_pl_pos = current_pl_pos - 1; + break; + } /* switch cmd */ } - return NULL; + if (next_pl_pos != -1) { + /* record the selection made */ + switch (cmd) { + /* shift the window one position to left/right as needed, + depending on the command */ + case gtkGetNextPlItem: + if (swi >= GUI_SHUFFLE_WINDOW_SIZE - 1) { + for (swi = 0; + swi < GUI_SHUFFLE_WINDOW_SIZE - 1; + swi++) { + shuffle_window[swi] = shuffle_window[swi+1]; + } + } else { swi++; } + break; + case gtkGetPrevPlItem: + if (swi <= 0) { + for (swi = GUI_SHUFFLE_WINDOW_SIZE - 1; + swi > 0; + swi--) { + shuffle_window[swi] = shuffle_window[swi-1]; + } + } + break; + } /* switch cmd */ + shuffle_window[swi] = next_pl_pos; + } + } +/* + printf( "pl_size = %d, current_pl_pos = %d, next_pl_pos = %d, swi = %d\n", + pl_size, current_pl_pos, next_pl_pos, swi ); + printf( "shuffle_window = { "); + for (i = 0; i < GUI_SHUFFLE_WINDOW_SIZE; i++) { + if (i != 0) printf(", "); + printf("%d", shuffle_window[i]); + } + printf(" }\n"); +*/ + if (next_pl_pos != -1) { + /* set the current entry to plList[next_pl_pos] */ + for (plCurrent = plList; + next_pl_pos > 0 && plCurrent; + next_pl_pos--, plCurrent = plCurrent->next); + } + } /* if (plCurrent) */ + return plCurrent; + case gtkSetCurrPlItem: // set current item plCurrent=item; return plCurrent; @@ -975,7 +1069,7 @@ free( curr ); } mplCurr(); // Instead of using mplNext && mplPrev - + swi = -1; /* invalidate shuffle window */ return plCurrent; case gtkDelPl: // delete list { @@ -1001,6 +1095,7 @@ } plList=NULL; plCurrent=NULL; } + swi = -1; /* invalidate shuffle window */ return NULL; // ----- Handle url case gtkAddURLItem: diff -NurwbBE main/Gui/mplayer/gtk/menu.c main.dev/Gui/mplayer/gtk/menu.c --- main/Gui/mplayer/gtk/menu.c 2004-06-26 17:26:11.000000000 +0400 +++ main.dev/Gui/mplayer/gtk/menu.c 2004-09-12 13:16:03.000000000 +0400 @@ -18,6 +18,7 @@ #include "../../../libmpdemux/demuxer.h" extern mixer_t mixer; // mixer from mplayer.c +extern int gui_shuffle_playlist; // gui_shuffle config variable from cfg.c void ActivateMenuItem( int Item ) { @@ -467,6 +468,7 @@ MenuItem=AddMenuCheckItem( Menu,MSGTR_MENU_Mute,mixer.muted,evMute ); if ( !guiIntfStruct.AudioType ) gtk_widget_set_sensitive( MenuItem,FALSE ); AddMenuItem( Menu,MSGTR_MENU_PlayList, evPlayList ); + AddMenuCheckItem( Menu,MSGTR_MENU_Shuffle, gui_shuffle_playlist, evShuffle ); AddMenuItem( Menu,MSGTR_MENU_SkinBrowser, evSkinBrowser ); AddMenuItem( Menu,MSGTR_MENU_Preferences, evPreferences ); AddMenuItem( Menu,MSGTR_Equalizer, evEqualizer ); diff -NurwbBE main/Gui/mplayer/mw.c main.dev/Gui/mplayer/mw.c --- main/Gui/mplayer/mw.c 2004-06-26 17:26:11.000000000 +0400 +++ main.dev/Gui/mplayer/mw.c 2004-09-12 13:16:03.000000000 +0400 @@ -31,6 +31,7 @@ #include "widgets.h" extern mixer_t mixer; // mixer from mplayer.c +extern int gui_shuffle_playlist; // gui_shuffle config variable from cfg.c extern unsigned int GetTimerMS( void ); @@ -245,6 +246,7 @@ case evIncVolume: vo_x11_putkey( wsGrayMul ); break; case evDecVolume: vo_x11_putkey( wsGrayDiv ); break; case evMute: mixer_mute( &mixer ); break; + case evShuffle: gui_shuffle_playlist ^= 1; break; case evSetVolume: guiIntfStruct.Volume=param; diff -NurwbBE main/help/help_mp-en.h main.dev/help/help_mp-en.h --- main/help/help_mp-en.h 2004-09-08 07:51:37.000000000 +0400 +++ main.dev/help/help_mp-en.h 2004-09-12 13:16:04.000000000 +0400 @@ -597,6 +597,7 @@ #define MSGTR_MENU_AudioLanguages "Audio languages" #define MSGTR_MENU_SubtitleLanguages "Subtitle languages" #define MSGTR_MENU_PlayList "Playlist" +#define MSGTR_MENU_Shuffle "Shuffle" #define MSGTR_MENU_SkinBrowser "Skin browser" #define MSGTR_MENU_Preferences "Preferences" #define MSGTR_MENU_Exit "Exit..."