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         playback_play (0, FALSE);
00054 }
00055 
00056 void drct_pause (void)
00057 {
00058     if (playback_get_playing ())
00059         playback_pause ();
00060 }
00061 
00062 void drct_stop (void)
00063 {
00064     if (playback_get_playing ())
00065         playback_stop ();
00066 }
00067 
00068 gboolean drct_get_playing (void)
00069 {
00070     return playback_get_playing ();
00071 }
00072 
00073 gboolean drct_get_ready (void)
00074 {
00075     return playback_get_ready ();
00076 }
00077 
00078 gboolean drct_get_paused (void)
00079 {
00080     return playback_get_paused ();
00081 }
00082 
00083 gchar * drct_get_title (void)
00084 {
00085     return playback_get_title ();
00086 }
00087 
00088 void drct_get_info (gint * bitrate, gint * samplerate, gint * channels)
00089 {
00090     playback_get_info (bitrate, samplerate, channels);
00091 }
00092 
00093 gint drct_get_time (void)
00094 {
00095     return playback_get_time ();
00096 }
00097 
00098 gint drct_get_length (void)
00099 {
00100     return playback_get_length ();
00101 }
00102 
00103 void drct_seek (gint time)
00104 {
00105     playback_seek (time);
00106 }
00107 
00108 /* --- VOLUME CONTROL --- */
00109 
00110 void drct_get_volume (gint * left, gint * right)
00111 {
00112     playback_get_volume (left, right);
00113     * left = CLAMP (* left, 0, 100);
00114     * right = CLAMP (* right, 0, 100);
00115 }
00116 
00117 void drct_set_volume (gint left, gint right)
00118 {
00119     playback_set_volume (CLAMP (left, 0, 100), CLAMP (right, 0, 100));
00120 }
00121 
00122 void drct_get_volume_main (gint * volume)
00123 {
00124     gint left, right;
00125     drct_get_volume (& left, & right);
00126     * volume = MAX (left, right);
00127 }
00128 
00129 void drct_set_volume_main (gint volume)
00130 {
00131     gint left, right, current;
00132     drct_get_volume (& left, & right);
00133     current = MAX (left, right);
00134 
00135     if (current > 0)
00136         drct_set_volume (volume * left / current, volume * right / current);
00137     else
00138         drct_set_volume (volume, volume);
00139 }
00140 
00141 void drct_get_volume_balance (gint * balance)
00142 {
00143     gint left, right;
00144     drct_get_volume (& left, & right);
00145 
00146     if (left == right)
00147         * balance = 0;
00148     else if (left > right)
00149         * balance = -100 + right * 100 / left;
00150     else
00151         * balance = 100 - left * 100 / right;
00152 }
00153 
00154 void drct_set_volume_balance (gint balance)
00155 {
00156     gint left, right;
00157     drct_get_volume_main (& left);
00158 
00159     if (balance < 0)
00160         right = left * (100 + balance) / 100;
00161     else
00162     {
00163         right = left;
00164         left = right * (100 - balance) / 100;
00165     }
00166 
00167     drct_set_volume (left, right);
00168 }
00169 
00170 /* --- PLAYLIST CONTROL --- */
00171 
00172 gint drct_pl_get_length (void)
00173 {
00174     return playlist_entry_count (playlist_get_active ());
00175 }
00176 
00177 void drct_pl_next (void)
00178 {
00179     gboolean play = playback_get_playing ();
00180     if (playlist_get_playing () < 0)
00181         playlist_set_playing (playlist_get_active ());
00182     if (playlist_next_song (playlist_get_playing (), cfg.repeat) && play)
00183         playback_play (0, FALSE);
00184 }
00185 
00186 void drct_pl_prev (void)
00187 {
00188     gboolean play = playback_get_playing ();
00189     if (playlist_get_playing () < 0)
00190         playlist_set_playing (playlist_get_active ());
00191     if (playlist_prev_song (playlist_get_playing ()) && play)
00192         playback_play (0, FALSE);
00193 }
00194 
00195 gint drct_pl_get_pos (void)
00196 {
00197     return playlist_get_position (playlist_get_active ());
00198 }
00199 
00200 void drct_pl_set_pos (gint pos)
00201 {
00202     gint playlist = playlist_get_active ();
00203     gboolean play = playback_get_playing ();
00204 
00205     playlist_set_position (playlist, pos);
00206 
00207     if (play)
00208     {
00209         playlist_set_playing (playlist);
00210         playback_play (0, FALSE);
00211     }
00212 }
00213 
00214 gboolean drct_pl_repeat_is_enabled (void)
00215 {
00216     return cfg.repeat;
00217 }
00218 
00219 void drct_pl_repeat_toggle (void)
00220 {
00221     cfg.repeat = ! cfg.repeat;
00222     hook_call ("toggle repeat", NULL);
00223 }
00224 
00225 gboolean drct_pl_shuffle_is_enabled (void)
00226 {
00227     return cfg.shuffle;
00228 }
00229 
00230 void drct_pl_shuffle_toggle (void)
00231 {
00232     cfg.shuffle = ! cfg.shuffle;
00233     hook_call ("toggle shuffle", NULL);
00234 }
00235 
00236 gchar * drct_pl_get_file (gint entry)
00237 {
00238     const gchar * filename = playlist_entry_get_filename
00239      (playlist_get_active (), entry);
00240     return (filename == NULL) ? NULL : g_strdup (filename);
00241 }
00242 
00243 gchar * drct_pl_get_title (gint entry)
00244 {
00245     const gchar * title = playlist_entry_get_title (playlist_get_active (),
00246      entry, FALSE);
00247     return (title == NULL) ? NULL : g_strdup (title);
00248 }
00249 
00250 gint drct_pl_get_time (gint pos)
00251 {
00252     return playlist_entry_get_length (playlist_get_active (), pos, FALSE);
00253 }
00254 
00255 static void activate_temp (void)
00256 {
00257     gint playlists = playlist_count ();
00258     const gchar * title = _("Temporary Playlist");
00259 
00260     for (gint playlist = 0; playlist < playlists; playlist ++)
00261     {
00262         if (! strcmp (playlist_get_title (playlist), title))
00263         {
00264             playlist_set_active (playlist);
00265             return;
00266         }
00267     }
00268 
00269     if (! playlist_entry_count (playlist_get_active ()))
00270         playlist_set_title (playlist_get_active (), title);
00271     else
00272     {
00273         playlist_insert (playlists);
00274         playlist_set_title (playlists, title);
00275         playlist_set_active (playlists);
00276     }
00277 }
00278 
00279 static void add_list (GList * list, gint at, gboolean to_temp, gboolean play)
00280 {
00281     if (to_temp)
00282         activate_temp ();
00283 
00284     gint playlist = playlist_get_active ();
00285 
00286     if (play)
00287     {
00288         if (cfg.clear_playlist)
00289             playlist_entry_delete (playlist, 0, playlist_entry_count (playlist));
00290         else
00291             playlist_queue_delete (playlist, 0, playlist_queue_count (playlist));
00292     }
00293 
00294     gint entries = playlist_entry_count (playlist);
00295     if (at < 0)
00296         at = entries;
00297 
00298     gint added = 0;
00299     GQueue folders = G_QUEUE_INIT;
00300     struct index * filenames = index_new ();
00301 
00302     for (; list != NULL; list = list->next)
00303     {
00304         if (filename_is_playlist (list->data))
00305         {
00306             playlist_insert_playlist (playlist, at + added, list->data);
00307             added += playlist_entry_count (playlist) - entries;
00308             entries = playlist_entry_count (playlist);
00309         }
00310         else if (vfs_file_test (list->data, G_FILE_TEST_IS_DIR))
00311             g_queue_push_tail (& folders, list->data);
00312         else
00313             index_append (filenames, g_strdup (list->data));
00314     }
00315 
00316     playlist_entry_insert_batch (playlist, at + added, filenames, NULL);
00317     added += playlist_entry_count (playlist) - entries;
00318 
00319     if (added && play)
00320     {
00321         playlist_set_playing (playlist);
00322         if (! cfg.shuffle)
00323             playlist_set_position (playlist, at);
00324         playback_play (0, FALSE);
00325         play = FALSE;
00326     }
00327 
00328     const gchar * folder;
00329     while ((folder = g_queue_pop_head (& folders)) != NULL)
00330     {
00331         playlist_insert_folder (playlist, at + added, folder, play);
00332         play = FALSE;
00333     }
00334 }
00335 
00336 void drct_pl_add (const gchar * filename, gint at)
00337 {
00338     GList * list = g_list_prepend (NULL, (void *) filename);
00339     add_list (list, at, FALSE, FALSE);
00340     g_list_free (list);
00341 }
00342 
00343 void drct_pl_add_list (GList * list, gint at)
00344 {
00345     add_list (list, at, FALSE, FALSE);
00346 }
00347 
00348 void drct_pl_open (const gchar * filename)
00349 {
00350     GList * list = g_list_prepend (NULL, (void *) filename);
00351     add_list (list, -1, cfg.open_to_temporary, TRUE);
00352     g_list_free (list);
00353 }
00354 
00355 void drct_pl_open_list (GList * list)
00356 {
00357     add_list (list, -1, cfg.open_to_temporary, TRUE);
00358 }
00359 
00360 void drct_pl_open_temp (const gchar * filename)
00361 {
00362     GList * list = g_list_prepend (NULL, (void *) filename);
00363     add_list (list, -1, TRUE, TRUE);
00364     g_list_free (list);
00365 }
00366 
00367 void drct_pl_open_temp_list (GList * list)
00368 {
00369     add_list (list, -1, TRUE, TRUE);
00370 }
00371 
00372 void drct_pl_delete (gint entry)
00373 {
00374     playlist_entry_delete (playlist_get_active (), entry, 1);
00375 }
00376 
00377 /* Advancing to the next song when the current one is deleted is tricky.  First,
00378  * we delete all the selected songs except the current one.  We can then advance
00379  * to a new song without worrying about picking one that is also selected.
00380  * Finally, we can delete the former current song without stopping playback. */
00381 
00382 void drct_pl_delete_selected (void)
00383 {
00384     gint list = playlist_get_active ();
00385     gint pos = playlist_get_position (list);
00386 
00387     if (cfg.advance_on_delete && ! cfg.no_playlist_advance
00388      && playback_get_playing () && list == playlist_get_playing ()
00389      && pos >= 0 && playlist_entry_get_selected (list, pos))
00390     {
00391         playlist_entry_set_selected (list, pos, FALSE);
00392         playlist_delete_selected (list);
00393         pos = playlist_get_position (list); /* it may have moved */
00394 
00395         if (playlist_next_song (list, cfg.repeat)
00396          && playlist_get_position (list) != pos)
00397             playback_play (0, FALSE);
00398 
00399         playlist_entry_delete (list, pos, 1);
00400     }
00401     else
00402         playlist_delete_selected (list);
00403 }
00404 
00405 void drct_pl_clear (void)
00406 {
00407     gint playlist = playlist_get_active ();
00408     playlist_entry_delete (playlist, 0, playlist_entry_count (playlist));
00409 }
00410 
00411 /* --- PLAYLIST QUEUE CONTROL --- */
00412 
00413 gint drct_pq_get_length (void)
00414 {
00415     return playlist_queue_count (playlist_get_active ());
00416 }
00417 
00418 gint drct_pq_get_entry (gint queue_position)
00419 {
00420     return playlist_queue_get_entry (playlist_get_active (), queue_position);
00421 }
00422 
00423 gboolean drct_pq_is_queued (gint entry)
00424 {
00425     return (drct_pq_get_queue_position (entry) >= 0);
00426 }
00427 
00428 gint drct_pq_get_queue_position (gint entry)
00429 {
00430     return playlist_queue_find_entry (playlist_get_active (), entry);
00431 }
00432 
00433 void drct_pq_add (gint entry)
00434 {
00435     playlist_queue_insert (playlist_get_active (), -1, entry);
00436 }
00437 
00438 void drct_pq_remove (gint entry)
00439 {
00440     gint playlist = playlist_get_active ();
00441     playlist_queue_delete (playlist, playlist_queue_find_entry (playlist,
00442      entry), 1);
00443 }
00444 
00445 void drct_pq_clear (void)
00446 {
00447     gint playlist = playlist_get_active ();
00448     playlist_queue_delete (playlist, 0, playlist_queue_count (playlist));
00449 }