Index: src/Dap/Banshee.Dap.Ipod/IPodPlaylistSource.cs
===================================================================
--- src/Dap/Banshee.Dap.Ipod/IPodPlaylistSource.cs	(revision 0)
+++ src/Dap/Banshee.Dap.Ipod/IPodPlaylistSource.cs	(revision 0)
@@ -0,0 +1,57 @@
+
+using System;
+using Banshee.Dap;
+using Banshee.Sources;
+using Banshee.Base;
+using IPod;
+
+
+namespace Banshee.Dap.Ipod
+{
+	
+	public class IPodPlaylistSource : DapPlaylistSource
+	{
+	    protected IpodDap device;
+	    
+		public IPodPlaylistSource(IpodDap device, string name) : base(device, name)
+        {
+            this.device = device;
+        }
+        
+        public override void AddTrack(TrackInfo track)
+        {
+            if (track == null) {
+            	return;
+            }
+
+            if (!ContainsTrack(track)) {
+                base.AddTrack(track);
+            }
+        }
+
+        public override void SourceDrop(Banshee.Sources.Source source)
+        {
+            if(source == this || source == null ) {
+                return;
+            }
+            
+            if (source.Tracks == null) {
+            	return;
+            }
+            	
+            LogCore.Instance.PushDebug("In IPodPlaylistSource.SourceDrop" , "");
+            
+            foreach(TrackInfo ti in source.Tracks) {
+                LogCore.Instance.PushDebug("Adding track " + ti.ToString() , " to playlist " + source.Name);
+                IpodDapTrackInfo idti = new IpodDapTrackInfo(ti, device.Device.TrackDatabase);
+                AddTrack(idti);
+            }
+        }
+        
+        public override bool AcceptsInput {
+            get { return true; }
+        }
+ 
+	}
+}
+
Index: src/Dap/Banshee.Dap.Ipod/IpodDap.cs
===================================================================
--- src/Dap/Banshee.Dap.Ipod/IpodDap.cs	(revision 2231)
+++ src/Dap/Banshee.Dap.Ipod/IpodDap.cs	(working copy)
@@ -29,6 +29,7 @@
 using System; 
 using System.IO;
 using System.Collections;
+using System.Collections.Generic;
 using System.Reflection;
 using System.Diagnostics;
 using Mono.Unix;
@@ -38,8 +39,9 @@
 
 using Banshee.Base;
 using Banshee.Dap;
+using Banshee.Metadata;
+using Banshee.Sources;
 using Banshee.Widgets;
