Logo Search packages:      
Sourcecode: zinf version File versions  Download package

gtkplaylist.cpp

#include <vector>
#include <string>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <time.h>
#include <gtkmm/treerowreference.h>
using namespace std;

#include "gtkmusicbrowser.h"
#include "gtkplaylist.h"
#include "playlist.h"
#include "player.h"
#include "facontext.h"
#include "eventdata.h"

GTKPlaylist::GTKPlaylist(FAContext *context, PlaylistManager *plm, GTKBrowserMusic *musicbrowser)
      : GTKMusicList()
{
      //Init Variables
      m_context = context;
      m_plm = plm;
      m_musicbrowser = musicbrowser;
      m_editing_rows = false;
      loading_playlist = false;
      playlist_changed = false;
      last_update = time(NULL);

      //Create List Store And Set Possible Columns    
      set_list_model_columns(&m_PlaylistCols);
      
      //Set Style
      m_listMusic.set_reorderable();
      
      //Assign Signal Handlers
      m_listmodelMusic->signal_row_deleted().connect( SigC::slot(*this, &GTKPlaylist::row_deleted), true );
      m_listmodelMusic->signal_row_inserted().connect( SigC::slot(*this, &GTKPlaylist::row_inserted), true );
      
      //Create Menu
      Gtk::Menu::MenuList& MenuList = m_Menu.items();
      
      MenuList.push_back( Gtk::Menu_Helpers::MenuElem("Play Now", SigC::slot(*this, &GTKPlaylist::on_menu_play)) );
      MenuList.push_back( Gtk::Menu_Helpers::MenuElem("Move Up", SigC::slot(*this, &GTKPlaylist::on_menu_moveup)) );
      MenuList.push_back( Gtk::Menu_Helpers::MenuElem("Move Down", SigC::slot(*this, &GTKPlaylist::on_menu_movedown)) );
      MenuList.push_back( Gtk::Menu_Helpers::SeparatorElem() );
      MenuList.push_back( Gtk::Menu_Helpers::MenuElem("Remove", SigC::slot(*this, &GTKPlaylist::on_menu_remove)) );
      MenuList.push_back( Gtk::Menu_Helpers::SeparatorElem() );
      MenuList.push_back( Gtk::Menu_Helpers::MenuElem("Edit Info", SigC::slot(*this, &GTKPlaylist::on_menu_editinfo)) );
      
      //Fill Playlist List With Data
      loading_playlist = true;
      PlaylistLengthChanged();
      loading_playlist = false;
      
      //Ensure Playlist Widget Is Updated
      show_all();
}

void GTKPlaylist::set_list_columns()
{
      std::string cols;
      bool finished = false;
      unsigned int startPos, endPos;
      Gtk::TreeView::Column* addedCol;
      
      //Reset Columns
      m_listMusic.remove_all_columns();
      m_listMusic.append_column("#", m_PlaylistCols.playlistposition);
      addedCol = m_listMusic.get_column(0);
      addedCol->add_attribute(*(addedCol->get_first_cell_renderer()), "weight", (int) m_PlaylistCols.fontweight.index());
      
      m_context->prefs->GetPrefString(kPlaylistHeaderColumnsPref, cols);
      
      //Parse Prefrence String
      startPos = 0;
      int addedcolindex = 1;
      while(!finished) {
            std::string Column;
            
            //Get Next Column
            endPos = cols.find("|", startPos);
            if(endPos == string::npos) {
                  endPos = cols.length();
                  finished = true;
            }
            Column = cols.substr(startPos, endPos - startPos);
            
            //Add Next Column
            if(Column == "Artist")
                  m_listMusic.append_column("Artist", m_PlaylistCols.artist);
            else if(Column == "Album")
                  m_listMusic.append_column("Album", m_PlaylistCols.album);
            else if(Column == "Comment")
                  m_listMusic.append_column("Comment", m_PlaylistCols.comment);
            else if(Column == "Genre")
                  m_listMusic.append_column("Genre", m_PlaylistCols.genre);
            else if(Column == "Location")
                  m_listMusic.append_column("Location", m_PlaylistCols.location);
            else if(Column == "Title")
                  m_listMusic.append_column("Title", m_PlaylistCols.title);
            else if(Column == "Time")
                  m_listMusic.append_column("Time", m_PlaylistCols.time);
            else if(Column == "Track")
                  m_listMusic.append_column("Track", m_PlaylistCols.track);
            else if(Column == "Year")
                  m_listMusic.append_column("Year", m_PlaylistCols.year);
            
            addedCol = m_listMusic.get_column(addedcolindex);
            addedCol->add_attribute(*(addedCol->get_first_cell_renderer()), "weight", (int) m_PlaylistCols.fontweight.index());
            addedCol->set_resizable();
            addedcolindex++;
            startPos = endPos + 1;
      }
}

