~ubuntu-branches/ubuntu/quantal/gtkpod-aac/quantal

« back to all changes in this revision

Viewing changes to src/display_playlists.c

  • Committer: Bazaar Package Importer
  • Author(s): Steve Kowalik
  • Date: 2007-07-17 18:25:25 UTC
  • mfrom: (1.1.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20070717182525-rhl5w4pk8lbk6pna
Tags: 0.99.10-2ubuntu1
* Resynchronise with gtkpod 0.9.10-2.
* Hack in dpatch support, since it was removed.
* Rename debian/patches/03-configure.dpatch to
  debian/patches/aac-configure.dpatch.
* Update debian/gtkpod-aac.diff.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Time-stamp: <2006-06-28 01:25:27 jcs>
2
 
|
 
1
/*
3
2
|  Copyright (C) 2002-2005 Jorg Schuler <jcsjcs at users sourceforge net>
4
3
|  Part of the gtkpod project.
5
4
24
23
25
24
|  This product is not supported/written/published by Apple!
26
25
|
27
 
|  $Id: display_playlists.c,v 1.92 2006/06/27 16:29:43 jcsjcs Exp $
 
26
|  $Id: display_playlists.c 1596 2007-06-26 14:33:01Z dforsi $
28
27
*/
29
28
 
30
29
#ifdef HAVE_CONFIG_H
66
65
};
67
66
 
68
67
 
69
 
void pm_rows_reordered (void);
 
68
static void pm_rows_reordered (void);
 
69
static GtkTreePath *pm_get_path_for_itdb (iTunesDB *itdb);
 
70
static GtkTreePath *pm_get_path_for_playlist (Playlist *pl);
 
71
static gint pm_get_position_for_playlist (Playlist *pl);
 
72
static gboolean pm_get_iter_for_itdb (iTunesDB *itdb, GtkTreeIter *iter);
 
73
static gboolean pm_get_iter_for_playlist (Playlist *pl, GtkTreeIter *iter);
70
74
 
71
75
 
72
76
 
182
186
    GdkAtom target;
183
187
    guint info;
184
188
    Playlist *pl_d;
 
189
    iTunesDB *itdb;
 
190
    ExtraiTunesDBData *eitdb;
185
191
 
186
192
    g_return_val_if_fail (widget, FALSE);
187
193
    g_return_val_if_fail (GTK_IS_TREE_VIEW (widget), FALSE);
206
212
 
207
213
    if(gtk_tree_model_get_iter (model, &iter_d, path))
208
214
    {
209
 
        gtk_tree_model_get (model, &iter_d, 0, &pl_d, -1);
 
215
        gtk_tree_model_get (model, &iter_d, PM_COLUMN_PLAYLIST, &pl_d, -1);
210
216
    }
211
217
    g_return_val_if_fail (pl_d, FALSE);
 
218
    itdb = pl_d->itdb;
 
219
    g_return_val_if_fail (itdb, FALSE);
 
220
    eitdb = itdb->userdata;
 
221
    g_return_val_if_fail (eitdb, FALSE);
212
222
 
213
223
    target = gtk_drag_dest_find_target (widget, dc, NULL);
214
224
 
 
225
    /* no drop possible if repository is not loaded */
 
226
    if (!eitdb->itdb_imported)
 
227
    {
 
228
        gtk_tree_path_free (path);
 
229
        gdk_drag_status (dc, 0, time);
 
230
        return FALSE;
 
231
    }
 
232
 
215
233
    /* no drop possible if no valid target can be found */
216
234
    if (target == GDK_NONE)
217
235
    {
 
236
        gtk_tree_path_free (path);
218
237
        gdk_drag_status (dc, 0, time);
219
 
        gtk_tree_path_free (path);
220
238
        return FALSE;
221
239
    }
222
240
 
225
243
    {   /* MPL */
226
244
        if (pos == GTK_TREE_VIEW_DROP_BEFORE)
227
245
        {
 
246
            gtk_tree_path_free (path);
228
247
            gdk_drag_status (dc, 0, time);
229
 
            gtk_tree_path_free (path);
230
248
            return FALSE;
231
249
        }
232
250
    }
235
253
    if (!gtk_target_list_find (
236
254
            gtk_drag_dest_get_target_list (widget), target, &info))
237
255
    {
 
256
        gtk_tree_path_free (path);
238
257
        gdk_drag_status (dc, 0, time);
239
 
        gtk_tree_path_free (path);
240
258
        return FALSE;
241
259
    }
242
260
 
255
273
            if ((pos == GTK_TREE_VIEW_DROP_INTO_OR_BEFORE) ||
256
274
                (pos == GTK_TREE_VIEW_DROP_INTO_OR_AFTER))
257
275
            {
258
 
                gdk_drag_status (dc, 0, time);
259
276
                gtk_tree_path_free (path);
 
277
                gdk_drag_status (dc, 0, time);
260
278
                return FALSE;
261
279
            }
262
280
        }
295
313
    g_return_if_fail (data);
296
314
 
297
315
    /* get current playlist */
298
 
    gtk_tree_model_get(tm, iter, PM_COLUMN_PLAYLIST, &pl, -1); 
 
316
    gtk_tree_model_get (tm, iter, PM_COLUMN_PLAYLIST, &pl, -1); 
299
317
    g_return_if_fail (pl);
300
318
 
