Audacious  $Id:Doxyfile42802007-03-2104:39:00Znenolod$
drct.c
Go to the documentation of this file.
00001 /*
00002  * drct.c
00003  * Copyright 2009-2011 John Lindgren
00004  *
00005  * This file is part of Audacious.
00006  *
00007  * Audacious is free software: you can redistribute it and/or modify it under
00008  * the terms of the GNU General Public License as published by the Free Software
00009  * Foundation, version 2 or version 3 of the License.
00010  *
00011  * Audacious is distributed in the hope that it will be useful, but WITHOUT ANY
00012  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
00013  * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU General Public License along with
00016  * Audacious. If not, see <http://www.gnu.org/licenses/>.
00017  *
00018  * The Audacious team does not consider modular code linking to Audacious or
00019  * using our public API to be a derived work.
00020  */
00021 
00022 #include <glib.h>
00023 #include <libaudcore/hook.h>
00024 #include <libaudcore/vfs.h>
00025 
00026 #include "audconfig.h"
00027 #include "config.h"
00028 #include "drct.h"
00029 #include "glib-compat.h"
00030 #include "i18n.h"
00031 #include "playback.h"
00032 #include "playlist.h"
00033 
00034 /* --- PROGRAM CONTROL --- */
00035 
00036 void drct_quit (void)
00037 {
00038     hook_call ("quit", NULL);
00039 }
00040 
00041 /* --- PLAYBACK CONTROL --- */
00042 
00043 void drct_play (void)
00044 {
00045     if (playback_get_playing ())
00046     {
00047         if (playback_get_paused ())
00048             playback_pause ();
00049         else
00050             playback_seek (0);
00051     }
00052     else
00053     {
00054         playlist_set_playing (playlist_get_active ());
00055         playback_play (0, FALSE);
00056     }
00057 }
00058 
00059 void drct_pause (void)
00060 {
00061     if (playback_get_playing ())
00062         playback_pause ();
00063 }
00064 
00065 void drct_stop (void)
00066 {
00067     if (playback_get_playing ())
00068         playback_stop ();
00069 }
00070 
00071 gboolean drct_get_playing (void)
00072 {
00073     return playback_get_playing ();
00074 }
00075 
00076 gboolean drct_get_ready (void)
00077 {
00078     return playback_get_ready ();
00079 }
00080 
00081 gboolean drct_get_paused (void)
00082 {
00083     return playback_get_paused ();
00084 }
00085 
00086 gchar * drct_get_title (void)
00087 {
00088     return playback_get_title ();
00089 }
00090 
00091 void drct_get_info (gint * bitrate, gint * samplerate, gint * channels)
00092 {
00093     playback_get_info (bitrate, samplerate, channels);
00094 }
00095 
00096 gint drct_get_time (void)
00097 {
00098     return playback_get_time ();
00099 }
00100 
00101 gint drct_get_length (void)
00102 {
00103     return playback_get_length ();
00104 }
00105 
00106 void drct_seek (gint time)
00107 {
00108     playback_seek (time);
00109 }
00110 
00111 /* --- VOLUME CONTROL --- */
00112 
00113 void drct_get_volume (gint * left, gint * right)
00114 {
00115     playback_get_volume (left, right);
00116     * left = CLAMP (* left, 0, 100);
00117     * right = CLAMP (* right, 0, 100);
00118 }
00119 
00120 void drct_set_volume (gint left, gint right)
00121 {
00122     playback_set_volume (CLAMP (left, 0, 100), CLAMP (right, 0, 100));
00123 }
00124 
00125 void drct_get_volume_main (gint * volume)
00126 {
00127     gint left, right;
00128     drct_get_volume (& left, & right);
00129     * volume = MAX (left, right);
00130 }
00131 
00132 void drct_set_volume_main (gint volume)
00133 {
00134     gint left, right, current;
00135     drct_get_volume (& left, & right);
00136     current = MAX (left, right);
00137 
00138     if (current > 0)
00139         drct_set_volume (volume * left / current, volume * right / current);
00140     else
00141         drct_set_volume (volume, volume);
00142 }
00143 
00144 void drct_get_volume_balance (gint * balance)
00145 {
00146     gint left, right;
00147     drct_get_volume (& left, & right);
00148 
00149     if (left == right)
00150         * balance = 0;
00151     else if (left > right)
00152         * balance = -100 + right * 100 / left;
00153     else
00154         * balance = 100 - left * 100 / right;
00155 }
00156 
00157 void drct_set_volume_balance (gint balance)
00158 {
00159     gint left, right;
00160     drct_get_volume_main (& left);
00161 
00162     if (balance < 0)
00163         right = left * (100 + balance) / 100;
00164     else
00165     {
00166         right = left;
00167         left = right * (100 - balance) / 100;
00168     }
00169 
00170     drct_set_volume (left, right);
00171 }
00172 
00173 /* --- PLAYLIST CONTROL --- */
00174 
00175 gint drct_pl_get_length (void)
00176 {
00177     return playlist_entry_count (playlist_get_active ());
00178 }
00179 
00180 void drct_pl_next (void)
00181 {
00182     gboolean play = playback_get_playing ();
00183     if (playlist_get_playing () < 0)
00184         playlist_set_playing (playlist_get_active ());
00185     if (playlist_next_song (playlist_get_playing (), cfg.repeat) && play)
00186         playback_play (0, FALSE);
00187 }
00188 
00189 void drct_pl_prev (void)
00190 {
00191     gboolean play = playback_get_playing ();
00192     if (playlist_get_playing () < 0)
00193         playlist_set_playing (playlist_get_active ());
00194     if (playlist_prev_song (playlist_get_playing ()) && play)
00195         playback_play (0, FALSE);
00196 }
00197 
00198 gint drct_pl_get_pos (void)
00199 {
00200     return playlist_get_position (playlist_get_active ());
00201 }
00202 
00203 void drct_pl_set_pos (gint pos)
00204 {
00205     gint playlist = playlist_get_active ();
00206     gboolean play = playback_get_playing ();
00207 
00208     playlist_set_position (playlist, pos);
00209 
00210     if (play)
00211     {
00212         playlist_set_playing (playlist);
00213         playback_play (0, FALSE);
00214     }
00215 }
00216 
00217 gboolean drct_pl_repeat_is_enabled (void)
00218 {
00219     return cfg.repeat;
00220 }
00221 
00222 void drct_pl_repeat_toggle (void)
00223 {
00224     cfg.repeat = ! cfg.repeat;
00225     hook_call ("toggle repeat", NULL);
00226 }
00227 
00228 gboolean drct_pl_shuffle_is_enabled (void)
00229 {
00230     return cfg.shuffle;
00231 }
00232 
00233 void drct_pl_shuffle_toggle (void)
00234 {
00235     cfg.shuffle = ! cfg.shuffle;
00236     hook_call ("toggle shuffle", NULL);
00237 }
00238 
00239 gchar * drct_pl_get_file (gint entry)
00240 {
00241     const gchar * filename = playlist_entry_get_filename
00242      (playlist_get_active (), entry);
00243     return (filename == NULL) ? NULL : g_strdup (filename);
00244 }
00245 
00246 gchar * drct_pl_get_title (gint entry)
00247 {
00248     const gchar * title = playlist_entry_get_title (playlist_get_active (),
00249      entry, FALSE);
00250     return (title == NULL) ? NULL : g_strdup (title);
00251 }
00252 
00253 gint drct_pl_get_time (gint pos)
00254 {
00255     return playlist_entry_get_length (playlist_get_active (), pos, FALSE);
00256 }
00257 
00258 static void activate_temp (void)
00259 {
00260     gint playlists = playlist_count ();
00261     const gchar * title = _("Temporary Playlist");
00262 
00263     for (gint playlist = 0; playlist < playlists; playlist ++)
00264     {
00265         if (! strcmp (playlist_get_title (playlist), title))
00266         {
00267             playlist_set_active (playlist);
00268             return;
00269         }
00270     }
00271 
00272     if (! playlist_entry_count (playlist_get_active ()))
00273         playlist_set_title (playlist_get_active (), title);
00274     else
00275     {
00276         playlist_insert (playlists);
00277         playlist_set_title (playlists, title);
00278         playlist_set_active (playlists);
00279     }
00280 }
00281 
00282 static void add_list (GList * list, gint at, gboolean to_temp, gboolean play)
00283 {
00284     if (to_temp)
00285         activate_temp ();
00286 
00287     gint playlist = playlist_get_active ();
00288 
00289     if (play)
00290     {
00291         if (cfg.clear_playlist)
00292             playlist_entry_delete (playlist, 0, playlist_entry_count (playlist));
00293         else
00294             playlist_queue_delete (playlist, 0, playlist_queue_count (playlist));
00295     }
00296 
00297     gint entries = playlist_entry_count (playlist);
00298     if (at < 0)
00299         at = entries;
00300 
00301     gint added = 0;
00302     GQueue folders = G_QUEUE_INIT;
00303     struct index * filenames = index_new ();
00304 
00305     for (; list != NULL; list = list->next)
00306     {
00307         if (filename_is_playlist (list->data))
00308         {
00309             playlist_insert_playlist (playlist, at + added, list->data);
00310             added += playlist_entry_count (playlist) - entries;
00311             entries = playlist_entry_count (playlist);
00312         }
00313         else if (vfs_file_test (list->data, G_FILE_TEST_IS_DIR))
00314             g_queue_push_tail (& folders, list->data);
00315         else
00316             index_append (filenames, g_strdup (list->data));
00317     }
00318 
00319     playlist_entry_insert_batch (playlist, at + added, filenames, NULL);
00320     added += playlist_entry_count (playlist) - entries;
00321 
00322     if (added && play)
00323     {
00324         playlist_set_playing (playlist);
00325         if (! cfg.shuffle)
00326             playlist_set_position (playlist, at);
00327         playback_play (0, FALSE);
00328         play = FALSE;
00329     }
00330 
00331     const gchar * folder;
00332     while ((folder = g_queue_pop_head (& folders)) != NULL)
00333     {
00334         playlist_insert_folder (playlist, at + added, folder, play);
00335         play = FALSE;
00336     }
00337 }
00338 
00339 void drct_pl_add (const gchar * filename, gint at)
00340 {
00341     GList * list = g_list_prepend (NULL, (void *) filename);
00342     add_list (list, at, FALSE, FALSE);
00343     g_list_free (list);
00344 }
00345 
00346 void drct_pl_add_list (GList * list, gint at)
00347 {
00348     add_list (list, at, FALSE, FALSE);
00349 }
00350 
00351 void drct_pl_open (const gchar * filename)
00352 {
00353     GList * list = g_list_prepend (NULL, (void *) filename);
00354     add_list (list, -1, cfg.open_to_temporary, TRUE);
00355     g_list_free (list);
00356 }
00357 
00358 void drct_pl_open_list (GList * list)
00359 {
00360     add_list (list, -1, cfg.open_to_temporary, TRUE);
00361 }
00362 
00363 void drct_pl_open_temp (const gchar * filename)
00364 {
00365     GList * list = g_list_prepend (NULL, (void *) filename);
00366     add_list (list, -1, TRUE, TRUE);
00367     g_list_free (list);
00368 }
00369 
00370 void drct_pl_open_temp_list (GList * list)
00371 {
00372     add_list (list, -1, TRUE, TRUE);
00373 }
00374 
00375 void drct_pl_delete (gint entry)
00376 {
00377     playlist_entry_delete (playlist_get_active (), entry, 1);
00378 }
00379 
00380 /* Advancing to the next song when the current one is deleted is tricky.  First,
00381  * we delete all the selected songs except the current one.  We can then advance
00382  * to a new song without worrying about picking one that is also selected.
00383  * Finally, we can delete the former current song without stopping playback. */
00384 
00385 void drct_pl_delete_selected (void)
00386 {
00387     gint list = playlist_get_active ();
00388     gint pos = playlist_get_position (list);
00389 
00390     if (cfg.advance_on_delete && ! cfg.no_playlist_advance
00391      && playback_get_playing () && list == playlist_get_playing ()
00392      && pos >= 0 && playlist_entry_get_selected (list, pos))
00393     {
00394         playlist_entry_set_selected (list, pos, FALSE);
00395         playlist_delete_selected (list);
00396         pos = playlist_get_position (list); /* it may have moved */
00397 
00398         if (playlist_next_song (list, cfg.repeat)
00399          && playlist_get_position (list) != pos)
00400             playback_play (0, FALSE);
00401 
00402         playlist_entry_delete (list, pos, 1);
00403     }
00404     else
00405         playlist_delete_selected (list);
00406 }
00407 
00408 void drct_pl_clear (void)
00409 {
00410     gint playlist = playlist_get_active ();
00411     playlist_entry_delete (playlist, 0, playlist_entry_count (playlist));
00412 }
00413 
00414 /* --- PLAYLIST QUEUE CONTROL --- */
00415 
00416 gint drct_pq_get_length (void)
00417 {
00418     return playlist_queue_count (playlist_get_active ());
00419 }
00420 
00421 gint drct_pq_get_entry (gint queue_position)
00422 {
00423     return playlist_queue_get_entry (playlist_get_active (), queue_position);
00424 }
00425 
00426 gboolean drct_pq_is_queued (gint entry)
00427 {
00428     return (drct_pq_get_queue_position (entry) >= 0);
00429 }
00430 
00431 gint drct_pq_get_queue_position (gint entry)
00432 {
00433     return playlist_queue_find_entry (playlist_get_active (), entry);
00434 }
00435 
00436 void drct_pq_add (gint entry)
00437 {
00438     playlist_queue_insert (playlist_get_active (), -1, entry);
00439 }
00440 
00441 void drct_pq_remove (gint entry)
00442 {
00443     gint playlist = playlist_get_active ();
00444     playlist_queue_delete (playlist, playlist_queue_find_entry (playlist,
00445      entry), 1);
00446 }
00447 
00448 void drct_pq_clear (void)
00449 {
00450     gint playlist = playlist_get_active ();
00451     playlist_queue_delete (playlist, 0, playlist_queue_count (playlist));
00452 }