void GTKPlaylist::PlaylistChanged(bool mark_as_changed)
{
      //Refresh List
      last_update = time(NULL);
      scrolledwindow_changed_visible();
      
      if(!loading_playlist && mark_as_changed) {
            playlist_changed = true;
      }
      
      //Refresh Total Time Display
      m_musicbrowser->UpdateListTime();
}

void GTKPlaylist::PlaylistLengthChanged()
{
      uint32_t playlist_count, list_count;
      
      //Get Lengths
      //KGK playlist_count = m_plm->CountItems();
    playlist_count = m_plm->size();
      list_count = m_listmodelMusic->children().size();
      
      //Correct Difference
      while(list_count < playlist_count) {
            m_listmodelMusic->append();
            list_count++;
      }
      while(list_count > playlist_count) {
            m_listmodelMusic->erase(m_listmodelMusic->children()[list_count - 1]);
            list_count--;
      }
      
      //Refresh List
      PlaylistChanged();
}

void GTKPlaylist::set_rows_data(std::vector<Gtk::TreeModel::Path> RowPaths)
{
      bool using_edit_flag;
      
      if(m_editing_rows)
            using_edit_flag = false;
      else {
            m_editing_rows = true;
            using_edit_flag = true;
      }
      
      //Get Shown Paths
      std::vector<Gtk::TreeModel::Path>::iterator visible_path;
      
      //Set Data
      for(visible_path = RowPaths.begin(); 
        visible_path != RowPaths.end(); visible_path++) {
            Gtk::TreeModel::Row visible_row = 
            *(m_listmodelMusic->get_iter(*visible_path));
            
            //Refresh Font Weight, if needed
        if(((uint32_t)(*visible_path)[0] != m_plm->GetCurrentIndex()) 
           && (visible_row[m_PlaylistCols.fontweight] == Pango::WEIGHT_BOLD))
            visible_row[m_PlaylistCols.fontweight] = Pango::WEIGHT_NORMAL;
            
            //Refresh Data If Required
            if(visible_row[m_PlaylistCols.last_refresh] < last_update) {
                  //Get Playlist Item
#if 0
                  PlaylistItem *Item = m_plm->ItemAt((*visible_path)[0]);
                  
                  //If Metadata Not Read, Read It Now
                  if(Item->GetState() == kPlaylistItemState_RetrievingMetaData)
                        m_plm->RetrieveMetaDataNow(Item);
                  MetaData ItemInfo = Item->GetMetaData();

                  
                  ostringstream sPos;
                  sPos << (*visible_path)[0] + 1 << ".";
                  visible_row[m_PlaylistCols.playlistposition] = sPos.str();
                  visible_row[m_PlaylistCols.artist] = ItemInfo.Artist();
                  visible_row[m_PlaylistCols.album] = ItemInfo.Album();
                  visible_row[m_PlaylistCols.comment] = ItemInfo.Comment();
                  visible_row[m_PlaylistCols.genre] = ItemInfo.Genre();
                  visible_row[m_PlaylistCols.location] = Item->URL();
                  visible_row[m_PlaylistCols.title] = ItemInfo.Title();
#endif
            
            string text;
            string url = (*m_plm)[(*visible_path)[0]];
            Metadata md;

            //BEGIN TODO
            // only initialize tags needed for display.
            md.initialize_tags(); 
            //END TODO
            m_context->collection->readMetadata(url, md);

                  ostringstream sPos;
                  sPos << (*visible_path)[0] + 1 << ".";
                  visible_row[m_PlaylistCols.playlistposition] = sPos.str();
                  visible_row[m_PlaylistCols.artist] = md[Metadata::kArtist];
                  visible_row[m_PlaylistCols.album] = md[Metadata::kAlbum];
                  visible_row[m_PlaylistCols.comment] = md[Metadata::kComment];
                  visible_row[m_PlaylistCols.genre] = md[Metadata::kGenre];
                  visible_row[m_PlaylistCols.location] = url;
                  visible_row[m_PlaylistCols.title] = md[Metadata::kTitle];

                  int32_t Minutes, Seconds, Total;
            md.getTag(Metadata::kTime, Total);

                  ostringstream sTime;
                  if(Total > 0) {
                        Seconds = Total % 60;
                        Minutes = Total / 60;
                        sTime << Minutes << ":" << setw(2) << setfill('0') << Seconds;
                  } else
                        sTime << "-";
                  visible_row[m_PlaylistCols.time] = sTime.str();
                  
                  //Represent Track Number
            if (md.hasKey(Metadata::kTrack)) {
                text = md[Metadata::kTrack];
            } else {
                text = "-";
            }
                  visible_row[m_PlaylistCols.track] = text;
                  
                  //Represent Year
            text.clear();
            if (md.hasKey(Metadata::kYear)) {
                text = md[Metadata::kYear];
            } else {
                text = "-";
            }
                  visible_row[m_PlaylistCols.year] = text;
                  visible_row[m_PlaylistCols.last_refresh] = time(NULL);
            }
      }
      
      if(using_edit_flag)
            m_editing_rows = false;
}