301
319
    for (gl=pl->members; gl; gl=gl->next)
330
348
    g_return_if_fail (data);
331
349
 
332
350
    /* get current playlist */
333
 
    gtk_tree_model_get(tm, iter, PM_COLUMN_PLAYLIST, &pl, -1); 
 
351
    gtk_tree_model_get (tm, iter, PM_COLUMN_PLAYLIST, &pl, -1); 
334
352
    g_return_if_fail (pl);
335
353
 
336
354
    for (gl=pl->members; gl; gl=gl->next)
578
596
                                   gpointer         user_data)
579
597
{
580
598
    GtkTreeIter iter_d, iter_s;
581
 
    GtkTreePath *path_d=NULL, *path_s;
 
599
    GtkTreePath *path_d=NULL;
582
600
    GtkTreePath *path_m;
583
601
    GtkTreeModel *model;
584
602
    GtkTreeViewDropPosition pos = 0;
614
632
        g_object_set_data (G_OBJECT (widget), "drag_data_by_motion_pos", NULL);
615
633
        if(gtk_tree_model_get_iter (model, &iter_d, path_m))
616
634
        {
617
 
            gtk_tree_model_get (model, &iter_d, 0, &pl, -1);
 
635
            gtk_tree_model_get (model, &iter_d, PM_COLUMN_PLAYLIST, &pl, -1);
618
636
        }
619
637
        gtk_tree_path_free (path_m);
620
638
 
673
691
    }
674
692
    g_return_if_fail (path_d);
675
693
 
676
 
    if(gtk_tree_model_get_iter(model, &iter_d, path_d))
677
 
    {
678
 
        gtk_tree_model_get(model, &iter_d, 0, &pl, -1);
679
 
    }
680
 
    g_return_if_fail (pl);
681
 
 
682
 
    /* get position of current path */
683
 
    if (gtk_tree_path_get_depth (path_d) == 1)
684
 
    {   /* MPL */
685
 
        position = 0;
686
 
    }
687
 
    else
688
 
    {
689
 
        gint *indices = gtk_tree_path_get_indices (path_d);
690
 
        /* need to add 1 because MPL is one level higher and not
691
 
           counted */
692
 
        position = indices[1] + 1;
 
694
    if(gtk_tree_model_get_iter (model, &iter_d, path_d))
 
695
    {
 
696
        gtk_tree_model_get (model, &iter_d, PM_COLUMN_PLAYLIST, &pl, -1);
693
697
    }
694
698
    gtk_tree_path_free (path_d);
695
699
    path_d = NULL;
696
700
 
 
701
    g_return_if_fail (pl);
 
702
 
 
703
    position = pm_get_position_for_playlist (pl);
 
704
 
697
705
/*  printf("position: %d\n", position); */
698
706
    switch (info)
699
707
    {
846
854
                gtk_drag_finish (dc, TRUE, FALSE, time);
847
855
                break;
848
856
            case GDK_ACTION_MOVE:
849
 
                if (prefs_get_int("pm_sort") != SORT_NONE)
850
 
                {
851
 
                    gtkpod_statusbar_message (_("Can't reorder sorted treeview."));
852
 
                    gtk_drag_finish (dc, FALSE, FALSE, time);
853
 
                    return;
854
 
                }
855
 
                path_s = pm_get_path (pl_s);
856
 
                g_return_if_fail (path_s);
857
 
                g_return_if_fail (gtk_tree_model_get_iter (
858
 
                                      model, &iter_s, path_s));
859
 
                gtk_tree_path_free (path_s);
 
857
                pm_get_iter_for_playlist (pl_s, &iter_s);
860
858
                switch (pos)
861
859
                {
862
860
                case GTK_TREE_VIEW_DROP_BEFORE:
 
861
                    if (prefs_get_int("pm_sort") != SORT_NONE)
 
862
                    {
 
863
                        gtkpod_statusbar_message (_("Can't reorder sorted treeview."));
 
864
                        gtk_drag_finish (dc, FALSE, FALSE, time);
 
865
                        return;
 
866
                    }
863
867
                    gtk_tree_store_move_before (GTK_TREE_STORE (model),
864
868
                                                &iter_s, &iter_d);
865
869
                    pm_rows_reordered ();
866
870
                    gtk_drag_finish (dc, TRUE, FALSE, time);
867
871
                    break;
868
872
                case GTK_TREE_VIEW_DROP_AFTER:
 
873
                    if (prefs_get_int("pm_sort") != SORT_NONE)
 
874
                    {
 
875
                        gtkpod_statusbar_message (_("Can't reorder sorted treeview."));
 
876
                        gtk_drag_finish (dc, FALSE, FALSE, time);
 
877
                        return;
 
878
                    }
869
879
                    gtk_tree_store_move_after (GTK_TREE_STORE (model),
870
880
                                               &iter_s, &iter_d);
871
881
                    pm_rows_reordered ();
875
885
                    pl_d = pl;
876
886
                    if (pl_d != pl_s)
877
887
                        add_trackglist_to_playlist (pl_d, pl_s->members);
878
 
                    gtk_drag_finish (dc, TRUE, TRUE, time);
 
888
                    gtk_drag_finish (dc, TRUE, FALSE, time);
879
889
                    break;
880
890
                }
881
891
                break;
883
893
                gtk_drag_finish (dc, FALSE, FALSE, time);
884
894
                g_return_if_reached ();
885
895
            }
886
 
            pm_rows_reordered ();
887
 
            return;
888
896
        }
