3
// GNOME Do is the legal property of its developers, whose names are too numerous
4
// to list here. Please refer to the COPYRIGHT file distributed with this
5
// source distribution.
7
// This program is free software: you can redistribute it and/or modify
8
// it under the terms of the GNU General Public License as published by
9
// the Free Software Foundation, either version 3 of the License, or
10
// (at your option) any later version.
12
// This program is distributed in the hope that it will be useful,
13
// but WITHOUT ANY WARRANTY; without even the implied warranty of
14
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
// GNU General Public License for more details.
17
// You should have received a copy of the GNU General Public License
18
// along with this program. If not, see <http://www.gnu.org/licenses/>.
22
using System.Threading;
23
using System.Text.RegularExpressions;
24
using System.Diagnostics;
25
using System.Collections.Generic;
29
namespace Do.Addins.xmms2 {
31
public static class xmms2 {
32
//coverart to be added later
33
//static readonly string MusicLibraryFile;
34
//static readonly string CoverArtDirectory;
36
public static List<SongMusicItem> songs;
37
public static List<PlaylistItem> playlists;
39
static Timer clearSongsTimer;
40
static Timer clearPlaylistsTimer;
41
const int SecondsSongsCached = 45;
46
//home = Environment.GetFolderPath (Environment.SpecialFolder.Personal);
47
//not needed and not implemented, respectively
48
//MusicLibraryFile = "~/.gnome2/rhythmbox/rhythmdb.xml".Replace("~", home);
49
//CoverArtDirectory = "~/.gnome2/rhythmbox/covers".Replace("~", home);
51
clearSongsTimer = new Timer (ClearSongs);
52
clearPlaylistsTimer = new Timer (ClearPlaylists);
53
playlists = new List<PlaylistItem>();
54
songs = new List<SongMusicItem> ();
57
public static void LoadAlbumsAndArtists (out List<AlbumMusicItem> albums_out, out List<ArtistMusicItem> artists_out)
59
Dictionary<string, AlbumMusicItem> albums;
60
Dictionary<string, ArtistMusicItem> artists;
62
albums_out = new List<AlbumMusicItem> ();
63
artists_out = new List<ArtistMusicItem> ();
65
albums = new Dictionary<string, AlbumMusicItem> ();
66
artists = new Dictionary<string, ArtistMusicItem> ();
67
foreach (SongMusicItem song in LoadAllSongs ()) { //this is genius, Mr. Siegel.
68
// Don't let null covers replace non-null covers.
69
if (!artists.ContainsKey (song.Artist) || artists[song.Artist].Cover == null) {
70
artists[song.Artist] = new ArtistMusicItem (song.Artist, song.Cover);
72
if (!albums.ContainsKey (song.Album) || albums[song.Album].Cover == null) {
73
albums[song.Album] = new AlbumMusicItem (song.Album, song.Artist, song.Cover);
76
albums_out.AddRange (albums.Values);
77
artists_out.AddRange (artists.Values);
80
public static List<SongMusicItem> LoadSongsFor (MusicItem item)
82
if(item is SongMusicItem) {
83
List<SongMusicItem> single = new List<SongMusicItem> ();
84
single.Add (item as SongMusicItem);
86
}else if(item is AlbumMusicItem){
87
List<SongMusicItem> songs = search(string.Format("album:\"{0}\"*", item.Name)); //cuts down on extraneous search results, more efficient
90
}else if(item is ArtistMusicItem){
91
List<SongMusicItem> songs = search(string.Format("artist:\"{0}\"*", item.Name));
95
return new List<SongMusicItem>();
97
// songs = new SortedList<SongMusicItem, SongMusicItem> ();
98
// foreach (SongMusicItem song in LoadAllSongs ()) { //this is slowish, and causes O(songs) complexity, instead of O(albumlength) or O(SongsbyArtist)
99
// switch (item.GetType ().Name) {
100
// case "AlbumMusicItem":
101
// if (item.Name != song.Album) continue;
103
// case "ArtistMusicItem":
104
// if (item.Name != song.Artist) continue;
108
// songs.Add (song, song);
111
// return new List<SongMusicItem> (songs.Values);
114
public static List<SongMusicItem> LoadSongsFor (PlaylistItem list){
116
string[] delimarr = new string[] {" - ",};
120
List<SongMusicItem> entries = new List<SongMusicItem>();
122
System.Diagnostics.Process getList;
123
getList = new System.Diagnostics.Process();
124
getList.StartInfo.FileName = "xmms2";
125
getList.StartInfo.Arguments = string.Format("list {0}", list.Name); //Warning: does not guard against improperly formatted queries
126
getList.StartInfo.RedirectStandardOutput = true;
127
getList.StartInfo.UseShellExecute = false;
129
while(null != (line = getList.StandardOutput.ReadLine())){
131
if(line.Substring(2,1) == "["){
132
line = Regex.Replace(line, "..\\[.+?\\/", ""); //clears out beginning of line format
133
line = Regex.Replace(line, "\\]", " -"); //clears the other ]
134
data = line.Split(delimarr, StringSplitOptions.None);
135
id = int.Parse(data[0]);
136
data[2] = Regex.Replace(data[2], "[^\\w\\s\\d].+$", "");
137
entry = new SongMusicItem(id, data[1], "", data[2]); //blank album to match default output. phooey.
141
Console.Error.WriteLine("failed to load playlist: " + e.Message + " at " + line);
148
private static void ClearSongs (object state)
155
public static List<SongMusicItem> LoadAllSongs ()
157
List<SongMusicItem> songsCopy;
160
// Begin a new timer to clear the songs SecondsSongsCached seconds from now.
161
clearSongsTimer.Change (SecondsSongsCached*1000, Timeout.Infinite);
163
if (songs.Count == 0) {
164
// Song list is not cached. Load songs from output of the search
165
songs = search("title:*");
167
songsCopy = new List<SongMusicItem> (songs);
172
private static void ClearPlaylists (object state)
179
public static List<PlaylistItem> LoadAllPlaylists(){
181
List<PlaylistItem> playlistsCopy;
183
System.Diagnostics.Process getPla;
184
getPla = new System.Diagnostics.Process();
185
getPla.StartInfo.FileName = "xmms2";
186
getPla.StartInfo.Arguments = "playlist list";
187
getPla.StartInfo.RedirectStandardOutput = true;
188
getPla.StartInfo.UseShellExecute = false;
191
if (playlists.Count == 0) {
192
clearPlaylistsTimer.Change (SecondsSongsCached*1000, Timeout.Infinite);
193
while(null != (line = getPla.StandardOutput.ReadLine())){
194
item = new PlaylistItem(line.Substring(2));
195
if(line.Substring(0,2) == "->"){
201
playlistsCopy = new List<PlaylistItem>(playlists);
203
return playlistsCopy;
206
public static List<SongMusicItem> search(string query){ //queries should be in the form <field>:\"<name>\"
208
List<SongMusicItem> songs = new List<SongMusicItem>();
212
string[] delimarr = new string[] {"| ",};
217
System.Diagnostics.Process getLib;
218
getLib = new System.Diagnostics.Process();
219
getLib.StartInfo.FileName = "xmms2";
220
getLib.StartInfo.Arguments = string.Format("mlib search {0}", query);
221
getLib.StartInfo.RedirectStandardOutput = true;
222
getLib.StartInfo.UseShellExecute = false;
224
getLib.StandardOutput.ReadLine(); //get rid of extraneous
225
getLib.StandardOutput.ReadLine(); //lines at the top
226
while(null != (line = getLib.StandardOutput.ReadLine())){
227
if(line.Substring(0,1) != "-"){
228
data = line.Split(delimarr, StringSplitOptions.RemoveEmptyEntries);
229
int id = int.Parse(data[0]);
230
for(int i = 1; i <= 3; i++){
231
data[i] = Regex.Replace(data[i], " +$", "");//keeps formatting right, also ensures searches actually work!
233
song = new SongMusicItem(id, data[1], data[2], data[3]);
238
} catch (Exception e) {
239
Console.Error.WriteLine ("xmms2 mlib search failed: " + e.Message + " query was " + query);
244
public static void StartIfNeccessary ()
246
if (!InstanceIsRunning) {
247
Process.Start ("xmms2d");
248
System.Threading.Thread.Sleep (3 * 1000);
252
public static bool InstanceIsRunning
258
// Use pidof command to look for xmms2d process. Exit
259
// status is 0 if at least one matching process is found.
260
// If there's any error, just assume some it's running.
261
pidof = Process.Start ("pidof", "xmms2d");
262
pidof.WaitForExit ();
263
return pidof.ExitCode == 0;
270
public static void Client (string command)
272
Client (command, false);
275
public static void Client (string command, bool wait)
279
client = Process.Start ("xmms2", command);
281
client.WaitForExit ();