Archive
/
/
/
/
/
/
PlaySourceTreeModel.cc
2008-10-21 13:54:12 UTC
previous
next
/* Echo Media Player
* Copyright (C) 2008 Shane O'Connell
*
* [ The original file includes a copyright header in this location describing
* the file as being released under the terms of the GNU General Public
* License. It has been removed in order to display the file as part of the
* archive. ]
*/
#include "PlaySourceTreeModel.h"
#include "../../PlaybackManager.h"
#include <cassert>
#include <iostream>
#include <memory>
using namespace std;
PlaySourceTreeModel::PlaySourceTreeModel(PlaySourceRef source)
:
Glib::ObjectBase( typeid(PlaySourceTreeModel) ), //register a custom GType.
Glib::Object(), //The custom GType is actually registered here.
m_source(source), m_stamp(1)
{
m_source->signal_track_removed().connect(
sigc::mem_fun(*this, &PlaySourceTreeModel::on_source_row_deleted));
m_source->signal_track_inserted().connect(
sigc::mem_fun(*this, &PlaySourceTreeModel::on_source_row_inserted));
m_source->signal_track_changed().connect(
sigc::mem_fun(*this, &PlaySourceTreeModel::on_source_row_changed));
PlaybackManager::signal_track_started().connect(
sigc::mem_fun(*this, &PlaySourceTreeModel::on_track_started));
PlaybackManager::signal_track_stopped().connect(
sigc::mem_fun(*this, &PlaySourceTreeModel::on_track_stopped));
}
Glib::RefPtr<PlaySourceTreeModel> PlaySourceTreeModel::create(PlaySourceRef source) {
return Glib::RefPtr<PlaySourceTreeModel>(new PlaySourceTreeModel(source));
}
void PlaySourceTreeModel::on_source_row_deleted(int index)
{
m_stamp++;
Gtk::TreePath path;
path.append_index(index);
row_deleted(path);
}
void PlaySourceTreeModel::on_source_row_inserted(int index)
{
m_stamp++;
Gtk::TreePath path;
path.append_index(index);
Gtk::TreeIter iter;
iter.set_stamp(m_stamp);
iter.gobj()->user_data = (void*)index;
row_inserted(path, iter);
}
void PlaySourceTreeModel::on_source_row_changed(int index)
{
Gtk::TreePath path;
path.append_index(index);
Gtk::TreeIter iter;
iter.set_stamp(m_stamp);
iter.gobj()->user_data = (void*)index;
row_changed(path, iter);
}
void PlaySourceTreeModel::on_track_started(
PlaySourceRef playlist, int index, bool was_paused)
{
// Update to show the "currently playing" icon next to the track
if (playlist == m_source)
on_source_row_changed(index);
}
void PlaySourceTreeModel::on_track_stopped(
PlaySourceRef playlist, int index, bool is_paused)
{
if (playlist == m_source)
on_source_row_changed(index);
}
GType PlaySourceTreeModel::get_column_type_vfunc(int index) const
{
assert(index >= 0);
assert(index < (int)m_column_records.size());
switch (index)
{
case 0:
return m_column_records.title.type();
case 1:
return m_column_records.artist.type();
case 2:
return m_column_records.album.type();
case 3:
return m_column_records.track_number.type();
default:
return m_column_records.is_playing.type();
}
}
bool PlaySourceTreeModel::get_iter_vfunc(const Gtk::TreePath& path, Gtk::TreeIter& iter) const
{
assert(path[0] >= 0);
if (path.size() != 1 || path[0] >= m_source->get_num_tracks()) {
return false;
}
iter = Gtk::TreeIter();
iter.set_stamp(m_stamp);
iter.gobj()->user_data = (void*)path[0];
return true;
}
Gtk::TreePath PlaySourceTreeModel::get_path_vfunc(const Gtk::TreeIter& iter) const
{
assert(iter.get_stamp() == m_stamp);
int index = (int)(iter.gobj()->user_data);
//cout << "get_path for " << index << endl;
assert(index >= 0);
assert(index < m_source->get_num_tracks());
Gtk::TreePath path;
path.append_index((int)iter.gobj()->user_data);
return path;
}
void PlaySourceTreeModel::get_value_vfunc(const Gtk::TreeIter& iter, int column, Glib::ValueBase& value) const
{
assert(iter.get_stamp() == m_stamp);
int index = (int)(iter.gobj()->user_data);
//if (column == 0)
// cout << "get_value for " << index << endl;
assert(index >= 0);
assert(index < m_source->get_num_tracks());
Glib::Value<Glib::ustring> value_ustring;
value_ustring.init(Glib::Value<Glib::ustring>::value_type());
Glib::Value<int> value_int;
value_int.init(Glib::Value<int>::value_type());
Glib::Value<bool> value_bool;
value_bool.init(Glib::Value<bool>::value_type());
assert(column >= 0);
assert(column < (int)m_column_records.size());
switch (column)
{
case 0: // title
value.init(Glib::Value<Glib::ustring>::value_type());
value_ustring.set(m_source->get_track(index)->get_title());
value = value_ustring;
break;
case 1: // artist
value.init(Glib::Value<Glib::ustring>::value_type());
value_ustring.set(m_source->get_track(index)->get_artist());
value = value_ustring;
break;
case 2: // album
value.init(Glib::Value<Glib::ustring>::value_type());
value_ustring.set(m_source->get_track(index)->get_album());
value = value_ustring;
break;
case 3: // track number
value.init(Glib::Value<int>::value_type());
value_int.set(m_source->get_track(index)->get_track_number());
value = value_int;
break;
case 4: // is currently playing
value.init(Glib::Value<bool>::value_type());
value_bool.set(
PlaybackManager::get_playing_source() == m_source &&
PlaybackManager::get_playing_index() == index);
value = value_bool;
break;
}
}
bool PlaySourceTreeModel::iter_next_vfunc(const Gtk::TreeIter& iter, Gtk::TreeIter& iter_next) const
{
assert(iter.get_stamp() == m_stamp);
int index = (int)(iter.gobj()->user_data);
//cout << "iter_next for " << index << " -> " << (index+1) << endl;
assert(index >= 0);
assert(index < m_source->get_num_tracks());
index++;
if (index >= m_source->get_num_tracks()) {
return false;
}
iter_next = Gtk::TreeIter();
iter_next.set_stamp(m_stamp);
iter_next.gobj()->user_data = (void*)index;
return true;
}
bool PlaySourceTreeModel::iter_nth_root_child_vfunc (int n, Gtk::TreeIter& iter) const
{
assert(n >= 0);
//cout << "iter_nth_root_child for " << n << endl;
if (n >= m_source->get_num_tracks()) {
return false;
}
iter = Gtk::TreeIter();
iter.set_stamp(m_stamp);
iter.gobj()->user_data = (void*)n;
return true;
}
// Drag/drop functions
bool PlaySourceTreeModel::row_draggable_vfunc (const Gtk::TreePath& path) const
{
assert(path.size() == 1);
assert(path[0] >= 0);
assert(path[0] < m_source->get_num_tracks());
return true;
}
bool PlaySourceTreeModel::drag_data_get_vfunc (const Gtk::TreePath& path, Gtk::SelectionData& selection_data) const
{
assert(path.size() == 1);
assert(path[0] >= 0);
assert(path[0] < m_source->get_num_tracks());
if (selection_data.get_target() == "PLAYLIST_ITEM") {
DragData drag_data(m_source, path[0]);
selection_data.set(selection_data.get_target(), 0, (guint8*)&drag_data, sizeof(drag_data));
return true;
}
return false;
}
bool PlaySourceTreeModel::drag_data_delete_vfunc (const Gtk::TreePath& path)
{
return false;
}
bool PlaySourceTreeModel::row_drop_possible_vfunc (const Gtk::TreePath& dest, const Gtk::SelectionData& selection_data) const
{
if (dest.size() != 1) {
return false;
}
assert(dest[0] >= 0);
return true;
}
bool PlaySourceTreeModel::drag_data_received_vfunc (const Gtk::TreePath& dest, const Gtk::SelectionData& selection_data)
{
assert(dest.size() == 1);
assert(dest[0] >= 0);
ModPlaySourceRef mod_source = boost::dynamic_pointer_cast<ModPlaySource>(m_source);
assert(mod_source); // Make sure the source is a modifiable source
int index = dest[0];
if (index >= m_source->get_num_tracks())
index = m_source->get_num_tracks();
if (selection_data.get_data_type() == "PLAYLIST_ITEM") {
DragData* drag_data = (DragData*)selection_data.get_data();
if (drag_data->playlist == m_source)
mod_source->move_track(drag_data->index, index);
else {
mod_source->insert_track(index, drag_data->playlist->get_track(drag_data->index));
// TODO should we move or copy tracks when dragged from another tab?
//drag_data->playlist->remove_track(drag_data->index);
}
return true;
}
if (selection_data.get_data_type() == "text/uri-list") {
mod_source->insert_from_uris(index, selection_data.get_uris());
return true;
}
return false;
}