889
897
        else
890
898
        {   /*handle DND between two itdbs */
945
953
        gtk_drag_finish (dc, FALSE, FALSE, time);
946
954
        break;
947
955
    }
 
956
 
 
957
    /* display if any duplicates were skipped */
 
958
    gp_duplicate_remove (NULL, NULL);
948
959
}
949
960
 
950
961
 
992
1003
 
993
1004
 
994
1005
/* ---------------------------------------------------------------- */
 
1006
/* Section for playlist display helper functions                    */
 
1007
/* ---------------------------------------------------------------- */
 
1008
 
 
1009
 
 
1010
/* Find the iter that represents the repository @itdb
 
1011
 *
 
1012
 * Return TRUE if the repository could be found. In that case @itdb_iter
 
1013
 * will be set to the corresponding iter. The value of @itdb_iter is
 
1014
 * undefined when the repository couldn't be found, in which case FALSE
 
1015
 * is returned. */
 
1016
static gboolean pm_get_iter_for_itdb (iTunesDB *itdb, GtkTreeIter *itdb_iter)
 
1017
{
 
1018
    GtkTreeModel *model;
 
1019
 
 
1020
    g_return_val_if_fail (playlist_treeview, FALSE);
 
1021
    g_return_val_if_fail (itdb, FALSE);
 
1022
    g_return_val_if_fail (itdb_iter, FALSE);
 
1023
 
 
1024
    model = GTK_TREE_MODEL (gtk_tree_view_get_model (playlist_treeview));
 
1025
 
 
1026
    if (gtk_tree_model_get_iter_first (model, itdb_iter))
 
1027
    {
 
1028
        do
 
1029
        {
 
1030
            iTunesDB *itdb_model;
 
1031
            gtk_tree_model_get (model, itdb_iter,
 
1032
                                PM_COLUMN_ITDB, &itdb_model,
 
1033
                                -1);
 
1034
            g_return_val_if_fail (itdb_model, FALSE);
 
1035
            if (itdb == itdb_model)
 
1036
            {
 
1037
                return TRUE;
 
1038
            }
 
1039
        } while (gtk_tree_model_iter_next (model, itdb_iter));
 
1040
    }
 
1041
    return FALSE;
 
1042
}
 
1043
 
 
1044
 
 
1045
/* Find the iter that contains Playlist @playlist
 
1046
 *
 
1047
 * Return TRUE if the playlist could be found. In that case @pl_iter
 
1048
 * will be set to the corresponding iter. The value of @pl_iter is
 
1049
 * undefined when the playlist couldn't be found, in which case FALSE
 
1050
 * is returned. */
 
1051
static gboolean pm_get_iter_for_playlist (Playlist *playlist, GtkTreeIter *pl_iter)
 
1052
{
 
1053
    GtkTreeIter itdb_iter;
 
1054
 
 
1055
    g_return_val_if_fail (playlist_treeview, FALSE);
 
1056
    g_return_val_if_fail (playlist, FALSE);
 
1057
    g_return_val_if_fail (pl_iter, FALSE);
 
1058
 
 
1059
    /* First get the iter with the itdb in it */
 
1060
 
 
1061
    if (pm_get_iter_for_itdb (playlist->itdb, &itdb_iter))
 
1062
    {
 
1063
        GtkTreeModel *model;
 
1064
        Playlist *pl;
 
1065
 
 
1066
        model = GTK_TREE_MODEL (gtk_tree_view_get_model (playlist_treeview));
 
1067
 
 
1068
        /* Check if this is already the right iter */
 
1069
        gtk_tree_model_get (model, &itdb_iter,
 
1070
                            PM_COLUMN_PLAYLIST, &pl,
 
1071
                            -1);
 
1072
        g_return_val_if_fail (pl, FALSE);
 
1073
        if (pl == playlist)
 
1074
        {
 
1075
            *pl_iter = itdb_iter;
 
1076
            return TRUE;
 
1077
        }
 
1078
 
 
1079
        /* no -- go down one hierarchy and try all other iters */
 
1080
        if (!gtk_tree_model_iter_children (model, pl_iter, &itdb_iter))
 
1081
        {   /* This indicates screwed up programming so we better cry
 
1082
               out */
 
1083
            g_return_val_if_reached (FALSE);
 
1084
        }
 
1085
 
 
1086
        do
 
1087
        {
 
1088
            gtk_tree_model_get (model, pl_iter,
 
1089
                                PM_COLUMN_PLAYLIST, &pl,
 
1090
                                -1);
 
1091
            g_return_val_if_fail (pl, FALSE);
 
1092
            if (pl == playlist)
 
1093
            {
 
1094
                return TRUE;
 
1095
            }
 
1096
        } while (gtk_tree_model_iter_next (model, pl_iter));
 
1097
    }
 
1098
    return FALSE;
 
1099
}
 
1100
 
 
1101
 
 
1102
 
 
1103
 
 
1104
/* ---------------------------------------------------------------- */
995
1105
/* Section for playlist display                                     */
996
1106
/* ---------------------------------------------------------------- */
997
1107
 
1010
1120
            if ((playlist == current_playlist) ||
1011
1121
                itdb_playlist_is_mpl (current_playlist))
