//////////////////////////////////////////////////////////////////////////////// // Plainamp, Open source Winamp core // // Copyright © 2005 Sebastian Pipping // // --> http://www.hartwork.org // // This source code is released under the GNU General Public License (GPL). // See GPL.txt for details. Any non-GPL usage is strictly forbidden. //////////////////////////////////////////////////////////////////////////////// #include "Playlist.h" #include "AddDirectory.h" #include "Rebar.h" #include "Main.h" #include "Status.h" #include "Console.h" #include "Font.h" #include "Playback.h" #include "InputPlugin.h" #include "Prefs.h" #include "Config.h" #include "Unicode.h" #include "Path.h" #include "commdlg.h" HWND WindowPlaylist = NULL; // extern // WNDPROC WndprocPlaylistBackup = NULL; // int iCurIndex = -1; // int iMaxIndex = -1; // LRESULT CALLBACK WndprocPlaylist( HWND hwnd, UINT message, WPARAM wp, LPARAM lp ); void Playlist_SelectSingle( int iIndex ); struct PlaylistEntry { TCHAR * szFilename; // More to come }; /* /////////////////////////////////////////////////////////////////////////////// /// //////////////////////////////////////////////////////////////////////////////// int Playlist::GetCurIndex() { return iCurIndex; } //////////////////////////////////////////////////////////////////////////////// /// //////////////////////////////////////////////////////////////////////////////// int Playlist::GetMaxIndex() { return iMaxIndex; } //////////////////////////////////////////////////////////////////////////////// /// //////////////////////////////////////////////////////////////////////////////// bool Playlist::SetCurIndex( int iIndex ) { if( iIndex < 0 || iIndex > iMaxIndex ) return false; iCurIndex = iIndex; if( bPlaylistFollow ) { Playlist_SelectSingle( iCurIndex ); } return true; } */ //////////////////////////////////////////////////////////////////////////////// /// //////////////////////////////////////////////////////////////////////////////// bool Playlist::Create() { if( WindowPlaylist ) return false; // If this is not called a crash occurs PlaylistView::Create(); #ifndef NOGUI RECT ClientMain; GetClientRect( WindowMain, &ClientMain ); const int iClientHeight = ClientMain.bottom - ClientMain.top; const int iClientWidth = ClientMain.right - ClientMain.left; const int iPlaylistHeight = iClientHeight - iRebarHeight - iStatusHeight; WindowPlaylist = CreateWindowEx( WS_EX_CLIENTEDGE, TEXT( "LISTBOX" ), NULL, WS_VSCROLL | LBS_DISABLENOSCROLL | LBS_EXTENDEDSEL | LBS_HASSTRINGS | LBS_NOTIFY | LBS_NOINTEGRALHEIGHT | WS_CHILD | WS_VISIBLE, // 0, iRebarHeight, // + -2, iClientWidth, iPlaylistHeight, WindowMain, NULL, g_hInstance, NULL ); // Exchange window procedure WndprocPlaylistBackup = ( WNDPROC )GetWindowLong( WindowPlaylist, GWL_WNDPROC ); if( WndprocPlaylistBackup != NULL ) { SetWindowLong( WindowPlaylist, GWL_WNDPROC, ( LONG )WndprocPlaylist ); } Font::Apply( WindowPlaylist ); #endif NOGUI TCHAR * szPlaylistMind = new TCHAR[ iHomeDirLen + 12 + 1 ]; memcpy( szPlaylistMind, szHomeDir, iHomeDirLen * sizeof( TCHAR ) ); memcpy( szPlaylistMind + iHomeDirLen, TEXT( "Plainamp.m3u" ), 12 * sizeof( TCHAR ) ); szPlaylistMind[ iHomeDirLen + 12 ] = TEXT( '\0' ); Playlist::AppendPlaylistFile( szPlaylistMind ); return true; } //////////////////////////////////////////////////////////////////////////////// /// //////////////////////////////////////////////////////////////////////////////// inline void Playlist_SelectSingle( int iIndex ) { SendMessage( WindowPlaylist, LB_SETSEL, FALSE, -1 ); SendMessage( WindowPlaylist, LB_SETSEL, TRUE, iIndex ); } //////////////////////////////////////////////////////////////////////////////// /// //////////////////////////////////////////////////////////////////////////////// inline bool Playlist_IsSelected( int iIndex ) { return ( 0 != SendMessage( WindowPlaylist, LB_GETSEL, ( WPARAM )iIndex, 0 ) ); } //////////////////////////////////////////////////////////////////////////////// /// //////////////////////////////////////////////////////////////////////////////// inline bool Playlist_SelectModify( int iIndex, bool bSelected ) { return ( LB_ERR != SendMessage( WindowPlaylist, LB_SETSEL, ( WPARAM )( bSelected ? TRUE : FALSE ), iIndex ) ); } /* //////////////////////////////////////////////////////////////////////////////// /// //////////////////////////////////////////////////////////////////////////////// bool Playlist_Remove( int iIndex ) { if( iIndex < 0 || iIndex > iMaxIndex ) return false; // Get entry data PlaylistEntry * entry = ( PlaylistEntry * )SendMessage( WindowPlaylist, LB_GETITEMDATA, iIndex, 0 ); // Free data if( entry ) { if( entry->szFilename ) delete [] entry->szFilename; delete entry; } SendMessage( WindowPlaylist, LB_DELETESTRING, iIndex, 0 ); if( iIndex < iCurIndex ) iCurIndex--; if( ( iIndex == iCurIndex ) && ( iCurIndex == iMaxIndex ) ) iCurIndex = iMaxIndex - 1; iMaxIndex--; return true; } */ //////////////////////////////////////////////////////////////////////////////// /// //////////////////////////////////////////////////////////////////////////////// inline int Playlist_GetCount() { return ( int )SendMessage( WindowPlaylist, LB_GETCOUNT, 0, 0 ); } //////////////////////////////////////////////////////////////////////////////// /// //////////////////////////////////////////////////////////////////////////////// inline int Playlist_GetCaretIndex() { return ( int )SendMessage( WindowPlaylist, LB_GETCARETINDEX, 0, 0 ); } //////////////////////////////////////////////////////////////////////////////// /// //////////////////////////////////////////////////////////////////////////////// inline bool Playlist_SetCaretIndex( int iIndex ) { return ( LB_OKAY == SendMessage( WindowPlaylist, LB_SETCARETINDEX, ( WPARAM )iIndex, FALSE ) ); } //////////////////////////////////////////////////////////////////////////////// /// //////////////////////////////////////////////////////////////////////////////// inline int Playlist_GetSelCount() { return ( int )SendMessage( WindowPlaylist, LB_GETSELCOUNT, 0, 0 ); } /* //////////////////////////////////////////////////////////////////////////////// /// //////////////////////////////////////////////////////////////////////////////// int Playlist_MouseToIndex() { POINT p; GetCursorPos( &p ); ScreenToClient( WindowPlaylist, &p ); int iIndex = ( int )SendMessage( WindowPlaylist, LB_ITEMFROMPOINT, 0, p.x | ( p.y << 16 ) ); if( ( iIndex < 0 ) || ( iIndex > iMaxIndex ) ) return -1; else return iIndex; } //////////////////////////////////////////////////////////////////////////////// /// //////////////////////////////////////////////////////////////////////////////// bool Playlist::Clear() { if( iMaxIndex < 0 ) return false; int iCount = iMaxIndex + 1; while( iCount-- ) { Playlist_Remove( iCount ); } return true; } //////////////////////////////////////////////////////////////////////////////// /// //////////////////////////////////////////////////////////////////////////////// bool Playlist::RemoveSelected() { int iSelCount = Playlist_GetSelCount(); if( iSelCount < 0 ) return false; // Which items are selected? int * sel = new int[ iSelCount ]; LRESULT lResult = SendMessage( WindowPlaylist, LB_GETSELITEMS, ( WPARAM )iSelCount, ( LPARAM )sel ); // Remove if( lResult > 0 ) { while( lResult-- ) { int iIndex = sel[ lResult ]; Playlist_Remove( iIndex ); } } delete [] sel; return true; } //////////////////////////////////////////////////////////////////////////////// /// //////////////////////////////////////////////////////////////////////////////// bool Playlist::Crop() { int iAllCount = Playlist_GetCount(); if( iAllCount < 1 ) return false; int iSelCount = Playlist_GetSelCount(); if( iSelCount < 0 ) { return false; } else if( iSelCount == 0 ) { // None selected return Clear(); } // Which items are selected? int * sel = new int[ iSelCount ]; LRESULT lResult = SendMessage( WindowPlaylist, LB_GETSELITEMS, ( WPARAM )iSelCount, ( LPARAM )sel ); int iLowerEqualIndex = iSelCount - 1; for( int i = iAllCount - 1; i >= 0; i-- ) { while( ( sel[ iLowerEqualIndex ] > i ) && ( iLowerEqualIndex > 0 ) ) { iLowerEqualIndex--; } if( i != sel[ iLowerEqualIndex ] ) { // Not selected -> remove Playlist_Remove( i ); } } delete [] sel; return true; } */ /* //////////////////////////////////////////////////////////////////////////////// /// //////////////////////////////////////////////////////////////////////////////// bool Playlist_MoveSel( bool bUpOrDown ) { static bool bMoving = false; if( bMoving ) return false; bMoving = true; const int iSelCount = Playlist_GetSelCount(); if( iSelCount < 0 ) { // No items selected bMoving = false; return false; } // Which items are selected? int * sel = new int[ iSelCount ]; LRESULT lResult = SendMessage( WindowPlaylist, LB_GETSELITEMS, ( WPARAM )iSelCount, ( LPARAM )sel ); if( lResult <= 0 ) { // Nothing to move delete [] sel; bMoving = false; return false; } if( ( bUpOrDown && ( sel[ 0 ] == 0 ) ) || ( !bUpOrDown && ( sel[ iSelCount - 1 ] == iMaxIndex ) ) ) { // Cannot move delete [] sel; bMoving = false; return false; } const int iOldTop = ( int )SendMessage( WindowPlaylist, LB_GETTOPINDEX, 0, 0 ); // 1 _2_[3][4][5] 6 7 [8] 9 // --> 1 [3][4][5]_2_ 6 [8]_7_ 9 // Redrawing OFF // SendMessage( WindowPlaylist, WM_SETREDRAW, ( WPARAM )FALSE, 0 ); int i = ( bUpOrDown ? 0 : iSelCount - 1 ); do { // Backup the jumper PlaylistEntry * entry_old = ( PlaylistEntry * )SendMessage( WindowPlaylist, LB_GETITEMDATA, sel[ i ] + ( bUpOrDown ? -1 : 1 ), 0 ); do { // Copy on PlaylistEntry * entry_new = ( PlaylistEntry * )SendMessage( WindowPlaylist, LB_GETITEMDATA, sel[ i ], 0 ); int iDest = sel[ i ] + ( bUpOrDown ? -1 : 1 ); // Update entry display == delete, insert, set data SendMessage( WindowPlaylist, LB_DELETESTRING, iDest, 0 ); iDest = ( int )SendMessage( WindowPlaylist, LB_INSERTSTRING, iDest, ( LPARAM )entry_new->szFilename ); SendMessage( WindowPlaylist, LB_SETITEMDATA, iDest, ( LPARAM )entry_new ); if( sel[ i ] == iCurIndex ) { iCurIndex += ( bUpOrDown ? -1 : 1 ); } i += ( bUpOrDown ? 1 : -1 ); } while( bUpOrDown ? ( i < iSelCount ) && ( sel[ i - 1 ] + 1 == sel[ i ] ) : ( i >= 0 ) && ( sel[ i + 1 ] - 1 == sel[ i ] ) ); // Place the jumper int iLast = ( bUpOrDown ? sel[ i - 1 ] : sel[ i + 1 ] ); // Update entry display == delete, insert, set data SendMessage( WindowPlaylist, LB_DELETESTRING, iLast, 0 ); iLast = ( int )SendMessage( WindowPlaylist, LB_INSERTSTRING, iLast, ( LPARAM )entry_old->szFilename ); SendMessage( WindowPlaylist, LB_SETITEMDATA, iLast, ( LPARAM )entry_old ); } while( bUpOrDown ? ( i < iSelCount ) : ( i >= 0 ) ); // Select new indices (old selection went away on insert/delete if( bUpOrDown ) { for( i = 0; i < iSelCount; i++ ) SendMessage( WindowPlaylist, LB_SETSEL, TRUE, sel[ i ] - 1 ); } else { for( i = 0; i < iSelCount; i++ ) SendMessage( WindowPlaylist, LB_SETSEL, TRUE, sel[ i ] + 1 ); } // Prevent scrolling SendMessage( WindowPlaylist, LB_SETTOPINDEX, ( WPARAM )iOldTop, 0 ); // Redrawing ON // SendMessage( WindowPlaylist, WM_SETREDRAW, ( WPARAM )TRUE, 0 ); delete [] sel; bMoving = false; return true; } //////////////////////////////////////////////////////////////////////////////// /// //////////////////////////////////////////////////////////////////////////////// LRESULT CALLBACK WndprocPlaylist( HWND hwnd, UINT message, WPARAM wp, LPARAM lp ) { static bool bDragging = false; static bool bMoveLock = false; static int iDragStartY; static int iItemHeight = 0x7fffffff; switch( message ) { case WM_MOUSEMOVE: { if( !bDragging || bMoveLock ) break; bMoveLock = true; const int y = HIWORD( lp ); const int diff = y - iDragStartY; if( abs( diff ) > iItemHeight / 2 ) { iDragStartY += ( ( diff > 0 ) ? iItemHeight : -iItemHeight ); Playlist_MoveSel( diff < 0 ); } bMoveLock = false; break; } case WM_LBUTTONDOWN: { if( GetKeyState( VK_MENU ) >= 0 ) break; // Dragging ON iDragStartY = HIWORD( lp ); iItemHeight = ( int )SendMessage( WindowPlaylist, LB_GETITEMHEIGHT, 0, 0 ); bDragging = true; return 0; } case WM_LBUTTONUP: // Dragging OFF bDragging = false; break; case WM_SYSKEYDOWN: switch( wp ) // [Alt]+[...] { case VK_UP: Playlist_MoveSel( true ); break; case VK_DOWN: Playlist_MoveSel( false ); break; } break; case WM_CHAR: case WM_KEYUP: // SMALL LETTERS!!!!!! switch( wp ) { case 'z': case 'y': case 'x': case 'c': case 'v': case 'b': case 'l': return 0; } break; case WM_KEYDOWN: { const bool bShift = ( ( GetKeyState( VK_SHIFT ) & 0x8000 ) != 0 ); const bool bControl = ( ( GetKeyState( VK_CONTROL ) & 0x8000 ) != 0 ); // const bool bAlt = ( ( GetKeyState( VK_MENU ) & 0x8000 ) != 0 ); switch( wp ) { case VK_LEFT: if( bShift || bControl ) return 0; SendMessage( WindowMain, WM_COMMAND, WINAMP_REW5S, 0 ); return 0; case VK_RIGHT: if( bShift || bControl ) return 0; SendMessage( WindowMain, WM_COMMAND, WINAMP_FFWD5S, 0 ); return 0; case VK_UP: if( bControl && !bShift ) { // Move caret not selection const int iCaretBefore = Playlist_GetCaretIndex(); if( iCaretBefore > 0 ) { Playlist_SetCaretIndex( iCaretBefore - 1 ); } else if( ( iCaretBefore == 0 ) && bInfinitePlaylist ) { Playlist_SetCaretIndex( iMaxIndex ); } return 0; } else { if( bInfinitePlaylist ) { if( Playlist_GetCaretIndex() != 0 ) break; Playlist_SelectSingle( iMaxIndex ); return 0; // Or it will increase one more } } break; case VK_DOWN: if( bControl && !bShift ) { // Move caret not selection const int iCaretBefore = Playlist_GetCaretIndex(); if( ( iCaretBefore < iMaxIndex ) && ( iCaretBefore >= 0 ) ) { Playlist_SetCaretIndex( iCaretBefore + 1 ); } else if( ( iCaretBefore == iMaxIndex ) && bInfinitePlaylist ) { Playlist_SetCaretIndex( 0 ); } return 0; } else { if( bInfinitePlaylist ) { if( Playlist_GetCaretIndex() != iMaxIndex ) break; Playlist_SelectSingle( 0 ); return 0; // Or it will increase one more } } break; case VK_SPACE: if( bControl && !bShift ) { const int iCaret = Playlist_GetCaretIndex(); if( iCaret == -1 ) return 0; bool bSelected = Playlist_IsSelected( iCaret ); Playlist_SelectModify( iCaret, !bSelected ); } return 0; case VK_DELETE: { if( bShift ) break; if( bControl ) playlist->RemoveSelected( false ); else playlist->RemoveSelected( true ); break; } case VK_RETURN: iCurIndex = Playlist_GetCaretIndex(); SendMessage( WindowMain, WM_COMMAND, WINAMP_BUTTON2, 0 ); return 0; case 'Y': case 'Z': if( bShift || bControl ) return 0; SendMessage( WindowMain, WM_COMMAND, WINAMP_BUTTON1, 0 ); return 0; case 'X': if( bShift || bControl ) return 0; SendMessage( WindowMain, WM_COMMAND, WINAMP_BUTTON2, 0 ); return 0; case 'C': if( bShift || bControl ) return 0; SendMessage( WindowMain, WM_COMMAND, WINAMP_BUTTON3, 0 ); return 0; case 'V': // Todo modifiers pressed? -> fadeout/... if( bShift || bControl ) return 0; SendMessage( WindowMain, WM_COMMAND, WINAMP_BUTTON4, 0 ); return 0; case 'B': if( bShift || bControl ) return 0; SendMessage( WindowMain, WM_COMMAND, WINAMP_BUTTON5, 0 ); return 0; / case 'J': if( bShift || bControl ) return 0; SendMessage( WindowMain, WM_COMMAND, WINAMP_JUMPFILE, 0 ); return 0; / case 'L': if( bControl ) return 0; SendMessage( WindowMain, WM_COMMAND, bShift ? WINAMP_FILE_DIR : WINAMP_FILE_PLAY, 0 ); return 0; } break; } case WM_LBUTTONDBLCLK: iCurIndex = Playlist_MouseToIndex(); if( iCurIndex < 0 ) break; Playback::Play(); Playback::UpdateSeek(); break; } return CallWindowProc( WndprocPlaylistBackup, hwnd, message, wp, lp ); } //////////////////////////////////////////////////////////////////////////////// /// //////////////////////////////////////////////////////////////////////////////// bool Playlist::Add( int iIndex, TCHAR * szDisplay, TCHAR * szFilename ) { iMaxIndex++; if( iIndex < 0 || iIndex > iMaxIndex ) iIndex = iMaxIndex; if( iIndex <= iCurIndex ) { iCurIndex++; } // Create entry data PlaylistEntry * new_entry = new PlaylistEntry; new_entry->szFilename = szFilename; iIndex = ( int )SendMessage( WindowPlaylist, LB_INSERTSTRING, // LB_ADDSTRING, iIndex, ( LPARAM )szDisplay ); // Associate data SendMessage( WindowPlaylist, LB_SETITEMDATA, iIndex, ( LPARAM )new_entry ); return true; } */ //////////////////////////////////////////////////////////////////////////////// /// Opens a dialog box and loads the playlist if is [true], /// or saves the playlist if it is [false]. //////////////////////////////////////////////////////////////////////////////// bool Playlist_DialogBoth( bool bOpenOrSave ) { TCHAR szFilters[] = TEXT( "All files (*.*)\0*.*\0" "Playlist files (*.M3U)\0*.m3u\0" "\0" ); TCHAR szFilename[ MAX_PATH ] = TEXT( "\0" ); OPENFILENAME ofn; memset( &ofn, 0, sizeof( OPENFILENAME ) ); ofn.lStructSize = sizeof( OPENFILENAME ); ofn.hwndOwner = WindowMain; ofn.hInstance = g_hInstance; ofn.lpstrFilter = szFilters; ofn.lpstrCustomFilter = NULL; ofn.nMaxCustFilter = 0; ofn.nFilterIndex = 2; ofn.lpstrFile = szFilename; ofn.nMaxFile = MAX_PATH; ofn.Flags = OFN_EXPLORER | OFN_ENABLESIZING | ( bOpenOrSave ? OFN_FILEMUSTEXIST : OFN_OVERWRITEPROMPT ) | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY; ofn.nMaxFileTitle = 0, ofn.lpstrInitialDir = NULL; ofn.lpstrTitle = ( bOpenOrSave ? TEXT( "Open playlist" ) : TEXT( "Save playlist" ) ); if( bOpenOrSave ) { if( !GetOpenFileName( &ofn ) ) return false; } else { if( !GetSaveFileName( &ofn ) ) return false; } if( bOpenOrSave ) { // Open const int iFilenameLen = ( int )_tcslen( szFilename ); if( !_tcsncmp( szFilename + iFilenameLen - 3, TEXT( "m3u" ), 3 ) ) { // Playlist file playlist->RemoveAll(); Playlist::AppendPlaylistFile( szFilename ); Playback::Play(); Console::Append( TEXT( "Playlist.cpp:Playlist_DialogBoth() called Playback::Play()" ) ); Console::Append( TEXT( " " ) ); } } else { // TODO: Check extension, ask for appending if missing // Save Playlist::ExportPlaylistFile( szFilename ); } return true; } //////////////////////////////////////////////////////////////////////////////// /// Opens a dialog box and loads the selected playlist //////////////////////////////////////////////////////////////////////////////// bool Playlist::DialogOpen() { return Playlist_DialogBoth( true ); } //////////////////////////////////////////////////////////////////////////////// /// Opens a dialog box and saves the playlist to the filename selected //////////////////////////////////////////////////////////////////////////////// bool Playlist::DialogSaveAs() { return Playlist_DialogBoth( false ); } //////////////////////////////////////////////////////////////////////////////// /// //////////////////////////////////////////////////////////////////////////////// bool Playlist::AppendPlaylistFile( TCHAR * szFilename ) { // Open playlist file HANDLE hFile = CreateFile( szFilename, // LPCTSTR lpFileName FILE_READ_DATA, // DWORD dwDesiredAccess FILE_SHARE_READ, // DWORD dwShareMode NULL, // LPSECURITY_ATTRIBUTES lpSecurityAttributes OPEN_EXISTING, // DWORD dwCreationDisposition FILE_ATTRIBUTE_NORMAL, // DWORD dwFlagsAndAttributes NULL // HANDLE hTemplateFile ); // This will happen if there is no Playlist.m3u /* if( hFile == INVALID_HANDLE_VALUE ) { // MessageBox( 0, TEXT( "Could not read playlist file" ), TEXT( "Error" ), MB_ICONERROR ); //Console::Append( "We got INVALID_HANDLE_VALUE" ); return false; } */ // Disable this //const bool bEmptyBefore = ( playlist->GetSize() == 0 ); // ======================================================================================= // Remove filename from so we can // use it as relative directory root TCHAR * szWalk = szFilename + _tcslen( szFilename ) - 1; while( ( szWalk > szFilename ) && ( *szWalk != TEXT( '\\' ) ) ) szWalk--; szWalk++; *szWalk = TEXT( '\0' ); TCHAR * szBaseDir = szFilename; const int iBaseDirLen = ( int )_tcslen( szBaseDir ); DWORD iSizeBytes = GetFileSize( hFile, NULL ); if( iSizeBytes <= 0 ) { CloseHandle( hFile ); return false; } // Allocate char * rawdata = new char[ iSizeBytes + 1 ]; // One more so we can write '\0' on EOF DWORD iBytesRead; // ======================================================================================= // Read whole file ReadFile( hFile, // HANDLE hFile rawdata, // LPVOID lpBuffer iSizeBytes, // DWORD nNumberOfBytesToRead &iBytesRead, // LPDWORD lpNumberOfBytesRead NULL // LPOVERLAPPED lpOverlapped ); if( iBytesRead < iSizeBytes ) { delete [] rawdata; CloseHandle( hFile ); MessageBox( 0, TEXT( "Could not read whole file" ), TEXT( "Error" ), MB_ICONERROR ); return false; } // Parse file content // File must be // * M3U // * ANSI char * walk = rawdata; const char * eof = rawdata + iSizeBytes; char * beg = rawdata; char * end; while( true ) { // Find newline or eof while( ( walk < eof ) && ( *walk != '\015' ) && ( *walk != '\012' ) ) walk++; end = walk; if( ( end - beg > 2 ) && ( *beg != '#' ) ) { TCHAR * szKeep; if( beg[ 1 ] == ':' ) { // TODO: Better detection, network path? // Absolute path, skip this /* const int iLen = end - beg; TCHAR szBuffer[ 5000 ]; _stprintf( szBuffer, TEXT( "iLen <%i>" ), iLen ); Console::Append( szBuffer ); szKeep = new TCHAR[ iLen + 1 ]; ToTchar( szKeep, beg, iLen ); szKeep[ iLen ] = TEXT( '\0' ); */ } else { // Skip initial so we don't get a double backslash in between while( ( beg[ 0 ] == '\\' ) && ( beg < end ) ) beg++; // Relative path const int iSecondLen = end - beg; szKeep = new TCHAR[ iBaseDirLen + iSecondLen + 1 ]; memcpy( szKeep, szBaseDir, iBaseDirLen * sizeof( TCHAR ) ); ToTchar( szKeep + iBaseDirLen, beg, iSecondLen ); szKeep[ iBaseDirLen + iSecondLen ] = TEXT( '\0' ); UnbloatFilename( szKeep, false ); } // if( !Add( iMaxIndex + 1, szKeep, szKeep ) ) break; playlist->PushBack( szKeep ); } // Skip newlines while( ( walk < eof ) && ( ( *walk == '\015' ) || ( *walk == '\012' ) ) ) walk++; if( walk == eof ) { break; } beg = walk; } delete [] rawdata; CloseHandle( hFile ); /* if( bEmptyBefore ) { iCurIndex = 0; } */ return true; } //////////////////////////////////////////////////////////////////////////////// /// //////////////////////////////////////////////////////////////////////////////// bool Playlist::ExportPlaylistFile( TCHAR * szFilename ) { // Open playlist file HANDLE hFile = CreateFile( szFilename, // LPCTSTR lpFileName FILE_WRITE_DATA, // DWORD dwDesiredAccess 0, // DWORD dwShareMode NULL, // LPSECURITY_ATTRIBUTES lpSecurityAttributes CREATE_ALWAYS, // DWORD dwCreationDisposition FILE_ATTRIBUTE_NORMAL, // DWORD dwFlagsAndAttributes NULL // HANDLE hTemplateFile ); if( hFile == INVALID_HANDLE_VALUE ) { MessageBox( 0, TEXT( "Could not write playlist file" ), TEXT( "Error" ), MB_ICONERROR ); return false; } // Remove filename from so we can // use it as relative directory root TCHAR * szWalk = szFilename + _tcslen( szFilename ) - 1; while( ( szWalk > szFilename ) && ( *szWalk != TEXT( '\\' ) ) ) szWalk--; szWalk++; *szWalk = TEXT( '\0' ); TCHAR * szBaseDir = szFilename; const int iBaseDirLen = ( int )_tcslen( szBaseDir ); char * rawdata = new char[ ( playlist->GetMaxIndex() + 1 ) * ( MAX_PATH + 2 ) ]; char * walk = rawdata; // Write playlist to buffer const int iMaxMax = playlist->GetMaxIndex(); for( int i = 0; i <= iMaxMax; i++ ) { // Get TCHAR * szEntry = GetFilename( i ); if( !szEntry ) break; int iEntryLen = ( int )_tcslen( szEntry ); // Copy TCHAR * szTemp = new TCHAR[ iEntryLen + 1 ]; memcpy( szTemp, szEntry, iEntryLen * sizeof( TCHAR ) ); szTemp[ iEntryLen ] = TEXT( '\0' ); // Convert if( ApplyRootToFilename( szBaseDir, szTemp ) ) { // Update length or we are writing too much iEntryLen = ( int )_tcslen( szTemp ); } // Copy #ifdef PA_UNICODE ToAnsi( walk, szTemp, iEntryLen ); #else memcpy( walk, szTemp, iEntryLen ); #endif delete [] szTemp; walk += iEntryLen; memcpy( walk, "\015\012", 2 ); walk += 2; } const DWORD iSizeBytes = walk - rawdata; DWORD iBytesRead; WriteFile( hFile, // HANDLE hFile, rawdata, // LPCVOID lpBuffer, iSizeBytes, // DWORD nNumberOfBytesToWrite, &iBytesRead, // LPDWORD lpNumberOfBytesWritten, NULL // LPOVERLAPPED lpOverlapped ); if( iBytesRead < iSizeBytes ) { delete [] rawdata; CloseHandle( hFile ); MessageBox( 0, TEXT( "Could not write whole file" ), TEXT( "Error" ), MB_ICONERROR ); return false; } delete [] rawdata; CloseHandle( hFile ); return true; } /* //////////////////////////////////////////////////////////////////////////////// /// //////////////////////////////////////////////////////////////////////////////// bool Playlist::Append( TCHAR * szDisplay, TCHAR * szFilename ) { return Add( iMaxIndex + 1, szDisplay, szFilename ); } */ //////////////////////////////////////////////////////////////////////////////// /// //////////////////////////////////////////////////////////////////////////////// TCHAR * Playlist::GetFilename( int iIndex ) { // if( iIndex < 0 || iIndex > iMaxIndex ) return NULL; /* PlaylistEntry * entry = ( PlaylistEntry * )SendMessage( WindowPlaylist, LB_GETITEMDATA, iIndex, 0 ); return ( entry ? entry->szFilename : NULL ); */ //TCHAR * szFilename = "C:\Files\Spel och spelfusk\Console\Gamecube\Code\vgmstream (isolate ast)\Music\demo36_02.ast"; //return szFilename; return ( TCHAR * )playlist->Get( iIndex ); } //////////////////////////////////////////////////////////////////////////////// /// //////////////////////////////////////////////////////////////////////////////// int Playlist::GetFilename( int iIndex, char * szAnsiFilename, int iChars ) { // if( iIndex < 0 || iIndex > iMaxIndex ) return 0; /* PlaylistEntry * entry = ( PlaylistEntry * )SendMessage( WindowPlaylist, LB_GETITEMDATA, iIndex, 0 ); if( !entry || !entry->szFilename ) return 0; TCHAR * & szFilename = entry->szFilename; */ TCHAR * szFilename = ( TCHAR * )playlist->Get( iIndex ); const int iFilenameLen = ( int )_tcslen( szFilename ); const int iCopyLen = ( iFilenameLen < iChars ) ? iFilenameLen : iChars; #ifdef PA_UNICODE ToAnsi( szAnsiFilename, szFilename, iCopyLen ); #else memcpy( szAnsiFilename, szFilename, iCopyLen ); #endif szAnsiFilename[ iCopyLen ] = '\0'; return iCopyLen; } //////////////////////////////////////////////////////////////////////////////// /// //////////////////////////////////////////////////////////////////////////////// int Playlist::GetTitle( int iIndex, char * szAnsiTitle, int iChars ) { // if( iIndex < 0 || iIndex > iMaxIndex ) return 0; /* TCHAR * szFilename = ( TCHAR * )SendMessage( WindowPlaylist, LB_GETITEMDATA, iIndex, 0 ); if( !szFilename ) return 0; */ TCHAR * szFilename = ( TCHAR * )playlist->Get( iIndex ); // Get extension const int iFilenameLen = ( int )_tcslen( szFilename ); TCHAR * szExt = szFilename + iFilenameLen - 1; while( ( szExt > szFilename ) && ( *szExt != TEXT( '.' ) ) ) szExt--; szExt++; // Get plugin for extension map ::iterator iter = ext_map.find( szExt ); if( iter == ext_map.end() ) return 0; InputPlugin * input_plugin = iter->second; #ifdef PA_UNICODE // Filename char * szTemp = new char[ iFilenameLen + 1 ]; ToAnsi( szTemp, szFilename, iFilenameLen ); szTemp[ iFilenameLen ] = '\0'; // Ansi Title char szTitle[ 2000 ] = "\0"; int length_in_ms; input_plugin->plugin->GetFileInfo( szTemp, szTitle, &length_in_ms ); const int iTitleLen = strlen( szTitle ); memcpy( szAnsiTitle, szTitle, iChars * sizeof( char ) ); szTitle[ iChars ] = '\0'; #else char szTitle[ 2000 ] = "\0"; int length_in_ms; input_plugin->plugin->GetFileInfo( szFilename, szTitle, &length_in_ms ); const int iTitleLen = ( int )strlen( szAnsiTitle ); memcpy( szAnsiTitle, szTitle, iChars * sizeof( char ) ); szTitle[ iChars ] = '\0'; #endif return ( iTitleLen < iChars ) ? iTitleLen : iChars; } /* //////////////////////////////////////////////////////////////////////////////// /// //////////////////////////////////////////////////////////////////////////////// bool Playlist::SelectZero() { SendMessage( WindowPlaylist, LB_SETSEL, FALSE, -1 ); return true; } //////////////////////////////////////////////////////////////////////////////// /// //////////////////////////////////////////////////////////////////////////////// bool Playlist::SelectAll() { SendMessage( WindowPlaylist, LB_SETSEL, TRUE, -1 ); return true; } */