Error GTKPlaylist::AcceptEvent(Event *event)
{
      switch(event->Type()) {
            case INFO_PlaylistItemsAdded: {
                  PlaylistItemsAddedEvent *EventInfo = (PlaylistItemsAddedEvent *)event;
                  if(EventInfo->Manager() == m_plm) {
                        //We Need To Check Its This Playlist So We Know When Playlist Loaded
                        PlaylistLengthChanged();
                        loading_playlist = false;
                  }
                  break;
            }
            
            case INFO_PlaylistItemRemoved:
            case INFO_PlaylistItemAdded:
            case INFO_PlaylistUpdated: //Does This Ever Get Sent?? When??
                  PlaylistLengthChanged();
                  break;
            
            case INFO_PlaylistItemMoved:
            case INFO_PlaylistSorted: 
                  PlaylistChanged(true);
                  break;
            
            case INFO_PlaylistItemsUpdated: {
                  //Only Track MetaData Changed, Playlist Hasn't So Don't mark_as_changed
                  PlaylistChanged(false);
                  break;
            }
            
            case INFO_Playing:
            case INFO_PlaylistCurrentItemInfo:
                  CheckCurrentIndex();
                  break;
            
            case INFO_PrefsChanged:
                  set_list_columns();
                  break;
            
            default:
                  break;
      }
      
      return kError_NoErr;
}

void GTKPlaylist::CheckCurrentIndex()
{
      //Get Current Index
      uint32_t Index;
      Index = m_plm->GetCurrentIndex();
      
      //Save Playlist Position
      if(m_plm->GetActivePlaylist() == kPlaylistKey_MasterPlaylist)
            m_context->prefs->SetPrefInt32(kSavedPlaylistPositionPref, Index);      
      
      //Check Index Is In List
      if(IndexListed(Index)) {
            //Scroll To Current Index
            Gtk::TreeModel::Path path;
            path.push_back(Index);
            m_listMusic.scroll_to_row(path);
            
            //Highlight Current Index
            Gtk::TreeModel::Row current_row = *(m_listmodelMusic->get_iter(path));
            current_row[m_PlaylistCols.fontweight] = Pango::WEIGHT_BOLD;
            
            //Refresh Data
            scrolledwindow_changed_visible();
      }
}

void GTKPlaylist::show_menu(guint button, guint32 time)
{
      m_Menu.popup(button, time);
}

void GTKPlaylist::row_activated(Gtk::TreeModel::Path path)
{
      //Play Activated Item
      m_musicbrowser->StartPlaying(true, path[0]);
}