1012
1122
            {
 
1123
                if (prefs_get_int (KEY_DISPLAY_COVERART))
 
1124
            {
 
1125
                        coverart_track_changed (track, COVERART_REMOVE_SIGNAL);
 
1126
            }
1013
1127
                st_remove_track (track, 0);
1014
1128
            }
1015
1129
        }
1024
1138
    if (playlist == current_playlist)
1025
1139
    {
1026
1140
        st_add_track (track, TRUE, display, 0); /* Add to first sort tab */
 
1141
    
 
1142
        /* As with add_track above, only add to the playlist if it is the current one */
 
1143
        if (prefs_get_int (KEY_DISPLAY_COVERART))
 
1144
            {
 
1145
                        coverart_track_changed (track, COVERART_CREATE_SIGNAL);
 
1146
            }
1027
1147
    }
1028
1148
}
1029
1149
 
1030
 
/* Used by pm_name_changed() to find the playlist that
1031
 
   changed name. If found, emit a "row changed" signal to display the change */
1032
 
static gboolean sr_model_playlist_name_changed (GtkTreeModel *model,
1033
 
                                                GtkTreePath *path,
1034
 
                                                GtkTreeIter *iter,
1035
 
                                                gpointer data)
1036
 
{
1037
 
  Playlist *playlist=NULL;
1038
 
 
1039
 
  gtk_tree_model_get (model, iter, PM_COLUMN_PLAYLIST, &playlist, -1);
1040
 
  if(playlist == (Playlist *)data) {
1041
 
    gtk_tree_model_row_changed (model, path, iter);
1042
 
    return TRUE;
1043
 
  }
1044
 
  return FALSE;
1045
 
}
1046
 
 
1047
 
 
1048
1150
/* One of the playlist names has changed (this happens when the
1049
1151
   iTunesDB is read */
1050
 
void pm_name_changed (Playlist *pl)
 
1152
void pm_itdb_name_changed (iTunesDB *itdb)
1051
1153
{
1052
 
  GtkTreeModel *model = gtk_tree_view_get_model (playlist_treeview);
1053
 
 
1054
 
  g_return_if_fail (pl);
1055
 
  g_return_if_fail (model);
1056
 
 
1057
 
  gtk_tree_model_foreach (model, sr_model_playlist_name_changed, pl);
 
1154
  GtkTreeIter iter;
 
1155
 
 
1156
  g_return_if_fail (itdb);
 
1157
 
 
1158
  if (pm_get_iter_for_itdb (itdb, &iter))
 
1159
  {
 
1160
      GtkTreeModel *model;
 
1161
      GtkTreePath *path;
 
1162
      model = GTK_TREE_MODEL (gtk_tree_view_get_model (playlist_treeview));
 
1163
      path = gtk_tree_model_get_path (model, &iter);
 
1164
      gtk_tree_model_row_changed (model, path, &iter);
 
1165
      gtk_tree_path_free (path);
 
1166
  }
1058
1167
}
1059
1168
 
1060
1169
 
1064
1173
void pm_track_changed (Track *track)
1065
1174
{
1066
1175
  if (!current_playlist) return;
 
1176
  
 
1177
  if (prefs_get_int (KEY_DISPLAY_COVERART))
 
1178
        coverart_track_changed (track, COVERART_CHANGE_SIGNAL);
 
1179
  
1067
1180
  /* Check if track is member of current playlist */
1068
1181
  if (g_list_find (current_playlist->members, track))
1069
1182
      st_track_changed (track, FALSE, 0);
1070
1183
}
1071
1184
 
1072
 
 
1073
1185
/* Add playlist to the playlist model */
1074
1186
/* If @position = -1: append to end */
1075
1187
/* If @position >=0: insert at that position (count starts with MPL as
1081
1193
  GtkTreeIter iter;
1082
1194
  GtkTreeModel *model;
1083
1195
  GtkTreeSelection *selection;
 
1196
  iTunesDB *itdb;
1084
1197
 
1085
1198
  g_return_if_fail (playlist_treeview);
1086
1199
  g_return_if_fail (playlist);
1091
1204
  if (itdb_playlist_is_mpl (playlist))
1092
1205
  {   /* MPLs are always added top-level */
1093
1206
      mpl = NULL;
 
1207
      itdb = playlist->itdb;
1094
1208
  }
1095
1209
  else
1096
1210
  {   /* We need to find the iter with the mpl in it */
1097
 
      if (gtk_tree_model_get_iter_first (model, &mpl_iter))
 
1211
      if (pm_get_iter_for_itdb (playlist->itdb, &mpl_iter))
1098
1212
      {
1099
 
          do
1100
 
          {
1101
 
              Playlist *pl;
1102
 
              gtk_tree_model_get (model, &mpl_iter,
1103
 
                                  PM_COLUMN_PLAYLIST, &pl, -1);
1104
 
              g_return_if_fail (pl);
1105
 
              if (pl->itdb == playlist->itdb)
1106
 
              {
1107
 
                  mpl = &mpl_iter;
1108
 
              }
1109
 
          } while ((mpl == NULL) &&
1110
 
                   gtk_tree_model_iter_next (model, &mpl_iter));
 
1213
          mpl = &mpl_iter;
1111
1214
      }
1112
 
      if (!mpl)
 
1215
      else
1113
1216
      {
1114
1217
          g_warning ("Programming error: need to add mpl before adding normal playlists.\n");
1115
1218
      }
1116
1219
      /* reduce position by one because the MPL is not included in the
1117
1220
         tree model's count */
1118
1221
      --pos;
 
1222
      itdb = NULL;
1119
1223
  }