-using Banshee.Metadata;
 
 public static class PluginModuleEntry
 {
@@ -56,13 +58,14 @@
     [DapProperties(DapType = DapType.NonGeneric, PipelineName="Ipod")]
     [SupportedCodec(CodecType.Mp3)]
     [SupportedCodec(CodecType.Mp4)]
-    public sealed class IpodDap : DapDevice
+    public sealed class IpodDap : DapDevice, IPlaylistCapable
     {
         private IPod.Device device;
         private Hal.Device hal_device;
         private bool database_supported;
         private UnsupportedDatabaseView db_unsupported_container;
         private bool metadata_provider_initialized = false;
+        private List<SafeUri> added_tracks = new List<SafeUri>();
     
         public override InitializeResult Initialize(Hal.Device halDevice)
         {
@@ -173,20 +176,41 @@
             if (track == null || (IsReadOnly && !loading))
                 return;
 
-            TrackInfo new_track = null;
+            IpodDapTrackInfo new_track = null;
 
             if(track is IpodDapTrackInfo)
-                new_track = track;
+                new_track = track as IpodDapTrackInfo;
             else
                 new_track = new IpodDapTrackInfo(track, device.TrackDatabase);
-            // FIXME: only add a new track if we don't have it already
-
-
-            if (new_track != null) {
+            
+            if (new_track != null && !added_tracks.Contains(new_track.Uri)) {                
                 tracks.Add(new_track);
                 OnTrackAdded(new_track);
+                added_tracks.Add(new_track.Uri);                
             }
         }
+        
+        public DapPlaylistSource AddPlaylist(Source playlist){        	
+       		IPodPlaylistSource ips = new IPodPlaylistSource(this, playlist.Name);       		
+       		       		
+       		LogCore.Instance.PushDebug("In IPodDap.AddPlaylist" , "");
+            
+            foreach(TrackInfo ti in playlist.Tracks) {
+                LogCore.Instance.PushDebug("Adding track " + ti.ToString() , " to new playlist " + ips.Name);
+                IpodDapTrackInfo idti = new IpodDapTrackInfo(ti, device.TrackDatabase);
+                ips.AddTrack(ti);
+                AddTrack(idti);                
+            }
+            
+            /* old
+       		foreach (TrackInfo ti in playlist.Tracks) {       		         
+                ips.AddTrack(ti);
+                AddTrack(ti);
+        	}
+        	*/
+       		
+        	return (DapPlaylistSource) ips;
+        }
 
         protected override void OnTrackRemoved(TrackInfo track)
         {
@@ -211,11 +235,34 @@
                 device.TrackDatabase.Reload();
             }
             
-            if(database_supported || (device.IsNew && device.IsShuffle)) {
-                foreach(Track track in device.TrackDatabase.Tracks) {
+            
+            if(database_supported || (device.IsNew && !device.IsShuffle)) {
+                
+                foreach(Playlist p in device.TrackDatabase.Playlists) {
+                    IPodPlaylistSource ps = new IPodPlaylistSource(this, p.Name);
+           			foreach (Track t in p.Tracks) {
+           			    IpodDapTrackInfo idti = new IpodDapTrackInfo(t);           			    
+           			    ps.AddTrack(idti);
+           			    AddTrack(idti, true);           			    
+           			}       
+                    Source.SourceDrop(ps);
+                }
+                
+                // Add tracks that aren't in a playlist to the master DAP
+                // playlist.
+                foreach(Track t in device.TrackDatabase.Tracks) {
+                    IpodDapTrackInfo idti = new IpodDapTrackInfo(t);  
+                    AddTrack(idti, true);                    
+                }
+                
+            } else if (database_supported || (device.IsNew && device.IsShuffle)) {
+            
+                // Shuffles don't support playlists ???  I think this is true.
+                foreach(Track track in device.TrackDatabase.Tracks) {                    
                     IpodDapTrackInfo ti = new IpodDapTrackInfo(track);
                     AddTrack(ti, true);
                 }
+                
             } else {
                 BuildDatabaseUnsupportedWidget();
             }
@@ -251,6 +298,98 @@
                 }
             }
             
+            LogCore.Instance.PushDebug("Starting Synchronize", "Finished Tracks, starting playlists");
+            
+            // Loop through the playlists in Banshee that the user has configured for the iPod.
+            // Add playlists on the iPod if they don't exist. We remove all tracks and then add them back
+            // to ensure the right tracks exist in the playlist in the proper order.
+            foreach (Source c in Source.Children) {
+                LogCore.Instance.PushDebug("Checking ChildSource " + c.Name + "", "");
+                Playlist p = device.TrackDatabase.LookupPlaylist(c.Name);
+                if (p == null) {
+                    LogCore.Instance.PushDebug("Adding ipod playlist " + c.Name , "It wasn't on the iPod.");
+                    try {
+                        p = device.TrackDatabase.CreatePlaylist(c.Name);
+                    } catch (InvalidCastException ice) {
+                        LogCore.Instance.PushDebug("Caught InvalidCastException when creating " + c.Name , ice.ToString());
+                        continue;
+                    }
+                }
+                
+                if (p == null) {
+                    LogCore.Instance.PushDebug("Creating playlist on ipod failed for " + c.Name , "");
+                    continue;
+                } else {
+                    LogCore.Instance.PushDebug("Playlist is not null.", "");
+                }
+                
+                // Remove all tracks in the playlist.
+                int num_tracks = p.Tracks.Count;
+                for (int i = 0; i < num_tracks; i++) {
+                    p.RemoveTrack(0);
+                    LogCore.Instance.PushDebug("Removed first row.", p.Tracks.Count + " remaining in playlist.");
+                }                
+                
+                // Add them back.
+                foreach (TrackInfo ti in c.Tracks) {
+                    LogCore.Instance.PushDebug("Adding track " + ti.ToString() , " to playlist " + p.Name);
+                    
+                    IpodDapTrackInfo idti = null;
+                    if (ti is IpodDapTrackInfo) {
+                        LogCore.Instance.PushDebug("ti is IpodDapTrackInfo", "");
+                        idti = ti as IpodDapTrackInfo;
+                    } else {
+                        LogCore.Instance.PushDebug("ti is not IpodDapTrackInfo", "ti is: " + ti.ToString());
+                        idti = new IpodDapTrackInfo(ti, device.TrackDatabase);
+                    }                    
+                    
+                    if (idti == null) {
+                        LogCore.Instance.PushDebug("idti is null", "");
+                        continue;
+                    }
+                    
+                    // TODO: the track may already be on the ipod.  I don't want to copy it again if it is, so 
+                    // I need to figure out how to determine which tracks have already been added to the ipod 
+                    // and get a ref to the Track for this case.
+                    Track track = idti.Track;
+                    if(track == null) {
+                        LogCore.Instance.PushDebug("track is null", "Adding track to ipod");
+                        track = CommitTrackToDevice(idti);
+                        
+                        if (track == null) {
+                            LogCore.Instance.PushDebug("track is still null after committing!", "");
+                            continue;
+                        }
+                    } 
+                    
+                    LogCore.Instance.PushDebug("Adding Ipod track", "");
+                    p.AddTrack(track);
+                }
+            }
+            
+            LogCore.Instance.PushDebug("Finished adding playlists, checking for removed playlists. ", "");
+            
+            // Remove playlists that have been deleted.
+            foreach (Playlist p in device.TrackDatabase.Playlists) {
+                LogCore.Instance.PushDebug("Checking ipod playlist " + p.Name , "");
+                bool found_playlist = false;
+                foreach (Source c in Source.Children) {
+                    if (c.Name == p.Name) {
+                        found_playlist = true;
+                        break;
+                    }
+                }
+                
+                if (!found_playlist) {
+                    LogCore.Instance.PushDebug("Removing playlist " + p.Name + "; It is missing in Banshee", "");
+                    device.TrackDatabase.RemovePlaylist(p);
+                } else {
+                    LogCore.Instance.PushDebug("Found playlist " + p.Name + " in Banshee", "");
+                }
+            }
+                        
+            LogCore.Instance.PushDebug("Finished modifying playlists", "Continuing regular synchronization process");
+            
             device.TrackDatabase.SaveProgressChanged += delegate(object o, TrackSaveProgressArgs args)
             {
                 double progress = args.CurrentTrack == null ? 0.0 : args.TotalProgress;
@@ -272,15 +411,15 @@
             }
         }
         
-        private void CommitTrackToDevice(IpodDapTrackInfo ti)
+        private Track CommitTrackToDevice(IpodDapTrackInfo ti)
         {
             Track track = device.TrackDatabase.CreateTrack();
-
+                        
             try {
                 track.Uri = new Uri(ti.Uri.AbsoluteUri);
             } catch {
                 device.TrackDatabase.RemoveTrack (track);
-                return;
+                return null;
             }
         
             if(ti.Album != null) {
@@ -342,6 +481,10 @@
                     Console.Error.WriteLine ("Failed to set cover art from {0}: {1}", ti.CoverArtFileName, e);
                 }
             }
+            
+            // tale: I don't think this will break things.  I added it
+            // because I need the track to add to playlists.
+            return track;
         }
 
         private void SetCoverArt (Track track, ArtworkUsage usage, Gdk.Pixbuf pixbuf)
Index: src/Dap/Banshee.Dap.Ipod/Makefile.am
===================================================================
--- src/Dap/Banshee.Dap.Ipod/Makefile.am	(revision 2231)
+++ src/Dap/Banshee.Dap.Ipod/Makefile.am	(working copy)
@@ -10,7 +10,8 @@
 	$(srcdir)/IpodQueryJob.cs \
 	$(srcdir)/IpodDapTrackInfo.cs \
 	$(srcdir)/UnsupportedDatabaseView.cs \
-	$(srcdir)/DatabaseRebuilder.cs
+	$(srcdir)/DatabaseRebuilder.cs	\
+	$(srcdir)/IPodPlaylistSource.cs
 
 if ENABLE_IPOD
 bansheedapdir = $(pkglibdir)/Banshee.Dap
Index: src/Core/Banshee.Base/Sources/DapPlaylistSource.cs
===================================================================
--- src/Core/Banshee.Base/Sources/DapPlaylistSource.cs	(revision 2231)
+++ src/Core/Banshee.Base/Sources/DapPlaylistSource.cs	(working copy)
@@ -16,7 +16,10 @@
 
         public override void AddTrack(TrackInfo track)
         {
-            base.AddTrack(track);
+            if (!base.ContainsTrack(track)) {
+                base.AddTrack(track);
+            }
+            
             device.AddTrack(track);
         }
     }