void GTKPlaylist::row_deleted(const Gtk::TreeModel::Path& path)
{
      if(!m_editing_rows && !m_last_inserted.empty()) {
            //Item Must Have Been Dragged To New Position
            //So Tell Playlist Manager
            uint32_t oldindex, newindex;
            oldindex = path[0];
            newindex = m_last_inserted[0];
            //Calculate Locations (Take Into Account Extra Row Added At NewIndex)
            if(oldindex < newindex)
                  newindex--;
            else if(oldindex > newindex)
                  oldindex--;
            
            //Move Item
            m_plm->MoveItem(oldindex, newindex);
            
            //Clear Last Inserted
            m_last_inserted.clear();
      }
}

void GTKPlaylist::row_inserted(const Gtk::TreeModel::Path& path, const Gtk::TreeModel::iterator& iter)
{
      if(!m_editing_rows) {
            //Item Must Have Been Dragged Here
            m_last_inserted = path;
      }
      
}

bool GTKPlaylist::IndexListed(uint32_t Index)
{
      Gtk::TreeModel::Path indexPath;
      if((Index == kInvalidIndex) || !is_realized())
            return false;
      
      indexPath.push_front(Index);
      Gtk::TreeModel::RowReference indexRow(m_listmodelMusic, indexPath);
      
      if(indexRow.is_valid()) {
            return true;
      }
      else {
            return false;
      }
}

void GTKPlaylist::on_menu_play()
{
      if(!m_path_menu_shown_for.empty()) {
            m_musicbrowser->StartPlaying(true, m_path_menu_shown_for[0]);
      }
}

void GTKPlaylist::on_menu_moveup()
{
      std::vector<Gtk::TreeModel::Path> selected_paths;
      std::vector<Gtk::TreeModel::Path>::iterator selected_path;
      
      selected_paths = m_listMusic.get_selection()->get_selected_rows();
      
      //Move Each Selected Item
      for(selected_path = selected_paths.begin(); selected_path != selected_paths.end(); selected_path++) {
            m_plm->MoveItem((*selected_path)[0], (*selected_path)[0] - 1);
      }
}

void GTKPlaylist::on_menu_movedown()
{
      std::vector<Gtk::TreeModel::Path> selected_paths;
      std::vector<Gtk::TreeModel::Path>::iterator selected_path;
      
      selected_paths = m_listMusic.get_selection()->get_selected_rows();
      
      //Move Each Selected Item
      for(selected_path = selected_paths.begin(); selected_path != selected_paths.end(); selected_path++) {
            m_plm->MoveItem((*selected_path)[0], (*selected_path)[0] + 1);
      }
}

void GTKPlaylist::on_menu_remove()
{
      std::vector<Gtk::TreeModel::Path> selected_paths;
      std::vector<Gtk::TreeModel::Path>::iterator selected_path;
      std::vector<PlaylistItem *> items;
      selected_paths = m_listMusic.get_selection()->get_selected_rows();
      
      //Get Each Selected Item
      for(selected_path = selected_paths.begin(); selected_path != selected_paths.end(); selected_path++) {
            items.push_back(m_plm->ItemAt((*selected_path)[0]));
      }
      
      //If Any Items, Remove Them
      if(items.size() > 0){
            m_plm->RemoveItems(&items);
    }
}

void GTKPlaylist::on_menu_editinfo()
{
      std::vector<Gtk::TreeModel::Path> selected_paths;
      std::vector<Gtk::TreeModel::Path>::iterator selected_path;
      std::vector<PlaylistItem *> *items;
      selected_paths = m_listMusic.get_selection()->get_selected_rows();
      
      //Need Pointer To Vector, As It Will Be Deleted By TracksToEdit, not here
      items = new std::vector<PlaylistItem *>;
      //Get Each Selected Item
      for(selected_path = selected_paths.begin(); selected_path != selected_paths.end(); selected_path++) {
            items->push_back(m_plm->ItemAt((*selected_path)[0]));
      }
      
      //If Any Items, edit them
      if(items->size() > 0)
            m_musicbrowser->TracksToEdit(items);
}
/* arch-tag: 393bb0f3-73d5-472a-8af3-b807e2c5b20d */

Generated by  Doxygen 1.6.0   Back to index