1120
1224
 
1121
1225
  gtk_tree_store_insert (GTK_TREE_STORE (model), &iter, mpl, pos);
1122
1226
 
1123
1227
  gtk_tree_store_set (GTK_TREE_STORE (model), &iter,
 
1228
                      PM_COLUMN_ITDB, itdb,
1124
1229
                      PM_COLUMN_PLAYLIST, playlist,
1125
1230
                      -1);
1126
1231
 
1146
1251
 
1147
1252
 
1148
1253
 
1149
 
    /* former inline function: used by pm_remove_playlist() */
1150
 
    static gboolean pm_delete_playlist_fe (GtkTreeModel *model,
1151
 
                                           GtkTreePath *path,
1152
 
                                           GtkTreeIter *iter,
1153
 
                                           gpointer data)
1154
 
        {
1155
 
            Playlist *playlist=NULL;
1156
 
            
1157
 
            gtk_tree_model_get (model, iter, PM_COLUMN_PLAYLIST, &playlist, -1);
1158
 
            if(playlist == (Playlist *)data) {
1159
 
                gtk_tree_store_remove (GTK_TREE_STORE (model), iter);
1160
 
                return TRUE;
1161
 
            }
1162
 
            return FALSE;
1163
 
        }
1164
 
 
1165
1254
/* Remove "playlist" from the display model. 
1166
1255
   "select": TRUE: a new playlist is selected
1167
1256
             FALSE: no selection is taking place
1170
1259
{
1171
1260
    GtkTreeModel *model;
1172
1261
    gboolean have_iter = FALSE;
1173
 
    GtkTreeIter i;
 
1262
    GtkTreeIter select_iter, delete_iter;
1174
1263
    GtkTreeSelection *ts = NULL;
1175
1264
 
1176
1265
  g_return_if_fail (playlist);
1192
1281
  if (select && (current_playlist == playlist))
1193
1282
  {   /* We are about to delete the currently selected
1194
1283
         playlist. Try to select the next. */
1195
 
      if (gtk_tree_selection_get_selected (ts, NULL, &i))
 
1284
      if (gtk_tree_selection_get_selected (ts, NULL, &select_iter))
1196
1285
      {
1197
 
          GtkTreePath *path = gtk_tree_model_get_path (model, &i);
1198
 
          if(gtk_tree_model_iter_next (model, &i))
 
1286
          GtkTreePath *path = gtk_tree_model_get_path (model, &select_iter);
 
1287
          if(gtk_tree_model_iter_next (model, &select_iter))
1199
1288
          {
1200
1289
              have_iter = TRUE;
1201
1290
          }
1203
1292
          {   /* no next iter -- try previous iter */
1204
1293
              if (gtk_tree_path_prev (path))
1205
1294
              {   /* OK -- make iter from it */
1206
 
                  gtk_tree_model_get_iter (model, &i, path);
 
1295
                  gtk_tree_model_get_iter (model, &select_iter, path);
1207
1296
                  have_iter = TRUE;
1208
1297
              }
1209
1298
          }
1211
1300
      }
1212
1301
  }
1213
1302
 
1214
 
  /* find the pl and delete it */
1215
 
  gtk_tree_model_foreach (model, pm_delete_playlist_fe, playlist);
 
1303
  if (pm_get_iter_for_playlist (playlist, &delete_iter))
 
1304
  {
 
1305
      gtk_tree_store_remove (GTK_TREE_STORE (model), &delete_iter);
 
1306
  }
 
1307
 
1216
1308
  /* select our new iter !!! */
1217
 
  if (have_iter && select)   gtk_tree_selection_select_iter(ts, &i);
 
1309
  if (have_iter && select)   gtk_tree_selection_select_iter(ts, &select_iter);
1218
1310
}
1219
1311
 
1220
1312
 
1249
1341
}
1250
1342
 
1251
1343
 
1252
 
    /* former inline function: used by pm_select_playlist */
1253
 
    static gboolean pm_select_playlist_fe (GtkTreeModel *model,
1254
 
                                           GtkTreePath *path,
1255
 
                                           GtkTreeIter *iter,
1256
 
                                           gpointer data)
1257
 
        {
1258
 
            Playlist *playlist=NULL;
1259
 
 
1260
 
            gtk_tree_model_get (model, iter,
1261
 
                                PM_COLUMN_PLAYLIST, &playlist, -1);
1262
 
            if(playlist == data)
1263
 
            {
1264
 
                GtkTreeSelection *ts = gtk_tree_view_get_selection (
1265
 
                    playlist_treeview);
1266
 
                gtk_tree_selection_select_iter (ts, iter);
1267
 
                return TRUE;
1268
 
            }
1269
 
            return FALSE;
1270
 
        }
1271
 
 
1272
1344
/* Select specified playlist */
1273
1345
void pm_select_playlist (Playlist *playlist)
1274
1346
{
1275
 
    GtkTreeModel *model;
 
1347
    GtkTreeIter iter;
1276
1348
 
1277
1349
    g_return_if_fail (playlist_treeview);
1278
1350
    g_return_if_fail (playlist);
1279
 
    model = gtk_tree_view_get_model (playlist_treeview);
1280
 
    g_return_if_fail (model);
1281
1351
 
1282
 
    /* find the pl and select it */
1283
 
    gtk_tree_model_foreach (model, pm_select_playlist_fe,
1284
 
                            playlist);
 
1352
    if (pm_get_iter_for_playlist (playlist, &iter))
 
1353
    {
 
1354
        GtkTreeSelection *ts;
 
1355
        ts = gtk_tree_view_get_selection (playlist_treeview);
 
1356
        gtk_tree_selection_select_iter (ts, &iter);
 
1357
    }
1285
1358
}
1286
1359
 
1287
1360
 
1288
 
    /* former inline function: used by pm_unselect_playlist */
1289
 
    static gboolean pm_unselect_playlist_fe (GtkTreeModel *model,
1290
 
                                             GtkTreePath *path,
1291
 
                                             GtkTreeIter *iter,
1292
 
                                             gpointer data)
1293
 
        {
1294
 
            Playlist *playlist=NULL;
1295
 
 
1296
 
            gtk_tree_model_get (model, iter,
1297
 
                                PM_COLUMN_PLAYLIST, &playlist, -1);
1298
 
            if(playlist == data)
1299
 
            {
1300
 
                GtkTreeSelection *ts = gtk_tree_view_get_selection (
1301
 
                    playlist_treeview);
1302
 
                gtk_tree_selection_unselect_iter (ts, iter);
1303
 
                return TRUE;
1304
 
            }
1305
 
            return FALSE;
1306
 
        }
1307
 
 
1308
1361
/* Unselect specified playlist */
1309
1362
void pm_unselect_playlist (Playlist *playlist)
1310
1363
{
1311
 
    GtkTreeModel *model;
 
1364
    GtkTreeIter iter;
1312
1365
 
1313
1366
    g_return_if_fail (playlist_treeview);
1314
1367
    g_return_if_fail (playlist);
1315
 
    model = gtk_tree_view_get_model (playlist_treeview);
1316
 
    g_return_if_fail (model);
1317
1368
 
1318
 
    /* find the pl and unselect it */
1319
 
    gtk_tree_model_foreach (model, pm_unselect_playlist_fe,
1320
 
                            playlist);
 
1369
    if (pm_get_iter_for_playlist (playlist, &iter))
 
1370
    {
 
1371
        GtkTreeSelection *ts;
 
1372
        ts = gtk_tree_view_get_selection (playlist_treeview);
 
1373
        gtk_tree_selection_unselect_iter (ts, &iter);
 
1374
    }
1321
1375
}
1322
1376
 
1323
1377
 
1324
 
static void pm_selection_changed_cb (gpointer user_data1, gpointer user_data2)
 
1378
static void pm_selection_changed_cb (GtkTreeSelection *selection,
 
1379
                                     gpointer user_data2)
1325
1380
{
1326
 
  GtkTreeSelection *selection = (GtkTreeSelection *)user_data1;
1327
1381
  GtkTreeModel *model;
1328
1382
  GtkTreeIter  iter;
1329
1383
  Playlist *new_playlist = NULL;
1335
1389
          time.tv_sec % 3600, time.tv_usec);
1336
1390
#endif
1337
1391
 
 
1392
        /* Avoid track selection errors on coverart while enacting a change
 
1393
         * in playlist
 
1394
         */
 
1395
         coverart_block_change (TRUE);
 
1396
  
1338
1397
  if (gtk_tree_selection_get_selected (selection, &model, &iter) == FALSE)
1339
1398
  {  /* no selection -> reset sort tabs */
1340
1399
      st_init (-1, 0);
1365
1424
          itdb_spl_update (new_playlist);
1366
1425
      if (new_playlist->members)
1367
1426
      {
1368
 
          GTimeVal time;
1369
 
          float max_count = REFRESH_INIT_COUNT;
1370
 
          gint count = max_count - 1;
1371
 
          float ms;
1372
1427
          GList *gl;
1373
1428
 
1374
 
          if (!prefs_get_int("block_display"))
1375
 
          {
1376
 
              block_selection (-1);
1377
 
              g_get_current_time (&time);
1378
 
          }
1379
1429
          st_enable_disable_view_sort (0, FALSE);
1380
1430
          for (gl=new_playlist->members; gl; gl=gl->next)
1381
1431
          { /* add all tracks to sort tab 0 */
1382
1432
              Track *track = gl->data;
1383
 
              if (stop_add == -1)  break;
1384
1433
              st_add_track (track, FALSE, TRUE, 0);
1385
 
              --count;
1386
 
              if ((count < 0) && !prefs_get_int("block_display"))
1387
 
              {
1388
 
                  gtkpod_tracks_statusbar_update();
1389
 
                  while (gtk_events_pending ())       gtk_main_iteration ();
1390
 
                  ms = get_ms_since (&time, TRUE);
1391
 
                  /* first time takes significantly longer, so we adjust
1392
 
                     the max_count */
1393
 
                  if (max_count == REFRESH_INIT_COUNT) max_count *= 2.5;
1394
 
                  /* average the new and the old max_count */
1395
 
                  max_count *= (1 + 2 * REFRESH_MS / ms) / 3;
1396
 
                  count = max_count - 1;
1397
 
#if DEBUG_TIMING
1398
 
                  printf("pm_s_c ms: %f mc: %f\n", ms, max_count);
1399
 
#endif
1400
 
              }
1401
1434
          }
1402
1435
          st_enable_disable_view_sort (0, TRUE);
1403
 
          if (stop_add != -1) st_add_track (NULL, TRUE, TRUE, 0);
1404
 
          if (!prefs_get_int("block_display"))
1405
 
          {
1406
 
              while (gtk_events_pending ())           gtk_main_iteration ();
1407
 
              release_selection (-1);
1408
 
          }
 
1436
          st_add_track (NULL, TRUE, TRUE, 0);
1409
1437
      }
1410
1438
      gtkpod_tracks_statusbar_update();
1411
1439
  }
 
1440
  
 
1441
  /* Reallow the coverart selection update */
 
1442
  coverart_block_change (FALSE);
 
1443
  /* Set the coverart display based on the selected playlist */
 
1444
  coverart_set_images(TRUE);
 
1445
         
 
1446
  space_data_update ();
 
1447
    
1412
1448
#if DEBUG_TIMING
1413
1449
  g_get_current_time (&time);
1414
1450
  printf ("pm_selection_changed_cb exit:  %ld.%06ld sec\n",
1420
1456
 
1421
1457
/* Callback function called when the selection
1422
1458
   of the playlist view has changed */
1423
 
/* Instead of handling the selection directly, we add a
1424
 
   "callback". Currently running display updates will be stopped
1425
 
   before the pm_selection_changed_cb is actually called */
1426
1459
static void pm_selection_changed (GtkTreeSelection *selection,
1427
1460
                                  gpointer user_data)
1428
1461
{
1429
 
    space_data_update ();
1430
1462
    if (!pm_selection_blocked)
1431
 
        add_selection_callback (-1, pm_selection_changed_cb,
1432
 
                                (gpointer)selection, user_data);
 
1463
        pm_selection_changed_cb (selection, user_data);
1433
1464
}
1434
1465
 
1435
1466
 
1476
1507
 
1477
1508
    for (gl_pl=itdb->playlists; gl_pl; gl_pl=gl_pl->next)
1478
1509
    {
1479
 
        Playlist *pl = gl_pl->data;
1480
 
        g_return_if_fail (pl);
1481
 
        if (itdb_playlist_is_mpl (pl))     pm_add_playlist (pl, pos);
1482
 
        else                               pm_add_playlist (pl, -1);
 
1510
                        Playlist *pl = gl_pl->data;
 
1511
                        g_return_if_fail (pl);
 
1512
                        if (itdb_playlist_is_mpl (pl))     pm_add_playlist (pl, pos);
 
1513
                        else                               pm_add_playlist (pl, -1);
1483
1514
    }
1484
1515
}
1485
1516
 
1486
1517
 
1487
1518
/* Helper function: add all playlists to playlist model */
1488
 
void pm_add_all_playlists (void)
 
1519
void pm_add_all_itdbs (void)
1489
1520
{
1490
1521
    GList *gl_itdb;    
1491
1522
    struct itdbs_head *itdbs_head;
1503
1534
}
1504
1535
 
1505
1536
 
1506
 
/* Return path of playlist @pl. After use the return value must be
1507
 
 * freed by calling gtk_tree_path_free() */
1508
 
GtkTreePath *pm_get_path (Playlist *pl)
1509
 
{
1510
 
    struct userdata
1511
 
    {
1512
 
        Playlist *pl;
1513
 
        GtkTreePath *path;
1514
 
    };
1515
 
    GtkTreeModel *model;
1516
 
    struct userdata userdata;
1517
 
    gboolean pm_get_path_fe (GtkTreeModel *model,
1518
 
                                    GtkTreePath *path,
1519
 
                                    GtkTreeIter *iter,
1520
 
                                    gpointer data)
1521
 
        {
1522
 
            struct userdata *ud = data;
1523
 
            Playlist *pl;
1524
 
 
1525
 
            gtk_tree_model_get (model, iter,
1526
 
                                PM_COLUMN_PLAYLIST, &pl, -1);
1527
 
            if(pl == ud->pl)
1528
 
            {
1529
 
                ud->path = gtk_tree_model_get_path (model, iter);
1530
 
                return TRUE;
1531
 
            }
1532
 
            return FALSE;
1533
 
        }
1534
 
    g_return_val_if_fail (playlist_treeview, NULL);
1535
 
    g_return_val_if_fail (pl, NULL);
1536
 
    model = gtk_tree_view_get_model (playlist_treeview);
1537
 
    g_return_val_if_fail (model, NULL);
1538
 
 
1539
 
    userdata.pl = pl;
1540
 
    userdata.path = NULL;
1541
 
 
1542
 
    /* find the pl and fill in path */
1543
 
    gtk_tree_model_foreach (model, pm_get_path_fe, &userdata);
1544
 
 
1545
 
    return userdata.path;
1546
 
}
1547
 
 
 
1537
/* Return GtkTreePath for playlist @playlist. The returned path must be
 
1538
   freed using gtk_tree_path_free() after it is no needed any more */
 
1539
static GtkTreePath *pm_get_path_for_playlist (Playlist *playlist)
 
1540
{
 
1541
    GtkTreeIter iter;
 
1542
 
 
1543
    g_return_val_if_fail (playlist_treeview, NULL);
 
1544
    g_return_val_if_fail (playlist, NULL);
 
1545
 
 
1546
    if (pm_get_iter_for_playlist (playlist, &iter))
 
1547
    {
 
1548
        GtkTreeModel *model;
 
1549
        model = gtk_tree_view_get_model (playlist_treeview);
 
1550
        return gtk_tree_model_get_path (model, &iter);
 
1551
    }
 
1552
    return NULL;
 
1553
}
 
1554
 
 
1555
 
 
1556
/* Return GtkTreePath for repository @itdb. The returned path must be
 
1557
   freed using gtk_tree_path_free() after it is no needed any more */
 
1558
GtkTreePath *pm_get_path_for_itdb (iTunesDB *itdb)
 
1559
{
 
1560
    GtkTreeIter iter;
 
1561
 
 
1562
    g_return_val_if_fail (playlist_treeview, NULL);
 
1563
    g_return_val_if_fail (itdb, NULL);
 
1564
 
 
1565
    if (pm_get_iter_for_itdb (itdb, &iter))
 
1566
    {
 
1567
        GtkTreeModel *model;
 
1568
        model = gtk_tree_view_get_model (playlist_treeview);
 
1569
        return gtk_tree_model_get_path (model, &iter);
 
1570
    }
 
1571
    return NULL;
 
1572
}
 
1573
 
 
1574
 
 
1575
/* Return position of repository @itdb */
 
1576
gint pm_get_position_for_itdb (iTunesDB *itdb)
 
1577
{
 
1578
    GtkTreePath *path;
 
1579
    gint position = -1;
 
1580
 
 
1581
    g_return_val_if_fail (playlist_treeview, -1);
 
1582
    g_return_val_if_fail (itdb, -1);
 
1583
 
 
1584
    path = pm_get_path_for_itdb (itdb);
 
1585
 
 
1586
    if (path)
 
1587
    {
 
1588
        gint *indices = gtk_tree_path_get_indices (path);
 
1589
        if (indices)
 
1590
        {
 
1591
            position = indices[0];
 
1592
        }
 
1593
        gtk_tree_path_free (path);
 
1594
    }
 
1595
    return position;
 
1596
}
 
1597
 
 
1598
 
 
1599
/* Return position of repository @itdb */
 
1600
static gint pm_get_position_for_playlist (Playlist *playlist)
 
1601
{
 
1602
    GtkTreePath *path;
 
1603
    gint position = -1;
 
1604
 
 
1605
    g_return_val_if_fail (playlist_treeview, -1);
 
1606
    g_return_val_if_fail (playlist, -1);
 
1607
 
 
1608
    path = pm_get_path_for_playlist (playlist);
 
1609
 
 
1610
    if (path)
 
1611
    {
 
1612
        /* get position of current path */
 
1613
        if (gtk_tree_path_get_depth (path) == 1)
 
1614
        {   /* MPL */
 
1615
            position = 0;
 
1616
        }
 
1617
        else
 
1618
        {
 
1619
            gint *indices = gtk_tree_path_get_indices (path);
 
1620
            /* need to add 1 because MPL is one level higher and not
 
1621
               counted */
 
1622
            position = indices[1] + 1;
 
1623
        }
 
1624
        gtk_tree_path_free (path);
 
1625
    }
 
1626
    return position;
 
1627
}
1548
1628
 
1549
1629
 
1550
1630
/* "unsort" the playlist view without causing the sort tabs to be
1563
1643
    pm_set_selected_playlist (cur_pl);
1564
1644
 
1565
1645
    /* add playlists back to model (without selecting) */
1566
 
    pm_add_all_playlists ();
 
1646
    pm_add_all_itdbs ();
1567
1647
 
1568
1648
    pm_selection_blocked = FALSE;
1569
1649
    /* reset sort counter */
2036
2116
                                               e->x, e->y, NULL);
2037
2117
        if (cell_nr == 0)
2038
2118
        {
 
2119
            /* don't accept clicks while widgets are blocked -- this
 
2120
               might cause a crash (e.g. when we click the 'Eject
 
2121
               iPod' symbol while we are ejecting it already) */
 
2122
            if (widgets_blocked) return FALSE;
2039
2123
            /* */
2040
2124
            model= gtk_tree_view_get_model (GTK_TREE_VIEW (w));
2041
2125
            gtk_tree_view_get_path_at_pos (GTK_TREE_VIEW(w),
2167
2251
  gtk_container_add (GTK_CONTAINER (playlist_window), tree);
2168
2252
 
2169
2253
  /* create model */
2170
 
  model =   gtk_tree_store_new (PM_NUM_COLUMNS, G_TYPE_POINTER);
 
2254
  model =   gtk_tree_store_new (PM_NUM_COLUMNS, G_TYPE_POINTER, G_TYPE_POINTER);
2171
2255
 
2172
2256
  /* set tree model */
2173
2257
  gtk_tree_view_set_model (playlist_treeview, GTK_TREE_MODEL (model));
2184
2268
                       pm_drag_types, TGNR (pm_drag_types),
2185
2269
                       GDK_ACTION_COPY|GDK_ACTION_MOVE);
2186
2270
  gtk_drag_dest_set (GTK_WIDGET (playlist_treeview),
2187
 
                     GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_HIGHLIGHT,
 
2271
                     GTK_DEST_DEFAULT_HIGHLIGHT,
2188
2272
                     pm_drop_types, TGNR (pm_drop_types),
2189
2273
                     GDK_ACTION_COPY|GDK_ACTION_MOVE);
2190
2274