gxmms2-0.7.1/0000755000175000017500000000000011427742710011435 5ustar wejpwejpgxmms2-0.7.1/COPYING0000644000175000017500000004313110601276546012474 0ustar wejpwejp GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. gxmms2-0.7.1/gtrackinfo/0000755000175000017500000000000011427742710013564 5ustar wejpwejpgxmms2-0.7.1/gtrackinfo/gtrackinfo.h0000644000175000017500000000323210601276543016063 0ustar wejpwejp/* * File: gtrackinfo.h * * GKrellM 2 Plugin to control XMMS2 * Copyright (c) 2005 Johannes Heimansberg * * requires GKrellM 2.0.0 or better and XMMS2 DR1 or better * * Released under the GNU General Public License v2 */ #ifndef __GTRACKINFO_H__ #define __GTRACKINFO_H__ #include #include #include #include "trackinfo.h" G_BEGIN_DECLS #define GTRACKINFO_TYPE (gtrackinfo_get_type ()) #define GTRACKINFO(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTRACKINFO_TYPE, GTrackinfo)) #define GTRACKINFO_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTRACKINFO_TYPE, GTrackinfoClass)) #define IS_GTRACKINFO(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTRACKINFO_TYPE)) #define IS_GTRACKINFO_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTRACKINFO_TYPE)) typedef struct _GTrackinfo GTrackinfo; typedef struct _GTrackinfoClass GTrackinfoClass; gboolean gtrackinfo_set_info(GTrackinfo *gti, trackinfo *info); struct _GTrackinfo { GtkDialog dialog; GtkWidget *hbox; GtkWidget *table; GtkWidget *entry_title, *entry_artist, *entry_album; GtkWidget *entry_date, *entry_comment, *entry_url, *entry_genre; GtkWidget *label_title, *label_artist, *label_album; GtkWidget *label_date, *label_comment, *label_url, *label_genre; GtkWidget *ok_button; GtkWidget *frame, *frame_vbox; GtkWidget *label_length, *label_bitrate, *label_filetype, *label_id; GtkWidget *label_samplerate, *label_filesize; }; struct _GTrackinfoClass { GtkDialogClass parent_class; void (* gtrackinfo) (GTrackinfo *gti); }; GType gtrackinfo_get_type(void); GtkWidget* gtrackinfo_new(void); G_END_DECLS #endif gxmms2-0.7.1/gtrackinfo/trackinfo.h0000644000175000017500000000475711130200116015706 0ustar wejpwejp/* * File: trackinfo.h * * Copyright (c) 2005 Johannes Heimansberg * * requires XMMS2 DR2 or better * * Released under the GNU General Public License v2 */ #ifndef __TRACKINFO_H__ #define __TRACKINFO_H__ #include #include #include struct _trackinfo { gchar artist[512]; gchar title[512]; gchar album[512]; gchar date[128]; gchar comment[512]; gchar genre[128]; gchar channel[256]; gint32 playtime; gchar url[1024]; gchar full_title[1200]; gint32 bitrate; gint32 samplerate; gint32 filesize; gchar filetype[256]; gint min; gint sec; gint32 id; gboolean vbr; gboolean stream; gboolean no_album; gboolean no_artist; gboolean no_bitrate; gboolean no_playtime; gboolean no_title; gboolean no_samplerate; gboolean no_filesize; }; typedef struct _trackinfo trackinfo; void trackinfo_update(xmmsv_t *val, trackinfo *track); gchar *trackinfo_get_album_str(trackinfo *track); gchar *trackinfo_get_artist_str(trackinfo *track); gchar *trackinfo_get_bitrate_str_alloc(trackinfo *track); gchar *trackinfo_get_channel_str(trackinfo *track); gchar *trackinfo_get_comment_str(trackinfo *track); gchar *trackinfo_get_date_str(trackinfo *track); gint32 trackinfo_get_file_size(trackinfo *track); void trackinfo_get_full_title(gchar *target, gint target_length, trackinfo *track, gboolean show_time); gchar *trackinfo_get_genre_str(trackinfo *track); guint trackinfo_get_id(trackinfo *track); gchar *trackinfo_get_mimetype_str(trackinfo *track); guint trackinfo_get_minutes(trackinfo *track); gint32 trackinfo_get_playtime(trackinfo *track); gchar *trackinfo_get_playtime_str_alloc(trackinfo *track); gchar *trackinfo_get_samplerate_str_alloc(trackinfo *track); guint trackinfo_get_seconds(trackinfo *track); gchar *trackinfo_get_title_str(trackinfo *track); gchar *trackinfo_get_url_str(trackinfo *track); gboolean trackinfo_has_album(trackinfo *track); gboolean trackinfo_has_artist(trackinfo *track); gboolean trackinfo_has_bitrate(trackinfo *track); gboolean trackinfo_has_file_size(trackinfo *track); gboolean trackinfo_has_playtime(trackinfo *track); gboolean trackinfo_has_samplerate(trackinfo *track); gboolean trackinfo_has_title(trackinfo *track); gboolean trackinfo_is_stream(trackinfo *track); gboolean trackinfo_is_vbr(trackinfo *track); gchar *decode_url(const gchar *url); #endif gxmms2-0.7.1/gtrackinfo/gtrackinfo.c0000644000175000017500000002012210601276543016053 0ustar wejpwejp/* * File: gtrackinfo.c * * Copyright (c) 2005 Johannes Heimansberg * * Released under the GNU General Public License v2 */ #include #include #include #include #include "gtrackinfo.h" #include "trackinfo.h" static void gtrackinfo_class_init(GTrackinfoClass *klass); static void gtrackinfo_init(GTrackinfo *gti); GType gtrackinfo_get_type(void) { static GType gti_type = 0; if (!gti_type) { static const GTypeInfo gti_info = { sizeof (GTrackinfoClass), NULL, /* base_init */ NULL, /* base_finalize */ (GClassInitFunc) gtrackinfo_class_init, NULL, /* class_finalize */ NULL, /* class_data */ sizeof (GTrackinfo), 0, (GInstanceInitFunc) gtrackinfo_init, }; gti_type = g_type_register_static (GTK_TYPE_DIALOG, "GTrackinfo", >i_info, 0); } return gti_type; } static void gtrackinfo_class_init(GTrackinfoClass *klass) { } static void cb_close_trackinfo_dialog(GtkWidget *widget, gpointer pt) { GtkWidget *gti = (GtkWidget *)pt; gtk_widget_destroy(gti); } static void gtrackinfo_init(GTrackinfo *gti) { gtk_window_set_title(GTK_WINDOW(gti), "File details"); gti->hbox = gtk_hbox_new(FALSE, 3); gtk_container_set_border_width(GTK_CONTAINER(gti->hbox), 8); gtk_box_pack_start(GTK_BOX(GTK_DIALOG(gti)->vbox), gti->hbox, FALSE, FALSE, 0); gti->table = gtk_table_new(3, 7, FALSE); gtk_table_set_row_spacings(GTK_TABLE(gti->table), 4); gtk_table_set_col_spacings(GTK_TABLE(gti->table), 4); gtk_box_pack_start(GTK_BOX(gti->hbox), gti->table, TRUE, TRUE, 0); /* ... */ gti->label_title = gtk_label_new("Title:"); gtk_table_attach(GTK_TABLE (gti->table), gti->label_title, 0, 1, 0, 1, GTK_SHRINK, GTK_SHRINK, 0, 0); gti->entry_title = gtk_entry_new(); gtk_entry_set_editable(GTK_ENTRY(gti->entry_title), FALSE); gtk_table_attach_defaults(GTK_TABLE(gti->table), gti->entry_title, 1, 2, 0, 1); /* ... */ gti->label_artist = gtk_label_new("Artist:"); gtk_table_attach(GTK_TABLE(gti->table), gti->label_artist, 0, 1, 1, 2, GTK_SHRINK, GTK_SHRINK, 0, 0); gti->entry_artist = gtk_entry_new(); gtk_entry_set_editable(GTK_ENTRY(gti->entry_artist), FALSE); gtk_table_attach_defaults(GTK_TABLE(gti->table), gti->entry_artist, 1, 2, 1, 2); /* ... */ gti->label_album = gtk_label_new("Album:"); gtk_table_attach(GTK_TABLE(gti->table), gti->label_album, 0, 1, 2, 3, GTK_SHRINK, GTK_SHRINK, 0, 0); gti->entry_album = gtk_entry_new(); gtk_entry_set_editable(GTK_ENTRY(gti->entry_album), FALSE); gtk_table_attach_defaults(GTK_TABLE(gti->table), gti->entry_album, 1, 2, 2, 3); /* ... */ gti->label_date = gtk_label_new("Date:"); gtk_table_attach(GTK_TABLE(gti->table), gti->label_date, 0, 1, 3, 4, GTK_SHRINK, GTK_SHRINK, 0, 0); gti->entry_date = gtk_entry_new(); gtk_entry_set_editable(GTK_ENTRY(gti->entry_date), FALSE); gtk_table_attach_defaults(GTK_TABLE(gti->table), gti->entry_date, 1, 2, 3, 4); /* ... */ gti->label_comment = gtk_label_new("Comment:"); gtk_table_attach(GTK_TABLE(gti->table), gti->label_comment, 0, 1, 4, 5, GTK_SHRINK, GTK_SHRINK, 0, 0); gti->entry_comment = gtk_entry_new(); gtk_entry_set_editable(GTK_ENTRY(gti->entry_comment), FALSE); gtk_table_attach_defaults(GTK_TABLE(gti->table), gti->entry_comment, 1, 2, 4, 5); /* ... */ gti->label_genre = gtk_label_new("Genre:"); gtk_table_attach(GTK_TABLE(gti->table), gti->label_genre, 0, 1, 5, 6, GTK_SHRINK, GTK_SHRINK, 0, 0); gti->entry_genre = gtk_entry_new(); gtk_entry_set_editable(GTK_ENTRY(gti->entry_genre), FALSE); gtk_table_attach_defaults(GTK_TABLE(gti->table), gti->entry_genre, 1, 2, 5, 6); /* ... */ gti->label_url = gtk_label_new("URL:"); gtk_table_attach(GTK_TABLE (gti->table), gti->label_url, 0, 1, 6, 7, GTK_SHRINK, GTK_SHRINK, 0, 0); gti->entry_url = gtk_entry_new(); gtk_entry_set_editable(GTK_ENTRY(gti->entry_url), FALSE); gtk_table_attach_defaults(GTK_TABLE (gti->table), gti->entry_url, 1, 3, 6, 7); /* ... */ gti->frame = gtk_frame_new("File details"); gtk_widget_set_size_request(gti->frame, 175, 100); gtk_table_attach(GTK_TABLE(gti->table), gti->frame, 2, 3, 0, 6, GTK_SHRINK, GTK_EXPAND | GTK_FILL, 0, 0); gti->frame_vbox = gtk_vbox_new(4, FALSE); gtk_container_add(GTK_CONTAINER(gti->frame), gti->frame_vbox); gti->label_length = gtk_label_new("Length: unknown"); gtk_container_add(GTK_CONTAINER(gti->frame_vbox), gti->label_length); gti->label_filetype = gtk_label_new("Filetype: unknown"); gtk_container_add(GTK_CONTAINER(gti->frame_vbox), gti->label_filetype); gti->label_filesize = gtk_label_new("File size: N/A"); gtk_container_add(GTK_CONTAINER(gti->frame_vbox), gti->label_filesize); gti->label_bitrate = gtk_label_new("Bit rate: unknown"); gtk_container_add(GTK_CONTAINER(gti->frame_vbox), gti->label_bitrate); gti->label_samplerate = gtk_label_new("Sample rate: unknown"); gtk_container_add(GTK_CONTAINER(gti->frame_vbox), gti->label_samplerate); gti->label_id = gtk_label_new("ID: unknown"); gtk_container_add(GTK_CONTAINER(gti->frame_vbox), gti->label_id); /* ok button */ gti->ok_button = gtk_button_new_from_stock(GTK_STOCK_OK); gtk_box_pack_start(GTK_BOX (GTK_DIALOG (gti)->action_area), gti->ok_button, TRUE, TRUE, 0); g_signal_connect(G_OBJECT(gti->ok_button), "clicked", G_CALLBACK(cb_close_trackinfo_dialog), (gpointer)gti); gtk_widget_show_all(GTK_WIDGET(gti)); } gboolean gtrackinfo_set_info(GTrackinfo *gti, trackinfo *info) { char tmp[256]; gchar *bitrate, *samplerate, *playtime; gtk_entry_set_text(GTK_ENTRY(gti->entry_title), trackinfo_get_title_str(info)); gtk_entry_set_text(GTK_ENTRY(gti->entry_artist), trackinfo_get_artist_str(info)); gtk_entry_set_text(GTK_ENTRY(gti->entry_album), trackinfo_get_album_str(info)); gtk_entry_set_text(GTK_ENTRY(gti->entry_date), trackinfo_get_date_str(info)); gtk_entry_set_text(GTK_ENTRY(gti->entry_url), trackinfo_get_url_str(info)); gtk_entry_set_text(GTK_ENTRY(gti->entry_comment), trackinfo_get_comment_str(info)); gtk_entry_set_text(GTK_ENTRY(gti->entry_genre), trackinfo_get_genre_str(info)); playtime = trackinfo_get_playtime_str_alloc(info); g_snprintf(tmp, 254, "Length: %s", playtime); g_free(playtime); gtk_label_set_text(GTK_LABEL(gti->label_length), tmp); bitrate = trackinfo_get_bitrate_str_alloc(info); if (trackinfo_is_vbr(info) == FALSE) g_snprintf(tmp, 254, "Bit rate: %s", bitrate); else g_snprintf(tmp, 254, "Avg. Bit rate: %s (VBR)", bitrate); g_free(bitrate); gtk_label_set_text(GTK_LABEL(gti->label_bitrate), tmp); samplerate = trackinfo_get_samplerate_str_alloc(info); g_snprintf(tmp, 254, "Sample rate: %s", samplerate); g_free(samplerate); gtk_label_set_text(GTK_LABEL(gti->label_samplerate), tmp); g_snprintf(tmp, 254, "File type: %s", trackinfo_get_mimetype_str(info)); gtk_label_set_text(GTK_LABEL(gti->label_filetype), tmp); g_snprintf(tmp, 254, "File size: %d KiB", trackinfo_get_file_size(info)); gtk_label_set_text(GTK_LABEL(gti->label_filesize), tmp); g_snprintf(tmp, 254, "ID: %d", trackinfo_get_id(info)); gtk_label_set_text(GTK_LABEL(gti->label_id), tmp); return TRUE; } GtkWidget* gtrackinfo_new(void) { return GTK_WIDGET(g_object_new(gtrackinfo_get_type(), NULL)); } gxmms2-0.7.1/gtrackinfo/trackinfo.c0000644000175000017500000001765211213135526015715 0ustar wejpwejp/* * File: trackinfo.c * * Copyright (c) 2005-2008 Johannes Heimansberg * * Released under the GNU General Public License v2 */ #include #include #include #include #include #include "trackinfo.h" #include "xmms2ctrl/xmms2ctrl.h" #include "sdecode/sdecode.h" gchar *decode_url(const gchar *url) { xmmsv_t *url_v; gchar *res = NULL; url_v = xmmsv_new_string(url); if (url_v) { xmmsv_t *decoded_url_v; decoded_url_v = xmmsv_decode_url(url_v); xmmsv_unref(url_v); if (decoded_url_v) { const unsigned char *burl; unsigned int blen; if (xmmsv_get_bin(decoded_url_v, &burl, &blen)) { res = g_malloc(blen + 1); memcpy(res, burl, blen); res[blen] = '\0'; } xmmsv_unref(decoded_url_v); } } return res; } void trackinfo_update(xmmsv_t *val, trackinfo *track) { gint32 bitrate = 0, samplerate = 0, id, playtime = 0, vbr = 0, filesize = 0; gchar *album, *artist, *channel, *comment, *date; gchar *genre, *mime, *title, *url, *url_utf8; track->stream = FALSE; track->vbr = FALSE; track->no_artist = FALSE; track->no_title = FALSE; track->no_album = FALSE; track->no_playtime = FALSE; track->no_bitrate = FALSE; track->no_samplerate = FALSE; track->no_filesize = FALSE; val = xmmsv_propdict_to_dict(val, NULL); if (!xmmsv_dict_entry_get_string(val, "artist", (const gchar **)&artist)) { artist = "Unknown"; track->no_artist = TRUE; } if (!xmmsv_dict_entry_get_string(val, "title", (const gchar **)&title)) { title = "Unknown"; track->no_title = TRUE; } if (!xmmsv_dict_entry_get_string(val, "album", (const gchar **)&album)) { album = "Unknown"; track->no_album = TRUE; } if (!xmmsv_dict_entry_get_string(val, "comment", (const gchar **)&comment)) comment = ""; if (!xmmsv_dict_entry_get_int(val, "duration", &playtime)) track->no_playtime = TRUE; if (!xmmsv_dict_entry_get_int(val, "id", &id)) id = 0; if (!xmmsv_dict_entry_get_string(val, "mime", (const gchar **)&mime)) mime = "Unknown"; if (!xmmsv_dict_entry_get_string(val, "genre", (const gchar **)&genre)) genre = ""; if (!xmmsv_dict_entry_get_int(val, "bitrate", &bitrate)) track->no_bitrate = TRUE; if (!xmmsv_dict_entry_get_int(val, "samplerate", &samplerate)) track->no_samplerate = TRUE; if (!xmmsv_dict_entry_get_int(val, "size", &filesize)) track->no_filesize = TRUE; if (!xmmsv_dict_entry_get_string(val, "url", (const gchar **)&url)) url = ""; if (!xmmsv_dict_entry_get_string(val, "date", (const gchar **)&date)) date = ""; if (!xmmsv_dict_entry_get_string(val, "channel", (const gchar **)&channel)) channel = ""; else track->stream = TRUE; xmmsv_dict_entry_get_int(val, "isvbr", &vbr); if (vbr == 1) track->vbr = TRUE; url_utf8 = decode_url(url); g_utf8_strncpy(track->artist, artist, sizeof(track->artist)); g_utf8_strncpy(track->title, title, sizeof(track->title)); g_utf8_strncpy(track->album, album, sizeof(track->album)); g_utf8_strncpy(track->comment, comment, sizeof(track->comment)); g_utf8_strncpy(track->genre, genre, sizeof(track->genre)); g_utf8_strncpy(track->date, date, sizeof(track->date)); g_utf8_strncpy(track->filetype, mime, sizeof(track->filetype)); g_utf8_strncpy(track->url, url_utf8, sizeof(track->url)); g_utf8_strncpy(track->channel, channel, sizeof(track->channel)); track->id = id; track->bitrate = bitrate / 1000; track->samplerate = samplerate; /* playtime/1000=track length in seconds */ track->playtime = playtime; track->min = playtime / 60000; track->sec = playtime % 60000 / 1000; track->filesize = filesize / 1024; g_free(url_utf8); if (strcmp(track->artist, "Unknown Artist") == 0 && strcmp(track->title, "Unknown Track") == 0) { gchar tmp[1024] = ""; gint left = 0, right = 0, counter = 0; while(counter < strlen(track->url)) { if (track->url[counter] == '/' && counter+1 < strlen(track->url)) left = counter+1; if (track->url[counter] == '.' && counter-1 > 0) right = counter-1; counter++; } for (counter = left; counter <= right && counter - left < 1023; counter++) { tmp[counter - left] = track->url[counter]; } tmp[counter] = '\0'; g_snprintf(track->full_title, sizeof(track->full_title), "%s (%d:%02d)", tmp, track->min, track->sec); } else { g_snprintf(track->full_title, sizeof(track->full_title), "%s - %s (%d:%02d)", track->artist, track->title, track->min, track->sec); } xmmsv_unref(val); } gchar *trackinfo_get_album_str(trackinfo *track) { return track->album; } gchar *trackinfo_get_artist_str(trackinfo *track) { return track->artist; } gchar *trackinfo_get_bitrate_str_alloc(trackinfo *track) { gchar *result = g_malloc(sizeof(gchar) * 14); if (track->no_bitrate == FALSE) g_snprintf(result, 14, "%d kbit/s", track->bitrate); else g_snprintf(result, 14, "N/A"); return result; } gint32 trackinfo_get_file_size(trackinfo *track) { return track->filesize; } void trackinfo_get_full_title(gchar *target, gint target_length, trackinfo *track, gboolean show_time) { gchar *prefix = "", *separator = ""; gchar *filename = NULL; gchar *artist = trackinfo_get_artist_str(track); gchar *title = trackinfo_get_title_str(track); gchar time[16] = ""; if (show_time) { g_snprintf(time, 15, " (%d:%02d)", trackinfo_get_minutes(track), trackinfo_get_seconds(track)); } filename = g_path_get_basename(trackinfo_get_url_str(track)); if (trackinfo_is_stream(track)) prefix = "[Stream] "; if (!trackinfo_has_artist(track)) artist = ""; else separator = " - "; if (!trackinfo_has_artist(track) && !trackinfo_has_title(track)) title = filename; g_snprintf(target, target_length, "%s%s%s%s%s", prefix, artist, separator, title, time); g_free(filename); } gchar *trackinfo_get_samplerate_str_alloc(trackinfo *track) { gchar *result = g_malloc(sizeof(gchar) * 14); if (track->no_samplerate == FALSE) g_snprintf(result, 14, "%d Hz", track->samplerate); else g_snprintf(result, 14, "N/A"); return result; } gchar *trackinfo_get_channel_str(trackinfo *track) { return track->channel; } gchar *trackinfo_get_comment_str(trackinfo *track) { return track->comment; } gchar *trackinfo_get_date_str(trackinfo *track) { return track->date; } gchar *trackinfo_get_genre_str(trackinfo *track) { return track->genre; } guint trackinfo_get_id(trackinfo *track) { return track->id; } gchar *trackinfo_get_mimetype_str(trackinfo *track) { return track->filetype; } guint trackinfo_get_minutes(trackinfo *track) { return track->min; } gint32 trackinfo_get_playtime(trackinfo *track) { return track->playtime; } gchar *trackinfo_get_playtime_str_alloc(trackinfo *track) { gchar *result = g_malloc(sizeof(gchar) * 10); if (track->no_playtime == FALSE) g_snprintf(result, 10, "%d:%02d", track->min, track->sec); else g_snprintf(result, 10, "N/A"); return result; } guint trackinfo_get_seconds(trackinfo *track) { return track->sec; } gchar *trackinfo_get_title_str(trackinfo *track) { return track->title; } gchar *trackinfo_get_url_str(trackinfo *track) { return track->url; } gboolean trackinfo_has_album(trackinfo *track) { return !track->no_album; } gboolean trackinfo_has_artist(trackinfo *track) { return !track->no_artist; } gboolean trackinfo_has_bitrate(trackinfo *track) { return !track->no_bitrate; } gboolean trackinfo_has_file_size(trackinfo *track) { return !track->no_filesize; } gboolean trackinfo_has_playtime(trackinfo *track) { return !track->no_playtime; } gboolean trackinfo_has_samplerate(trackinfo *track) { return !track->no_samplerate; } gboolean trackinfo_has_title(trackinfo *track) { return !track->no_title; } gboolean trackinfo_is_stream(trackinfo *track) { return track->stream; } gboolean trackinfo_is_vbr(trackinfo *track) { return track->vbr; } gxmms2-0.7.1/gkrellxmms2/0000755000175000017500000000000011427742710013704 5ustar wejpwejpgxmms2-0.7.1/gkrellxmms2/setupwidget.c0000644000175000017500000000542010740447563016422 0ustar wejpwejp/* * File: setupwidget.c * * GKrellM 2 Plugin to control XMMS2 * Copyright (c) 2005-2008 Johannes Heimansberg * * requires GKrellM 2 and XMMS2 * * Released under the GNU General Public License v2 */ #include "setupwidget.h" const char *setup_widget_get_ipc_path(SetupWidget *sw) { return gtk_entry_get_text(GTK_ENTRY(sw->entry_ipc_path)); } void setup_widget_set_ipc_path(SetupWidget *sw, char *path) { gtk_entry_set_text(GTK_ENTRY(sw->entry_ipc_path), path); } void setup_widget_set_scroll_speed(SetupWidget *sw, int speed) { gtk_range_set_value(GTK_RANGE(sw->hscale_scroll_speed), speed); } int setup_widget_get_scroll_speed(SetupWidget *sw) { return gtk_range_get_value(GTK_RANGE(sw->hscale_scroll_speed)); } void setup_widget_set_auto_reconnect(SetupWidget *sw, gboolean value) { gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(sw->checkbox_auto_reconnect), value); } gboolean setup_widget_get_auto_reconnect(SetupWidget *sw) { return gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(sw->checkbox_auto_reconnect)); } GtkWidget *setup_widget_create(SetupWidget *sw) { sw->box = gtk_vbox_new(FALSE, 3); sw->frame1 = gtk_frame_new("xmms2d settings"); sw->frame2 = gtk_frame_new("gkrellxmms2 settings"); gtk_box_pack_start(GTK_BOX(sw->box), sw->frame1, TRUE, TRUE, 0); gtk_box_pack_start(GTK_BOX(sw->box), sw->frame2, TRUE, TRUE, 0); /* xmms2d setup widgets */ sw->table1 = gtk_table_new(1, 2, FALSE); gtk_container_add(GTK_CONTAINER(sw->frame1), sw->table1); sw->label_ipc_path = gtk_label_new("xmms2d IPC path"); gtk_table_attach(GTK_TABLE(sw->table1), sw->label_ipc_path, 0, 1, 0, 1, GTK_SHRINK | GTK_FILL, GTK_EXPAND | GTK_FILL, 5, 5); sw->entry_ipc_path = gtk_entry_new(); gtk_table_attach(GTK_TABLE(sw->table1), sw->entry_ipc_path, 1, 2, 0, 1, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 5, 5); /* gkrellxmms2 setup widgets */ sw->table2 = gtk_table_new(3, 2, FALSE); gtk_container_add(GTK_CONTAINER(sw->frame2), sw->table2); sw->checkbox_show_volume_slider = gtk_check_button_new_with_mnemonic("Show _volume slider"); gtk_table_attach(GTK_TABLE(sw->table2), sw->checkbox_show_volume_slider, 0, 2, 0, 1, GTK_SHRINK | GTK_FILL, GTK_EXPAND | GTK_FILL, 5, 5); sw->checkbox_auto_reconnect = gtk_check_button_new_with_mnemonic("Auto _reconnect"); gtk_table_attach(GTK_TABLE(sw->table2), sw->checkbox_auto_reconnect, 0, 2, 2, 3, GTK_SHRINK | GTK_FILL, GTK_EXPAND | GTK_FILL, 5, 5); sw->label_scroll_speed = gtk_label_new("Title scroll speed"); gtk_table_attach(GTK_TABLE(sw->table2), sw->label_scroll_speed, 0, 1, 3, 4, GTK_SHRINK | GTK_FILL, GTK_EXPAND | GTK_FILL, 5, 5); sw->hscale_scroll_speed = gtk_hscale_new_with_range(0, 5, 1); gtk_table_attach(GTK_TABLE(sw->table2), sw->hscale_scroll_speed, 1, 2, 3, 4, GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 5, 5); return sw->box; } gxmms2-0.7.1/gkrellxmms2/buttons.c0000644000175000017500000002324310601276546015554 0ustar wejpwejp/* * File: buttons.c * * GKrellM 2 Plugin to control XMMS2 * Copyright (c) 2005 Johannes Heimansberg * * requires GKrellM 2.0.0 or better and XMMS2 DR1 or better * * Released under the GNU General Public License v2 */ #if !defined(WIN32) #include #else #include #include #endif #include "buttons.h" #include "button_prev.xpm" #include "button_next.xpm" #include "button_play.xpm" #include "button_pause.xpm" #include "button_stop.xpm" #include "button_menu.xpm" #define STYLE_NAME "gkrellxmms2" void control_buttons_set_play_pause_button(ControlButtons *cb, gint status) { if (status == PLAY_BUTTON) { gkrellm_show_button(cb->button_play); gkrellm_hide_button(cb->button_pause); } else if (status == PAUSE_BUTTON) { gkrellm_show_button(cb->button_pause); gkrellm_hide_button(cb->button_play); } } void control_buttons_create(ControlButtons *cb, GkrellmPanel *panel, gint y, void(*cb_button)()) { gfloat scale_factor = gkrellm_chart_width() / 75.0f; gint button_space = (gint)(14.0f * scale_factor) * 5 + 4; gint x = (gkrellm_chart_width() - button_space) / 2; gkrellm_load_piximage("button_prev", button_prev_xpm, &cb->image_prev, STYLE_NAME); cb->button_prev = gkrellm_make_scaled_button(panel, cb->image_prev, /* GkrellmPiximage image to use to */ /* create the button images. Use a */ /* builtin default if NULL */ cb_button, /* Button clicked callback function */ GINT_TO_POINTER(PREV_BUTTON), /* Arg to callback function */ FALSE, /* auto_hide: if TRUE, button is visible */ /* only when mouse is in the panel */ FALSE, /* set_default_border: if TRUE, apply a */ /* default border of 1,1,1,1. If false */ /* use the GkrellmPiximage border which */ /* in this case is 0,0,0,0 */ 0, /* Image depth if image != NULL */ 0, /* Initial out frame if image != NULL */ 1, /* Pressed frame if image != NULL */ x, /* x position of button */ y, /* y position of button */ 14 * scale_factor, /* Width for scaling the button */ 15); /* Height for scaling the button */ x = cb->button_prev->decal->x + cb->button_prev->decal->w + 1; gkrellm_load_piximage("button_play", button_play_xpm, &cb->image_play, STYLE_NAME); cb->button_play = gkrellm_make_scaled_button(panel, cb->image_play, /* GkrellmPiximage image to use to */ /* create the button images. Use a */ /* builtin default if NULL */ cb_button, /* Button clicked callback function */ GINT_TO_POINTER(PLAY_BUTTON), /* Arg to callback function */ FALSE, /* auto_hide: if TRUE, button is visible */ /* only when mouse is in the panel */ FALSE, /* set_default_border: if TRUE, apply a */ /* default border of 1,1,1,1. If false */ /* use the GkrellmPiximage border which */ /* in this case is 0,0,0,0 */ 0, /* Image depth if image != NULL */ 0, /* Initial out frame if image != NULL */ 1, /* Pressed frame if image != NULL */ x, /* x position of button */ y, /* y position of button */ 14 * scale_factor, /* Width for scaling the button */ 15); /* Height for scaling the button */ gkrellm_load_piximage("button_pause", button_pause_xpm, &cb->image_pause, STYLE_NAME); cb->button_pause = gkrellm_make_scaled_button(panel, cb->image_pause, /* GkrellmPiximage image to use to */ /* create the button images. Use a */ /* builtin default if NULL */ cb_button, /* Button clicked callback function */ GINT_TO_POINTER(PLAY_BUTTON), /* Arg to callback function */ FALSE, /* auto_hide: if TRUE, button is visible */ /* only when mouse is in the panel */ FALSE, /* set_default_border: if TRUE, apply a */ /* default border of 1,1,1,1. If false */ /* use the GkrellmPiximage border which */ /* in this case is 0,0,0,0 */ 0, /* Image depth if image != NULL */ 0, /* Initial out frame if image != NULL */ 1, /* Pressed frame if image != NULL */ x, /* x position of button */ y, /* y position of button */ 14 * scale_factor, /* Width for scaling the button */ 15); /* Height for scaling the button */ gkrellm_hide_button(cb->button_pause); x = cb->button_play->decal->x + cb->button_play->decal->w + 1; gkrellm_load_piximage("button_stop", button_stop_xpm, &cb->image_stop, STYLE_NAME); cb->button_stop = gkrellm_make_scaled_button(panel, cb->image_stop, /* GkrellmPiximage image to use to */ /* create the button images. Use a */ /* builtin default if NULL */ cb_button, /* Button clicked callback function */ GINT_TO_POINTER(STOP_BUTTON), /* Arg to callback function */ FALSE, /* auto_hide: if TRUE, button is visible */ /* only when mouse is in the panel */ FALSE, /* set_default_border: if TRUE, apply a */ /* default border of 1,1,1,1. If false */ /* use the GkrellmPiximage border which */ /* in this case is 0,0,0,0 */ 0, /* Image depth if image != NULL */ 0, /* Initial out frame if image != NULL */ 1, /* Pressed frame if image != NULL */ x, /* x position of button */ y, /* y position of button */ 14 * scale_factor, /* Width for scaling the button */ 15); /* Height for scaling the button */ x = cb->button_stop->decal->x + cb->button_stop->decal->w + 1; gkrellm_load_piximage("button_next", button_next_xpm, &cb->image_next, STYLE_NAME); cb->button_next = gkrellm_make_scaled_button(panel, cb->image_next, /* GkrellmPiximage image to use to */ /* create the button images. Use a */ /* builtin default if NULL */ cb_button, /* Button clicked callback function */ GINT_TO_POINTER(NEXT_BUTTON), /* Arg to callback function */ FALSE, /* auto_hide: if TRUE, button is visible */ /* only when mouse is in the panel */ FALSE, /* set_default_border: if TRUE, apply a */ /* default border of 1,1,1,1. If false */ /* use the GkrellmPiximage border which */ /* in this case is 0,0,0,0 */ 0, /* Image depth if image != NULL */ 0, /* Initial out frame if image != NULL */ 1, /* Pressed frame if image != NULL */ x, /* x position of button */ y, /* y position of button */ 14 * scale_factor, /* Width for scaling the button */ 15); /* Height for scaling the button */ x = cb->button_next->decal->x + cb->button_next->decal->w + 1; gkrellm_load_piximage("button_menu", button_menu_xpm, &cb->image_menu, STYLE_NAME); cb->button_menu = gkrellm_make_scaled_button(panel, cb->image_menu, /* GkrellmPiximage image to use to */ /* create the button images. Use a */ /* builtin default if NULL */ cb_button, /* Button clicked callback function */ GINT_TO_POINTER(MENU_BUTTON), /* Arg to callback function */ FALSE, /* auto_hide: if TRUE, button is visible */ /* only when mouse is in the panel */ FALSE, /* set_default_border: if TRUE, apply a */ /* default border of 1,1,1,1. If false */ /* use the GkrellmPiximage border which */ /* in this case is 0,0,0,0 */ 0, /* Image depth if image != NULL */ 0, /* Initial out frame if image != NULL */ 1, /* Pressed frame if image != NULL */ x, /* x position of button */ y, /* y position of button */ 14 * scale_factor, /* Width for scaling the button */ 15); /* Height for scaling the button */ /* x = cb->button_menu->decal->x + cb->button_menu->decal->w + 1; */ } gxmms2-0.7.1/gkrellxmms2/setupwidget.h0000644000175000017500000000200010740447606016414 0ustar wejpwejp/* * File: setupwidget.h * * GKrellM 2 Plugin to control XMMS2 * Copyright (c) 2005-2008 Johannes Heimansberg * * requires GKrellM 2 and XMMS2 * * Released under the GNU General Public License v2 */ #include typedef struct _SetupWidget { GtkWidget *box; GtkWidget *frame1, *frame2, *table1, *table2; /* xmms2d setup widgets */ GtkWidget *label_ipc_path, *entry_ipc_path; /* gkrellxmms2 setup widgets */ GtkWidget *checkbox_show_volume_slider; GtkWidget *checkbox_auto_reconnect; GtkWidget *label_scroll_speed, *hscale_scroll_speed; } SetupWidget; const char *setup_widget_get_ipc_path(SetupWidget *sw); void setup_widget_set_ipc_path(SetupWidget *sw, char *path); void setup_widget_set_scroll_speed(SetupWidget *sw, int speed); int setup_widget_get_scroll_speed(SetupWidget *sw); void setup_widget_set_auto_reconnect(SetupWidget *sw, gboolean value); gboolean setup_widget_get_auto_reconnect(SetupWidget *sw); GtkWidget *setup_widget_create(SetupWidget *sw); gxmms2-0.7.1/gkrellxmms2/button_pause.xpm0000644000175000017500000000116710601276545017150 0ustar wejpwejp/* XPM */ static char * button_pause_xpm[] = { "13 30 4 1", " c #FFFFFF", ". c #858585", "+ c #D2D2D2", "@ c #000000", " ", " .", " +++++++++..", " +@@+++@@+..", " +@@+++@@+..", " +@@+++@@+..", " +@@+++@@+..", " +@@+++@@+..", " +@@+++@@+..", " +@@+++@@+..", " +@@+++@@+..", " +@@+++@@+..", " +++++++++..", " ............", ".............", ".............", "............ ", "..+++++++++ ", "..+@@+++@@+ ", "..+@@+++@@+ ", "..+@@+++@@+ ", "..+@@+++@@+ ", "..+@@+++@@+ ", "..+@@+++@@+ ", "..+@@+++@@+ ", "..+@@+++@@+ ", "..+@@+++@@+ ", "..+++++++++ ", ". ", " "}; gxmms2-0.7.1/gkrellxmms2/buttons.h0000644000175000017500000000156010601276546015557 0ustar wejpwejp/* * File: buttons.h * * GKrellM 2 Plugin to control XMMS2 * Copyright (c) 2005 Johannes Heimansberg * * requires GKrellM 2.0.0 or better and XMMS2 DR1 or better * * Released under the GNU General Public License v2 */ #ifndef _BUTTONS_H #define _BUTTONS_H typedef struct { GkrellmDecalbutton *button_prev, *button_next, *button_play; GkrellmDecalbutton *button_pause, *button_stop, *button_menu; GkrellmPiximage *image_prev, *image_next, *image_play; GkrellmPiximage *image_pause, *image_stop, *image_menu; } ControlButtons; void control_buttons_create(ControlButtons *cb, GkrellmPanel *panel, gint y, void(*cb_button)()); void control_buttons_set_play_pause_button(ControlButtons *cb, gint status); enum { PREV_BUTTON = 0, PLAY_BUTTON, PAUSE_BUTTON, NEXT_BUTTON, STOP_BUTTON, MENU_BUTTON }; #endif gxmms2-0.7.1/gkrellxmms2/button_empty.xpm0000644000175000017500000000115010601276545017161 0ustar wejpwejp/* XPM */ static char * button_empty_xpm[] = { "13 30 3 1", " c #EEEEEE", ". c #858585", "+ c #D2D2D2", " ", " .", " +++++++++..", " +++++++++..", " +++++++++..", " +++++++++..", " +++++++++..", " +++++++++..", " +++++++++..", " +++++++++..", " +++++++++..", " +++++++++..", " +++++++++..", " ............", ".............", ".............", "............ ", "..+++++++++ ", "..+++++++++ ", "..+++++++++ ", "..+++++++++ ", "..+++++++++ ", "..+++++++++ ", "..+++++++++ ", "..+++++++++ ", "..+++++++++ ", "..+++++++++ ", "..+++++++++ ", ". ", " "}; gxmms2-0.7.1/gkrellxmms2/playlist.xpm0000644000175000017500000000410710601276546016277 0ustar wejpwejp/* XPM */ static char * playlist_xpm[] = { "16 16 93 2", " c None", ". c #000000", "+ c #0E0E0E", "@ c #282828", "# c #F6F6F6", "$ c #FFFFFF", "% c #F9F9F9", "& c #F9F9F8", "* c #E7E7E7", "= c #CDCDCD", "- c #2E2E2E", "; c #DADADA", "> c #9F9F9F", ", c #FEFEFE", "' c #9B9B9A", ") c #9E9E9E", "! c #FDFDFD", "~ c #FCFCFB", "{ c #F4F4F4", "] c #D4D4D3", "^ c #9D9D9C", "/ c #FBFBFB", "( c #FAFAF9", "_ c #9A9A99", ": c #979696", "< c #CACAC8", "[ c #B6B6B4", "} c #9B9B9B", "| c #F8F8F7", "1 c #F6F6F4", "2 c #F4F3F2", "3 c #F1F0EF", "4 c #F0EFED", "5 c #E5E4E2", "6 c #C4C3C0", "7 c #F8F7F6", "8 c #F7F6F5", "9 c #EBEAE8", "0 c #E1DFDC", "a c #F6F5F4", "b c #B1B0AF", "c c #818180", "d c #AFAFAD", "e c #EFEFED", "f c #E8E7E5", "g c #A4A4A1", "h c #7F7F7E", "i c #7F7E7D", "j c #EEEDEB", "k c #ECEBE9", "l c #E8E7E4", "m c #E7E6E3", "n c #EDECEA", "o c #7D7D7C", "p c #ACABA9", "q c #91908E", "r c #8E8E8C", "s c #E6E4E1", "t c #A2A19F", "u c #646462", "v c #F0F0EE", "w c #7C7B7A", "x c #7B7B7A", "y c #E7E5E2", "z c #E4E3DF", "A c #E3E2DE", "B c #DEDDD9", "C c #DDDCD8", "D c #EDEDEB", "E c #E6E5E2", "F c #E5E4E1", "G c #747371", "H c #0B0B0B", "I c #DCDBD7", "J c #DBD9D5", "K c #E0DFDB", "L c #E3E2DF", "M c #E4E2DF", "N c #DCDAD6", "O c #D9D7D3", "P c #E1E0DC", "Q c #E2E1DD", "R c #71716F", "S c #0B0B0A", "T c #706F6D", "U c #D8D6D1", "V c #E1DFDB", "W c #E0DEDA", "X c #DFDEDA", "Y c #DEDCD8", "Z c #D8D6D2", "` c #D7D6D1", " . c #D5D3CE", " . . . . . . . . + @ . ", " . # $ $ $ $ % & & * . = - ", " . $ ; > $ , ' ' ' * . = = . ", " . $ > ) ! ~ & & { ] . . . . ", " . , ! ^ / ( _ ' : * * < [ . ", " . ~ / } & | 1 2 3 4 4 5 6 . ", " . ( & | 7 8 7 7 7 2 9 0 0 . ", " . a b c d e ' ' f . . g 0 . ", " . 2 h e i j k l m . . . 0 . ", " . 2 n o p k q r s . t u 0 . ", " . v w w x l y z A . B C 0 . ", " . D E E E F G H H . I J K . ", " . 9 L A M z . . . . N O C . ", " . m 0 P K Q R H S T O U I . ", " . V W X B K Y Y N N Z ` .. ", " . . . . . . . . . . . . "}; gxmms2-0.7.1/gkrellxmms2/gkrellxmms2.c0000644000175000017500000006534711427741422016335 0ustar wejpwejp/* * File: gkrellxmms2.c * * GKrellM 2 Plugin to control XMMS2 * Copyright (c) 2005-2010 Johannes Heimansberg * * requires GKrellM 2 and XMMS2 * * Version: 0.7.1 * * Released under the GNU General Public License v2 */ #define VERSION_NUMBER "0.7.1" #if !defined(WIN32) #include #else #include #include #endif #include #include "xmms2ctrl/xmms2ctrl.h" #include "gtrackinfo/trackinfo.h" #include "gtrackinfo/gtrackinfo.h" #include "gmedialib/gmedialib.h" #include "buttons.h" #include "setupwidget.h" #include "playlist.xpm" #define PLUGIN_NAME "gkrellxmms2" #define SCROLL_TEXT_LENGTH 1200 static GkrellmMonitor *monitor; static GkrellmPanel *panel; static GkrellmDecal *text1_decal; static GkrellmKrell *krell; static ControlButtons cb; static GtkTooltips *tooltip = NULL; static gchar scroll_text[SCROLL_TEXT_LENGTH] = "XMMS2 Control "; static gint style_id; static gboolean reset_scroller = TRUE; static gboolean seek_in_progress = FALSE; static GtkWidget *gml = NULL; xmmsc_connection_t *connection; static trackinfo track; static gboolean local_xmms2d = FALSE; static SetupWidget sw; #if defined(GKRELLM_HAVE_DECAL_SCROLL_TEXT) static gboolean scroll_loop_mode; #endif static int xmms2_connect(void); static struct Configuration { gint scroll_speed; gint medialib_window_width, medialib_window_height; gint medialib_window_pos_x, medialib_window_pos_y; gboolean medialib_search_column_id, medialib_search_column_artist; gboolean medialib_search_column_track, medialib_search_column_album; gboolean medialib_search_column_rating; gboolean medialib_playlist_column_id, medialib_playlist_column_artist; gboolean medialib_playlist_column_track, medialib_playlist_column_album; gboolean medialib_playlist_column_rating, medialib_playlist_column_pos; gboolean medialib_playlist_new_confirm; gboolean auto_reconnect; gchar ipc_path[256]; } config; static void update_krell(void) { gchar scroll_text_old[SCROLL_TEXT_LENGTH] = ""; if (trackinfo_has_playtime(&track) && trackinfo_get_playtime(&track) > 0) { gkrellm_set_krell_full_scale(krell, trackinfo_get_playtime(&track) / 1000, 1); } else { gkrellm_set_krell_full_scale(krell, 1, 1); } g_strlcpy(scroll_text_old, scroll_text, sizeof(scroll_text_old)); trackinfo_get_full_title(scroll_text, SCROLL_TEXT_LENGTH, &track, TRUE); if (strcmp(scroll_text, scroll_text_old) != 0) reset_scroller = TRUE; gtk_tooltips_set_tip(tooltip, panel->drawing_area, scroll_text, "empty"); } static void cb_menu_trackinfo(GtkWidget *widget, gpointer pt) { GtkWidget *dialog = gtrackinfo_new(); gtrackinfo_set_info(GTRACKINFO(dialog), &track); gtk_widget_show(dialog); } static void cb_menu_playlist(GtkWidget *widget, gpointer pt) { if (!GTK_IS_WIDGET(gml)) { gml = gmedialib_new(TRUE, TRUE, local_xmms2d, TRUE, TRUE); gml_pl_set_new_playlist_confirm(GMEDIALIB(gml), config.medialib_playlist_new_confirm); gtk_window_resize(GTK_WINDOW(gml), config.medialib_window_width, config.medialib_window_height); if (gml_notebook_is_mlib_search_visible(GMEDIALIB(gml))) { gml_search_set_column_id_visible(GMEDIALIB(gml), config.medialib_search_column_id); gml_search_set_column_artist_visible(GMEDIALIB(gml), config.medialib_search_column_artist); gml_search_set_column_track_visible(GMEDIALIB(gml), config.medialib_search_column_track); gml_search_set_column_album_visible(GMEDIALIB(gml), config.medialib_search_column_album); gml_search_set_column_rating_visible(GMEDIALIB(gml), config.medialib_search_column_rating); } if (gml_notebook_is_playlist_visible(GMEDIALIB(gml))) { gml_pl_set_column_id_visible(GMEDIALIB(gml), config.medialib_playlist_column_id); gml_pl_set_column_artist_visible(GMEDIALIB(gml), config.medialib_playlist_column_artist); gml_pl_set_column_track_visible(GMEDIALIB(gml), config.medialib_playlist_column_track); gml_pl_set_column_album_visible(GMEDIALIB(gml), config.medialib_playlist_column_album); gml_pl_set_column_rating_visible(GMEDIALIB(gml), config.medialib_playlist_column_rating); gml_pl_set_column_pos_visible(GMEDIALIB(gml), config.medialib_playlist_column_pos); } } gtk_window_present(GTK_WINDOW(gml)); } static void open_menu() { GtkWidget *menu, *menuitem, *image; menu = gtk_menu_new(); menuitem = gtk_image_menu_item_new_from_stock(GTK_STOCK_DIALOG_INFO, NULL); g_signal_connect(menuitem, "activate", G_CALLBACK(cb_menu_trackinfo), NULL); gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); menuitem = gtk_separator_menu_item_new(); gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); menuitem = gtk_image_menu_item_new_with_mnemonic("_Open Playlist Editor"); image = gtk_image_new_from_pixbuf(gdk_pixbuf_new_from_xpm_data((const char **)playlist_xpm)); gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuitem), image); g_signal_connect(menuitem, "activate", G_CALLBACK(cb_menu_playlist), NULL); gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); gtk_widget_show_all(menu); gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, 0, 0); } static void cb_panel_click_event(GtkWidget *widget, GdkEventButton *event, gpointer user_data) { guint yoffset = *(guint *)user_data; if (event->button == 3) gkrellm_open_config_window(monitor); if (event->button == 1 && event->y < yoffset) { seek_in_progress = TRUE; gkrellm_update_krell(panel, krell, event->x * (trackinfo_get_playtime(&track) / 1000) / gkrellm_chart_width()); } } static void cb_panel_release_event(GtkWidget *widget, GdkEventButton *event, gpointer user_data) { guint yoffset = *(guint *)user_data; if (event->button == 1) { xmmsc_result_t *res; guint seek_ms; seek_ms = (guint)(event->x * trackinfo_get_playtime(&track)/gkrellm_chart_width()); if (xmms2ctrl_get_error() != ERROR_CONNECTION && trackinfo_get_playtime(&track) > seek_ms && event->y < yoffset && seek_in_progress) { res = xmmsc_playback_seek_ms(connection, seek_ms, XMMS_PLAYBACK_SEEK_SET); xmmsc_result_unref(res); } seek_in_progress = FALSE; } } static gboolean cb_motion_notify_event(GtkWidget *widget, GdkEventMotion *event, gpointer user_data) { int x, y; GdkModifierType state; guint yoffset = *(guint *)user_data; if (event->is_hint) { gdk_window_get_pointer(event->window, &x, &y, &state); } else { x = event->x; y = event->y; state = event->state; } if (state & GDK_BUTTON1_MASK && y < yoffset && seek_in_progress) { int pos = x*(trackinfo_get_playtime(&track)/1000)/gkrellm_chart_width(); gkrellm_update_krell(panel, krell, pos); } else if (seek_in_progress) { seek_in_progress = FALSE; } return TRUE; } static gboolean reconnect(void) { gboolean result = TRUE; printf("gkrellxmms2: reconnecting to xmms2d..."); /* try to reconnect */ if (xmms2_connect() != ERROR_NONE) { strncpy(scroll_text, xmmsc_get_last_error(connection), SCROLL_TEXT_LENGTH); result = FALSE; } else if (GTK_IS_WIDGET(gml)) { gml_pl_setup_xmms_callbacks((GMedialib *)gml); gml_setup_xmms_callbacks((GMedialib *)gml); } printf("%s\n", result ? "ok" : "failed"); return result; } static void cb_button(GkrellmDecalbutton *button, gpointer data) { gint button_pressed = GPOINTER_TO_INT(data); if (xmms2ctrl_get_error() == ERROR_CONNECTION) { if (!reconnect()) button_pressed = -1; } switch(button_pressed) { case PREV_BUTTON: xmms2ctrl_do_reljump(connection, -1); break; case PLAY_BUTTON: xmms2ctrl_toggle_pause(connection, TRUE); break; case NEXT_BUTTON: xmms2ctrl_do_reljump(connection, 1); break; case STOP_BUTTON: xmms2ctrl_stop(connection); break; case MENU_BUTTON: open_menu(); break; } } static gint panel_expose_event(GtkWidget *widget, GdkEventExpose *ev) { gdk_draw_pixmap(widget->window, widget->style->fg_gc[GTK_WIDGET_STATE (widget)], panel->pixmap, ev->area.x, ev->area.y, ev->area.x, ev->area.y, ev->area.width, ev->area.height); return FALSE; } static int sig_handle_playtime(xmmsv_t *val, void *userdata) { gint ptime = 0; static guint cnt = 0; if (xmms2ctrl_get_error() != ERROR_CONNECTION && !xmmsv_is_error(val)) { xmmsv_get_int(val, &ptime); } if (cnt > 10) { cnt = 0; if (trackinfo_get_playtime(&track) <= 0) ptime = 0; if (!seek_in_progress) gkrellm_update_krell(panel, krell, ptime / 1000); } cnt++; return TRUE; } static void update_plugin() { gint w_scroll, w_decal; static gint x_scroll; /* static guint current_track_time = 0; */ #if defined(GKRELLM_HAVE_DECAL_SCROLL_TEXT) /* Gkrellm version 2.2.0 adds a scrolling text mode to a text decal so | that inherently slow Pango text draws can be avoided at each scroll | step as long as the sroll text string is unchanged. */ gkrellm_decal_scroll_text_set_text(panel, text1_decal, scroll_text); gkrellm_decal_scroll_text_get_size(text1_decal, &w_scroll, NULL); gkrellm_decal_get_size(text1_decal, &w_decal, NULL); if (reset_scroller) { x_scroll = w_decal; reset_scroller = FALSE; } x_scroll -= config.scroll_speed; if (x_scroll <= -w_scroll) x_scroll = scroll_loop_mode ? 0 : w_decal; gkrellm_decal_text_set_offset(text1_decal, x_scroll, 0); #else w_decal = text1_decal->w; w_scroll = gdk_string_width(text1_decal->text_style.font, scroll_text); x_scroll -= config.scroll_speed; if (reset_scroller) { x_scroll = w_decal; reset_scroller = FALSE; } if (x_scroll <= -w_scroll) x_scroll = w_decal; text1_decal->x_off = x_scroll; gkrellm_draw_decal_text(panel, text1_decal, scroll_text, x_scroll); #endif gkrellm_draw_panel_layers(panel); } static int n_media_lib_get_info(xmmsv_t *val, void *arg) { trackinfo_update(val, &track); update_krell(); update_plugin(); return FALSE; } static gint current_id; static int bc_handle_medialib_entry_changed(xmmsv_t *val, void *userdata) { gint id; if (xmmsv_get_int(val, &id) && xmms2ctrl_get_error() != ERROR_CONNECTION) { if (current_id == id) { xmmsc_result_t *res2; res2 = xmmsc_medialib_get_info(connection, current_id); xmmsc_result_notifier_set(res2, n_media_lib_get_info, ¤t_id); xmmsc_result_unref(res2); } } return TRUE; } static int bc_handle_current_id(xmmsv_t *val, void *userdata) { if (xmmsv_get_int(val, ¤t_id) && xmms2ctrl_get_error() != ERROR_CONNECTION) { xmmsc_result_t *res2; res2 = xmmsc_medialib_get_info(connection, current_id); xmmsc_result_notifier_set(res2, n_media_lib_get_info, ¤t_id); xmmsc_result_unref(res2); } return TRUE; } static int sig_handle_current_id(xmmsv_t *val, void *userdata) { if (xmmsv_get_int(val, ¤t_id) && xmms2ctrl_get_error() != ERROR_CONNECTION) { xmmsc_result_t *res2; res2 = xmmsc_medialib_get_info(connection, current_id); xmmsc_result_notifier_set(res2, n_media_lib_get_info, ¤t_id); xmmsc_result_unref(res2); } return TRUE; } static int bc_handle_playback_status_change(xmmsv_t *val, void *userdata) { gint pb_status = 0; if (xmmsv_is_error(val)) return FALSE; if (!xmmsv_get_int(val, &pb_status)) return FALSE; switch (pb_status) { case XMMS_PLAYBACK_STATUS_PLAY: control_buttons_set_play_pause_button(&cb, PAUSE_BUTTON); break; case XMMS_PLAYBACK_STATUS_STOP: gkrellm_update_krell(panel, krell, 0); case XMMS_PLAYBACK_STATUS_PAUSE: control_buttons_set_play_pause_button(&cb, PLAY_BUTTON); break; } return TRUE; } static int n_handle_playback_status(xmmsv_t *val, void *userdata) { gint pb_status = 0; if (xmmsv_is_error(val)) return FALSE; if (!xmmsv_get_int(val, &pb_status)) return FALSE; if (pb_status == XMMS_PLAYBACK_STATUS_PLAY) { control_buttons_set_play_pause_button(&cb, PAUSE_BUTTON); } else { control_buttons_set_play_pause_button(&cb, PLAY_BUTTON); } return FALSE; } static gboolean cb_timer_connection_lost(gpointer userdata) { gboolean result = TRUE; if (xmms2ctrl_get_error() == ERROR_CONNECTION) { if (reconnect()) result = FALSE; /* do not restart timer on success */ } else { result = FALSE; /* do not restart timer if there is no connection prob*/ } return result; } static void connection_lost(void *data) { strcpy(scroll_text, "ERROR: Connection to xmms2d lost."); xmms2ctrl_set_error(ERROR_CONNECTION); xmmsc_unref(connection); if (config.auto_reconnect) g_timeout_add(6000, &cb_timer_connection_lost, NULL); } static int xmms2_connect() { gchar *path = NULL; path = getenv("XMMS_PATH"); if (path == NULL) path = config.ipc_path; xmms2ctrl_set_error(ERROR_NONE); if (!path || g_ascii_strncasecmp(path, "unix://", 7) == 0) local_xmms2d = TRUE; /* Initialize connection to XMMS2 daemon */ if (!xmmsc_connect(connection, path)) { strncpy(scroll_text, xmmsc_get_last_error(connection), SCROLL_TEXT_LENGTH); xmms2ctrl_set_error(ERROR_CONNECTION); } else { xmmsc_mainloop_gmain_init(connection); XMMS_CALLBACK_SET(connection, xmmsc_playback_current_id, sig_handle_current_id, connection); XMMS_CALLBACK_SET(connection, xmmsc_broadcast_playback_current_id, bc_handle_current_id, connection); XMMS_CALLBACK_SET(connection, xmmsc_broadcast_medialib_entry_changed, bc_handle_medialib_entry_changed, connection); XMMS_CALLBACK_SET(connection, xmmsc_signal_playback_playtime, sig_handle_playtime, NULL); XMMS_CALLBACK_SET(connection, xmmsc_broadcast_playback_status, bc_handle_playback_status_change, NULL); xmmsc_disconnect_callback_set(connection, connection_lost, NULL); } seek_in_progress = FALSE; return xmms2ctrl_get_error(); } static void create_plugin(GtkWidget *vbox, gint first_create) { GkrellmPiximage *krell_image = NULL; GkrellmStyle *style; GkrellmTextstyle *ts, *ts_alt; static gint y; xmmsc_result_t *res; /* Initialize connection to XMMS2 daemon */ connection = xmmsc_init("gkrellxmms2"); xmms2_connect(); if (first_create) panel = gkrellm_panel_new0(); style = gkrellm_meter_style(style_id); krell_image = gkrellm_krell_meter_piximage(style_id); krell = gkrellm_create_krell(panel, krell_image, style); gkrellm_set_krell_full_scale(krell, 230, 1); gkrellm_monotonic_krell_values(krell, FALSE); ts = gkrellm_meter_textstyle(style_id); ts_alt = gkrellm_meter_alt_textstyle(style_id); /* text decal for scroll text */ text1_decal = gkrellm_create_decal_text(panel, "Ay", ts, style, -1, /* x = -1 places at left margin */ -1, /* y = -1 places at top margin */ -1); /* w = -1 makes decal the panel width minus margins */ y = text1_decal->y + text1_decal->h + 2; control_buttons_create(&cb, panel, y, &cb_button); gkrellm_panel_configure(panel, NULL, style); gkrellm_panel_create(vbox, monitor, panel); tooltip = gtk_tooltips_new(); gtk_tooltips_set_tip(tooltip, panel->drawing_area, "XMMS2 Plugin", "empty"); gtk_tooltips_set_delay(tooltip, 750); gtk_tooltips_enable(tooltip); if (first_create) { g_signal_connect(G_OBJECT(panel->drawing_area), "expose_event", G_CALLBACK(panel_expose_event), NULL); g_signal_connect(G_OBJECT(panel->drawing_area), "button_press_event", G_CALLBACK(cb_panel_click_event), &y); g_signal_connect(G_OBJECT(panel->drawing_area), "button_release_event", G_CALLBACK(cb_panel_release_event), &y); g_signal_connect(G_OBJECT(panel->drawing_area), "motion_notify_event", G_CALLBACK(cb_motion_notify_event), &y); } if (xmms2ctrl_get_error() == ERROR_NONE) { res = xmmsc_playback_status(connection); xmmsc_result_notifier_set(res, n_handle_playback_status, NULL); xmmsc_result_unref(res); } } static gchar *plugin_info_text[] = { "GkrellM XMMS2 Control (gkrellxmms2)\n", "Version: ", VERSION_NUMBER, "\n", "gkrellxmms2 Copyright (c) 2005-2010 Johannes Heimansberg\n", "http://wejp.k.vu/\n\n", "Usage:\n", "gkrellxmms2 has five buttons to control the XMMS2 audio player.\n", "From left to right those buttons are:\n", "- Previous track button: Jumps back to the previously played track.\n", "- Play/Pause button: Toggles play/pause.\n", "- Stop button: Stops playback.\n", "- Next track button: Jumps to the next track in the playlist.\n", "- Menu button: Opens a menu, where you can either open a track info dialog\n", " or the medialib/playlist editor.\n", }; static void create_plugin_tab(GtkWidget *tab_vbox) { GtkWidget *tabs, *text, *label, *widget; GtkWidget *vbox; gint i; gchar *about_text; tabs = gtk_notebook_new(); gtk_notebook_set_tab_pos(GTK_NOTEBOOK(tabs), GTK_POS_TOP); gtk_box_pack_start(GTK_BOX(tab_vbox), tabs, TRUE, TRUE, 0); /* Info tab */ vbox = gkrellm_gtk_framed_notebook_page(tabs, "Info"); text = gkrellm_gtk_scrolled_text_view(vbox, NULL, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); for (i = 0; i < sizeof(plugin_info_text)/sizeof(gchar *); i++) gkrellm_gtk_text_view_append(text, plugin_info_text[i]); /* About tab */ about_text = g_strdup_printf( "gkrellxmms2 %s\n" "GKrellM XMMS2 Control Plugin\n\n" "Copyright (c) 2005-2010 Johannes Heimansberg\n" "http://wejp.k.vu/\n\n" "Released under the GNU General Public License v2.0", VERSION_NUMBER); text = gtk_label_new(about_text); label = gtk_label_new("About"); gtk_notebook_append_page(GTK_NOTEBOOK(tabs), text, label); g_free(about_text); /* Setup tab */ label = gtk_label_new("Setup"); widget = setup_widget_create(&sw); gtk_notebook_append_page(GTK_NOTEBOOK(tabs), widget, label); setup_widget_set_ipc_path(&sw, config.ipc_path); setup_widget_set_scroll_speed(&sw, config.scroll_speed); setup_widget_set_auto_reconnect(&sw, config.auto_reconnect); } static void apply_config(void) { config.scroll_speed = setup_widget_get_scroll_speed(&sw); config.auto_reconnect = setup_widget_get_auto_reconnect(&sw); g_strlcpy(config.ipc_path, setup_widget_get_ipc_path(&sw), sizeof(config.ipc_path)); } static void save_config(FILE *f) { if (gml != NULL) { config.medialib_window_width = gml_window_get_width(GMEDIALIB(gml)); config.medialib_window_height = gml_window_get_height(GMEDIALIB(gml)); config.medialib_window_pos_x = gml_window_get_pos_x(GMEDIALIB(gml)); config.medialib_window_pos_y = gml_window_get_pos_y(GMEDIALIB(gml)); config.medialib_playlist_new_confirm = gml_pl_get_new_playlist_confirm(GMEDIALIB(gml)); if (gml_notebook_is_mlib_search_visible(GMEDIALIB(gml))) { config.medialib_search_column_id = gml_search_get_column_id_visible(GMEDIALIB(gml)); config.medialib_search_column_artist = gml_search_get_column_artist_visible(GMEDIALIB(gml)); config.medialib_search_column_track = gml_search_get_column_track_visible(GMEDIALIB(gml)); config.medialib_search_column_album = gml_search_get_column_album_visible(GMEDIALIB(gml)); config.medialib_search_column_rating = gml_search_get_column_rating_visible(GMEDIALIB(gml)); } if (gml_notebook_is_playlist_visible(GMEDIALIB(gml))) { config.medialib_playlist_column_id = gml_pl_get_column_id_visible(GMEDIALIB(gml)); config.medialib_playlist_column_artist = gml_pl_get_column_artist_visible(GMEDIALIB(gml)); config.medialib_playlist_column_track = gml_pl_get_column_track_visible(GMEDIALIB(gml)); config.medialib_playlist_column_album = gml_pl_get_column_album_visible(GMEDIALIB(gml)); config.medialib_playlist_column_rating = gml_pl_get_column_rating_visible(GMEDIALIB(gml)); config.medialib_playlist_column_pos = gml_pl_get_column_pos_visible(GMEDIALIB(gml)); } } fprintf(f, "%s scroll_speed %d\n", PLUGIN_NAME, config.scroll_speed); fprintf(f, "%s medialib_window_width %d\n", PLUGIN_NAME, config.medialib_window_width); fprintf(f, "%s medialib_window_height %d\n", PLUGIN_NAME, config.medialib_window_height); fprintf(f, "%s medialib_window_pos_x %d\n", PLUGIN_NAME, config.medialib_window_pos_x); fprintf(f, "%s medialib_window_pos_y %d\n", PLUGIN_NAME, config.medialib_window_pos_y); fprintf(f, "%s medialib_search_column_id %d\n", PLUGIN_NAME, config.medialib_search_column_id); fprintf(f, "%s medialib_search_column_artist %d\n", PLUGIN_NAME, config.medialib_search_column_artist); fprintf(f, "%s medialib_search_column_track %d\n", PLUGIN_NAME, config.medialib_search_column_track); fprintf(f, "%s medialib_search_column_album %d\n", PLUGIN_NAME, config.medialib_search_column_album); fprintf(f, "%s medialib_search_column_rating %d\n", PLUGIN_NAME, config.medialib_search_column_rating); fprintf(f, "%s medialib_playlist_column_id %d\n", PLUGIN_NAME, config.medialib_playlist_column_id); fprintf(f, "%s medialib_playlist_column_artist %d\n", PLUGIN_NAME, config.medialib_playlist_column_artist); fprintf(f, "%s medialib_playlist_column_track %d\n", PLUGIN_NAME, config.medialib_playlist_column_track); fprintf(f, "%s medialib_playlist_column_album %d\n", PLUGIN_NAME, config.medialib_playlist_column_album); fprintf(f, "%s medialib_playlist_column_rating %d\n", PLUGIN_NAME, config.medialib_playlist_column_rating); fprintf(f, "%s medialib_playlist_column_pos %d\n", PLUGIN_NAME, config.medialib_playlist_column_pos); fprintf(f, "%s medialib_playlist_new_confirm %d\n", PLUGIN_NAME, config.medialib_playlist_new_confirm); fprintf(f, "%s ipc_path %s\n", PLUGIN_NAME, config.ipc_path); fprintf(f, "%s auto_reconnect %d\n", PLUGIN_NAME, config.auto_reconnect); } static void load_config(gchar *arg) { gchar cfg[64], item[1024]; gint n; n = sscanf(arg, "%s %[^\n]", cfg, item); if (n == 2) { if (strcmp(cfg, "scroll_speed") == 0) config.scroll_speed = atoi(item); if (strcmp(cfg, "medialib_window_width") == 0) config.medialib_window_width = (atoi(item) < 200 ? 200 : atoi(item)); if (strcmp(cfg, "medialib_window_height") == 0) config.medialib_window_height = (atoi(item) < 200 ? 200 : atoi(item)); if (strcmp(cfg, "medialib_window_pos_x") == 0) config.medialib_window_pos_x = (atoi(item) < 0 ? 0 : atoi(item)); if (strcmp(cfg, "medialib_window_pos_y") == 0) config.medialib_window_pos_y = (atoi(item) < 0 ? 0 : atoi(item)); if (strcmp(cfg, "medialib_search_column_id") == 0) config.medialib_search_column_id = atoi(item); if (strcmp(cfg, "medialib_search_column_artist") == 0) config.medialib_search_column_artist = atoi(item); if (strcmp(cfg, "medialib_search_column_track") == 0) config.medialib_search_column_track = atoi(item); if (strcmp(cfg, "medialib_search_column_album") == 0) config.medialib_search_column_album = atoi(item); if (strcmp(cfg, "medialib_search_column_rating") == 0) config.medialib_search_column_rating = atoi(item); if (strcmp(cfg, "medialib_playlist_column_id") == 0) config.medialib_playlist_column_id = atoi(item); if (strcmp(cfg, "medialib_playlist_column_artist") == 0) config.medialib_playlist_column_artist = atoi(item); if (strcmp(cfg, "medialib_playlist_column_track") == 0) config.medialib_playlist_column_track = atoi(item); if (strcmp(cfg, "medialib_playlist_column_album") == 0) config.medialib_playlist_column_album = atoi(item); if (strcmp(cfg, "medialib_playlist_column_rating") == 0) config.medialib_playlist_column_rating = atoi(item); if (strcmp(cfg, "medialib_playlist_column_pos") == 0) config.medialib_playlist_column_pos = atoi(item); if (strcmp(cfg, "medialib_playlist_new_confirm") == 0) config.medialib_playlist_new_confirm = atoi(item); if (strcmp(cfg, "ipc_path") == 0) g_strlcpy(config.ipc_path, item, sizeof(config.ipc_path)); if (strcmp(cfg, "auto_reconnect") == 0) config.auto_reconnect = atoi(item); } } static GkrellmMonitor plugin_mon = { PLUGIN_NAME, /* Name, for config tab. */ 0, /* Id, 0 if a plugin */ create_plugin, /* The create function */ update_plugin, /* The update function */ create_plugin_tab, /* The config tab create function */ apply_config, /* Apply the config function */ save_config, /* Save user config */ load_config, /* Load user config */ PLUGIN_NAME, /* config keyword */ NULL, /* Undefined 2 */ NULL, /* Undefined 1 */ NULL, /* private */ MON_MAIL, /* Insert plugin before this monitor */ NULL, /* Handle if a plugin, filled in by GKrellM */ NULL /* path if a plugin, filled in by GKrellM */ }; #if defined(WIN32) __declspec(dllexport) GkrellmMonitor * gkrellm_init_plugin(win32_plugin_callbacks* calls) #else GkrellmMonitor * gkrellm_init_plugin(void) #endif { gchar *ipc_path_default; const gchar *username; gint str_length = 0; /* set default config values */ config.scroll_speed = 1; config.medialib_window_width = 460; config.medialib_window_height = 320; config.medialib_window_pos_x = 20; config.medialib_window_pos_y = 20; config.medialib_search_column_id = TRUE; config.medialib_search_column_artist = TRUE; config.medialib_search_column_track = TRUE; config.medialib_search_column_album = TRUE; config.medialib_search_column_rating = TRUE; config.medialib_playlist_column_id = TRUE; config.medialib_playlist_column_artist = TRUE; config.medialib_playlist_column_track = TRUE; config.medialib_playlist_column_album = TRUE; config.medialib_playlist_column_rating = TRUE; config.medialib_playlist_column_pos = TRUE; config.medialib_playlist_new_confirm = TRUE; config.auto_reconnect = FALSE; username = g_get_user_name(); str_length = strlen(username) + 128; ipc_path_default = g_malloc(str_length * sizeof(gchar)); snprintf(ipc_path_default, str_length, "unix:///tmp/xmms-ipc-%s", username); g_strlcpy(config.ipc_path, ipc_path_default, sizeof(config.ipc_path)); g_free(ipc_path_default); /* If this call is made, the background and krell images for this plugin | can be custom themed by putting bg_meter.png or krell.png in the | subdirectory PLUGIN_NAME of the theme directory. Text colors (and | other things) can also be specified for the plugin with gkrellmrc | lines like: StyleMeter PLUGIN_NAME.textcolor orange black shadow | If no custom themeing has been done, then all above calls using | style_id will be equivalent to style_id = DEFAULT_STYLE_ID. */ style_id = gkrellm_add_meter_style(&plugin_mon, PLUGIN_NAME); monitor = &plugin_mon; return &plugin_mon; } gxmms2-0.7.1/gkrellxmms2/button_play.xpm0000644000175000017500000000116610601276545016777 0ustar wejpwejp/* XPM */ static char * button_play_xpm[] = { "13 30 4 1", " c #FFFFFF", ". c #858585", "+ c #D2D2D2", "@ c #000000", " ", " .", " +++++++++..", " +@+++++++..", " +@@@+++++..", " +@@@@@+++..", " +@@@@@@++..", " +@@@@@@@+..", " +@@@@@@++..", " +@@@@@+++..", " +@@@+++++..", " +@+++++++..", " +++++++++..", " ............", ".............", ".............", "............ ", "..+++++++++ ", "..+@+++++++ ", "..+@@@+++++ ", "..+@@@@@+++ ", "..+@@@@@@++ ", "..+@@@@@@@+ ", "..+@@@@@@++ ", "..+@@@@@+++ ", "..+@@@+++++ ", "..+@+++++++ ", "..+++++++++ ", ". ", " "}; gxmms2-0.7.1/gkrellxmms2/button_stop.xpm0000644000175000017500000000116610601276545017017 0ustar wejpwejp/* XPM */ static char * button_stop_xpm[] = { "13 30 4 1", " c #FFFFFF", ". c #858585", "+ c #D2D2D2", "@ c #000000", " ", " .", " +++++++++..", " +@@@@@@@+..", " +@@@@@@@+..", " +@@@@@@@+..", " +@@@@@@@+..", " +@@@@@@@+..", " +@@@@@@@+..", " +@@@@@@@+..", " +@@@@@@@+..", " +@@@@@@@+..", " +++++++++..", " ............", ".............", ".............", "............ ", "..+++++++++ ", "..+@@@@@@@+ ", "..+@@@@@@@+ ", "..+@@@@@@@+ ", "..+@@@@@@@+ ", "..+@@@@@@@+ ", "..+@@@@@@@+ ", "..+@@@@@@@+ ", "..+@@@@@@@+ ", "..+@@@@@@@+ ", "..+++++++++ ", ". ", " "}; gxmms2-0.7.1/gkrellxmms2/button_prev.xpm0000644000175000017500000000116610601276546017007 0ustar wejpwejp/* XPM */ static char * button_prev_xpm[] = { "13 30 4 1", " c #FFFFFF", ". c #858585", "+ c #D2D2D2", "@ c #000000", " ", " .", " +++++++++..", " +@@++++@+..", " +@@++@@@+..", " +@@+@@@@+..", " +@@@@@@@+..", " +@@@@@@@+..", " +@@@@@@@+..", " +@@+@@@@+..", " +@@++@@@+..", " +@@++++@+..", " +++++++++..", " ............", ".............", ".............", "............ ", "..+++++++++ ", "..+@@++++@+ ", "..+@@++@@@+ ", "..+@@+@@@@+ ", "..+@@@@@@@+ ", "..+@@@@@@@+ ", "..+@@@@@@@+ ", "..+@@+@@@@+ ", "..+@@++@@@+ ", "..+@@++++@+ ", "..+++++++++ ", ". ", " "}; gxmms2-0.7.1/gkrellxmms2/button_menu.xpm0000644000175000017500000000120210601276545016765 0ustar wejpwejp/* XPM */ static char * button_menu_xpm[] = { "13 30 5 1", " c None", ". c #EEEEEE", "+ c #858585", "@ c #D2D2D2", "# c #000000", ".............", "............+", "..@@@@@@@@@++", "..@#@@@@@#@++", "..@##@@@##@++", "..@#@#@#@#@++", "..@#@@#@@#@++", "..@#@@@@@#@++", "..@#@@@@@#@++", "..@#@@@@@#@++", "..@#@@@@@#@++", "..@#@@@@@#@++", "..@@@@@@@@@++", ".++++++++++++", "+++++++++++++", "+++++++++++++", "++++++++++++.", "++@@@@@@@@@..", "++@#@@@@@#@..", "++@##@@@##@..", "++@#@#@#@#@..", "++@#@@#@@#@..", "++@#@@@@@#@..", "++@#@@@@@#@..", "++@#@@@@@#@..", "++@#@@@@@#@..", "++@#@@@@@#@..", "++@@@@@@@@@..", "+............", "............."}; gxmms2-0.7.1/gkrellxmms2/button_next.xpm0000644000175000017500000000120210601276545016777 0ustar wejpwejp/* XPM */ static char * button_next_xpm[] = { "13 30 5 1", " c None", ". c #FFFFFF", "+ c #858585", "@ c #D2D2D2", "# c #000000", ".............", "............+", "..@@@@@@@@@++", "..@#@@@@##@++", "..@###@@##@++", "..@####@##@++", "..@#######@++", "..@#######@++", "..@#######@++", "..@####@##@++", "..@###@@##@++", "..@#@@@@##@++", "..@@@@@@@@@++", ".++++++++++++", "+++++++++++++", "+++++++++++++", "++++++++++++.", "++@@@@@@@@@..", "++@#@@@@##@..", "++@###@@##@..", "++@####@##@..", "++@#######@..", "++@#######@..", "++@#######@..", "++@####@##@..", "++@###@@##@..", "++@#@@@@##@..", "++@@@@@@@@@..", "+............", "............."}; gxmms2-0.7.1/gxmms2src/0000755000175000017500000000000011427742710013362 5ustar wejpwejpgxmms2-0.7.1/gxmms2src/status_pause.xpm0000644000175000017500000000063010601276546016631 0ustar wejpwejp/* XPM */ static char * status_pause_xpm[] = { "16 16 2 1", " c None", ". c #000000", " ", " ", " ... ... ", " ... ... ", " ... ... ", " ... ... ", " ... ... ", " ... ... ", " ... ... ", " ... ... ", " ... ... ", " ... ... ", " ... ... ", " ... ... ", " ", " "}; gxmms2-0.7.1/gxmms2src/volume2.xpm0000644000175000017500000000062310601276546015504 0ustar wejpwejp/* XPM */ static char * volume2_xpm[] = { "16 16 2 1", " c None", ". c #000000", " ", " ", " . . ", " .. . ", " ... . . ", " .... . . ", " ....... . . ", " ....... . . ", " ....... . . ", " ....... . . ", " .... . . ", " ... . . ", " .. . ", " . . ", " ", " "}; gxmms2-0.7.1/gxmms2src/wejpscroller.h0000644000175000017500000000513210601276546016251 0ustar wejpwejp/* * File: wejpscroller.h * * A gtk2 text scroll widget * Copyright (c) 2005 Johannes Heimansberg * * Released under the GNU General Public License v2 */ #ifndef __WEJPSCROLLER_H__ #define __WEJPSCROLLER_H__ #include #include G_BEGIN_DECLS #define WEJPSCROLLER_TYPE (wejpscroller_get_type ()) #define WEJPSCROLLER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), WEJPSCROLLER_TYPE, WejpScroller)) #define WEJPSCROLLER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), WEJPSCROLLER_TYPE, WejpScrollerClass)) #define IS_WEJPSCROLLER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), WEJPSCROLLER_TYPE)) #define IS_WEJPSCROLLER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), WEJPSCROLLER_TYPE)) #define FONT_STR_LENGTH 128 struct _WejpScroller { GtkEventBox dummy; GdkPixmap *pixmap; GtkWidget *drawing_area; gchar *text; gint width, height; guint pos; PangoLayout *pgl; PangoFontDescription *pfd; GdkColormap *colormap; PangoRectangle extents; gchar font[FONT_STR_LENGTH]; guint scroll_delay; gboolean scroll; gboolean smart_scrolling; gint mouse_x; gint shortmessage_timeout; gint shortmessage_pos_backup; gchar shortmessage_text_backup[1024]; }; typedef struct _WejpScroller WejpScroller; typedef struct _WejpScrollerClass WejpScrollerClass; struct _WejpScrollerClass { GtkEventBoxClass parent_class; void (* wejpscroller) (WejpScroller *ws); }; GType wejpscroller_get_type (void); GtkWidget *wejpscroller_new (guint scroll_delay, gboolean smart); void wejpscroller_clear (WejpScroller *ws); void wejpscroller_draw (WejpScroller *ws); void wejpscroller_set_dimensions (WejpScroller *scroller, gint w, gint h); void wejpscroller_set_font (WejpScroller *ws, gchar *font, gint fontsize); void wejpscroller_set_text (WejpScroller *ws, gchar *new_text, gboolean reset_pos); const gchar *wejpscroller_get_text (WejpScroller *ws); void wejpscroller_shortmessage_show(WejpScroller *ws, gchar *message, guint timeout); G_END_DECLS #endif gxmms2-0.7.1/gxmms2src/statusdisplay.h0000644000175000017500000000123210601276546016444 0ustar wejpwejp/* * File: statusdisplay.h * * gxmms2 - A gtk2 frontend for XMMS2 * Copyright (c) 2005 Johannes Heimansberg * * requires GTK+ 2.6 or better and XMMS2 DR2 or better * * Released under the GNU General Public License v2 */ #ifndef _STATUSDISPLAY_H #define _STATUSDISPLAY_H struct _StatusDisplay { GtkWidget *image_status; GdkPixbuf *icon_stop, *icon_play, *icon_pause; }; typedef struct _StatusDisplay StatusDisplay; enum { STATUS_PLAY, STATUS_PAUSE, STATUS_STOP }; void status_display_set_status(StatusDisplay *sd, gint status); void status_display_init(StatusDisplay *sd); GtkWidget *status_display_get_image(StatusDisplay *sd); #endif gxmms2-0.7.1/gxmms2src/volume0.xpm0000644000175000017500000000062310601276546015502 0ustar wejpwejp/* XPM */ static char * volume0_xpm[] = { "16 16 2 1", " c None", ". c #000000", " ", " ", " . ", " .. ", " ... ", " .... ", " ....... ", " ....... ", " ....... ", " ....... ", " .... ", " ... ", " .. ", " . ", " ", " "}; gxmms2-0.7.1/gxmms2src/wejpvolume.c0000644000175000017500000001164110601276546015730 0ustar wejpwejp/* * File: wejpvolume.c * * A gtk2 volume control widget * Copyright (c) 2006 Johannes Heimansberg * * Released under the GNU General Public License v2 */ #include "wejpvolume.h" #include #include "volume0.xpm" #include "volume1.xpm" #include "volume2.xpm" #include "volume3.xpm" enum { VOLUME_CHANGED_SIGNAL, LAST_SIGNAL }; static guint wejpvolume_signals[LAST_SIGNAL] = { 0 }; static GdkPixbuf *get_current_volume_icon(WejpVolume *wv) { gint id = wv->current_volume / (wv->max_volume / 3); return wv->icon_volume[id]; } GtkWidget *wejpvolume_new(guint max_volume, guint initial_volume, gint volume_step) { GtkWidget *wv = GTK_WIDGET(g_object_new(WEJPVOLUME_TYPE, NULL)); WEJPVOLUME(wv)->max_volume = max_volume; WEJPVOLUME(wv)->current_volume = initial_volume; WEJPVOLUME(wv)->volume_step = volume_step; WEJPVOLUME(wv)->icon_volume[0] = gdk_pixbuf_new_from_xpm_data((const char **)volume0_xpm); WEJPVOLUME(wv)->icon_volume[1] = gdk_pixbuf_new_from_xpm_data((const char **)volume1_xpm); WEJPVOLUME(wv)->icon_volume[2] = gdk_pixbuf_new_from_xpm_data((const char **)volume2_xpm); WEJPVOLUME(wv)->icon_volume[3] = gdk_pixbuf_new_from_xpm_data((const char **)volume3_xpm); WEJPVOLUME(wv)->image_status = gtk_image_new_from_pixbuf(get_current_volume_icon(WEJPVOLUME(wv))); gtk_container_add(GTK_CONTAINER(wv), WEJPVOLUME(wv)->image_status); gtk_widget_show_all(wv); return wv; } void wejpvolume_set_volume(WejpVolume *wv, guint volume) { gint vol = (volume <= wv->max_volume ? volume : wv->max_volume); if (vol < 0) vol = 0; wv->current_volume = vol; gtk_image_set_from_pixbuf(GTK_IMAGE(wv->image_status), get_current_volume_icon(wv)); } guint wejpvolume_get_volume(WejpVolume *wv) { return wv->current_volume; } static void wejpvolume_class_init(WejpVolumeClass *class) { wejpvolume_signals[VOLUME_CHANGED_SIGNAL] = g_signal_new("volume-changed", G_TYPE_FROM_CLASS(class), G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION, G_STRUCT_OFFSET(WejpVolumeClass, wejpvolume), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); } void wejpvolume_draw(WejpVolume *wv) { } static void cb_volume_change_click(GtkWidget *widget, GdkEventButton *eb, gpointer data) { gint step = WEJPVOLUME(widget)->volume_step; switch (eb->button) { case 1: WEJPVOLUME(widget)->current_volume = (WEJPVOLUME(widget)->current_volume + step <= WEJPVOLUME(widget)->max_volume ? WEJPVOLUME(widget)->current_volume + step : WEJPVOLUME(widget)->max_volume); break; case 3: WEJPVOLUME(widget)->current_volume = (WEJPVOLUME(widget)->current_volume - step >= 0 ? WEJPVOLUME(widget)->current_volume - step : 0); break; } gtk_image_set_from_pixbuf(GTK_IMAGE(WEJPVOLUME(widget)->image_status), get_current_volume_icon(WEJPVOLUME(widget))); g_signal_emit(G_OBJECT(widget), wejpvolume_signals[VOLUME_CHANGED_SIGNAL], 0); } static void cb_volume_change_scroll(GtkWidget *widget, GdkEventScroll *es, gpointer data) { gint step = WEJPVOLUME(widget)->volume_step; if (es->direction == GDK_SCROLL_UP) { WEJPVOLUME(widget)->current_volume = (WEJPVOLUME(widget)->current_volume + step <= WEJPVOLUME(widget)->max_volume ? WEJPVOLUME(widget)->current_volume + step : WEJPVOLUME(widget)->max_volume); } else if (es->direction == GDK_SCROLL_DOWN) { WEJPVOLUME(widget)->current_volume = (WEJPVOLUME(widget)->current_volume - step >= 0 ? WEJPVOLUME(widget)->current_volume - step : 0); } gtk_image_set_from_pixbuf(GTK_IMAGE(WEJPVOLUME(widget)->image_status), get_current_volume_icon(WEJPVOLUME(widget))); g_signal_emit(G_OBJECT(widget), wejpvolume_signals[VOLUME_CHANGED_SIGNAL], 0); } static void wejpvolume_init(WejpVolume *wv) { g_signal_connect(G_OBJECT(wv), "button-press-event", G_CALLBACK(cb_volume_change_click), NULL); g_signal_connect(G_OBJECT(wv), "scroll-event", G_CALLBACK(cb_volume_change_scroll), NULL); } GType wejpvolume_get_type(void) { static GType wv_type = 0; if (!wv_type) { static const GTypeInfo wv_info = { sizeof(WejpVolumeClass), NULL, /* base_init */ NULL, /* base_finalize */ (GClassInitFunc) wejpvolume_class_init, NULL, /* class_finalize */ NULL, /* class_data */ sizeof(WejpVolume), 0, /* n_preallocs */ (GInstanceInitFunc) wejpvolume_init, }; wv_type = g_type_register_static(GTK_TYPE_EVENT_BOX, "WejpVolume", &wv_info, 0); } return wv_type; } gxmms2-0.7.1/gxmms2src/status_play.xpm0000644000175000017500000000062710601276546016467 0ustar wejpwejp/* XPM */ static char * status_play_xpm[] = { "16 16 2 1", " c None", ". c #000000", " ", " ", " . ", " .. ", " ... ", " .... ", " ..... ", " ...... ", " ...... ", " ..... ", " .... ", " ... ", " .. ", " . ", " ", " "}; gxmms2-0.7.1/gxmms2src/eggtrayicon.c0000644000175000017500000003236410601276546016053 0ustar wejpwejp/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* eggtrayicon.c * Copyright (C) 2002 Anders Carlsson * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG #include #endif #include #include "eggtrayicon.h" #include #include #define _(x) x #define N_(x) x #define SYSTEM_TRAY_REQUEST_DOCK 0 #define SYSTEM_TRAY_BEGIN_MESSAGE 1 #define SYSTEM_TRAY_CANCEL_MESSAGE 2 #define SYSTEM_TRAY_ORIENTATION_HORZ 0 #define SYSTEM_TRAY_ORIENTATION_VERT 1 enum { PROP_0, PROP_ORIENTATION }; static GtkPlugClass *parent_class = NULL; static void egg_tray_icon_init (EggTrayIcon *icon); static void egg_tray_icon_class_init (EggTrayIconClass *klass); static void egg_tray_icon_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec); static void egg_tray_icon_realize (GtkWidget *widget); static void egg_tray_icon_unrealize (GtkWidget *widget); static void egg_tray_icon_update_manager_window (EggTrayIcon *icon, gboolean dock_if_realized); static void egg_tray_icon_manager_window_destroyed (EggTrayIcon *icon); GType egg_tray_icon_get_type (void) { static GType our_type = 0; if (our_type == 0) { our_type = g_type_from_name("EggTrayIcon"); if (our_type == 0) { static const GTypeInfo our_info = { sizeof (EggTrayIconClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) egg_tray_icon_class_init, NULL, /* class_finalize */ NULL, /* class_data */ sizeof (EggTrayIcon), 0, /* n_preallocs */ (GInstanceInitFunc) egg_tray_icon_init }; our_type = g_type_register_static (GTK_TYPE_PLUG, "EggTrayIcon", &our_info, 0); } else if (parent_class == NULL) { /* we're reheating the old class from a previous instance - engage ugly hack =( */ egg_tray_icon_class_init((EggTrayIconClass *)g_type_class_peek(our_type)); } } return our_type; } static void egg_tray_icon_init (EggTrayIcon *icon) { icon->stamp = 1; icon->orientation = GTK_ORIENTATION_HORIZONTAL; gtk_widget_add_events (GTK_WIDGET (icon), GDK_PROPERTY_CHANGE_MASK); } static void egg_tray_icon_class_init (EggTrayIconClass *klass) { GObjectClass *gobject_class = (GObjectClass *)klass; GtkWidgetClass *widget_class = (GtkWidgetClass *)klass; parent_class = g_type_class_peek_parent (klass); gobject_class->get_property = egg_tray_icon_get_property; widget_class->realize = egg_tray_icon_realize; widget_class->unrealize = egg_tray_icon_unrealize; g_object_class_install_property (gobject_class, PROP_ORIENTATION, g_param_spec_enum ("orientation", _("Orientation"), _("The orientation of the tray."), GTK_TYPE_ORIENTATION, GTK_ORIENTATION_HORIZONTAL, G_PARAM_READABLE)); } static void egg_tray_icon_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { EggTrayIcon *icon = EGG_TRAY_ICON (object); switch (prop_id) { case PROP_ORIENTATION: g_value_set_enum (value, icon->orientation); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } static void egg_tray_icon_get_orientation_property (EggTrayIcon *icon) { Display *xdisplay; Atom type; int format; union { gulong *prop; guchar *prop_ch; } prop = { NULL }; gulong nitems; gulong bytes_after; int error, result; g_assert (icon->manager_window != None); #if GTK_CHECK_VERSION(2,1,0) xdisplay = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (GTK_WIDGET (icon))); #else xdisplay = gdk_display; #endif gdk_error_trap_push (); type = None; result = XGetWindowProperty (xdisplay, icon->manager_window, icon->orientation_atom, 0, G_MAXLONG, FALSE, XA_CARDINAL, &type, &format, &nitems, &bytes_after, &(prop.prop_ch)); error = gdk_error_trap_pop (); if (error || result != Success) return; if (type == XA_CARDINAL) { GtkOrientation orientation; orientation = (prop.prop [0] == SYSTEM_TRAY_ORIENTATION_HORZ) ? GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL; if (icon->orientation != orientation) { icon->orientation = orientation; g_object_notify (G_OBJECT (icon), "orientation"); } } if (prop.prop) XFree (prop.prop); } static GdkFilterReturn egg_tray_icon_manager_filter (GdkXEvent *xevent, GdkEvent *event, gpointer user_data) { EggTrayIcon *icon = user_data; XEvent *xev = (XEvent *)xevent; if (xev->xany.type == ClientMessage && xev->xclient.message_type == icon->manager_atom && xev->xclient.data.l[1] == icon->selection_atom) { egg_tray_icon_update_manager_window (icon, TRUE); } else if (xev->xany.window == icon->manager_window) { if (xev->xany.type == PropertyNotify && xev->xproperty.atom == icon->orientation_atom) { egg_tray_icon_get_orientation_property (icon); } if (xev->xany.type == DestroyNotify) { egg_tray_icon_manager_window_destroyed (icon); } } return GDK_FILTER_CONTINUE; } static void egg_tray_icon_unrealize (GtkWidget *widget) { EggTrayIcon *icon = EGG_TRAY_ICON (widget); GdkWindow *root_window; if (icon->manager_window != None) { GdkWindow *gdkwin; #if GTK_CHECK_VERSION(2,1,0) gdkwin = gdk_window_lookup_for_display (gtk_widget_get_display (widget), icon->manager_window); #else gdkwin = gdk_window_lookup (icon->manager_window); #endif gdk_window_remove_filter (gdkwin, egg_tray_icon_manager_filter, icon); } #if GTK_CHECK_VERSION(2,1,0) root_window = gdk_screen_get_root_window (gtk_widget_get_screen (widget)); #else root_window = gdk_window_lookup (gdk_x11_get_default_root_xwindow ()); #endif gdk_window_remove_filter (root_window, egg_tray_icon_manager_filter, icon); if (GTK_WIDGET_CLASS (parent_class)->unrealize) (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget); } static void egg_tray_icon_send_manager_message (EggTrayIcon *icon, long message, Window window, long data1, long data2, long data3) { XClientMessageEvent ev; Display *display; ev.type = ClientMessage; ev.window = window; ev.message_type = icon->system_tray_opcode_atom; ev.format = 32; ev.data.l[0] = gdk_x11_get_server_time (GTK_WIDGET (icon)->window); ev.data.l[1] = message; ev.data.l[2] = data1; ev.data.l[3] = data2; ev.data.l[4] = data3; #if GTK_CHECK_VERSION(2,1,0) display = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (GTK_WIDGET (icon))); #else display = gdk_display; #endif gdk_error_trap_push (); XSendEvent (display, icon->manager_window, False, NoEventMask, (XEvent *)&ev); XSync (display, False); gdk_error_trap_pop (); } static void egg_tray_icon_send_dock_request (EggTrayIcon *icon) { egg_tray_icon_send_manager_message (icon, SYSTEM_TRAY_REQUEST_DOCK, icon->manager_window, gtk_plug_get_id (GTK_PLUG (icon)), 0, 0); } static void egg_tray_icon_update_manager_window (EggTrayIcon *icon, gboolean dock_if_realized) { Display *xdisplay; if (icon->manager_window != None) return; #if GTK_CHECK_VERSION(2,1,0) xdisplay = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (GTK_WIDGET (icon))); #else xdisplay = gdk_display; #endif XGrabServer (xdisplay); icon->manager_window = XGetSelectionOwner (xdisplay, icon->selection_atom); if (icon->manager_window != None) XSelectInput (xdisplay, icon->manager_window, StructureNotifyMask|PropertyChangeMask); XUngrabServer (xdisplay); XFlush (xdisplay); if (icon->manager_window != None) { GdkWindow *gdkwin; #if GTK_CHECK_VERSION(2,1,0) gdkwin = gdk_window_lookup_for_display (gtk_widget_get_display (GTK_WIDGET (icon)), icon->manager_window); #else gdkwin = gdk_window_lookup (icon->manager_window); #endif gdk_window_add_filter (gdkwin, egg_tray_icon_manager_filter, icon); if (dock_if_realized && GTK_WIDGET_REALIZED (icon)) egg_tray_icon_send_dock_request (icon); egg_tray_icon_get_orientation_property (icon); } } static void egg_tray_icon_manager_window_destroyed (EggTrayIcon *icon) { GdkWindow *gdkwin; g_return_if_fail (icon->manager_window != None); #if GTK_CHECK_VERSION(2,1,0) gdkwin = gdk_window_lookup_for_display (gtk_widget_get_display (GTK_WIDGET (icon)), icon->manager_window); #else gdkwin = gdk_window_lookup (icon->manager_window); #endif gdk_window_remove_filter (gdkwin, egg_tray_icon_manager_filter, icon); icon->manager_window = None; egg_tray_icon_update_manager_window (icon, TRUE); } static void egg_tray_icon_realize (GtkWidget *widget) { EggTrayIcon *icon = EGG_TRAY_ICON (widget); gint screen; Display *xdisplay; char buffer[256]; GdkWindow *root_window; if (GTK_WIDGET_CLASS (parent_class)->realize) GTK_WIDGET_CLASS (parent_class)->realize (widget); #if GTK_CHECK_VERSION(2,1,0) screen = gdk_screen_get_number (gtk_widget_get_screen (widget)); xdisplay = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (widget)); #else screen = XScreenNumberOfScreen (DefaultScreenOfDisplay (gdk_display)); xdisplay = gdk_display; #endif /* Now see if there's a manager window around */ g_snprintf (buffer, sizeof (buffer), "_NET_SYSTEM_TRAY_S%d", screen); icon->selection_atom = XInternAtom (xdisplay, buffer, False); icon->manager_atom = XInternAtom (xdisplay, "MANAGER", False); icon->system_tray_opcode_atom = XInternAtom (xdisplay, "_NET_SYSTEM_TRAY_OPCODE", False); icon->orientation_atom = XInternAtom (xdisplay, "_NET_SYSTEM_TRAY_ORIENTATION", False); egg_tray_icon_update_manager_window (icon, FALSE); egg_tray_icon_send_dock_request (icon); #if GTK_CHECK_VERSION(2,1,0) root_window = gdk_screen_get_root_window (gtk_widget_get_screen (widget)); #else root_window = gdk_window_lookup (gdk_x11_get_default_root_xwindow ()); #endif /* Add a root window filter so that we get changes on MANAGER */ gdk_window_add_filter (root_window, egg_tray_icon_manager_filter, icon); } #if GTK_CHECK_VERSION(2,1,0) EggTrayIcon * egg_tray_icon_new_for_screen (GdkScreen *screen, const char *name) { g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL); return g_object_new (EGG_TYPE_TRAY_ICON, "screen", screen, "title", name, NULL); } #endif EggTrayIcon* egg_tray_icon_new (const gchar *name) { return g_object_new (EGG_TYPE_TRAY_ICON, "title", name, NULL); } guint egg_tray_icon_send_message (EggTrayIcon *icon, gint timeout, const gchar *message, gint len) { guint stamp; g_return_val_if_fail (EGG_IS_TRAY_ICON (icon), 0); g_return_val_if_fail (timeout >= 0, 0); g_return_val_if_fail (message != NULL, 0); if (icon->manager_window == None) return 0; if (len < 0) len = strlen (message); stamp = icon->stamp++; /* Get ready to send the message */ egg_tray_icon_send_manager_message (icon, SYSTEM_TRAY_BEGIN_MESSAGE, (Window)gtk_plug_get_id (GTK_PLUG (icon)), timeout, len, stamp); /* Now to send the actual message */ gdk_error_trap_push (); while (len > 0) { XClientMessageEvent ev; Display *xdisplay; #if GTK_CHECK_VERSION(2,1,0) xdisplay = GDK_DISPLAY_XDISPLAY (gtk_widget_get_display (GTK_WIDGET (icon))); #else xdisplay = gdk_display; #endif ev.type = ClientMessage; ev.window = (Window)gtk_plug_get_id (GTK_PLUG (icon)); ev.format = 8; ev.message_type = XInternAtom (xdisplay, "_NET_SYSTEM_TRAY_MESSAGE_DATA", False); if (len > 20) { memcpy (&ev.data, message, 20); len -= 20; message += 20; } else { memcpy (&ev.data, message, len); len = 0; } XSendEvent (xdisplay, icon->manager_window, False, StructureNotifyMask, (XEvent *)&ev); XSync (xdisplay, False); } gdk_error_trap_pop (); return stamp; } void egg_tray_icon_cancel_message (EggTrayIcon *icon, guint id) { g_return_if_fail (EGG_IS_TRAY_ICON (icon)); g_return_if_fail (id > 0); egg_tray_icon_send_manager_message (icon, SYSTEM_TRAY_CANCEL_MESSAGE, (Window)gtk_plug_get_id (GTK_PLUG (icon)), id, 0, 0); } GtkOrientation egg_tray_icon_get_orientation (EggTrayIcon *icon) { g_return_val_if_fail (EGG_IS_TRAY_ICON (icon), GTK_ORIENTATION_HORIZONTAL); return icon->orientation; } gxmms2-0.7.1/gxmms2src/status_stop.xpm0000644000175000017500000000062710601276546016507 0ustar wejpwejp/* XPM */ static char * status_stop_xpm[] = { "16 16 2 1", " c None", ". c #000000", " ", " ", " .......... ", " .......... ", " .......... ", " .......... ", " .......... ", " .......... ", " .......... ", " .......... ", " .......... ", " .......... ", " .......... ", " .......... ", " ", " "}; gxmms2-0.7.1/gxmms2src/volume1.xpm0000644000175000017500000000062310601276546015503 0ustar wejpwejp/* XPM */ static char * volume1_xpm[] = { "16 16 2 1", " c None", ". c #000000", " ", " ", " . ", " .. ", " ... . ", " .... . ", " ....... . ", " ....... . ", " ....... . ", " ....... . ", " .... . ", " ... . ", " .. ", " . ", " ", " "}; gxmms2-0.7.1/gxmms2src/volume3.xpm0000644000175000017500000000062310601276546015505 0ustar wejpwejp/* XPM */ static char * volume3_xpm[] = { "16 16 2 1", " c None", ". c #000000", " . ", " . ", " . . . ", " .. . . ", " ... . . . ", " .... . . . ", " ....... . . . ", " ....... . . . ", " ....... . . . ", " ....... . . . ", " .... . . . ", " ... . . . ", " .. . . ", " . . . ", " . ", " . "}; gxmms2-0.7.1/gxmms2src/wejpconfig.h0000644000175000017500000000277711337312675015706 0ustar wejpwejp/* * Wejp's Config File Parser * * File: wejpconfig.h * * Copyright (c) 2003-2009 Johannes Heimansberg * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _WEJPCONFIG_H #define _WEJPCONFIG_H #ifndef TRUE #define TRUE 1 #define FALSE 0 #endif #define MAXKEYS 128 typedef struct { char *key[MAXKEYS]; char *value[MAXKEYS]; int lastkey; } ConfigFile; #endif void cfg_init_config_file_struct(ConfigFile *cf); int cfg_add_key(ConfigFile *cf, char *key, char *value); void cfg_free_config_file_struct(ConfigFile *cf); int cfg_read_config_file(ConfigFile *cf, char *filename); int cfg_write_config_file(ConfigFile *cf, char *filename); char *cfg_get_key_value(ConfigFile cf, char *key); int cfg_check_config_file(char *filename); char *cfg_get_path_to_config_file(char *filename); int cfg_is_key_available(ConfigFile cf, char *key); int cfg_add_key_if_not_present(ConfigFile *cf, char *key, char *value); gxmms2-0.7.1/gxmms2src/wejpconfig.c0000644000175000017500000001427711343562274015676 0ustar wejpwejp/* * Wejp's Config File Parser * * File: wejpconfig.c * * Copyright (c) 2003-2009 Johannes Heimansberg * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #define VERSION 20090801 #include #include #include #include "wejpconfig.h" #define MAX_LINE_LENGTH 256 /* Returns the complete path to ~/"filename" */ char *cfg_get_path_to_config_file(char *filename) { char *home_directory, *path_to_config_file; home_directory = getenv("HOME"); path_to_config_file = (char*)malloc((strlen(home_directory) + strlen(filename) + 2) * sizeof(char)); sprintf(path_to_config_file, "%s/%s", home_directory, filename); return path_to_config_file; } /* Must be called before the first use of a ConfigFile struct element */ void cfg_init_config_file_struct(ConfigFile *cf) { cf->lastkey = 0; } /* Checks wether the config file exists or not */ int cfg_check_config_file(char *filename) { FILE *file; int result = 0; file = fopen(filename, "r"); if (file == NULL) result = -1; else fclose(file); return result; } /* Add a new key to the configuration */ int cfg_add_key(ConfigFile *cf, char *key, char *value) { int result = 0; int strsize = 0; int i; if (cfg_get_key_value(*cf, key) != NULL) { /* Key already exists->overwrite */ for (i = 0; i < cf->lastkey; i++) if (strncmp(key, cf->key[i], MAX_LINE_LENGTH-1) == 0) { free(cf->key[i]); /* Free allocated memory */ free(cf->value[i]); /* Allocate memory for the new string and save it... */ strsize = (strlen(key) < MAX_LINE_LENGTH-1 ? strlen(key) : MAX_LINE_LENGTH-2) + 1; cf->key[i] = (char*)malloc(strsize * sizeof(char)); snprintf(cf->key[i], strsize, "%s", key); strsize = (strlen(value) < MAX_LINE_LENGTH-1 ? strlen(value) : MAX_LINE_LENGTH-2) + 1; cf->value[i] = (char*)malloc(strsize * sizeof(char)); snprintf(cf->value[i], strsize, "%s", value); break; } } else if (cf->lastkey < MAXKEYS) { strsize = (strlen(key) < MAX_LINE_LENGTH-1 ? strlen(key) : MAX_LINE_LENGTH-2) + 1; cf->key[cf->lastkey] = (char*)malloc(strsize * sizeof(char)); sprintf(cf->key[cf->lastkey], "%s", key); strsize = (strlen(key) < MAX_LINE_LENGTH-1 ? strlen(value) : MAX_LINE_LENGTH-2) + 1; cf->value[cf->lastkey] = (char*)malloc(strsize * sizeof(char)); sprintf(cf->value[cf->lastkey], "%s", value); (cf->lastkey)++; } else result = -1; return result; } /* Frees all memory allocated by read_config_file() */ void cfg_free_config_file_struct(ConfigFile *cf) { int i; for (i = 0; i < cf->lastkey; i++) { free(cf->key[i]); free(cf->value[i]); } cf->lastkey = -1; } /* Loads a config file from disk */ int cfg_read_config_file(ConfigFile *cf, char *filename) { FILE *file; char ch; int bufcnt; char key_buffer[MAX_LINE_LENGTH] = "", value_buffer[MAX_LINE_LENGTH] = ""; /* parse config file and read keys+key values */ file = fopen(filename, "r"); if (file) { while(!feof(file)) { ch = fgetc(file); /* Skip blanks... */ if (ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n') while (ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n') ch = fgetc(file); /* ...and comments (#)... */ do { if (ch == '#') { while (ch != '\n' && ch != '\r') ch = fgetc(file); ch = fgetc(file); } if (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r') ch = fgetc(file); } while (ch == '#' || ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r'); bufcnt = 0; /* Read key name: */ while (ch != ' ' && ch != '\t' && ch != '\n' && ch != '\r' && ch != '=' && !feof(file) && bufcnt < MAX_LINE_LENGTH-2) { key_buffer[bufcnt] = ch; bufcnt++; ch = fgetc(file); } key_buffer[bufcnt] = '\0'; while (ch != '=' && !feof(file)) { ch = fgetc(file); } ch = fgetc(file); /* Skip blanks... */ if (ch == ' ' || ch == '\t') while (ch == ' ' || ch == '\t') ch = fgetc(file); /* Read key value: */ bufcnt = 0; while (ch != '\n' && ch != '\r' && !feof(file) && !feof(file) && bufcnt < MAX_LINE_LENGTH-2) { value_buffer[bufcnt] = ch; bufcnt++; ch = fgetc(file); } value_buffer[bufcnt] = '\0'; if (strlen(key_buffer) > 0) cfg_add_key(cf, key_buffer, value_buffer); } fclose(file); } else { printf("config: Cannot open config file!\n"); return -2; } return 0; } /* Saves the configuration to file */ int cfg_write_config_file(ConfigFile *cf, char *filename) { FILE *file; int i = 0, result = 0; char buffer[MAX_LINE_LENGTH]; file = fopen(filename, "w"); if (file != NULL) { while (i < cf->lastkey) { snprintf(buffer, MAX_LINE_LENGTH, "%s=%s\n", cf->key[i], cf->value[i]); if (!fwrite(buffer, strlen(buffer) * sizeof(char), 1, file)) { printf("config: ERROR: Failed writing configuration file.\n"); break; } i++; } fclose(file); } else { printf("config: Failed opening %s for write access.\n", filename); result = -1; } return result; } /* Returns the value (as string) of "key" */ char *cfg_get_key_value(ConfigFile cf, char *key) { char *result = NULL; int i; for (i = 0; i < cf.lastkey; i++) if (strncmp(key, cf.key[i], MAX_LINE_LENGTH-1) == 0) { result = cf.value[i]; break; } return result; } int cfg_is_key_available(ConfigFile cf, char *key) { int result = FALSE; int i; for (i = 0; i < cf.lastkey; i++) if (strncmp(key, cf.key[i], MAX_LINE_LENGTH-1) == 0) { result = TRUE; break; } return result; } int cfg_add_key_if_not_present(ConfigFile *cf, char *key, char *value) { int success = 0; if (!cfg_is_key_available(*cf, key)) { success = (cfg_add_key(cf, key, value) == 0 ? 1 : 0); } return success; } gxmms2-0.7.1/gxmms2src/eggtrayicon.h0000644000175000017500000000503710601276546016055 0ustar wejpwejp/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* eggtrayicon.h * Copyright (C) 2002 Anders Carlsson * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ #ifndef __EGG_TRAY_ICON_H__ #define __EGG_TRAY_ICON_H__ #include #include #include G_BEGIN_DECLS #define EGG_TYPE_TRAY_ICON (egg_tray_icon_get_type ()) #define EGG_TRAY_ICON(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EGG_TYPE_TRAY_ICON, EggTrayIcon)) #define EGG_TRAY_ICON_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EGG_TYPE_TRAY_ICON, EggTrayIconClass)) #define EGG_IS_TRAY_ICON(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EGG_TYPE_TRAY_ICON)) #define EGG_IS_TRAY_ICON_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EGG_TYPE_TRAY_ICON)) #define EGG_TRAY_ICON_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EGG_TYPE_TRAY_ICON, EggTrayIconClass)) typedef struct _EggTrayIcon EggTrayIcon; typedef struct _EggTrayIconClass EggTrayIconClass; struct _EggTrayIcon { GtkPlug parent_instance; guint stamp; Atom selection_atom; Atom manager_atom; Atom system_tray_opcode_atom; Atom orientation_atom; Window manager_window; GtkOrientation orientation; }; struct _EggTrayIconClass { GtkPlugClass parent_class; }; GType egg_tray_icon_get_type (void); #if GTK_CHECK_VERSION(2,1,0) EggTrayIcon *egg_tray_icon_new_for_screen (GdkScreen *screen, const gchar *name); #endif EggTrayIcon *egg_tray_icon_new (const gchar *name); guint egg_tray_icon_send_message (EggTrayIcon *icon, gint timeout, const char *message, gint len); void egg_tray_icon_cancel_message (EggTrayIcon *icon, guint id); GtkOrientation egg_tray_icon_get_orientation (EggTrayIcon *icon); G_END_DECLS #endif /* __EGG_TRAY_ICON_H__ */ gxmms2-0.7.1/gxmms2src/gxmms2_mini.xpm0000644000175000017500000000064610601276546016351 0ustar wejpwejp/* XPM */ static char * gxmms2_mini_xpm[] = { "16 16 3 1", " c None", ". c #6F6F6F", "+ c #000000", " ", " ", " ..+++ ", " ..+++++++ ", " +++++++.++ ", " +++.. ++ ", " ++ ++ ", " ++ ++ ", " ++ ++ ", " ++ +++ ", " +++ ++++ ", " ++++ ++++ ", " ++++ ++ ", " ++ ", " ", " "}; gxmms2-0.7.1/gxmms2src/wejpvolume.h0000644000175000017500000000301510601276546015731 0ustar wejpwejp/* * File: wejpvolume.h * * A gtk2 volume control widget * Copyright (c) 2006 Johannes Heimansberg * * Released under the GNU General Public License v2 */ #ifndef __WEJPVOLUME_H__ #define __WEJPVOLUME_H__ #include #include G_BEGIN_DECLS #define WEJPVOLUME_TYPE (wejpvolume_get_type ()) #define WEJPVOLUME(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), WEJPVOLUME_TYPE, WejpVolume)) #define WEJPVOLUME_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), WEJPVOLUME_TYPE, WejpVolumeClass)) #define IS_WEJPVOLUME(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), WEJPVOLUME_TYPE)) #define IS_WEJPVOLUME_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), WEJPVOLUME_TYPE)) struct _WejpVolume { GtkEventBox dummy; GtkWidget *image_status; GdkPixbuf *icon_volume[4]; guint max_volume; gint current_volume; gint volume_step; }; typedef struct _WejpVolume WejpVolume; typedef struct _WejpVolumeClass WejpVolumeClass; struct _WejpVolumeClass { GtkEventBoxClass parent_class; void (* wejpvolume) (WejpVolume *wv); }; GType wejpvolume_get_type (void); GtkWidget *wejpvolume_new (guint max_volume, guint initial_volume, gint volume_step); void wejpvolume_clear (WejpVolume *wv); void wejpvolume_draw (WejpVolume *wv); guint wejpvolume_get_volume(WejpVolume *wv); void wejpvolume_set_volume(WejpVolume *wv, guint volume); G_END_DECLS #endif gxmms2-0.7.1/gxmms2src/statusdisplay.c0000644000175000017500000000250710601276546016445 0ustar wejpwejp/* * File: statusdisplay.c * * gxmms2 - A gtk2 frontend for XMMS2 * Copyright (c) 2005-2006 Johannes Heimansberg * * requires GTK+ 2.6 or better and XMMS2 * * Released under the GNU General Public License v2 */ #include #include "statusdisplay.h" #include "status_play.xpm" #include "status_pause.xpm" #include "status_stop.xpm" void status_display_set_status(StatusDisplay *sd, gint status) { if (GTK_IS_IMAGE(sd->image_status)) { switch (status) { case STATUS_PLAY: gtk_image_set_from_pixbuf(GTK_IMAGE(sd->image_status), sd->icon_play); break; case STATUS_PAUSE: gtk_image_set_from_pixbuf(GTK_IMAGE(sd->image_status), sd->icon_pause); break; case STATUS_STOP: gtk_image_set_from_pixbuf(GTK_IMAGE(sd->image_status), sd->icon_stop); break; } } } void status_display_init(StatusDisplay *sd) { sd->icon_stop = gdk_pixbuf_new_from_xpm_data((const char **)status_stop_xpm); sd->icon_play = gdk_pixbuf_new_from_xpm_data((const char **)status_play_xpm); sd->icon_pause = gdk_pixbuf_new_from_xpm_data((const char **)status_pause_xpm); sd->image_status = gtk_image_new_from_pixbuf(sd->icon_stop); } GtkWidget *status_display_get_image(StatusDisplay *sd) { return sd->image_status; } gxmms2-0.7.1/gxmms2src/gxmms2.c0000644000175000017500000012041611427741402014744 0ustar wejpwejp/* * File: gxmms2.c * * gxmms2 - A gtk2 frontend for XMMS2 * Copyright (c) 2005-2010 Johannes Heimansberg * * requires GTK+ 2.6 or better and XMMS2 * * Version: 0.7.1 * * Released under the GNU General Public License v2 */ #define VERSION_NUMBER "0.7.1" #include #include #include #include #include #include #include "xmms2ctrl/xmms2ctrl.h" #include "gtrackinfo/trackinfo.h" #include "gtrackinfo/gtrackinfo.h" #include "gmedialib/gmedialib.h" #include "sdecode/sdecode.h" #include "wejpscroller.h" #include "statusdisplay.h" #include "wejpvolume.h" #include "wejpconfig.h" #include "gxmms2_mini.xpm" #include "playlist.xpm" #include "eggtrayicon.h" #define LABEL_WIDTH 19 #define TITLE_STR_SIZE 512 #define FONT_SIZE 12 static GtkWidget *label_time, *eventbox_time, *scroller; static GtkWidget *scale; static GtkWidget *playlist = NULL; static GtkWidget *window = NULL; static EggTrayIcon *docklet = NULL; static GtkTooltips *docklet_tooltip; static gboolean update_scale = TRUE; static gboolean flag_time_remaining = FALSE; xmmsc_connection_t *connection; static trackinfo track; static gchar title_str[TITLE_STR_SIZE] = "gxmms2 (not connected)"; static StatusDisplay sd; static GtkWidget *wv; static ConfigFile cf; static gboolean local_xmms2d = FALSE; static int xmms2_connect(void); enum { PREV_BUTTON = 0, PLAY_BUTTON, PAUSE_BUTTON, NEXT_BUTTON, STOP_BUTTON, PLAYLIST_BUTTON, INFO_BUTTON, ABOUT_BUTTON }; static void update_title_label(gchar *title_str, trackinfo *track, gboolean reset_scroller) { const gchar *current_str = wejpscroller_get_text(WEJPSCROLLER(scroller)); trackinfo_get_full_title(title_str, TITLE_STR_SIZE, track, FALSE); if (!current_str) { wejpscroller_set_text(WEJPSCROLLER(scroller), title_str, TRUE); } else if (strcmp(current_str, title_str)) { wejpscroller_set_text(WEJPSCROLLER(scroller), title_str, reset_scroller); } if (GTK_IS_WIDGET(docklet)) gtk_tooltips_set_tip(docklet_tooltip, GTK_WIDGET(docklet), title_str, NULL); } static gboolean cb_scale_press_event(GtkWidget *widget, GdkEventButton *event, gpointer user_data) { update_scale = FALSE; return FALSE; } static gboolean cb_scale_release_event(GtkWidget *widget, GdkEventButton *event, gpointer user_data) { xmmsc_result_t *res; if (xmms2ctrl_get_error() != ERROR_CONNECTION) { res = xmmsc_playback_seek_ms(connection, (guint)gtk_range_get_value(GTK_RANGE(widget)), XMMS_PLAYBACK_SEEK_SET); xmmsc_result_unref(res); } update_scale = TRUE; return FALSE; } /* Set initial_volume to -1 except for initialising (in that case volume_change should be 0) */ static void change_volume(gint volume_change, gint initial_volume) { static gint volume = 0; if (initial_volume >= 0) volume = initial_volume; if (volume < 100 && volume_change > 0) volume+=2; if (volume > 0 && volume_change < 0) volume-=2; xmms2ctrl_volume_set(connection, volume); } static int bc_handle_volume_change(xmmsv_t *val, void *userdata) { gint32 volume; gchar buf[64]; xmmsv_dict_entry_get_int(val, "left", &volume); wejpvolume_set_volume(WEJPVOLUME(wv), volume); snprintf(buf, 63, "Volume: %d %%", volume); wejpscroller_shortmessage_show(WEJPSCROLLER(scroller), buf, 50); return FALSE; } static int n_volume_init(xmmsv_t *val, void *userdata) { gint32 volume; xmmsv_dict_entry_get_int(val, "left", &volume); wejpvolume_set_volume(WEJPVOLUME(wv), volume); change_volume(0, volume); return FALSE; } static void cb_volume_changed(GtkWidget *widget, GdkEvent *e, gpointer data) { change_volume(-1, wejpvolume_get_volume(WEJPVOLUME(widget))); } static void show_gxmms2_about_dialog(void) { GtkWidget *dialog; dialog = gtk_about_dialog_new(); gtk_about_dialog_set_version(GTK_ABOUT_DIALOG(dialog), VERSION_NUMBER); gtk_about_dialog_set_copyright(GTK_ABOUT_DIALOG(dialog), "Copyright (c) 2005-2010 " \ "Johannes Heimansberg"); gtk_about_dialog_set_comments(GTK_ABOUT_DIALOG(dialog), "A XMMS2 frontend written in C " \ "using GTK+ 2.6. Released under " \ "the GNU General Public License v2."); gtk_about_dialog_set_website(GTK_ABOUT_DIALOG(dialog), "http://wejp.k.vu/"); g_signal_connect(G_OBJECT(dialog), "response", G_CALLBACK(gtk_widget_destroy), (gpointer)dialog); gtk_dialog_run(GTK_DIALOG(dialog)); } static void show_trackinfo(void) { GtkWidget *dialog; dialog = gtrackinfo_new(); gtrackinfo_set_info(GTRACKINFO(dialog), &track); gtk_widget_show(dialog); } static void load_medialib_config(ConfigFile *cf, GMedialib *playlist) { gml_set_font_size(GMEDIALIB(playlist), atoi(cfg_get_key_value(*cf, "MediaLibFontSizePt"))); if (strncasecmp(cfg_get_key_value(*cf, "MediaLibPlaylistNewConfirm"), "no", 3) == 0) { gml_pl_set_new_playlist_confirm(GMEDIALIB(playlist), FALSE); } if (strncasecmp(cfg_get_key_value(*cf, "RestoreMediaLibSize"), "yes", 3) == 0) { gtk_window_resize(GTK_WINDOW(playlist), atoi(cfg_get_key_value(*cf, "MediaLibWindowWidth")), atoi(cfg_get_key_value(*cf, "MediaLibWindowHeight"))); } if (strncasecmp(cfg_get_key_value(*cf, "RestoreMediaLibPosition"), "yes", 3) == 0) { gtk_window_move(GTK_WINDOW(playlist), atoi(cfg_get_key_value(*cf, "MediaLibWindowPosX")), atoi(cfg_get_key_value(*cf, "MediaLibWindowPosY"))); } if (gml_notebook_is_mlib_search_visible(GMEDIALIB(playlist))) { if (strncasecmp(cfg_get_key_value(*cf, "MediaLibSearchColumnID"), "hide", 4) == 0) { gml_search_set_column_id_visible(GMEDIALIB(playlist), FALSE); } if (strncasecmp(cfg_get_key_value(*cf, "MediaLibSearchColumnArtist"), "hide", 4) == 0) { gml_search_set_column_artist_visible(GMEDIALIB(playlist), FALSE); } if (strncasecmp(cfg_get_key_value(*cf, "MediaLibSearchColumnTrack"), "hide", 4) == 0) { gml_search_set_column_track_visible(GMEDIALIB(playlist), FALSE); } if (strncasecmp(cfg_get_key_value(*cf, "MediaLibSearchColumnAlbum"), "hide", 4) == 0) { gml_search_set_column_album_visible(GMEDIALIB(playlist), FALSE); } if (strncasecmp(cfg_get_key_value(*cf, "MediaLibSearchColumnRating"), "hide", 4) == 0) { gml_search_set_column_rating_visible(GMEDIALIB(playlist), FALSE); } } if (gml_notebook_is_playlist_visible(GMEDIALIB(playlist))) { if (strncasecmp(cfg_get_key_value(*cf, "MediaLibPlaylistColumnPos"), "hide", 4) == 0) { gml_pl_set_column_pos_visible(GMEDIALIB(playlist), FALSE); } if (strncasecmp(cfg_get_key_value(*cf, "MediaLibPlaylistColumnID"), "hide", 4) == 0) { gml_pl_set_column_id_visible(GMEDIALIB(playlist), FALSE); } if (strncasecmp(cfg_get_key_value(*cf, "MediaLibPlaylistColumnArtist"), "hide", 4) == 0) { gml_pl_set_column_artist_visible(GMEDIALIB(playlist), FALSE); } if (strncasecmp(cfg_get_key_value(*cf, "MediaLibPlaylistColumnAlbum"), "hide", 4) == 0) { gml_pl_set_column_album_visible(GMEDIALIB(playlist), FALSE); } if (strncasecmp(cfg_get_key_value(*cf, "MediaLibPlaylistColumnRating"), "hide", 4) == 0) { gml_pl_set_column_rating_visible(GMEDIALIB(playlist), FALSE); } } gml_set_album_tracknr_digits(GMEDIALIB(playlist), atoi(cfg_get_key_value(*cf, "MediaLibAlbumTrackNrDigits"))); } static void show_playlist_editor(void) { if (!GTK_IS_WIDGET(playlist)) { playlist = gmedialib_new(TRUE, TRUE, local_xmms2d, TRUE, TRUE); load_medialib_config(&cf, GMEDIALIB(playlist)); } else { gtk_window_move(GTK_WINDOW(playlist), gml_window_get_pos_x(GMEDIALIB(playlist)), gml_window_get_pos_y(GMEDIALIB(playlist))); } gtk_window_present(GTK_WINDOW(playlist)); } static void rate_current_track(guint rating) { if (rating >= 0 && rating <= 5) { gchar buf[64]; xmmsc_result_t *res; snprintf(buf, 63, "Rated track: %d", rating - 1); wejpscroller_shortmessage_show(WEJPSCROLLER(scroller), buf, 50); res = xmmsc_medialib_entry_property_set_int_with_source(connection, trackinfo_get_id(&track), "client/generic", "rating", rating); xmmsc_result_unref(res); } } static gboolean reconnect(void) { gboolean result = TRUE; /* try to reconnect */ if (xmms2_connect() != ERROR_NONE) { strncpy(title_str, xmmsc_get_last_error(connection), TITLE_STR_SIZE); wejpscroller_set_text(WEJPSCROLLER(scroller), title_str, TRUE); printf("ERROR: %s\n", xmmsc_get_last_error(connection)); result = FALSE; } else if (playlist) { gml_pl_setup_xmms_callbacks((GMedialib *)playlist); gml_setup_xmms_callbacks((GMedialib *)playlist); } return result; } static void cb_button_clicked(GtkWidget *widget, gpointer data) { gint button_pressed = GPOINTER_TO_INT(data); if (xmms2ctrl_get_error() == ERROR_CONNECTION) if (!reconnect()) if (button_pressed != ABOUT_BUTTON) button_pressed = -1;; switch(button_pressed) { case PREV_BUTTON: xmms2ctrl_do_reljump(connection, -1); break; case PLAY_BUTTON: xmms2ctrl_play(connection); break; case PAUSE_BUTTON: xmms2ctrl_toggle_pause(connection, FALSE); break; case NEXT_BUTTON: xmms2ctrl_do_reljump(connection, 1); break; case STOP_BUTTON: xmms2ctrl_stop(connection); break; case INFO_BUTTON: show_trackinfo(); break; case PLAYLIST_BUTTON: show_playlist_editor(); break; case ABOUT_BUTTON: show_gxmms2_about_dialog(); break; } } static gboolean cb_key_press(GtkWidget *widget, GdkEventKey *event, gpointer userdata) { gboolean result = FALSE; if (event->type == GDK_KEY_PRESS) { switch (event->keyval) { case GDK_b: cb_button_clicked(widget, (gpointer)NEXT_BUTTON); result = TRUE; break; case GDK_v: cb_button_clicked(widget, (gpointer)STOP_BUTTON); result = TRUE; break; case GDK_c: cb_button_clicked(widget, (gpointer)PAUSE_BUTTON); result = TRUE; break; case GDK_x: cb_button_clicked(widget, (gpointer)PLAY_BUTTON); result = TRUE; break; case GDK_z: cb_button_clicked(widget, (gpointer)PREV_BUTTON); result = TRUE; break; case GDK_j: cb_button_clicked(widget, (gpointer)PLAYLIST_BUTTON); result = TRUE; break; case GDK_t: flag_time_remaining = !flag_time_remaining; break; case GDK_0: rate_current_track(1); break; case GDK_1: rate_current_track(2); break; case GDK_2: rate_current_track(3); break; case GDK_3: rate_current_track(4); break; case GDK_4: rate_current_track(5); break; case GDK_plus: change_volume(1, -1); break; case GDK_minus: change_volume(-1, -1); break; } } return result; } static int n_media_lib_get_info(xmmsv_t *val, void *arg) { trackinfo_update(val, &track); gtk_range_set_value(GTK_RANGE(scale), 0); if (trackinfo_get_playtime(&track) > 0) { gtk_range_set_range(GTK_RANGE(scale), 0, trackinfo_get_playtime(&track)); gtk_widget_set_sensitive(GTK_WIDGET(scale), TRUE); update_scale = TRUE; } else { gtk_range_set_range(GTK_RANGE(scale), 0, 1); gtk_widget_set_sensitive(GTK_WIDGET(scale), FALSE); update_scale = FALSE; } update_title_label(title_str, &track, TRUE); return FALSE; } static gint current_id; static int bc_handle_medialib_entry_changed(xmmsv_t *val, void *userdata) { gint id; if (xmmsv_get_int(val, &id)) { if (current_id == id && xmms2ctrl_get_error() != ERROR_CONNECTION) { xmmsc_result_t *res2; res2 = xmmsc_medialib_get_info(connection, current_id); xmmsc_result_notifier_set(res2, n_media_lib_get_info, ¤t_id); xmmsc_result_unref(res2); } } return TRUE; } static int bc_handle_current_id(xmmsv_t *val, void *userdata) { if (xmmsv_get_int(val, ¤t_id) && xmms2ctrl_get_error() != ERROR_CONNECTION) { xmmsc_result_t *res2; res2 = xmmsc_medialib_get_info(connection, current_id); xmmsc_result_notifier_set(res2, n_media_lib_get_info, ¤t_id); xmmsc_result_unref(res2); } return TRUE; } static int sig_handle_current_id(xmmsv_t *val, void *userdata) { if (xmmsv_get_int(val, ¤t_id) && xmms2ctrl_get_error() != ERROR_CONNECTION) { xmmsc_result_t *res2; res2 = xmmsc_medialib_get_info(connection, current_id); xmmsc_result_notifier_set(res2, n_media_lib_get_info, ¤t_id); xmmsc_result_unref(res2); } return TRUE; } static int sig_handle_playtime(xmmsv_t *val, void *userdata) { gint ptime = 0; gchar buffer[20]; static guint cnt = 0; gint seconds_elapsed, seconds_remaining, seconds_total; if (xmms2ctrl_get_error() != ERROR_CONNECTION && !xmmsv_is_error(val)) { xmmsv_get_int(val, &ptime); } if (cnt > 10 && GTK_IS_RANGE(scale)) { cnt = 0; seconds_elapsed = ptime / 1000; seconds_total = trackinfo_get_minutes(&track) * 60 + trackinfo_get_seconds(&track); seconds_remaining = seconds_total - seconds_elapsed; if (flag_time_remaining == TRUE && trackinfo_has_playtime(&track) && seconds_total > seconds_elapsed) snprintf(buffer, sizeof(buffer), "-%02d:%02d", seconds_remaining / 60 % 100, seconds_remaining % 60); else snprintf(buffer, sizeof(buffer), " %02d:%02d", seconds_elapsed / 60 % 100, seconds_elapsed % 60); gtk_label_set_text(GTK_LABEL(label_time), buffer); if (update_scale) gtk_range_set_value(GTK_RANGE(scale), ptime); } cnt++; return TRUE; } static int bc_handle_playback_status_change(xmmsv_t *val, void *userdata) { gint pb_status = 0; if (xmmsv_is_error(val) || !xmmsv_get_int(val, &pb_status)) return TRUE; switch (pb_status) { case XMMS_PLAYBACK_STATUS_PAUSE: status_display_set_status(&sd, STATUS_PAUSE); break; case XMMS_PLAYBACK_STATUS_STOP: status_display_set_status(&sd, STATUS_STOP); if (GTK_IS_RANGE(scale)) gtk_range_set_value(GTK_RANGE(scale), 0); break; default: status_display_set_status(&sd, STATUS_PLAY); } return TRUE; } static int n_handle_playback_status_change(xmmsv_t *val, void *userdata) { gint pb_status = 0; if (!xmmsv_is_error(val) && xmmsv_get_int(val, &pb_status)) { switch (pb_status) { case XMMS_PLAYBACK_STATUS_PAUSE: status_display_set_status(&sd, STATUS_PAUSE); break; case XMMS_PLAYBACK_STATUS_STOP: status_display_set_status(&sd, STATUS_STOP); gtk_range_set_value(GTK_RANGE(scale), 0); break; default: status_display_set_status(&sd, STATUS_PLAY); } } return FALSE; } static gboolean cb_timer_connection_lost(gpointer userdata) { gboolean result = TRUE; printf("Reconnect timer cb.\n"); if (xmms2ctrl_get_error() == ERROR_CONNECTION) { if (reconnect()) result = FALSE; /* do not restart timer on success */ } else { result = FALSE; /* do not restart timer if there is no connection prob*/ } return result; } static void connection_lost(void *data) { strcpy(title_str, "ERROR: Connection to xmms2d lost."); wejpscroller_set_text(WEJPSCROLLER(scroller), title_str, TRUE); xmms2ctrl_set_error(ERROR_CONNECTION); xmmsc_unref(connection); printf("ERROR: Connection to xmms2d lost.\n"); if (strncasecmp(cfg_get_key_value(cf, "AutoReconnect"), "yes", 3) == 0) g_timeout_add(6000, &cb_timer_connection_lost, NULL); } static int xmms2_connect(void) { gchar *path = NULL; xmmsc_result_t *res; gint conn_status, autostart = FALSE; path = getenv("XMMS_PATH"); /* Try XMMS_PATH environment variable first */ if (path == NULL) path = cfg_get_key_value(cf, "IPCPath"); xmms2ctrl_set_error(ERROR_NONE); if (!path || g_ascii_strncasecmp(path, "unix://", 7) == 0) local_xmms2d = TRUE; if (strncasecmp(cfg_get_key_value(cf, "StartLocalXmms2dOnStartup"), "yes", 3) == 0) autostart = TRUE; conn_status = xmmsc_connect(connection, path); if (!conn_status && autostart) { if (!path || g_ascii_strncasecmp(path, "unix://", 7) == 0) { if (!system("xmms2-launcher")) { conn_status = xmmsc_connect(connection, path); } } } if (!conn_status) { strncpy(title_str, xmmsc_get_last_error(connection), TITLE_STR_SIZE); wejpscroller_set_text(WEJPSCROLLER(scroller), title_str, TRUE); xmms2ctrl_set_error(ERROR_CONNECTION); } else { xmmsc_mainloop_gmain_init(connection); XMMS_CALLBACK_SET(connection, xmmsc_playback_current_id, sig_handle_current_id, connection); XMMS_CALLBACK_SET(connection, xmmsc_broadcast_playback_current_id, bc_handle_current_id, connection); XMMS_CALLBACK_SET(connection, xmmsc_broadcast_medialib_entry_changed, bc_handle_medialib_entry_changed, connection); XMMS_CALLBACK_SET(connection, xmmsc_signal_playback_playtime, sig_handle_playtime, title_str); XMMS_CALLBACK_SET(connection, xmmsc_broadcast_playback_status, bc_handle_playback_status_change, NULL); XMMS_CALLBACK_SET(connection, xmmsc_broadcast_playback_volume_changed, bc_handle_volume_change, NULL); xmmsc_disconnect_callback_set(connection, connection_lost, NULL); res = xmmsc_playback_status(connection); xmmsc_result_notifier_set(res, n_handle_playback_status_change, NULL); xmmsc_result_unref(res); res = xmmsc_playback_volume_get(connection); xmmsc_result_notifier_set(res, n_volume_init, NULL); xmmsc_result_unref(res); } return xmms2ctrl_get_error(); } /* callback: close window (return FALSE = close window) */ static gint cb_delete_event(GtkWidget *widget, GdkEvent *event, gpointer data) { gint main_x_pos = 0, main_y_pos = 0; gchar buf[32] = "0"; ConfigFile *cf = (ConfigFile *)data; gtk_window_get_position(GTK_WINDOW(widget), &main_x_pos, &main_y_pos); snprintf(buf, 30, "%d", main_x_pos); cfg_add_key(cf, "MainWindowPosX", buf); snprintf(buf, 30, "%d", main_y_pos); cfg_add_key(cf, "MainWindowPosY", buf); return FALSE; } static void cb_toggle_time(GtkWidget *widget, gpointer data) { flag_time_remaining = !flag_time_remaining; } static int n_quit_gtk_main(xmmsv_t *val, void *userdata) { if (xmms2ctrl_get_error() == ERROR_NONE) xmmsc_disconnect_callback_set(connection, NULL, NULL); gtk_main_quit(); return FALSE; } static void cb_quit_function(GtkWidget *widget, gpointer data) { if (strncasecmp(cfg_get_key_value(cf, "TerminateXmms2dOnExit"), "yes", 3) == 0 && xmms2ctrl_get_error() != ERROR_CONNECTION) { xmmsc_result_t *res = xmmsc_quit(connection); xmmsc_result_notifier_set(res, n_quit_gtk_main, NULL); xmmsc_result_unref(res); } else { n_quit_gtk_main(NULL, NULL); } } static void cb_drag_data_received(GtkWidget *widget, GdkDragContext *context, gint x, gint y, GtkSelectionData *data, guint info, guint time) { xmmsc_result_t *res; if ((data->length >= 0) && (data->format == 8)) { gint n = 0, m = 0; gchar buffer[384], *uri_conv; /* seperate each file on the list: */ while (n < strlen((gchar *)data->data)) { if (((guchar *)data->data)[n] == '\n') { buffer[m] = '\0'; m = 0; /* decode %XX escape sequences to their corresponding chars: */ uri_conv = decode_string(buffer); res = xmmsc_playlist_add_url(connection, NULL, uri_conv); xmmsc_result_unref(res); g_free(uri_conv); } else if (((guchar *)data->data)[n] > 31) { buffer[m] = ((guchar *)data->data)[n]; if (m < 382) m++; } n++; } gtk_drag_finish(context, TRUE, FALSE, time); } else { gtk_drag_finish(context, FALSE, FALSE, time); } } static void load_config(gchar *path_to_config_file) { gchar *ipc_path_default; const gchar *username; gint str_length = 0; cfg_init_config_file_struct(&cf); /* default config values */ cfg_add_key(&cf, "ScrollerFont", "Sans Serif"); cfg_add_key(&cf, "ScrollerFontSizePx", "12"); cfg_add_key(&cf, "ScrollerDelay", "27"); cfg_add_key(&cf, "SmartScroller", "yes"); cfg_add_key(&cf, "MainWindowPosX", "10"); cfg_add_key(&cf, "MainWindowPosY", "10"); cfg_add_key(&cf, "MediaLibWindowPosX", "60"); cfg_add_key(&cf, "MediaLibWindowPosY", "50"); cfg_add_key(&cf, "MediaLibWindowWidth", "600"); cfg_add_key(&cf, "MediaLibWindowHeight", "360"); cfg_add_key(&cf, "MediaLibFontSizePt", "-1"); cfg_add_key(&cf, "RestoreMediaLibSize", "yes"); cfg_add_key(&cf, "RestoreMainWindowPosition", "no"); cfg_add_key(&cf, "RestoreMediaLibPosition", "no"); cfg_add_key(&cf, "OpenMediaLibOnStartup", "no"); cfg_add_key(&cf, "MediaLibSearchColumnID", "show"); cfg_add_key(&cf, "MediaLibSearchColumnArtist", "show"); cfg_add_key(&cf, "MediaLibSearchColumnTrack", "show"); cfg_add_key(&cf, "MediaLibSearchColumnAlbum", "show"); cfg_add_key(&cf, "MediaLibSearchColumnRating", "show"); cfg_add_key(&cf, "MediaLibPlaylistColumnPos", "show"); cfg_add_key(&cf, "MediaLibPlaylistColumnID", "show"); cfg_add_key(&cf, "MediaLibPlaylistColumnArtist", "show"); cfg_add_key(&cf, "MediaLibPlaylistColumnTrack", "show"); cfg_add_key(&cf, "MediaLibPlaylistColumnAlbum", "show"); cfg_add_key(&cf, "MediaLibPlaylistColumnRating", "show"); cfg_add_key(&cf, "MediaLibPlaylistNewConfirm", "yes"); cfg_add_key(&cf, "MediaLibAlbumTrackNrDigits", "3"); cfg_add_key(&cf, "TrayIcon", "yes"); cfg_add_key(&cf, "AutoReconnect", "no"); cfg_add_key(&cf, "ShowRemainingTime", "no"); cfg_add_key(&cf, "TerminateXmms2dOnExit", "no"); cfg_add_key(&cf, "StartLocalXmms2dOnStartup", "no"); username = g_get_user_name(); str_length = strlen(username) + 128; ipc_path_default = g_malloc(str_length * sizeof(gchar)); snprintf(ipc_path_default, str_length, "unix:///tmp/xmms-ipc-%s", username); cfg_add_key(&cf, "IPCPath", ipc_path_default); g_free(ipc_path_default); if (cfg_read_config_file(&cf, path_to_config_file) != 0) { printf("No config file found! Creating %s: ", path_to_config_file); if (cfg_write_config_file(&cf, path_to_config_file) != 0) printf("FAILED\n"); else printf("OKAY\n"); } } static void cb_docklet_menu() { GtkWidget *menu, *entry, *image; menu = gtk_menu_new(); entry = gtk_image_menu_item_new_from_stock(GTK_STOCK_MEDIA_PREVIOUS, NULL); gtk_menu_shell_append(GTK_MENU_SHELL(menu), entry); g_signal_connect(G_OBJECT(entry), "activate", G_CALLBACK(cb_button_clicked), (gpointer)PREV_BUTTON); entry = gtk_image_menu_item_new_from_stock(GTK_STOCK_MEDIA_PLAY, NULL); gtk_menu_shell_append(GTK_MENU_SHELL(menu), entry); g_signal_connect(G_OBJECT(entry), "activate", G_CALLBACK(cb_button_clicked), (gpointer)PLAY_BUTTON); entry = gtk_image_menu_item_new_from_stock(GTK_STOCK_MEDIA_PAUSE, NULL); gtk_menu_shell_append(GTK_MENU_SHELL(menu), entry); g_signal_connect(G_OBJECT(entry), "activate", G_CALLBACK(cb_button_clicked), (gpointer)PAUSE_BUTTON); entry = gtk_image_menu_item_new_from_stock(GTK_STOCK_MEDIA_STOP, NULL); gtk_menu_shell_append(GTK_MENU_SHELL(menu), entry); g_signal_connect(G_OBJECT(entry), "activate", G_CALLBACK(cb_button_clicked), (gpointer)STOP_BUTTON); entry = gtk_image_menu_item_new_from_stock(GTK_STOCK_MEDIA_NEXT, NULL); gtk_menu_shell_append(GTK_MENU_SHELL(menu), entry); g_signal_connect(G_OBJECT(entry), "activate", G_CALLBACK(cb_button_clicked), (gpointer)NEXT_BUTTON); entry = gtk_image_menu_item_new_with_mnemonic("_Open Playlist Editor"); image = gtk_image_new_from_pixbuf(gdk_pixbuf_new_from_xpm_data((const char **)playlist_xpm)); gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(entry), image); gtk_menu_shell_append(GTK_MENU_SHELL(menu), entry); g_signal_connect(G_OBJECT(entry), "activate", G_CALLBACK(cb_button_clicked), (gpointer)PLAYLIST_BUTTON); entry = gtk_separator_menu_item_new(); gtk_menu_shell_append(GTK_MENU_SHELL(menu), entry); entry = gtk_image_menu_item_new_from_stock(GTK_STOCK_ABOUT, NULL); gtk_menu_shell_append(GTK_MENU_SHELL(menu), entry); g_signal_connect(G_OBJECT(entry), "activate", G_CALLBACK(cb_button_clicked), (gpointer)ABOUT_BUTTON); entry = gtk_image_menu_item_new_from_stock(GTK_STOCK_QUIT, NULL); gtk_menu_shell_append(GTK_MENU_SHELL(menu), entry); g_signal_connect(G_OBJECT(entry), "activate", G_CALLBACK(cb_quit_function), NULL); gtk_widget_show_all(menu); gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, 0, gtk_get_current_event_time()); } static void cb_toggle_window(GtkWidget *window) { if (gtk_window_get_skip_taskbar_hint(GTK_WINDOW(window))) { gtk_window_set_skip_taskbar_hint(GTK_WINDOW(window), FALSE); gtk_window_present(GTK_WINDOW(window)); } else { gtk_window_iconify(GTK_WINDOW(window)); gtk_window_set_skip_taskbar_hint(GTK_WINDOW(window), TRUE); } } static void cb_docklet_clicked(GtkWidget *widget, GdkEventButton *event, gpointer data) { if (event->type == GDK_BUTTON_PRESS) { switch (event->button) { case 1: case 2: cb_toggle_window(window); break; case 3: cb_docklet_menu(); break; } } } static void create_trayicon(GdkPixbuf *icon); static void cb_trayicon_destroy(GtkWidget *widget, gpointer data) { printf("tray icon destroyed!\n"); docklet = NULL; docklet_tooltip = NULL; } static void create_trayicon(GdkPixbuf *icon) { GtkWidget *vbox; GtkWidget *image_docklet; docklet = egg_tray_icon_new("gxmms2"); g_signal_connect(G_OBJECT(docklet), "destroy", G_CALLBACK(cb_trayicon_destroy), icon); vbox = gtk_event_box_new(); icon = gdk_pixbuf_new_from_xpm_data((const char **)gxmms2_mini_xpm); image_docklet = gtk_image_new_from_pixbuf(icon); g_signal_connect(G_OBJECT(vbox), "button-press-event", G_CALLBACK(cb_docklet_clicked), NULL); gtk_container_add(GTK_CONTAINER(vbox), image_docklet); gtk_container_add(GTK_CONTAINER(docklet), vbox); gtk_widget_show_all(GTK_WIDGET(docklet)); docklet_tooltip = gtk_tooltips_new(); gtk_tooltips_set_tip(docklet_tooltip, GTK_WIDGET(docklet), "gxmms2", NULL); gtk_tooltips_enable(docklet_tooltip); } int main(int argc, char *argv[]) { GtkWidget *table, *vbox, *hbox; GtkWidget *button_prev, *button_next, *button_play, *button_pause; GtkWidget *button_stop, *button_playlist, *button_info, *button_about; GtkWidget *image_prev, *image_next, *image_play, *image_pause; GtkWidget *image_stop, *image_playlist, *image_info, *image_about; GtkTooltips *tooltips; GdkPixbuf *icon; gchar *path_to_config_file; gchar userconf[PATH_MAX]; gint scroller_font_size; PangoFontDescription *font_desc = pango_font_description_new(); enum { TARGET_STRING, TARGET_ROOTWIN }; GtkTargetEntry target_table[] = { { "text/uri-list", 0, TARGET_STRING }, { "application/x-rootwindow-drop", 0, TARGET_ROOTWIN } }; guint n_targets = sizeof(target_table) / sizeof(target_table[0]); xmmsc_userconfdir_get(userconf, PATH_MAX); path_to_config_file = g_build_path(G_DIR_SEPARATOR_S, userconf, "clients", "gxmms2.conf", NULL); if (!g_file_test(path_to_config_file, G_FILE_TEST_EXISTS)) { gchar *dir = g_build_path(G_DIR_SEPARATOR_S, userconf, "clients", NULL); g_mkdir_with_parents(dir, 0755); g_free(dir); } load_config(path_to_config_file); gtk_init(&argc, &argv); window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_policy(GTK_WINDOW(window), FALSE, TRUE, FALSE); gtk_window_set_default_size(GTK_WINDOW(window), 200, 32); gtk_window_set_title(GTK_WINDOW(window), "gxmms2"); gtk_container_set_border_width(GTK_CONTAINER(window), 5); gtk_window_set_resizable(GTK_WINDOW(window), FALSE); gtk_drag_dest_set(window, GTK_DEST_DEFAULT_ALL, target_table, n_targets - 1, GDK_ACTION_COPY | GDK_ACTION_MOVE); icon = gdk_pixbuf_new_from_xpm_data((const char **)gxmms2_mini_xpm); gtk_window_set_icon(GTK_WINDOW(window), icon); vbox = gtk_vbox_new(FALSE, 3); gtk_container_add(GTK_CONTAINER(window), vbox); hbox = gtk_hbox_new(FALSE, 3); gtk_container_add(GTK_CONTAINER(vbox), hbox); /* scale */ scale = gtk_hscale_new_with_range(0, 200, 1); gtk_scale_set_draw_value(GTK_SCALE(scale), FALSE); gtk_container_add(GTK_CONTAINER(vbox), scale); table = gtk_table_new(1, 8, FALSE); gtk_container_add(GTK_CONTAINER(vbox), table); /* status icon */ status_display_init(&sd); gtk_container_add(GTK_CONTAINER(hbox), status_display_get_image(&sd)); /* (scroller) font size */ scroller_font_size = atoi(cfg_get_key_value(cf, "ScrollerFontSizePx")); if (scroller_font_size > 0) gtk_widget_set_size_request(GTK_WIDGET(hbox), -1, scroller_font_size + 3); /* scroller */ scroller = wejpscroller_new(atoi(cfg_get_key_value(cf, "ScrollerDelay")), strncmp(cfg_get_key_value(cf, "SmartScroller"), "yes", 3) == 0 ? 1 : 0); wejpscroller_set_dimensions(WEJPSCROLLER(scroller), 120, scroller_font_size + 2); wejpscroller_set_font(WEJPSCROLLER(scroller), cfg_get_key_value(cf, "ScrollerFont"), scroller_font_size); gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(scroller), TRUE, TRUE, 1); /* eventbox time */ eventbox_time = gtk_event_box_new(); gtk_container_add(GTK_CONTAINER(hbox), eventbox_time); /* time label */ label_time = gtk_label_new("00:00"); gtk_container_add(GTK_CONTAINER(eventbox_time), label_time); if (scroller_font_size > 0) pango_font_description_set_absolute_size(font_desc, scroller_font_size*PANGO_SCALE); pango_font_description_set_family_static(font_desc, cfg_get_key_value(cf, "ScrollerFont")); gtk_widget_modify_font(label_time, font_desc); pango_font_description_free(font_desc); /* volume icon */ wv = wejpvolume_new(100, 0, 2); gtk_container_add(GTK_CONTAINER(hbox), wv); /* prev button */ image_prev = gtk_image_new_from_stock(GTK_STOCK_MEDIA_PREVIOUS, GTK_ICON_SIZE_MENU); button_prev = gtk_button_new(); gtk_container_add(GTK_CONTAINER(button_prev), image_prev); gtk_table_attach(GTK_TABLE(table), button_prev, 0, 1, 1, 2, GTK_SHRINK, GTK_SHRINK, 0, 0); /* play button */ image_play = gtk_image_new_from_stock(GTK_STOCK_MEDIA_PLAY, GTK_ICON_SIZE_MENU); button_play = gtk_button_new(); gtk_container_add(GTK_CONTAINER(button_play), image_play); gtk_table_attach(GTK_TABLE(table), button_play, 1, 2, 1, 2, GTK_SHRINK, GTK_SHRINK, 0, 0); /* pause button */ image_pause = gtk_image_new_from_stock(GTK_STOCK_MEDIA_PAUSE, GTK_ICON_SIZE_MENU); button_pause = gtk_button_new(); gtk_container_add(GTK_CONTAINER(button_pause), image_pause); gtk_table_attach(GTK_TABLE(table), button_pause, 2, 3, 1, 2, GTK_SHRINK, GTK_SHRINK, 0, 0); /* stop button */ image_stop = gtk_image_new_from_stock(GTK_STOCK_MEDIA_STOP, GTK_ICON_SIZE_MENU); button_stop = gtk_button_new(); gtk_container_add(GTK_CONTAINER(button_stop), image_stop); gtk_table_attach(GTK_TABLE(table), button_stop, 3, 4, 1, 2, GTK_SHRINK, GTK_SHRINK, 0, 0); /* next button */ image_next = gtk_image_new_from_stock(GTK_STOCK_MEDIA_NEXT, GTK_ICON_SIZE_MENU); button_next = gtk_button_new(); gtk_container_add(GTK_CONTAINER(button_next), image_next); gtk_table_attach(GTK_TABLE(table), button_next, 4, 5, 1, 2, GTK_SHRINK, GTK_SHRINK, 0, 0); /* info button */ image_info = gtk_image_new_from_stock(GTK_STOCK_DIALOG_INFO, GTK_ICON_SIZE_MENU); button_info = gtk_button_new(); gtk_container_add(GTK_CONTAINER(button_info), image_info); gtk_table_attach(GTK_TABLE(table), button_info, 5, 6, 1, 2, GTK_SHRINK, GTK_SHRINK, 0, 0); /* playlist button */ icon = gdk_pixbuf_new_from_xpm_data((const char **)playlist_xpm); image_playlist = gtk_image_new_from_pixbuf(icon); button_playlist = gtk_button_new(); gtk_container_add(GTK_CONTAINER(button_playlist), image_playlist); gtk_table_attach(GTK_TABLE(table), button_playlist, 6, 7, 1, 2, GTK_SHRINK, GTK_SHRINK, 0, 0); /* about button */ image_about = gtk_image_new_from_stock(GTK_STOCK_ABOUT, GTK_ICON_SIZE_MENU); button_about = gtk_button_new(); gtk_container_add(GTK_CONTAINER(button_about), image_about); gtk_table_attach(GTK_TABLE(table), button_about, 7, 8, 1, 2, GTK_SHRINK, GTK_SHRINK, 0, 0); /* tooltips */ tooltips = gtk_tooltips_new(); gtk_tooltips_set_tip(tooltips, button_prev, "Previous track", NULL); gtk_tooltips_set_tip(tooltips, button_next, "Next track", NULL); gtk_tooltips_set_tip(tooltips, button_play, "Play", NULL); gtk_tooltips_set_tip(tooltips, button_pause, "Pause", NULL); gtk_tooltips_set_tip(tooltips, button_stop, "Stop", NULL); gtk_tooltips_set_tip(tooltips, button_info, "Track info", NULL); gtk_tooltips_set_tip(tooltips, button_playlist, "Open playlist editor", NULL); gtk_tooltips_set_tip(tooltips, button_about, "About gxmms2", NULL); g_signal_connect(G_OBJECT(window), "delete_event", G_CALLBACK(cb_delete_event), &cf); g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(cb_quit_function), NULL); g_signal_connect(G_OBJECT(button_play), "clicked", G_CALLBACK(cb_button_clicked), (gpointer)PLAY_BUTTON); g_signal_connect(G_OBJECT(button_pause), "clicked", G_CALLBACK(cb_button_clicked), (gpointer)PAUSE_BUTTON); g_signal_connect(G_OBJECT(button_stop), "clicked", G_CALLBACK(cb_button_clicked), (gpointer)STOP_BUTTON); g_signal_connect(G_OBJECT(button_next), "clicked", G_CALLBACK(cb_button_clicked), (gpointer)NEXT_BUTTON); g_signal_connect(G_OBJECT(button_prev), "clicked", G_CALLBACK(cb_button_clicked), (gpointer)PREV_BUTTON); g_signal_connect(G_OBJECT(button_playlist), "clicked", G_CALLBACK(cb_button_clicked), (gpointer)PLAYLIST_BUTTON); g_signal_connect(G_OBJECT(button_info), "clicked", G_CALLBACK(cb_button_clicked), (gpointer)INFO_BUTTON); g_signal_connect(G_OBJECT(button_about), "clicked", G_CALLBACK(cb_button_clicked), (gpointer)ABOUT_BUTTON); g_signal_connect(G_OBJECT(scale), "button-press-event", G_CALLBACK(cb_scale_press_event), NULL); g_signal_connect(G_OBJECT(scale), "button-release-event", G_CALLBACK(cb_scale_release_event), NULL); g_signal_connect(G_OBJECT(eventbox_time), "button-press-event", G_CALLBACK(cb_toggle_time), NULL); g_signal_connect(G_OBJECT(wv), "volume-changed", G_CALLBACK(cb_volume_changed), NULL); g_signal_connect(G_OBJECT(window), "key-press-event", G_CALLBACK(cb_key_press), NULL); g_signal_connect(G_OBJECT(window), "drag_data_received", G_CALLBACK(cb_drag_data_received), NULL); if (strncasecmp(cfg_get_key_value(cf, "RestoreMainWindowPosition"), "yes", 3) == 0) { gtk_window_move(GTK_WINDOW(window), atoi(cfg_get_key_value(cf, "MainWindowPosX")), atoi(cfg_get_key_value(cf, "MainWindowPosY"))); } /* docklet */ if (strncasecmp(cfg_get_key_value(cf, "TrayIcon"), "yes", 3) == 0) { create_trayicon(icon); } if (strncasecmp(cfg_get_key_value(cf, "ShowRemainingTime"), "yes", 3) == 0) flag_time_remaining = TRUE; gtk_widget_show_all(window); connection = xmmsc_init("gxmms2"); xmms2_connect(); if (strncasecmp(cfg_get_key_value(cf, "OpenMediaLibOnStartup"), "yes", 3) == 0) { playlist = gmedialib_new(TRUE, TRUE, local_xmms2d, TRUE, TRUE); load_medialib_config(&cf, GMEDIALIB(playlist)); gtk_window_present(GTK_WINDOW(playlist)); } gtk_main(); if (playlist) { gchar buf[8]; snprintf(buf, 7, "%d", gml_window_get_width(GMEDIALIB(playlist))); cfg_add_key(&cf, "MediaLibWindowWidth", buf); snprintf(buf, 7, "%d", gml_window_get_height(GMEDIALIB(playlist))); cfg_add_key(&cf, "MediaLibWindowHeight", buf); snprintf(buf, 7, "%d", gml_window_get_pos_x(GMEDIALIB(playlist))); cfg_add_key(&cf, "MediaLibWindowPosX", buf); snprintf(buf, 7, "%d", gml_window_get_pos_y(GMEDIALIB(playlist))); cfg_add_key(&cf, "MediaLibWindowPosY", buf); snprintf(buf, 7, "%s", gml_pl_get_new_playlist_confirm(GMEDIALIB(playlist)) ? "yes" : "no"); cfg_add_key(&cf, "MediaLibPlaylistNewConfirm", buf); if (gml_notebook_is_mlib_search_visible(GMEDIALIB(playlist))) { snprintf(buf, 7, "%s", gml_search_get_column_id_visible(GMEDIALIB(playlist)) ? "show" : "hide"); cfg_add_key(&cf, "MediaLibSearchColumnID", buf); snprintf(buf, 7, "%s", gml_search_get_column_artist_visible(GMEDIALIB(playlist)) ? "show" : "hide"); cfg_add_key(&cf, "MediaLibSearchColumnArtist", buf); snprintf(buf, 7, "%s", gml_search_get_column_track_visible(GMEDIALIB(playlist)) ? "show" : "hide"); cfg_add_key(&cf, "MediaLibSearchColumnTrack", buf); snprintf(buf, 7, "%s", gml_search_get_column_album_visible(GMEDIALIB(playlist)) ? "show" : "hide"); cfg_add_key(&cf, "MediaLibSearchColumnAlbum", buf); snprintf(buf, 7, "%s", gml_search_get_column_rating_visible(GMEDIALIB(playlist)) ? "show" : "hide"); cfg_add_key(&cf, "MediaLibSearchColumnRating", buf); snprintf(buf, 7, "%s", gml_pl_get_column_pos_visible(GMEDIALIB(playlist)) ? "show" : "hide"); } if (gml_notebook_is_playlist_visible(GMEDIALIB(playlist))) { cfg_add_key(&cf, "MediaLibPlaylistColumnPos", buf); snprintf(buf, 7, "%s", gml_pl_get_column_id_visible(GMEDIALIB(playlist)) ? "show" : "hide"); cfg_add_key(&cf, "MediaLibPlaylistColumnID", buf); snprintf(buf, 7, "%s", gml_pl_get_column_artist_visible(GMEDIALIB(playlist)) ? "show" : "hide"); cfg_add_key(&cf, "MediaLibPlaylistColumnArtist", buf); snprintf(buf, 7, "%s", gml_pl_get_column_track_visible(GMEDIALIB(playlist)) ? "show" : "hide"); cfg_add_key(&cf, "MediaLibPlaylistColumnTrack", buf); snprintf(buf, 7, "%s", gml_pl_get_column_album_visible(GMEDIALIB(playlist)) ? "show" : "hide"); cfg_add_key(&cf, "MediaLibPlaylistColumnAlbum", buf); snprintf(buf, 7, "%s", gml_pl_get_column_rating_visible(GMEDIALIB(playlist)) ? "show" : "hide"); cfg_add_key(&cf, "MediaLibPlaylistColumnRating", buf); } } cfg_add_key(&cf, "ShowRemainingTime", (flag_time_remaining ? "yes" : "no")); cfg_write_config_file(&cf, path_to_config_file); cfg_free_config_file_struct(&cf); g_free(path_to_config_file); return 0; } gxmms2-0.7.1/gxmms2src/playlist.xpm0000644000175000017500000000410710601276546015755 0ustar wejpwejp/* XPM */ static char * playlist_xpm[] = { "16 16 93 2", " c None", ". c #000000", "+ c #0E0E0E", "@ c #282828", "# c #F6F6F6", "$ c #FFFFFF", "% c #F9F9F9", "& c #F9F9F8", "* c #E7E7E7", "= c #CDCDCD", "- c #2E2E2E", "; c #DADADA", "> c #9F9F9F", ", c #FEFEFE", "' c #9B9B9A", ") c #9E9E9E", "! c #FDFDFD", "~ c #FCFCFB", "{ c #F4F4F4", "] c #D4D4D3", "^ c #9D9D9C", "/ c #FBFBFB", "( c #FAFAF9", "_ c #9A9A99", ": c #979696", "< c #CACAC8", "[ c #B6B6B4", "} c #9B9B9B", "| c #F8F8F7", "1 c #F6F6F4", "2 c #F4F3F2", "3 c #F1F0EF", "4 c #F0EFED", "5 c #E5E4E2", "6 c #C4C3C0", "7 c #F8F7F6", "8 c #F7F6F5", "9 c #EBEAE8", "0 c #E1DFDC", "a c #F6F5F4", "b c #B1B0AF", "c c #818180", "d c #AFAFAD", "e c #EFEFED", "f c #E8E7E5", "g c #A4A4A1", "h c #7F7F7E", "i c #7F7E7D", "j c #EEEDEB", "k c #ECEBE9", "l c #E8E7E4", "m c #E7E6E3", "n c #EDECEA", "o c #7D7D7C", "p c #ACABA9", "q c #91908E", "r c #8E8E8C", "s c #E6E4E1", "t c #A2A19F", "u c #646462", "v c #F0F0EE", "w c #7C7B7A", "x c #7B7B7A", "y c #E7E5E2", "z c #E4E3DF", "A c #E3E2DE", "B c #DEDDD9", "C c #DDDCD8", "D c #EDEDEB", "E c #E6E5E2", "F c #E5E4E1", "G c #747371", "H c #0B0B0B", "I c #DCDBD7", "J c #DBD9D5", "K c #E0DFDB", "L c #E3E2DF", "M c #E4E2DF", "N c #DCDAD6", "O c #D9D7D3", "P c #E1E0DC", "Q c #E2E1DD", "R c #71716F", "S c #0B0B0A", "T c #706F6D", "U c #D8D6D1", "V c #E1DFDB", "W c #E0DEDA", "X c #DFDEDA", "Y c #DEDCD8", "Z c #D8D6D2", "` c #D7D6D1", " . c #D5D3CE", " . . . . . . . . + @ . ", " . # $ $ $ $ % & & * . = - ", " . $ ; > $ , ' ' ' * . = = . ", " . $ > ) ! ~ & & { ] . . . . ", " . , ! ^ / ( _ ' : * * < [ . ", " . ~ / } & | 1 2 3 4 4 5 6 . ", " . ( & | 7 8 7 7 7 2 9 0 0 . ", " . a b c d e ' ' f . . g 0 . ", " . 2 h e i j k l m . . . 0 . ", " . 2 n o p k q r s . t u 0 . ", " . v w w x l y z A . B C 0 . ", " . D E E E F G H H . I J K . ", " . 9 L A M z . . . . N O C . ", " . m 0 P K Q R H S T O U I . ", " . V W X B K Y Y N N Z ` .. ", " . . . . . . . . . . . . "}; gxmms2-0.7.1/gxmms2src/wejpscroller.c0000644000175000017500000002246010601276546016247 0ustar wejpwejp/* * File: wejpscroller.c * * A gtk2 text scroll widget * Copyright (c) 2005 Johannes Heimansberg * * Released under the GNU General Public License v2 */ #include "wejpscroller.h" #include #define MAX_HEIGHT 30 #define MAX_WIDTH 2000 void wejpscroller_scroll_one_pixel(WejpScroller *ws) { if (ws->extents.width <= ws->drawing_area->allocation.width && ws->smart_scrolling) ws->pos = ws->width; else if (ws->scroll == TRUE) ws->pos++; if (ws->pos > ws->extents.width + ws->drawing_area->allocation.width) ws->pos = 0; } static gboolean cb_timer(gpointer userdata) { gboolean result = TRUE; if (GTK_IS_WIDGET(userdata)) { WejpScroller *ws = WEJPSCROLLER(userdata); if (ws->shortmessage_timeout > 0) { ws->shortmessage_timeout--; } else { if (ws->shortmessage_pos_backup > 0) { ws->pos = ws->shortmessage_pos_backup; ws->shortmessage_pos_backup = -1; if (strlen(ws->shortmessage_text_backup) > 0) { wejpscroller_set_text(ws, ws->shortmessage_text_backup, FALSE); } } if (WEJPSCROLLER(ws)->scroll) wejpscroller_scroll_one_pixel(ws); } wejpscroller_draw(ws); } else { result = FALSE; } return result; } GtkWidget *wejpscroller_new(guint scroll_delay, gboolean smart) { GtkWidget *ws = GTK_WIDGET(g_object_new(WEJPSCROLLER_TYPE, NULL)); WEJPSCROLLER(ws)->scroll_delay = scroll_delay; WEJPSCROLLER(ws)->smart_scrolling = smart; if (scroll_delay != 0) { WEJPSCROLLER(ws)->scroll = TRUE; } else { WEJPSCROLLER(ws)->scroll = FALSE; } WEJPSCROLLER(ws)->shortmessage_timeout = 0; WEJPSCROLLER(ws)->shortmessage_text_backup[0] = '\0'; if (WEJPSCROLLER(ws)->scroll) g_timeout_add(WEJPSCROLLER(ws)->scroll_delay, &cb_timer, ws); else g_timeout_add(100, &cb_timer, ws); return ws; } static void wejpscroller_set_text_without_backup(WejpScroller *ws, gchar *new_text, gboolean reset_pos) { GdkColor *text_color, *bg_color; gdk_window_show(ws->drawing_area->window); bg_color = &ws->drawing_area->style->bg[GTK_WIDGET_STATE(ws->drawing_area)]; text_color = &ws->drawing_area->style->text[GTK_WIDGET_STATE(ws->drawing_area)]; gdk_gc_set_foreground(ws->drawing_area-> style->fg_gc[GTK_WIDGET_STATE(ws->drawing_area)], bg_color); if (ws->pixmap == NULL) ws->pixmap = gdk_pixmap_new(GDK_DRAWABLE(ws->drawing_area->window), MAX_WIDTH, MAX_HEIGHT, -1); gdk_draw_rectangle(GDK_DRAWABLE(ws->pixmap), ws->drawing_area-> style->fg_gc[GTK_WIDGET_STATE(ws->drawing_area)], TRUE, 0, 0, MAX_WIDTH, MAX_HEIGHT); gdk_gc_set_foreground(ws->drawing_area->style-> fg_gc[GTK_WIDGET_STATE(ws->drawing_area)], text_color); pango_layout_set_text(ws->pgl, new_text, strlen(new_text)); pango_layout_get_pixel_extents(ws->pgl, NULL, &ws->extents); gdk_draw_layout(GDK_DRAWABLE(ws->pixmap), ws->drawing_area-> style->fg_gc[GTK_WIDGET_STATE(ws->drawing_area)], ws->drawing_area->allocation.width, 0, ws->pgl); if (reset_pos) { if (ws->scroll_delay > 0) ws->pos = 0; else ws->pos = ws->width; } } void wejpscroller_set_text(WejpScroller *ws, gchar *new_text, gboolean reset_pos) { g_strlcpy(ws->shortmessage_text_backup, new_text, sizeof(ws->shortmessage_text_backup)); wejpscroller_set_text_without_backup(ws, new_text, reset_pos); } const gchar *wejpscroller_get_text(WejpScroller *ws) { return pango_layout_get_text(ws->pgl); } void wejpscroller_set_dimensions(WejpScroller *ws, gint w, gint h) { gint height; ws->width = (w > 0) ? w : -1; ws->height = (h > 0) ? h : -1; height = (ws->height > MAX_HEIGHT) ? MAX_HEIGHT : ws->height; gtk_widget_set_size_request(ws->drawing_area, ws->width, ws->height); gtk_widget_set_size_request(GTK_WIDGET(ws), ws->width, ws->height); if (height > 2) pango_font_description_set_absolute_size(ws->pfd, (height-2)*PANGO_SCALE); pango_font_description_set_family_static(ws->pfd, ws->font); pango_layout_set_font_description(ws->pgl, ws->pfd); } void wejpscroller_set_font(WejpScroller *ws, gchar *font, gint fontsize) { strncpy(ws->font, font, FONT_STR_LENGTH); pango_font_description_set_family_static(ws->pfd, ws->font); if (fontsize > 0) pango_font_description_set_absolute_size(ws->pfd, fontsize*PANGO_SCALE); pango_layout_set_font_description(ws->pgl, ws->pfd); } void wejpscroller_shortmessage_show(WejpScroller *ws, gchar *message, guint timeout) { ws->shortmessage_timeout = timeout; ws->shortmessage_pos_backup = ws->pos; ws->pos = ws->width; if (strlen(ws->shortmessage_text_backup) > 0) { wejpscroller_set_text(ws, ws->shortmessage_text_backup, FALSE); } g_strlcpy(ws->shortmessage_text_backup, wejpscroller_get_text(ws), sizeof(ws->shortmessage_text_backup)); wejpscroller_set_text_without_backup(ws, message, FALSE); } static void wejpscroller_class_init(WejpScrollerClass *class) { } void wejpscroller_draw(WejpScroller *ws) { GdkRectangle rect; rect.x = 0; rect.y = 0; rect.width = ws->drawing_area->allocation.width; rect.height = ws->drawing_area->allocation.height; gtk_widget_draw(ws->drawing_area, &rect); } static gboolean expose_event_callback(GtkWidget *widget, GdkEventExpose *event, gpointer data) { WejpScroller *ws = WEJPSCROLLER(widget->parent); if (ws->pixmap != NULL) gdk_draw_drawable(widget->window, ws->drawing_area->style-> fg_gc[GTK_WIDGET_STATE(ws->drawing_area)], GDK_DRAWABLE(ws->pixmap), ws->pos, 0, 0, 0, ws->drawing_area->allocation.width, ws->drawing_area->allocation.height); return TRUE; } static gboolean cb_button_press(GtkWidget *widget, GdkEventButton *event, gpointer data) { WEJPSCROLLER(data)->scroll = FALSE; WEJPSCROLLER(data)->mouse_x = event->x; return TRUE; } static gboolean cb_button_release(GtkWidget *widget, GdkEventButton *event, gpointer data) { if (WEJPSCROLLER(data)->scroll_delay > 0) WEJPSCROLLER(data)->scroll = TRUE; return TRUE; } static gboolean cb_motion_notify_event(GtkWidget *widget, GdkEventMotion *event, gpointer data) { gint x, y, tmp; GdkModifierType state; WejpScroller *ws = WEJPSCROLLER(data); if (event->is_hint) { gdk_window_get_pointer(event->window, &x, &y, &state); } else { x = event->x; y = event->y; state = event->state; } if (state & GDK_BUTTON1_MASK && ws->scroll == FALSE) { tmp = ws->mouse_x - x; if ((gint)ws->pos + tmp > 0 && (gint)ws->pos + tmp < ws->extents.width + ws->drawing_area->allocation.width) { ws->pos = ws->pos + tmp; } else if ((gint)ws->pos + tmp > ws->extents.width + ws->drawing_area->allocation.width) { ws->pos = 0; } else { ws->pos = ws->extents.width + ws->drawing_area->allocation.width; } ws->mouse_x = x; } return TRUE; } static void wejpscroller_init(WejpScroller *ws) { ws->pos = 0; ws->pixmap = NULL; ws->drawing_area = gtk_drawing_area_new(); gtk_container_add(GTK_CONTAINER(ws), ws->drawing_area); gtk_widget_show_all(GTK_WIDGET(ws)); ws->colormap = gdk_colormap_new(gdk_visual_get_best(), FALSE); ws->pgl = pango_layout_new(gdk_pango_context_get_for_screen( gdk_screen_get_default())); ws->pfd = pango_context_get_font_description(pango_layout_get_context(ws->pgl)); /*pango_font_description_set_absolute_size(ws->pfd, 12 * PANGO_SCALE);*/ pango_font_description_set_family_static(ws->pfd, "Sans Serif"); pango_layout_set_font_description(ws->pgl, ws->pfd); g_signal_connect(G_OBJECT(ws->drawing_area), "expose_event", G_CALLBACK(expose_event_callback), NULL); g_signal_connect(G_OBJECT(ws), "button_press_event", G_CALLBACK(cb_button_press), ws); g_signal_connect(G_OBJECT(ws), "button_release_event", G_CALLBACK(cb_button_release), ws); g_signal_connect(G_OBJECT(ws), "motion_notify_event", G_CALLBACK(cb_motion_notify_event), ws); } GType wejpscroller_get_type(void) { static GType ws_type = 0; if (!ws_type) { static const GTypeInfo ws_info = { sizeof(WejpScrollerClass), NULL, /* base_init */ NULL, /* base_finalize */ (GClassInitFunc) wejpscroller_class_init, NULL, /* class_finalize */ NULL, /* class_data */ sizeof(WejpScroller), 0, /* n_preallocs */ (GInstanceInitFunc) wejpscroller_init, }; ws_type = g_type_register_static(GTK_TYPE_EVENT_BOX, "WejpScroller", &ws_info, 0); } return ws_type; } gxmms2-0.7.1/README0000644000175000017500000001610011427740566012322 0ustar wejpwejpgxmms2 & gkrellxmms2 Copyright (c) 2005-2010 Johannes Heimansberg gxmms2 and gkrellxmms2 are XMMS2 clients. gxmms2 is a GTK2 based XMMS2 client. gkrellxmms2 is a gkrellm2 plugin. Website: http://wejp.k.vu/ gxmms2 and gkrellxmms2 are released under the GNU General Public License (GPL) Version 2. For details see COPYING file. Contents -------- 0 Quick start 1 Dependencies 2 gxmms2 3 gkrellxmms2 4 Media library 0 Quick start ------------- This package contains both gxmms2 and gkrellxmms2 (the xmms2 gkrellm2 plugin). To build gxmms2 run make gxmms2 and make install_gxmms2 to install gxmms2. To build gkrellxmms2 run make gkrellxmms2 and make install_gkrellxmms2 to install gkrellxmms2. This will install the plugin in /usr/lib/gkrellm2/plugins. If just you run "make", make will build both gxmms2 and gkrellxmms2. "make install" installs both gxmms2 and gkrellxmms2. 1 Dependencies -------------- gxmms2: - xmms2 client lib - gtk+2.6.0 or higher gkrellxmms2: - xmms2 client lib - gtk+2.6.0 or higher - gkrellm2 2.2 Please note: If you get lots of errors when trying to build gxmms2 and/or gkrellxmms2 please make sure that you have all required dependencies installed. Also make sure, that your PKG_CONFIG_PATH is set correctly. E.g. sometimes /usr/local/lib/pkgconfig is not in pkg-config's path, although there might be .pc files installed in that location. 2 gxmms2 -------- 2.1 Using gxmms2 2.1.0 Getting started The basic player controls are available through gxmms2's main window. There are buttons for play, pause, skip, stop, track info, player info and one button to open the medialib window. Furthermore you can control the volume by moving your mouse over the volume icon (upper right corner) and using either the mouse wheel or the left and right buttons to change the volume. For details on the keyboard control read section 2.1.1. For details on media library usage see chapter 4. 2.1.1 Keyboard control Besides the main window's buttons you can use your keyboard to control play, pause, stop, skip and volume. The keys are: - z for previous track - x for play - c for pause - v for stop - b for next track - j for medialib/playlist window - t for toggle elapsed/remaining time - +/- to increase/decrease the volume - 0..4 to rate the current track where 0 is worst and 4 is best 2.2 Customizing gxmms2 There are various options that can be changed. Some of them can be changed from within gxmms2 itself while others can be changed through editing the config file only. 2.2.1 Changing settings from within gxmms2 Things you can change in gxmms2 are the visible columns in both search and playlist view and in gxmms2's main window the time display whether it should show the elapsed or remaining time. 2.2.2 Editing the config file The config file's location depends on the operating system gxmms2 runs on, but it is usually ~/.config/xmms2/clients/gxmms2.conf . It is a plain text file which you can edit with your favorite text editor. Make sure gxmms2 is not running while editing the file, otherwise gxmms2 will overwrite your changes upon exit. There are things you probably should not change (such as ScrollerFontSizePx), because changes can lead to unexpected behaviour or a strange program layout. Settings of interest are: * MediaLibFontSizePt Setting this to -1 will tell gxmms2 to use gtk2's default font size. Numbers above 0 will tell gxmms2 to use treat that number as the new font size. * RestoreMediaLibSize Possible values are "yes" and "no". If set to "yes" gxmms2 will remember the medialib window's size and restore it each time gxmms2 is started. * RestoreMediaLibPosition Possible values are "yes" and "no". If set to "yes" gxmms2 will remember the medialib window's position and restore it each time gxmms2 is started. * RestoreMainWindowPosition Possible values are "yes" and "no". If set to "yes" gxmms2 will remember the main window's position and restore it each time gxmms2 is started. * OpenMediaLibOnStartup Possible values are "yes" and "no". If set to "yes" gxmms2 will open the medialib window on startup. * TrayIcon Possible values are "yes" and "no". If set to "yes" gxmms2 puts a tray icon in the window manager's tray icon area. * AutoReconnect Possible values are "yes" and "no". If set to "yes" gxmms2 will try to reconnect if it looses the connection to the daemon. * TerminateXmms2dOnExit Possible values are "yes" and "no". If set to "yes" gxmms2 will shut down xmms2d on exit. * StartLocalXmms2dOnStartup Possible values are "yes" and "no". If set to "yes" gxmms2 tries to start xmms2d if it is not running. Only works when the IPCPath is a local path (starting with unix://). * IPCPath By default this is set to the default local ipc path. When your xmms2d is running on another computer you need to change this. This setting will be overwritten by the XMMS_PATH environment variable. 3 gkrellxmms2 ------------- The gkrellxmms2 gkrellm2 plugin has a title scroller with a position marker and five buttons for playback control. The position marker can be moved with the mouse to seek in the current track. The M button opens a menu with two items for opening a trackinfo dialog and the media library window. 4 Media library --------------- 4.1 Getting started Assuming you have just installed XMMS2 and gxmms2/gkrellxmm2 and started the xmms2d daemon, the first thing you want to do is to add some files (or better yet all your media files) to XMMS2's media library. To add files to XMMS2's media library, start gxmms2/gkrellm2 and open the medialib/playlist editor by clicking on gxmms2's second button from the right or on the M button in gkrellxmms2 and select the media lib from there. Now select the "MLib Add files" tab. Now you can select one or more files and/or directories and add the selection to the medialib by clicking on the "Add" button below. This will only work when both xmms2d and gxmms2/gkrellxmms2 are running on the same computer. If that is not the case use the CLI client to add files to the medialib on the remote computer. When you are finished with adding files to the media library you can search for music within the medialib using the playlist editor's "MLib Search" tab or browse through the artists with the "MLib Browser". When you have found something you want to listen to, you can add it to the playlist by either double clicking on the item or by selecting the item or even multiple items and selecting the "Add" item from the context menu. If you can't decide what you want to listen to you can use the "+?" button in the playlist editor to add 10 random songs to the playlist. If you have created a playlist that you want to keep you can save it by clicking on the "Save playlist" button. When you do that you will be asked for a playlist name. 4.2 Modifying the playlist If you want to move a playlist item you can either use the arrow buttons in the upper right corner of the playlist tab or use your keyboard by pressing ALT + Cursor up/Cursor down key to move the selected item up or down. To remove the selected item(s) from the playlist you can use the delete item from the context menu or press the delete key on your keyboard. gxmms2-0.7.1/gmedialib/0000755000175000017500000000000011427742710013352 5ustar wejpwejpgxmms2-0.7.1/gmedialib/gmlplaylists.c0000644000175000017500000003357511213135526016251 0ustar wejpwejp/* * File: gmlplaylists.c * * Medialib search and playlist editor * Copyright (c) 2005 Johannes Heimansberg * * requires GTK+ 2.6 or better and XMMS2 DR2 or better * * Released under the GNU General Public License v2 */ #include #include #include #include #include #include "gmedialib.h" #include "gtrackinfo/trackinfo.h" #include "gtrackinfo/gtrackinfo.h" extern xmmsc_connection_t *connection; /* available from gxmms2.c */ struct pl_params { GMedialib *gml; gchar name[256]; }; static int n_query_playlists(xmmsv_t *val, void *pt) { struct pl_params *p = (struct pl_params *)pt; xmmsc_coll_t *coll, *operand; GtkTreeIter iter; char const *xerr; if (xmmsv_get_error(val, &xerr)) { gml_set_statusbar_text(p->gml, (gchar *) xerr); } else { xmmsv_t *v; gint cnt = 0; gchar *pl_type = NULL, buf[512]; xmmsv_get_coll(val, &coll); cnt = xmmsc_coll_idlist_get_size(coll); switch (xmmsc_coll_get_type (coll)) { case XMMS_COLLECTION_TYPE_IDLIST: pl_type = "ID list"; break; case XMMS_COLLECTION_TYPE_QUEUE: pl_type = "Queue"; break; case XMMS_COLLECTION_TYPE_PARTYSHUFFLE: pl_type = "Party shuffle"; if ( xmmsv_list_get (xmmsv_coll_operands_get (coll), 0, &v) && xmmsv_get_coll (v, &operand) && xmmsv_coll_get_type (operand) == XMMS_COLLECTION_TYPE_REFERENCE) { gchar *reference; xmmsc_coll_attribute_get(operand, "reference", &reference); snprintf(buf, 511, "Party shuffle (Source collection: %s)", reference); pl_type = buf; } break; default: pl_type = "Other"; break; } /* Hide all lists that start with _ */ if (p->gml->playlists.ls != NULL && p->name[0] != '_') { gtk_list_store_append(p->gml->playlists.ls, &iter); gtk_list_store_set(p->gml->playlists.ls, &iter, 0, (gchar *)p->name, 1, cnt, 2, pl_type, -1); } } g_free(p); return FALSE; } static int n_update_playlists(xmmsv_t *val, void *pt) { GMedialib *gml = (GMedialib *)pt; struct pl_params *p; char const *xerr; if (xmmsv_get_error(val, &xerr)) { gml_set_statusbar_text(gml, (gchar *) xerr); } else { xmmsv_list_iter_t *it; if (gml->playlists.ls != NULL) gtk_list_store_clear(gml->playlists.ls); xmmsv_get_list_iter(val, &it); for (; xmmsv_list_iter_valid(it); xmmsv_list_iter_next(it)) { xmmsv_t *entry; const gchar *name; xmmsc_result_t *res2; xmmsv_list_iter_entry(it, &entry); xmmsv_get_string(entry, &name); p = g_malloc(sizeof(struct pl_params)); p->gml = gml; g_strlcpy(p->name, name, sizeof(p->name)); res2 = xmmsc_coll_get(connection, name, XMMS_COLLECTION_NS_PLAYLISTS); xmmsc_result_notifier_set(res2, n_query_playlists, p); xmmsc_result_unref(res2); } gml_set_statusbar_text(gml, "Ready."); } return FALSE; } void gml_playlists_update_playlists(GMedialib *gml) { xmmsc_result_t *res; gml_set_statusbar_text(gml, "Loading playlists..."); res = xmmsc_playlist_list(connection); xmmsc_result_notifier_set(res, n_update_playlists, gml); xmmsc_result_unref(res); } static int n_playlist_load(xmmsv_t *val, void *pt) { GMedialib *gml = (GMedialib *)pt; gml_set_statusbar_text(gml, "Ready."); gml_pl_refresh_playlist(gml); gtk_notebook_set_current_page(GTK_NOTEBOOK(gml->notebook), 4); return FALSE; } static void cb_playlists_list_activated(GtkTreeView *view, GtkTreePath *path, GtkTreeViewColumn *col, gpointer userdata) { GtkTreeIter iter; GtkTreeModel *model; GMedialib *gml = (GMedialib *)userdata; model = gtk_tree_view_get_model(view); if (gtk_tree_model_get_iter(model, &iter, path)) { gchar *playlist = "Unknown"; xmmsc_result_t *res; gtk_tree_model_get(model, &iter, 0, &playlist, -1); res = xmmsc_playlist_load(connection, playlist); xmmsc_result_notifier_set(res, n_playlist_load, gml); xmmsc_result_unref(res); g_free(playlist); } } static int n_playlist_delete(xmmsv_t *val, void *pt) { GMedialib *gml = (GMedialib *)pt; gml_playlists_update_playlists(gml); gml_set_statusbar_text(gml, "Ready."); return FALSE; } static void cb_playlists_button_delete_pressed(GtkWidget *widget, gpointer pt) { GMedialib *gml = (GMedialib *)pt; GtkTreeSelection *sel; GtkTreeModel *model; GtkTreeIter selected_row; sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(gml->playlists.list)); g_assert(gtk_tree_selection_get_mode(sel) == GTK_SELECTION_SINGLE); if (gtk_tree_selection_get_selected(sel, &model, &selected_row)) { gchar *playlist; xmmsc_result_t *res; gtk_tree_model_get(model, &selected_row, 0, &playlist, -1); res = xmmsc_playlist_remove(connection, playlist); xmmsc_result_notifier_set(res, n_playlist_delete, gml); xmmsc_result_unref(res); g_free(playlist); } } static void cb_playlists_button_open_pressed(GtkWidget *widget, gpointer pt) { GMedialib *gml = (GMedialib *)pt; GtkTreeSelection *sel; GtkTreeModel *model; GtkTreeIter selected_row; sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(gml->playlists.list)); g_assert(gtk_tree_selection_get_mode(sel) == GTK_SELECTION_SINGLE); if (gtk_tree_selection_get_selected(sel, &model, &selected_row)) { gchar *playlist; xmmsc_result_t *res; gtk_tree_model_get(model, &selected_row, 0, &playlist, -1); res = xmmsc_playlist_load(connection, playlist); xmmsc_result_notifier_set(res, n_playlist_load, gml); xmmsc_result_unref(res); g_free(playlist); } } static int n_playlist_add_collection(xmmsv_t *val, void *pt) { GMedialib *gml = (GMedialib *)pt; xmmsc_coll_t *playlist_coll; xmmsc_result_t *res2; xmmsv_t *order; xmmsv_get_coll(val, &playlist_coll); order = xmmsv_new_list(); res2 = xmmsc_playlist_add_collection(connection, NULL, playlist_coll, order); xmmsv_unref(order); xmmsc_result_notifier_set(res2, n_playlist_load, gml); return FALSE; } static void cb_playlists_button_add_pressed(GtkWidget *widget, gpointer pt) { GMedialib *gml = (GMedialib *)pt; GtkTreeSelection *sel; GtkTreeModel *model; GtkTreeIter selected_row; sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(gml->playlists.list)); g_assert(gtk_tree_selection_get_mode(sel) == GTK_SELECTION_SINGLE); if (gtk_tree_selection_get_selected(sel, &model, &selected_row)) { gchar *playlist; xmmsc_result_t *res; gtk_tree_model_get(model, &selected_row, 0, &playlist, -1); res = xmmsc_coll_get(connection, playlist, XMMS_COLLECTION_NS_PLAYLISTS); xmmsc_result_notifier_set(res, n_playlist_add_collection, gml); xmmsc_result_unref(res); g_free(playlist); } } static void cb_playlists_popup_refresh_pressed(GtkWidget *widget, gpointer pt) { GMedialib *gml = (GMedialib *)pt; gml_playlists_update_playlists(gml); } static void playlists_view_popup_menu(GtkWidget *treeview, GdkEventButton *event, gpointer userdata) { GtkWidget *menu, *menuitem; GtkTreeSelection *selection; GMedialib *gml = (GMedialib *)userdata; gboolean multiple = FALSE, none = FALSE; selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(gml->playlists.list)); if (gtk_tree_selection_count_selected_rows(selection) > 1) multiple = TRUE; if (gtk_tree_selection_count_selected_rows(selection) == 0) none = TRUE; menu = gtk_menu_new(); /* open playlist */ menuitem = gtk_image_menu_item_new_from_stock(GTK_STOCK_OPEN, NULL); if (multiple || none) gtk_widget_set_sensitive(menuitem, FALSE); g_signal_connect(menuitem, "activate", G_CALLBACK(cb_playlists_button_open_pressed), userdata); gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); /* append to current playlist */ menuitem = gtk_image_menu_item_new_with_mnemonic("_Add to current playlist"); gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuitem), gtk_image_new_from_stock(GTK_STOCK_ADD, GTK_ICON_SIZE_SMALL_TOOLBAR)); if (multiple || none)gtk_widget_set_sensitive(menuitem, FALSE); g_signal_connect(menuitem, "activate", G_CALLBACK(cb_playlists_button_add_pressed), userdata); gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); /* delete playlist */ menuitem = gtk_image_menu_item_new_from_stock(GTK_STOCK_DELETE, NULL); if (multiple || none) gtk_widget_set_sensitive(menuitem, FALSE); g_signal_connect(menuitem, "activate", G_CALLBACK(cb_playlists_button_delete_pressed), userdata); gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); menuitem = gtk_separator_menu_item_new(); gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); /* refresh playlists list */ menuitem = gtk_image_menu_item_new_from_stock(GTK_STOCK_REFRESH, NULL); g_signal_connect(menuitem, "activate", G_CALLBACK(cb_playlists_popup_refresh_pressed), userdata); gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); gtk_widget_show_all(menu); gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, (event != NULL) ? event->button : 0, gdk_event_get_time((GdkEvent*)event)); } static gboolean cb_playlists_selection_button_press(GtkWidget *treeview, GdkEventButton *event, gpointer userdata) { gboolean result = FALSE; if (event->type == GDK_BUTTON_PRESS && event->button == 3) { playlists_view_popup_menu(treeview, event, userdata); result = TRUE; } return result; } static gboolean cb_playlists_selection_popup_menu(GtkWidget *treeview, gpointer userdata) { playlists_view_popup_menu(treeview, NULL, userdata); return TRUE; } void gml_create_playlists(GMedialib *gml) { GtkTreeViewColumn *column_playlist, *column_items, *column_type; gml->playlists.frame = gtk_frame_new("Playlists"); gtk_container_set_border_width(GTK_CONTAINER(gml->playlists.frame), 2); /* table mlib browse */ gml->playlists.table = gtk_table_new(2, 1, FALSE); gtk_container_set_border_width(GTK_CONTAINER(gml->playlists.table), 3); gtk_table_set_row_spacings(GTK_TABLE(gml->playlists.table), 4); gtk_table_set_col_spacings(GTK_TABLE(gml->playlists.table), 4); gtk_container_add(GTK_CONTAINER(gml->playlists.frame), gml->playlists.table); /* list artist browse */ gml->playlists.ls = gtk_list_store_new(3, G_TYPE_STRING, G_TYPE_INT, G_TYPE_STRING); gml->playlists.list = gtk_tree_view_new_with_model(GTK_TREE_MODEL(gml->playlists.ls)); gtk_tree_view_set_enable_search(GTK_TREE_VIEW(gml->playlists.list), TRUE); gml->playlists.scroll_widget = gtk_scrolled_window_new(NULL, NULL); gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW(gml->playlists.scroll_widget), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS); gtk_container_add(GTK_CONTAINER(gml->playlists.scroll_widget), gml->playlists.list); gtk_table_attach(GTK_TABLE(gml->playlists.table), gml->playlists.scroll_widget, 0, 1, 0, 1, GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, 0, 0); column_playlist = gtk_tree_view_column_new_with_attributes("Playlist", gml->renderer_text, "text", 0, NULL); gtk_tree_view_append_column(GTK_TREE_VIEW(gml->playlists.list), column_playlist); gtk_tree_view_column_set_resizable(column_playlist, TRUE); gtk_tree_view_column_set_cell_data_func(column_playlist, gml->renderer_text, gml_cell_data_function, gml, NULL); column_items = gtk_tree_view_column_new_with_attributes("Items", gml->renderer_text, "text", 1, NULL); gtk_tree_view_append_column(GTK_TREE_VIEW(gml->playlists.list), column_items); gtk_tree_view_column_set_resizable(column_items, TRUE); gtk_tree_view_column_set_cell_data_func(column_items, gml->renderer_text, gml_cell_data_function, gml, NULL); column_type = gtk_tree_view_column_new_with_attributes("Type", gml->renderer_text, "text", 2, NULL); gtk_tree_view_append_column(GTK_TREE_VIEW(gml->playlists.list), column_type); gtk_tree_view_column_set_resizable(column_type, TRUE); gtk_tree_view_column_set_cell_data_func(column_type, gml->renderer_text, gml_cell_data_function, gml, NULL); /* load button */ gml->playlists.button_load = gtk_button_new_from_stock(GTK_STOCK_OPEN); gtk_table_attach(GTK_TABLE(gml->playlists.table), gml->playlists.button_load, 0, 1, 1, 2, GTK_SHRINK, GTK_SHRINK, 0, 0); g_signal_connect(G_OBJECT(gml->playlists.list), "row-activated", G_CALLBACK(cb_playlists_list_activated), (gpointer)gml); g_signal_connect(G_OBJECT(gml->playlists.button_load), "clicked", G_CALLBACK(cb_playlists_button_open_pressed), (gpointer)gml); g_signal_connect(G_OBJECT(gml->playlists.list), "button-press-event", G_CALLBACK(cb_playlists_selection_button_press), (gpointer)gml); g_signal_connect(G_OBJECT(gml->playlists.list), "popup-menu", G_CALLBACK(cb_playlists_selection_popup_menu), (gpointer)gml); } gxmms2-0.7.1/gmedialib/rank1.xpm0000644000175000017500000000212510601276546015116 0ustar wejpwejp/* XPM */ static char * rank1_xpm[] = { "48 16 15 1", " c None", ". c #000000", "+ c #EEF63E", "@ c #EAF13D", "# c #F0F83F", "$ c #CBD235", "% c #E9F03D", "& c #E5EC3C", "* c #E8F03D", "= c #ABB02D", "- c #ECF33E", "; c #EFF73F", "> c #CED636", ", c #B4BA2F", "' c #CDD435", " ", " ", " ", " ", " . . . . ", " .+. . . . . . . ", " ..@#$.. .. .. .. .. .. .. ", " .######%. . . . . . . ", " .####&. . . . . . . ", " .*###=. . . . . . . ", " .#-.;>. . . . . . . . . . ", " .,. .'. . . . . . . . . . . . . ", " . . . . . . . . ", " ", " ", " "}; gxmms2-0.7.1/gmedialib/addrnd.xpm0000644000175000017500000000140110601276546015332 0ustar wejpwejp/* XPM */ static char * addrnd_xpm[] = { "24 24 3 1", " c None", ". c #000000", "+ c #3080F8", " ", " ", " ", " ", " ..... ", " ...+++.. ", " ..++++++.. ", " ... .++....++. ", " .+. .+. .++. ", " .+. ... ..++. ", " ....+.... ..++.. ", " .+++++++. ..++.. ", " ....+.... .++.. ", " .+. .++. ", " .+. .++. ", " ... .... ", " ", " .... ", " .++. ", " .++. ", " .... ", " ", " ", " "}; gxmms2-0.7.1/gmedialib/gmedialib.c0000644000175000017500000003010611213135526015425 0ustar wejpwejp/* * File: gmedialib.c * * Medialib search and playlist editor * Copyright (c) 2005-2006 Johannes Heimansberg * * requires GTK+ 2.6 or better and XMMS2 * * Released under the GNU General Public License v2 */ #include #include #include #include #include #include #include "gmedialib.h" #include "gtrackinfo/trackinfo.h" #include "gtrackinfo/gtrackinfo.h" #include "playlists.xpm" #include "browser.xpm" static void gmedialib_class_init(GMedialibClass *klass); static void gmedialib_init(GMedialib *gml); extern xmmsc_connection_t *connection; /* available from gxmms2.c */ GType gmedialib_get_type(void) { static GType gml_type = 0; if (!gml_type) { static const GTypeInfo gml_info = { sizeof(GMedialibClass), NULL, /* base_init */ NULL, /* base_finalize */ (GClassInitFunc) gmedialib_class_init, NULL, /* class_finalize */ NULL, /* class_data */ sizeof(GMedialib), 0, (GInstanceInitFunc) gmedialib_init, }; gml_type = g_type_register_static(GTK_TYPE_DIALOG, "GMedialib", &gml_info, 0); } return gml_type; } static void gmedialib_class_init(GMedialibClass *klass) { } void gml_set_statusbar_text(GMedialib *gml, gchar *text) { gtk_statusbar_pop(GTK_STATUSBAR(gml->statusbar), gml->statusbar_id); gtk_statusbar_push(GTK_STATUSBAR(gml->statusbar), gml->statusbar_id, text); } static void cb_close_medialib_dialog(GtkWidget *widget, gpointer pt) { GtkWidget *gml = (GtkWidget *)pt; gtk_widget_hide(gml); } /* callback: close window (return FALSE = close window) */ static gint cb_delete_event(GtkWidget *widget, GdkEvent *event, gpointer pt) { GtkWidget *gml = (GtkWidget *)pt; gtk_widget_hide(gml); return TRUE; } void gml_set_album_tracknr_digits(GMedialib *gml, gint digits) { if (digits >= 0 && digits <= 3) gml->album_tracknr_digits = digits; } gint gml_window_get_pos_x(GMedialib *gml) { return gml->window_pos_x; } gint gml_window_get_pos_y(GMedialib *gml) { return gml->window_pos_y; } gint gml_window_get_width(GMedialib *gml) { return gml->window_width; } gint gml_window_get_height(GMedialib *gml) { return gml->window_height; } void gml_set_font_size(GMedialib *gml, gint size) { if (size > 0 && size <= 100) { gml->font_size = size; g_object_set(gml->renderer_text, "size", gml->font_size * PANGO_SCALE, "size-set", TRUE, NULL); g_object_set(gml->renderer_text_ellipsize, "size", gml->font_size * PANGO_SCALE, "size-set", TRUE, NULL); } } void gml_cell_data_function(GtkTreeViewColumn *col, GtkCellRenderer *renderer, GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data) { GMedialib *gml = GMEDIALIB(user_data); g_object_set(gml->renderer_text, "weight-set", FALSE, NULL); g_object_set(gml->renderer_text_ellipsize, "weight-set", FALSE, NULL); } static gint cb_configure_event(GtkWidget *widget, GdkEvent *event, gpointer pt) { gint x, y; GMedialib *gml = (GMedialib *)pt; GdkEventConfigure *ce = (GdkEventConfigure *)event; gtk_window_get_position(GTK_WINDOW(gml), &x, &y); gml->window_width = ce->width; gml->window_height = ce->height; gml->window_pos_x = x; gml->window_pos_y = y; return FALSE; } static int bc_handle_mediainfo_reader_status(xmmsv_t *val, void *userdata) { GMedialib *gml = (GMedialib *)userdata; gint32 status; xmmsv_get_int(val, &status); if (status == 0) gml_set_statusbar_text(gml, "Done."); else if (status == 1) gml_set_statusbar_text(gml, "Reading media info of newly added files..."); return TRUE; } static int cb_handle_mediainfo_reader_unindexed(xmmsv_t *val, void *userdata) { gint32 remaining_files; gchar buf[256]; GMedialib *gml = (GMedialib *)userdata; xmmsv_get_int(val, &remaining_files); snprintf(buf, sizeof(buf), "Reading media info of newly added files: %d files remaining", remaining_files); gml_set_statusbar_text(gml, buf); return TRUE; } static gboolean cb_key_press(GtkWidget *widget, GdkEventKey *event, gpointer userdata) { GMedialib *gml = (GMedialib *)userdata; /* 0 = search tab */ if (gtk_notebook_get_current_page(GTK_NOTEBOOK(gml->notebook)) == 0) { gchar text[6] = ""; g_unichar_to_utf8(gdk_keyval_to_unicode(event->keyval), text); if (text[0] >= 32) { /* valid text character */ gtk_entry_set_text(GTK_ENTRY(gml->search.entry_searchstring), text); gtk_widget_grab_focus(gml->search.entry_searchstring); gtk_editable_set_position(GTK_EDITABLE(gml->search.entry_searchstring), -1); gtk_editable_select_region(GTK_EDITABLE(gml->search.entry_searchstring), 0, 0); gtk_editable_set_position(GTK_EDITABLE(gml->search.entry_searchstring), -1); } } return FALSE; } void gml_setup_xmms_callbacks(GMedialib *gml) { XMMS_CALLBACK_SET(connection, xmmsc_broadcast_mediainfo_reader_status, bc_handle_mediainfo_reader_status, gml); XMMS_CALLBACK_SET(connection, xmmsc_signal_mediainfo_reader_unindexed, cb_handle_mediainfo_reader_unindexed, gml); } gboolean gml_notebook_is_mlib_search_visible(GMedialib *gml) { return gml->notebook_mlib_search; } gboolean gml_notebook_is_mlib_browser_visible(GMedialib *gml) { return gml->notebook_mlib_browser; } gboolean gml_notebook_is_mlib_add_files_visible(GMedialib *gml) { return gml->notebook_mlib_add_files; } gboolean gml_notebook_is_playlists_visible(GMedialib *gml) { return gml->notebook_playlists; } gboolean gml_notebook_is_playlist_visible(GMedialib *gml) { return gml->notebook_playlist; } static void gml_create_notebook(GMedialib *gml) { GdkPixbuf *icon; if (gml->notebook_mlib_search) { gml_create_mlib_search(gml); gml->image_mlib_search = gtk_image_new_from_stock(GTK_STOCK_FIND, GTK_ICON_SIZE_MENU); gml->label_mlib_search = gtk_label_new_with_mnemonic("MLib _Search"); gml->hbox_mlib_search = gtk_hbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(gml->hbox_mlib_search), gml->image_mlib_search, FALSE, FALSE, 3); gtk_box_pack_start(GTK_BOX(gml->hbox_mlib_search), gml->label_mlib_search, FALSE, FALSE, 3); gtk_widget_show_all(gml->hbox_mlib_search); gtk_notebook_append_page(GTK_NOTEBOOK(gml->notebook), gml->search.frame, gml->hbox_mlib_search); } if (gml->notebook_mlib_browser) { gml_create_mlib_browser(gml); icon = gdk_pixbuf_new_from_xpm_data((const char **)browser_xpm); gml->image_mlib_browse = gtk_image_new_from_pixbuf(icon); gml->label_mlib_browse = gtk_label_new_with_mnemonic("MLib _Browser"); gml->hbox_mlib_browse = gtk_hbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(gml->hbox_mlib_browse), gml->image_mlib_browse, FALSE, FALSE, 3); gtk_box_pack_start(GTK_BOX(gml->hbox_mlib_browse), gml->label_mlib_browse, FALSE, FALSE, 3); gtk_widget_show_all(gml->hbox_mlib_browse); gtk_notebook_append_page(GTK_NOTEBOOK(gml->notebook), gml->browser.frame, gml->hbox_mlib_browse); } if (gml->notebook_mlib_add_files) { gml_create_mlib_add_files(gml); gml->image_mlib_add_files = gtk_image_new_from_stock(GTK_STOCK_OPEN, GTK_ICON_SIZE_MENU); gml->label_mlib_add_files = gtk_label_new_with_mnemonic("MLib _Add files"); gml->hbox_mlib_add_files = gtk_hbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(gml->hbox_mlib_add_files), gml->image_mlib_add_files, FALSE, FALSE, 3); gtk_box_pack_start(GTK_BOX(gml->hbox_mlib_add_files), gml->label_mlib_add_files, FALSE, FALSE, 3); gtk_widget_show_all(gml->hbox_mlib_add_files); gtk_notebook_append_page(GTK_NOTEBOOK(gml->notebook), gml->addfiles.frame, gml->hbox_mlib_add_files); } if (gml->notebook_playlists) { gml_create_playlists(gml); icon = gdk_pixbuf_new_from_xpm_data((const char **)playlists_xpm); gml->image_playlists = gtk_image_new_from_pixbuf(icon); gml->label_playlists = gtk_label_new_with_mnemonic("Pla_ylists"); gml->hbox_playlists = gtk_hbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(gml->hbox_playlists), gml->image_playlists, FALSE, FALSE, 3); gtk_box_pack_start(GTK_BOX(gml->hbox_playlists), gml->label_playlists, FALSE, FALSE, 3); gtk_widget_show_all(gml->hbox_playlists); gtk_notebook_append_page(GTK_NOTEBOOK(gml->notebook), gml->playlists.frame, gml->hbox_playlists); } if (gml->notebook_playlist) { gml_create_playlist(gml); gml->image_playlist = gtk_image_new_from_stock(GTK_STOCK_MEDIA_PLAY, GTK_ICON_SIZE_MENU); gml->label_playlist = gtk_label_new_with_mnemonic("_Playlist"); gml->hbox_playlist = gtk_hbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(gml->hbox_playlist), gml->image_playlist, FALSE, FALSE, 3); gtk_box_pack_start(GTK_BOX(gml->hbox_playlist), gml->label_playlist, FALSE, FALSE, 3); gtk_widget_show_all(gml->hbox_playlist); gtk_notebook_append_page(GTK_NOTEBOOK(gml->notebook), gml->playlist.frame, gml->hbox_playlist); } gtk_widget_show_all(GTK_WIDGET(gml)); } static void gmedialib_init(GMedialib *gml) { gml->renderer_text = gtk_cell_renderer_text_new(); gml->renderer_text_ellipsize = gtk_cell_renderer_text_new(); g_object_set(gml->renderer_text_ellipsize, "ellipsize", PANGO_ELLIPSIZE_END, "ellipsize-set", TRUE, NULL); gtk_window_set_title(GTK_WINDOW(gml), "Playlist Editor"); gtk_window_set_modal(GTK_WINDOW(gml), FALSE); gml->notebook = gtk_notebook_new(); gtk_box_pack_start(GTK_BOX(GTK_DIALOG(gml)->vbox), gml->notebook, TRUE, TRUE, 0); /* statusbar */ gml->statusbar = gtk_statusbar_new(); gtk_statusbar_set_has_resize_grip(GTK_STATUSBAR(gml->statusbar), FALSE); gml->statusbar_id = gtk_statusbar_get_context_id( GTK_STATUSBAR(gml->statusbar), "default"); gtk_box_pack_start(GTK_BOX(GTK_DIALOG(gml)->vbox), gml->statusbar, FALSE, FALSE, 0); gtk_statusbar_push(GTK_STATUSBAR(gml->statusbar), gml->statusbar_id, "Ready"); /* close button */ gml->button_close = gtk_button_new_from_stock(GTK_STOCK_CLOSE); gtk_box_pack_start(GTK_BOX(GTK_DIALOG(gml)->action_area), gml->button_close, TRUE, TRUE, 0); /* signals */ g_signal_connect(G_OBJECT(gml->button_close), "clicked", G_CALLBACK(cb_close_medialib_dialog), (gpointer)gml); g_signal_connect(G_OBJECT(gml), "delete_event", G_CALLBACK(cb_delete_event), (gpointer)gml); g_signal_connect(G_OBJECT(gml), "configure_event", G_CALLBACK(cb_configure_event), (gpointer)gml); g_signal_connect(G_OBJECT(gml->notebook), "key-press-event", G_CALLBACK(cb_key_press), (gpointer)gml); gtk_widget_set_size_request(GTK_WIDGET(gml), 540, 360); gtk_widget_show_all(GTK_WIDGET(gml)); gml_setup_xmms_callbacks(gml); gml->font_size = -1; /* default */ gml->album_tracknr_digits = 2; } GtkWidget* gmedialib_new(gboolean search, gboolean browser, gboolean add_files, gboolean playlists, gboolean playlist) { GMedialib *gml = g_object_new(gmedialib_get_type(), NULL); gml->notebook_mlib_search = search; gml->notebook_mlib_browser = browser; gml->notebook_mlib_add_files = add_files; gml->notebook_playlists = playlists; gml->notebook_playlist = playlist; gml_create_notebook(gml); if (gml->notebook_playlist) gml_pl_refresh_playlist(gml); if (gml->notebook_mlib_browser) gml_mlib_browse_update_artists(gml); if (gml->notebook_playlists) gml_playlists_update_playlists(gml); return GTK_WIDGET(gml); } gxmms2-0.7.1/gmedialib/gmladdfiles.c0000644000175000017500000001002711427740422015767 0ustar wejpwejp/* * File: gmladdfiles.c * * Medialib search and playlist editor * Copyright (c) 2005-2010 Johannes Heimansberg * * requires GTK+ 2.6 or better and XMMS2 * * Released under the GNU General Public License v2 */ #include #include #include #include #include #include "gmedialib.h" #include "gtrackinfo/trackinfo.h" #include "gtrackinfo/gtrackinfo.h" #include "sdecode/sdecode.h" extern xmmsc_connection_t *connection; /* available from gxmms2.c */ static int n_playlist_added(xmmsv_t *val, void *arg) { GMedialib *gml = (GMedialib *)arg; char const *xerr = "Playlist imported successfully.\n"; xmmsv_get_error(val, &xerr); gml_set_statusbar_text(gml, (gchar *) xerr); return FALSE; } static int n_idlist_from_playlist_file(xmmsv_t *val, void *arg) { xmmsc_result_t *res2; xmmsc_coll_t *coll; xmmsv_t *order_v; char *order[] = { "id", NULL }; char const *xerr; if (xmmsv_get_error(val, &xerr)) printf("%s\n", xerr); if (!xmmsv_get_coll(val, &coll)) printf("Couldn't get collection from result!\n"); order_v = xmmsv_make_stringlist(order, 1); res2 = xmmsc_playlist_add_collection(connection, NULL, coll, order_v); xmmsv_unref(order_v); xmmsc_result_notifier_set(res2, n_playlist_added, arg); xmmsc_result_unref(res2); return FALSE; } static void cb_add_files(GtkWidget *widget, gpointer pt) { GMedialib *gml = GMEDIALIB(pt); GSList *filelist = NULL; GSList *item = NULL; xmmsc_result_t *res; gchar *fname, *url = NULL; gml_set_statusbar_text(gml, "Adding files to the media library (this may take a while)..."); filelist = gtk_file_chooser_get_uris(GTK_FILE_CHOOSER(gml->addfiles.file_selector)); item = filelist; while (item != NULL) { fname = g_filename_from_uri((gchar *)item->data, NULL, NULL); if (fname != NULL) { url = g_malloc(strlen(fname) + 8); snprintf(url, strlen(fname) + 8, "file://%s", fname); if (g_file_test((fname), G_FILE_TEST_IS_DIR)) { /* directory */ res = xmmsc_medialib_import_path(connection, url); } else { /* file */ if (memcmp(url+(strlen(url)-4), ".pls", 4) == 0 || memcmp(url+(strlen(url)-4), ".m3u", 4) == 0) { res = xmmsc_coll_idlist_from_playlist_file(connection, url); xmmsc_result_notifier_set(res, n_idlist_from_playlist_file, gml); } else { res = xmmsc_medialib_add_entry(connection, url); } } xmmsc_result_unref(res); g_free(fname); g_free(url); } g_free(item->data); item = item->next; } g_slist_free(filelist); } void gml_create_mlib_add_files(GMedialib *gml) { GtkWidget *table; GtkTooltips *tooltips; gml->addfiles.frame = gtk_frame_new("MLib Add files"); gtk_container_set_border_width(GTK_CONTAINER(gml->addfiles.frame), 2); /* table */ table = gtk_table_new(2, 1, FALSE); gtk_container_set_border_width(GTK_CONTAINER(table), 3); gtk_table_set_row_spacings(GTK_TABLE(table), 4); gtk_table_set_col_spacings(GTK_TABLE(table), 4); gtk_container_add(GTK_CONTAINER(gml->addfiles.frame), table); gml->addfiles.file_selector = gtk_file_chooser_widget_new(GTK_FILE_CHOOSER_ACTION_OPEN); gtk_file_chooser_set_select_multiple( GTK_FILE_CHOOSER(gml->addfiles.file_selector), TRUE); gtk_table_attach(GTK_TABLE(table), gml->addfiles.file_selector, 0, 1, 0, 1, GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, 0, 0); /* add button */ gml->addfiles.button_add = gtk_button_new_from_stock(GTK_STOCK_ADD); gtk_table_attach(GTK_TABLE(table), gml->addfiles.button_add, 0, 1, 1, 2, GTK_SHRINK, GTK_SHRINK, 0, 0); /* tooltips */ tooltips = gtk_tooltips_new(); gtk_tooltips_set_tip(tooltips, gml->addfiles.button_add, "Add selected files/directories to the medialib", NULL); g_signal_connect(G_OBJECT(gml->addfiles.button_add), "clicked", G_CALLBACK(cb_add_files), (gpointer)gml); } gxmms2-0.7.1/gmedialib/rank2.xpm0000644000175000017500000000212510601276546015117 0ustar wejpwejp/* XPM */ static char * rank2_xpm[] = { "48 16 15 1", " c None", ". c #000000", "+ c #EEF63E", "@ c #EAF13D", "# c #F0F83F", "$ c #CBD235", "% c #E9F03D", "& c #E5EC3C", "* c #E8F03D", "= c #ABB02D", "- c #ECF33E", "; c #EFF73F", "> c #CED636", ", c #B4BA2F", "' c #CDD435", " ", " ", " ", " ", " . . . . ", " .+. .+. . . . . ", " ..@#$.. ..@#$.. .. .. .. .. ", " .######%. .######%. . . . . ", " .####&. .####&. . . . . ", " .*###=. .*###=. . . . . ", " .#-.;>. .#-.;>. . . . . . . ", " .,. .'. .,. .'. . . . . . . . . ", " . . . . . . . . ", " ", " ", " "}; gxmms2-0.7.1/gmedialib/gmlsearch.h0000644000175000017500000000202510672033732015465 0ustar wejpwejp/* * File: gmlsearch.h * * Medialib search and playlist editor * Copyright (c) 2005 Johannes Heimansberg * * requires GTK+ 2.6 or better and XMMS2 DR2 or better * * Released under the GNU General Public License v2 */ #ifndef __GMLSEARCH_H__ #define __GMLSEARCH_H__ #include struct _GMLSearch { GtkWidget *frame, *table; GtkWidget *list_results, *scroll_widget; GtkWidget *entry_searchstring; GtkWidget *label_search; GtkWidget *checkbutton_exact, *button_search, *image_search; GtkWidget *button_add, *search_combo; GtkListStore *ls; GtkTreeViewColumn *column_id; GtkTreeViewColumn *column_artist, *column_track; GtkTreeViewColumn *column_album, *column_rating; gboolean column_id_visible; gboolean column_artist_visible, column_track_visible; gboolean column_album_visible, column_rating_visible; gchar *last_search_str; gint last_category; gboolean last_exact; }; #endif gxmms2-0.7.1/gmedialib/playlists.xpm0000644000175000017500000000066310601276546016133 0ustar wejpwejp/* XPM */ static char * playlists_xpm[] = { "16 16 4 1", " c None", ". c #000000", "+ c #FFFFFF", "@ c #C7C7C7", " ....... ", " .+++++.. ", " .......++.@. ", " .+++++..+....", ".......++.@.+++.", ".+++++..+....++.", ".+++++.@.+++.++.", ".+++++....++.++.", ".++++++++.++..+.", ".+..++.++.++.++.", ".+.+.+.++..+.++.", ".+..++.++.++....", ".+.+++..+.++. ", ".++++++++.... ", ".++++++++. ", ".......... "}; gxmms2-0.7.1/gmedialib/gmlbrowser.h0000644000175000017500000000120710717125157015707 0ustar wejpwejp/* * File: gmlbrowser.h * * Medialib search and playlist editor * Copyright (c) 2005-2007 Johannes Heimansberg * * requires GTK+ 2.6 or better and XMMS2 * * Released under the GNU General Public License v2 */ #ifndef __GMLBROWSER_H__ #define __GMLBROWSER_H__ #include struct _GMLBrowser { GtkWidget *frame, *table; GtkWidget *button_refresh, *image_refresh; GtkWidget *button_rehash, *image_rehash; GtkWidget *button_expand_all, *image_expand_all; GtkWidget *button_collapse_all, *image_collapse_all; GtkWidget *list, *scroll_widget; GtkWidget *button_search; GtkTreeStore *ts; }; #endif gxmms2-0.7.1/gmedialib/shuffle.xpm0000644000175000017500000000174410601276546015544 0ustar wejpwejp/* XPM */ static char * shuffle_xpm[] = { "24 24 18 1", " c None", ". c #424242", "+ c #BEBEBE", "@ c #000000", "# c #BFBFBF", "$ c #0A0A0A", "% c #494949", "& c #FFFFFF", "* c #E3E3E3", "= c #F8F8F8", "- c #F9F9F9", "; c #E9E9E9", "> c #131313", ", c #A8A8A8", "' c #F7F7F7", ") c #E0E0E0", "! c #D3D3D3", "~ c #F6F6F6", " ", " ", " .+ ", " @.# ", " @@$@@@@@@@@%& ", " @@&&&&&&&&@@& ", " @& @& ", " @& & ", " @& * ", " @& @@@@@@@@@@= ", " @& &&&&&&&& @@- ", " @& @& ", " @; @& ", " @>, @& ", " @$@@@@@@@@& @& ", " &&&&&&&&&& @& ", " @& ", " @' @& ", " @@) @@& ", " !@@@@@@@@@@@@~& ", " &@@&&&&&&&&& ", " &@& ", " && ", " "}; gxmms2-0.7.1/gmedialib/sqlhelper.c0000644000175000017500000000073110601276546015520 0ustar wejpwejpstatic gchar *mask_sql_quotes(gchar *string) { int i, j; gchar *result = g_malloc((strlen(string) + 1) * 2 * sizeof(gchar)); /* mask sql single quotes ' with '' : */ for (i = 0, j = 0; i < strlen(string); i++) { if (string[i] == '\'') { result[j] = '\''; result[j+1] = '\''; j+=2; } else if (string[i] == '\"') { result[j] = '\"'; result[j+1] = '\"'; j+=2; } else { result[j] = string[i]; j++; } } result[j] = '\0'; return result; } gxmms2-0.7.1/gmedialib/browser.xpm0000644000175000017500000000064210601276546015567 0ustar wejpwejp/* XPM */ static char * browser_xpm[] = { "16 16 3 1", " c None", ". c #000000", "+ c #C7C7C7", " ", " .... ", " .+ .+ ", " .+ .+ ", " ....+... ", " .++.+.++. ", " .+ .+. .+ ", " ++ ++...++ .. ", " .++. .++. ", " . .+.+ ++", " ...++.+ ", " +++ .+ ", " .+ . ", " ..++", " ++ ", " "}; gxmms2-0.7.1/gmedialib/gmlbrowser.c0000644000175000017500000003332711213135526015703 0ustar wejpwejp/* * File: gmlbrowser.c * * Medialib search and playlist editor * Copyright (c) 2005-2007 Johannes Heimansberg * * requires GTK+ 2.6 or better and XMMS2 * * Released under the GNU General Public License v2 */ #include #include #include #include #include #include "gmedialib.h" #include "gtrackinfo/trackinfo.h" #include "gtrackinfo/gtrackinfo.h" extern xmmsc_connection_t *connection; /* available from gxmms2.c */ static void cb_browser_artist_activated(GtkTreeView *view, GtkTreePath *path, GtkTreeViewColumn *col, gpointer userdata) { GtkTreeIter iter; GtkTreeModel *model; GMedialib *gml = (GMedialib *)userdata; model = gtk_tree_view_get_model(view); if (gtk_tree_model_get_iter(model, &iter, path)) { gchar *search_str = "Unknown"; gtk_tree_model_get(model, &iter, 0, &search_str, -1); if (gml_notebook_is_mlib_search_visible(GMEDIALIB(gml))) { if (gtk_tree_model_iter_has_child(model, &iter)) { /* Artist */ gml_search_do_search(gml, SEARCH_ARTIST, search_str); } else { gml_search_do_search(gml, SEARCH_ALBUM, search_str); } gtk_notebook_set_current_page(GTK_NOTEBOOK(gml->notebook), 0); } g_free(search_str); } } static void cb_browser_button_search_pressed(GtkWidget *widget, gpointer pt) { GMedialib *gml = (GMedialib *)pt; GtkTreeSelection *sel; GtkTreeModel *model; GtkTreeIter selected_row; sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(gml->browser.list)); g_assert(gtk_tree_selection_get_mode(sel) == GTK_SELECTION_SINGLE); if (gtk_tree_selection_get_selected(sel, &model, &selected_row)) { gchar *search_str; gtk_tree_model_get(model, &selected_row, 0, &search_str, -1); if (gml_notebook_is_mlib_search_visible(GMEDIALIB(gml))) { if (gtk_tree_model_iter_has_child(model, &selected_row)) { /* Artist */ gml_search_do_search(gml, SEARCH_ARTIST, search_str); } else { gml_search_do_search(gml, SEARCH_ALBUM, search_str); } gtk_notebook_set_current_page(GTK_NOTEBOOK(gml->notebook), 0); } g_free(search_str); } } static void cb_browser_refresh_pressed(GtkWidget *widget, gpointer pt) { GMedialib *gml = (GMedialib *)pt; gml_mlib_browse_update_artists(gml); } static int n_rehash(xmmsv_t *val, void *userdata) { GMedialib *gml = (GMedialib *)userdata; gml_mlib_browse_update_artists(gml); return FALSE; } static void cb_browser_rehash_pressed(GtkWidget *widget, gpointer pt) { xmmsc_result_t *res = xmmsc_medialib_rehash(connection, 0); xmmsc_result_notifier_set(res, n_rehash, pt); xmmsc_result_unref(res); } static void cb_browser_expand_all_pressed(GtkWidget *widget, gpointer pt) { GMedialib *gml = (GMedialib *)pt; gtk_tree_view_expand_all(GTK_TREE_VIEW(gml->browser.list)); } static void cb_browser_collapse_all_pressed(GtkWidget *widget, gpointer pt) { GMedialib *gml = (GMedialib *)pt; gtk_tree_view_collapse_all(GTK_TREE_VIEW(gml->browser.list)); } static void browser_view_popup_menu(GtkWidget *treeview, GdkEventButton *event, gpointer userdata) { GtkWidget *menu, *menuitem; GtkTreeSelection *selection; GMedialib *gml = (GMedialib *)userdata; gboolean multiple = FALSE, none = FALSE; selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(gml->browser.list)); if (gtk_tree_selection_count_selected_rows(selection) > 1) multiple = TRUE; if (gtk_tree_selection_count_selected_rows(selection) == 0) none = TRUE; menu = gtk_menu_new(); menuitem = gtk_image_menu_item_new_from_stock(GTK_STOCK_FIND, NULL); if (multiple || none || !gml_notebook_is_mlib_search_visible(GMEDIALIB(gml))) gtk_widget_set_sensitive(menuitem, FALSE); g_signal_connect(menuitem, "activate", G_CALLBACK(cb_browser_button_search_pressed), userdata); gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); gtk_widget_show_all(menu); gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, (event != NULL) ? event->button : 0, gdk_event_get_time((GdkEvent*)event)); } static gboolean cb_browser_selection_button_press(GtkWidget *treeview, GdkEventButton *event, gpointer userdata) { gboolean result = FALSE; if (event->type == GDK_BUTTON_PRESS && event->button == 3) { browser_view_popup_menu(treeview, event, userdata); result = TRUE; } return result; } static gboolean cb_browser_selection_popup_menu(GtkWidget *treeview, gpointer userdata) { browser_view_popup_menu(treeview, NULL, userdata); return TRUE; } static int n_update_artists(xmmsv_t *val, void *userdata) { GMedialib *gml = (GMedialib *)userdata; gchar artist_tmp[192] = "", album_tmp[192] = ""; GtkTreeIter iter; GtkTreeModel *model; xmmsv_list_iter_t *it; model = gtk_tree_view_get_model(GTK_TREE_VIEW(gml->browser.list)); /* Make sure the model stays with us after the tree view unrefs it */ g_object_ref(model); /* Detach model from view */ gtk_tree_view_set_model(GTK_TREE_VIEW(gml->browser.list), NULL); xmmsv_get_list_iter(val, &it); for (; xmmsv_list_iter_valid(it); xmmsv_list_iter_next(it)) { const gchar *artist = "Unknown"; const gchar *album = "Unknown"; gint id; xmmsv_t *entry; xmmsv_list_iter_entry(it, &entry); xmmsv_dict_entry_get_string(entry, "artist", &artist); xmmsv_dict_entry_get_string(entry, "album", &album); xmmsv_dict_entry_get_int(entry, "id", &id); if (g_ascii_strcasecmp(artist, artist_tmp) != 0) { g_strlcpy(artist_tmp, artist, sizeof(artist_tmp)); g_strlcpy(album_tmp, album, sizeof(artist_tmp)); if (gml->browser.ts != NULL) { GtkTreeIter child_iter; gtk_tree_store_append(gml->browser.ts, &iter, NULL); gtk_tree_store_set(gml->browser.ts, &iter, 0, artist, -1); /* add child */ gtk_tree_store_append(gml->browser.ts, &child_iter, &iter); gtk_tree_store_set(gml->browser.ts, &child_iter, 0, album, -1); } } else if (artist[0] != '\0' && g_ascii_strcasecmp(album, album_tmp) != 0) { GtkTreeIter child_iter; g_strlcpy(album_tmp, album, sizeof(artist_tmp)); /* add child */ gtk_tree_store_append(gml->browser.ts, &child_iter, &iter); gtk_tree_store_set(gml->browser.ts, &child_iter, 0, album, -1); } } /* Re-attach model to view */ gtk_tree_view_set_model(GTK_TREE_VIEW(gml->browser.list), model); g_object_unref(model); gml_set_statusbar_text(gml, "Ready."); return FALSE; } void gml_mlib_browse_update_artists(GMedialib *gml) { xmmsc_result_t *res; xmmsc_coll_t *universe; gchar *properties[] = { "artist", "album", NULL }; gchar *group_by[] = { "album", NULL }; xmmsv_t *properties_v, *group_by_v; gml_set_statusbar_text(gml, "Loading artists..."); if (gml->browser.ts != NULL) { gtk_tree_store_clear(gml->browser.ts); } universe = xmmsc_coll_universe(); properties_v = xmmsv_make_stringlist(properties, 2); group_by_v = xmmsv_make_stringlist(group_by, 1); res = xmmsc_coll_query_infos(connection, universe, properties_v, 0, 0, properties_v, group_by_v); xmmsv_unref(properties_v); xmmsv_unref(group_by_v); xmmsc_result_notifier_set(res, n_update_artists, gml); xmmsc_coll_unref(universe); xmmsc_result_unref(res); } void gml_create_mlib_browser(GMedialib *gml) { GtkTreeViewColumn *column_artist; GtkTooltips *tooltips; gml->browser.frame = gtk_frame_new("Media Lib"); gtk_container_set_border_width(GTK_CONTAINER(gml->browser.frame), 2); /* table mlib browser */ gml->browser.table = gtk_table_new(3, 4, FALSE); gtk_container_set_border_width(GTK_CONTAINER(gml->browser.table), 3); gtk_table_set_row_spacings(GTK_TABLE(gml->browser.table), 4); gtk_table_set_col_spacings(GTK_TABLE(gml->browser.table), 4); gtk_container_add(GTK_CONTAINER(gml->browser.frame), gml->browser.table); /* refresh button */ gml->browser.button_refresh = gtk_button_new(); gml->browser.image_refresh = gtk_image_new_from_stock(GTK_STOCK_REFRESH, GTK_ICON_SIZE_LARGE_TOOLBAR); gtk_button_set_relief(GTK_BUTTON(gml->browser.button_refresh), GTK_RELIEF_NONE); gtk_container_add(GTK_CONTAINER(gml->browser.button_refresh), gml->browser.image_refresh); gtk_table_attach(GTK_TABLE(gml->browser.table), gml->browser.button_refresh, 0, 1, 0, 1, GTK_SHRINK, GTK_SHRINK, 0, 0); /* expand all button */ gml->browser.button_expand_all = gtk_button_new(); gml->browser.image_expand_all = gtk_image_new_from_stock(GTK_STOCK_ADD, GTK_ICON_SIZE_LARGE_TOOLBAR); gtk_button_set_relief(GTK_BUTTON(gml->browser.button_expand_all), GTK_RELIEF_NONE); gtk_container_add(GTK_CONTAINER(gml->browser.button_expand_all), gml->browser.image_expand_all); gtk_table_attach(GTK_TABLE(gml->browser.table), gml->browser.button_expand_all, 1, 2, 0, 1, GTK_SHRINK, GTK_SHRINK, 0, 0); /* collapse all button */ gml->browser.button_collapse_all = gtk_button_new(); gml->browser.image_collapse_all = gtk_image_new_from_stock(GTK_STOCK_REMOVE, GTK_ICON_SIZE_LARGE_TOOLBAR); gtk_button_set_relief(GTK_BUTTON(gml->browser.button_collapse_all), GTK_RELIEF_NONE); gtk_container_add(GTK_CONTAINER(gml->browser.button_collapse_all), gml->browser.image_collapse_all); gtk_table_attach(GTK_TABLE(gml->browser.table), gml->browser.button_collapse_all, 2, 3, 0, 1, GTK_SHRINK, GTK_SHRINK, 0, 0); /* rehash button */ gml->browser.button_rehash = gtk_button_new(); gml->browser.image_rehash = gtk_image_new_from_stock(GTK_STOCK_EXECUTE, GTK_ICON_SIZE_LARGE_TOOLBAR); gtk_button_set_relief(GTK_BUTTON(gml->browser.button_rehash), GTK_RELIEF_NONE); gtk_container_add(GTK_CONTAINER(gml->browser.button_rehash), gml->browser.image_rehash); gtk_table_attach(GTK_TABLE(gml->browser.table), gml->browser.button_rehash, 3, 4, 0, 1, GTK_SHRINK, GTK_SHRINK, 0, 0); /* list artist browser */ gml->browser.ts = gtk_tree_store_new(1, G_TYPE_STRING); gml->browser.list = gtk_tree_view_new_with_model(GTK_TREE_MODEL(gml->browser.ts)); gtk_tree_view_set_enable_search(GTK_TREE_VIEW(gml->browser.list), TRUE); gml->browser.scroll_widget = gtk_scrolled_window_new(NULL, NULL); gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW(gml->browser.scroll_widget), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS); gtk_container_add(GTK_CONTAINER(gml->browser.scroll_widget), gml->browser.list); gtk_table_attach(GTK_TABLE(gml->browser.table), gml->browser.scroll_widget, 0, 4, 1, 2, GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, 0, 0); column_artist = gtk_tree_view_column_new_with_attributes("Artist", gml->renderer_text, "text", 0, NULL); gtk_tree_view_append_column(GTK_TREE_VIEW(gml->browser.list), column_artist); gtk_tree_view_column_set_resizable(column_artist, TRUE); gtk_tree_view_column_set_cell_data_func(column_artist, gml->renderer_text, gml_cell_data_function, gml, NULL); /* search button */ gml->browser.button_search = gtk_button_new_from_stock(GTK_STOCK_FIND); gtk_table_attach(GTK_TABLE(gml->browser.table), gml->browser.button_search, 0, 4, 2, 3, GTK_SHRINK, GTK_SHRINK, 0, 0); /* tooltips */ tooltips = gtk_tooltips_new(); gtk_tooltips_set_tip(tooltips, gml->browser.button_refresh, "Refresh browser view", NULL); gtk_tooltips_set_tip(tooltips, gml->browser.button_rehash, "Rehash media library", NULL); gtk_tooltips_set_tip(tooltips, gml->browser.button_expand_all, "Expand all", NULL); gtk_tooltips_set_tip(tooltips, gml->browser.button_collapse_all, "Collapse all", NULL); g_signal_connect(G_OBJECT(gml->browser.list), "row-activated", G_CALLBACK(cb_browser_artist_activated), (gpointer)gml); g_signal_connect(G_OBJECT(gml->browser.button_search), "clicked", G_CALLBACK(cb_browser_button_search_pressed), (gpointer)gml); g_signal_connect(G_OBJECT(gml->browser.list), "button-press-event", G_CALLBACK(cb_browser_selection_button_press), (gpointer)gml); g_signal_connect(G_OBJECT(gml->browser.list), "popup-menu", G_CALLBACK(cb_browser_selection_popup_menu), (gpointer)gml); g_signal_connect(G_OBJECT(gml->browser.button_refresh), "clicked", G_CALLBACK(cb_browser_refresh_pressed), (gpointer)gml); g_signal_connect(G_OBJECT(gml->browser.button_rehash), "clicked", G_CALLBACK(cb_browser_rehash_pressed), (gpointer)gml); g_signal_connect(G_OBJECT(gml->browser.button_expand_all), "clicked", G_CALLBACK(cb_browser_expand_all_pressed), (gpointer)gml); g_signal_connect(G_OBJECT(gml->browser.button_collapse_all), "clicked", G_CALLBACK(cb_browser_collapse_all_pressed), (gpointer)gml); } gxmms2-0.7.1/gmedialib/gmlplaylist.c0000644000175000017500000020264111213135526016056 0ustar wejpwejp/* * File: gmlplaylist.c * * Medialib search and playlist editor * Copyright (c) 2005-2009 Johannes Heimansberg * * requires GTK+ 2.6 or better and XMMS2 * * Released under the GNU General Public License v2 */ #include #include #include #include #include #include #include "xmmsclient/xmmsclient.h" #include "gmedialib.h" #include "gtrackinfo/trackinfo.h" #include "gtrackinfo/gtrackinfo.h" #include "xmms2ctrl/xmms2ctrl.h" #include "sdecode/sdecode.h" #include "addrnd.xpm" #include "shuffle.xpm" #include "rank0.xpm" #include "rank1.xpm" #include "rank2.xpm" #include "rank3.xpm" #include "rank4.xpm" extern xmmsc_connection_t *connection; /* available from gxmms2.c */ static GdkAtom drag_atom; static void update_pl_entry(xmmsv_t *val, void *gmlptr, GtkTreeIter *iter, gint32 pos) { gint32 id; static gint32 last_pos = -2; GMedialib *gml = (GMedialib *)gmlptr; const gchar *url, *artist_tmp = NULL, *title_tmp = NULL, *channel; const gchar *album = "[Unknown Album]"; gchar *filename; gchar *artist = NULL, *title = NULL, *prefix = "", *url_utf8; gchar album_with_tracknr[256]; gint tracknr = -1, rating = -1; static gchar last_title[256] = "", last_artist[256] = ""; xmmsv_dict_entry_get_string(val, "artist", &artist_tmp); xmmsv_dict_entry_get_string(val, "title", &title_tmp); xmmsv_dict_entry_get_string(val, "album", &album); xmmsv_dict_entry_get_int(val, "id", &id); xmmsv_dict_entry_get_string(val, "url", &url); xmmsv_dict_entry_get_int(val, "tracknr", &tracknr); xmmsv_dict_entry_get_int(val, "rating", &rating); if (xmmsv_dict_entry_get_string(val, "channel", &channel)) { prefix = "[Stream] "; album = channel; } rating--; if (tracknr > 0 && gml->album_tracknr_digits > 0) if (gml->album_tracknr_digits >= 3) snprintf(album_with_tracknr, 256, "%s [%03d]", album, tracknr); else snprintf(album_with_tracknr, 256, "%s [%02d]", album, tracknr); else snprintf(album_with_tracknr, 256, "%s", album); if (url) { url_utf8 = decode_url(url); filename = g_path_get_basename(url_utf8); g_free(url_utf8); } else { filename = "[Unknown]"; } if (artist_tmp == NULL && channel == NULL) { artist = g_malloc(sizeof(gchar) * strlen(filename) + 1); g_strlcpy(artist, filename, sizeof(gchar) * strlen(filename) + 1); } else if (artist_tmp != NULL) { artist = g_malloc(sizeof(gchar) * (strlen(artist_tmp) + strlen(prefix) + 1)); g_snprintf(artist, strlen(artist_tmp) + strlen(prefix) + 1, "%s%s", prefix, artist_tmp); } else if (channel != NULL) { artist = g_malloc(sizeof(gchar) * (strlen(prefix) + 1)); g_snprintf(artist, strlen(prefix) + 1, "%s", prefix); } if (title_tmp == NULL) { title = g_malloc(sizeof(gchar) * strlen(filename) + 1); g_strlcpy(title, filename, sizeof(gchar) * strlen(filename) + 1); } else { title = g_malloc(sizeof(gchar) * strlen(title_tmp) + 1); g_strlcpy(title, title_tmp, sizeof(gchar) * strlen(title_tmp) + 1); } if (gml->playlist.ls != NULL && ( ( ((strcmp(title, last_title) != 0 || strcmp(artist, last_artist) != 0)) && (title[0] != '\0' || artist[0] != '\0') ) || pos != last_pos) ) { last_pos = pos; g_strlcpy(last_title, title, sizeof(last_title)); g_strlcpy(last_artist, artist, sizeof(last_artist)); if (gtk_list_store_iter_is_valid(gml->playlist.ls, iter)) { gtk_list_store_set(gml->playlist.ls, iter, 1, id, 2, artist, 3, title, 4, album_with_tracknr, -1); if (rating >= 0 && rating <= 4) { gtk_list_store_set(gml->playlist.ls, iter, 5, gml->playlist.icon_rating[rating], -1); } else { gtk_list_store_set(gml->playlist.ls, iter, 5, NULL, -1); } } } g_free(artist); g_free(title); if (url) g_free(filename); } int gml_playlist_n_add_track_with_info(xmmsv_t *val, void *gmlptr) { static const char *pref[] = { "client/generic", "server", "plugins/*", "client/*", "*", NULL }; guint pos; gint32 id; static GtkTreeIter iter; GMedialib *gml = (GMedialib *)gmlptr; xmmsv_t *info; pos = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(gml->playlist.ls), NULL); info = xmmsv_propdict_to_dict(val, pref); xmmsv_dict_entry_get_int(info, "id", &id); if (gml->playlist.ls != NULL) { gtk_list_store_append(gml->playlist.ls, &iter); gtk_list_store_set(gml->playlist.ls, &iter, 0, pos, 1, id, -1); } update_pl_entry(info, gml, &iter, pos); if (gml->playlist.refresh == TRUE) { gml->playlist.refresh_counter--; if (gml->playlist.refresh_counter == 0) gml->playlist.refresh = FALSE; } xmmsv_unref(info); return FALSE; } static int n_pl_playlist_list(xmmsv_t *val, void *userdata) { GMedialib *gml = (GMedialib *)userdata; if (gml->playlist.refresh_counter == 0) { xmmsv_list_iter_t *it; gml->playlist.refresh = TRUE; xmmsv_get_list_iter(val, &it); for (; xmmsv_list_iter_valid(it); xmmsv_list_iter_next(it)) { xmmsv_t *entry; xmmsc_result_t *res2; gint i; xmmsv_list_iter_entry(it, &entry); if (!xmmsv_get_int(entry, &i)) printf("Broken result\n"); gml->playlist.refresh_counter++; res2 = xmmsc_medialib_get_info(connection, i); xmmsc_result_notifier_set(res2, gml_playlist_n_add_track_with_info, gml); xmmsc_result_unref(res2); } } gml_set_statusbar_text(gml, "Ready."); return FALSE; } void gml_pl_refresh_playlist(GMedialib *gml) { xmmsc_result_t *res; if (gml->playlist.refresh_counter == 0) { gml_set_statusbar_text(gml, "Loading playlist..."); if (gml->playlist.ls != NULL) { gtk_list_store_clear(gml->playlist.ls); } res = xmmsc_playlist_list_entries(connection, "_active"); xmmsc_result_notifier_set(res, n_pl_playlist_list, gml); xmmsc_result_unref(res); } } static int n_pl_update_current_pos(xmmsv_t *val, void *arg) { gint pos = 0; GMedialib *gml = (GMedialib *)arg; xmmsv_dict_entry_get_int(val, "position", &pos); gml->playlist.current_pos = pos; if (gml->playlist.move_finished) gml_playlist_update_entry(gml, gml->playlist.current_pos); gtk_widget_queue_draw(gml->playlist.list); return FALSE; } static int bc_handle_current_id(xmmsv_t *val, void *userdata) { xmmsc_result_t *res2; res2 = xmmsc_playlist_current_pos(connection, NULL); xmmsc_result_notifier_set(res2, n_pl_update_current_pos, userdata); xmmsc_result_unref(res2); return TRUE; } static int bc_handle_medialib_entry_changed(xmmsv_t *val, void *gmlptr) { GMedialib *gml = GMEDIALIB(gmlptr); if (gml->playlist.move_finished) gml_playlist_update_entry(gml, gml->playlist.current_pos); return TRUE; } static int bc_handle_playlist_changed(xmmsv_t *val, void *gmlptr) { GMedialib *gml = GMEDIALIB(gmlptr); gint id, signal, pl_length, pos_del = -1, pos_ins = -1, pos = -1; guint counter; GtkTreeIter iter; GtkTreeModel *model; /* get playlist length */ pl_length = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(gml->playlist.ls), NULL); xmmsv_dict_entry_get_int(val, "type", &signal); switch (signal) { case XMMS_PLAYLIST_CHANGED_ADD: xmmsv_dict_entry_get_int(val, "id", &id); /* add item to gtk list */ if (gml->playlist.ls != NULL) { gtk_list_store_append(gml->playlist.ls, &iter); gtk_list_store_set(gml->playlist.ls, &iter, 0, pl_length, 1, id, -1); gml_playlist_update_entry(gml, pl_length); } break; case XMMS_PLAYLIST_CHANGED_INSERT: xmmsv_dict_entry_get_int(val, "id", &id); xmmsv_dict_entry_get_int(val, "position", &pos_ins); if (gml->playlist.ls != NULL) { gtk_list_store_insert(gml->playlist.ls, &iter, pos_ins); gtk_list_store_set(gml->playlist.ls, &iter, 0, pos_ins, 1, id, -1); gml_playlist_update_entry(gml, pos_ins); counter = pos_ins; model = GTK_TREE_MODEL(gml->playlist.ls); do { gtk_tree_model_get(model, &iter, 0, &pos, -1); gtk_list_store_set(gml->playlist.ls, &iter, 0, counter, -1); counter++; } while (gtk_tree_model_iter_next(model, &iter)); } break; case XMMS_PLAYLIST_CHANGED_SHUFFLE: case XMMS_PLAYLIST_CHANGED_SORT: gml_pl_refresh_playlist(gml); break; case XMMS_PLAYLIST_CHANGED_REMOVE: xmmsv_dict_entry_get_int(val, "position", &pos_del); if (gml->playlist.ls != NULL) { model = GTK_TREE_MODEL(gml->playlist.ls); if (gtk_tree_model_get_iter_first(model, &iter)) { gboolean flag = FALSE; counter = 0; do { gtk_tree_model_get(model, &iter, 0, &pos, -1); if (pos == pos_del) { flag = TRUE; gtk_list_store_remove(GTK_LIST_STORE(model), &iter); counter = pos; if (pos == pl_length - 1) break; } if (flag) { gtk_list_store_set(gml->playlist.ls, &iter, 0, counter, -1); counter++; } } while (gtk_tree_model_iter_next(model, &iter)); } } break; case XMMS_PLAYLIST_CHANGED_CLEAR: if (gml->playlist.ls != NULL) gtk_list_store_clear(gml->playlist.ls); break; case XMMS_PLAYLIST_CHANGED_MOVE: break; } return TRUE; } static void view_selected_foreach_func(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer userdata) { gint pos; gtk_tree_model_get(model, iter, 0, &pos, -1); *(gint *)userdata = pos; } /* returns the playlist position of the selected row (or -1 if more or less than one row is selected) */ gint gml_pl_get_selected_pos(GMedialib *gml) { GtkTreeSelection *selection; gint pos = -1; selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(gml->playlist.list)); /* exactly 1 row selected */ if (gtk_tree_selection_count_selected_rows(selection) == 1) { gtk_tree_selection_selected_foreach(selection, view_selected_foreach_func, &pos); } return pos; } static void update_current_pl_pos(GMedialib *gml) { xmmsc_result_t *res; res = xmmsc_playlist_current_pos(connection, NULL); xmmsc_result_notifier_set(res, n_pl_update_current_pos, gml); xmmsc_result_unref(res); } static void pl_cell_data_function(GtkTreeViewColumn *col, GtkCellRenderer *renderer, GtkTreeModel *model, GtkTreeIter *iter, gpointer userdata) { GMedialib *gml = GMEDIALIB(userdata); guint pos = 0; guint cur_pos = (guint)gml->playlist.current_pos; gtk_tree_model_get(model, iter, 0, &pos, -1); if (pos == cur_pos) g_object_set(renderer, "weight", PANGO_WEIGHT_BOLD, "weight-set", TRUE, NULL); else g_object_set(renderer, "weight-set", FALSE, NULL); } static int n_tickle(xmmsv_t *val, void *userdata) { GMedialib *gml = (GMedialib *)userdata; char const *xerr; if (xmmsv_get_error(val, &xerr)) { gchar buffer[128]; snprintf(buffer, 128, "ERROR: Couldn't jump to that song: %s", xerr); gml_set_statusbar_text(gml, buffer); } else { xmms2ctrl_play(connection); gml_set_statusbar_text(gml, "Ready."); } return FALSE; } static int n_jump_to_track(xmmsv_t *val, void *userdata) { GMedialib *gml = (GMedialib *)userdata; char const *xerr; if (xmmsv_get_error(val, &xerr)) { gchar buffer[128]; snprintf(buffer, 128, "ERROR: Couldn't jump to that song: %s", xerr); gml_set_statusbar_text(gml, buffer); } else { xmmsc_result_t *res2; res2 = xmmsc_playback_tickle(connection); xmmsc_result_notifier_set(res2, n_tickle, userdata); xmmsc_result_unref(res2); } return FALSE; } static void cb_pl_on_tree_view_row_activated(GtkTreeView *view, GtkTreePath *path, GtkTreeViewColumn *col, gpointer userdata) { GtkTreeIter iter; GtkTreeModel *model; xmmsc_result_t *res; model = gtk_tree_view_get_model(view); if (gtk_tree_model_get_iter(model, &iter, path)) { guint pos; gtk_tree_model_get(model, &iter, 0, &pos, -1); /* jump to track */ res = xmmsc_playlist_set_next(connection, pos); xmmsc_result_notifier_set(res, n_jump_to_track, userdata); xmmsc_result_unref(res); } } enum { UP = -1, DOWN = 1 }; struct params_2 { GMedialib *gml; guint direction; }; static int n_playlist_move(xmmsv_t *val, void *arguments) { struct params_2 *p = (struct params_2 *)arguments; GtkTreeSelection *sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(p->gml->playlist.list)); GtkTreeModel *model = GTK_TREE_MODEL(p->gml->playlist.ls); GList *list = gtk_tree_selection_get_selected_rows(sel, &model); GtkTreePath *path = list->data; GtkTreeIter selected_row, other_row; guint pos, id, other_pos, other_id; gchar *artist = NULL, *track = NULL, *album = NULL; gchar *other_artist = NULL, *other_track = NULL; gchar *other_album = NULL; GdkPixbuf *icon_rank, *icon_other_rank; char const *xerr; gtk_tree_model_get_iter(GTK_TREE_MODEL(p->gml->playlist.ls), &selected_row, path); gtk_tree_model_get(model, &selected_row, 0, &pos, 1, &id, 2, &artist, 3, &track, 4, &album, 5, &icon_rank, -1); if (xmmsv_get_error(val, &xerr)) { gchar buf[128]; snprintf(buf, 128, "Unable to move playlist entry: %s", xerr); gml_set_statusbar_text(p->gml, buf); } else { if (p->direction == DOWN) gtk_tree_path_next(path); else gtk_tree_path_prev(path); gtk_tree_model_get_iter(GTK_TREE_MODEL(p->gml->playlist.ls), &other_row, path); if (p->direction == DOWN) gtk_tree_path_prev(path); else gtk_tree_path_next(path); gtk_tree_model_get_iter(GTK_TREE_MODEL(p->gml->playlist.ls), &selected_row, path); gtk_tree_model_get(model, &other_row, 0, &other_pos, 1, &other_id, 2, &other_artist, 3, &other_track, 4, &other_album, 5, &icon_other_rank, -1); gtk_list_store_set(p->gml->playlist.ls, &selected_row, 0, pos, 1, other_id, 2, other_artist, 3, other_track, 4, other_album, 5, icon_other_rank, -1); gtk_list_store_set(p->gml->playlist.ls, &other_row, 0, other_pos, 1, id, 2, artist, 3, track, 4, album, 5, icon_rank, -1); if (p->direction == DOWN) gtk_tree_path_next(path); else gtk_tree_path_prev(path); gtk_tree_view_set_cursor(GTK_TREE_VIEW(p->gml->playlist.list), path, NULL, FALSE); gtk_widget_grab_focus(GTK_WIDGET(p->gml->playlist.list)); gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(p->gml->playlist.list), path, NULL, TRUE, 0.5, 0.5); g_free(artist); g_free(track); gml_set_statusbar_text(p->gml, "Ready."); } p->gml->playlist.move_finished = TRUE; g_list_foreach(list, (GFunc)gtk_tree_path_free, NULL); g_list_free(list); update_current_pl_pos(p->gml); g_free(p); return FALSE; } static void pl_move_item(GMedialib *gml, guint direction) { xmmsc_result_t *res; struct params_2 *p = g_malloc(sizeof(struct params_2)); GtkTreeSelection *sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(gml->playlist.list)); GtkTreeModel *model = GTK_TREE_MODEL(gml->playlist.ls); GtkTreeIter selected_row; GList *list = gtk_tree_selection_get_selected_rows(sel, &model); GtkTreePath *path = list->data; guint cnt = gtk_tree_selection_count_selected_rows(sel); guint pos; if (cnt == 1 && gml->playlist.move_finished) { /* exactly one row selected */ gml->playlist.move_finished = FALSE; p->gml = gml; p->direction = direction; gtk_tree_model_get_iter(GTK_TREE_MODEL(p->gml->playlist.ls), &selected_row, path); gtk_tree_model_get(model, &selected_row, 0, &pos, -1); g_list_foreach(list, (GFunc)gtk_tree_path_free, NULL); g_list_free(list); res = xmmsc_playlist_move_entry(connection, NULL, pos, pos + direction); xmmsc_result_notifier_set(res, n_playlist_move, p); xmmsc_result_unref(res); } } static int n_shuffle_or_sort_ready(xmmsv_t *val, void *userdata) { GMedialib *gml = (GMedialib *)userdata; update_current_pl_pos(gml); return FALSE; } static void cb_pl_shuffle_button_pressed(GtkWidget *widget, gpointer userdata) { GMedialib *gml = (GMedialib *)userdata; xmmsc_result_t *res; if (gml->playlist.refresh_counter == 0) { res = xmmsc_playlist_shuffle(connection, NULL); xmmsc_result_notifier_set(res, n_shuffle_or_sort_ready, userdata); xmmsc_result_unref(res); } } static void pl_sort_menu_pos_func(GtkMenu *menu, gint *x, gint *y, gboolean *push_in, gpointer userdata) { GMedialib *gml = (GMedialib *)userdata; GtkAllocation allocation = gml->playlist.button_sort_pl->allocation; gdk_window_get_origin(gml->playlist.button_sort_pl->window, x, y); *x += allocation.x; *y += allocation.y + allocation.height; } static gboolean cb_pl_sort_button_raw_pressed(GtkWidget *widget, GdkEventButton *event, gpointer userdata) { GMedialib *gml = (GMedialib *)userdata; gboolean res = FALSE; if (event->button == 1) { gtk_menu_popup( GTK_MENU(gml->playlist.menu_sort_pl), NULL, NULL, (GtkMenuPositionFunc) pl_sort_menu_pos_func, userdata, 3, event->time); res = TRUE; } return res; } static void cb_pl_sort_menu_activate(GtkMenuItem *menuitem, gpointer userdata) { xmmsc_result_t *res; gchar *sortby; xmmsv_t *sortprop; sortby = g_utf8_strdown( gtk_label_get_label(GTK_LABEL( gtk_bin_get_child(GTK_BIN(menuitem)))), -1); sortprop = xmmsv_make_stringlist(&sortby, 1); res = xmmsc_playlist_sort(connection, NULL, sortprop); xmmsv_unref(sortprop); g_free(sortby); xmmsc_result_notifier_set(res, n_shuffle_or_sort_ready, userdata); xmmsc_result_unref(res); } struct params_entry_update { GMedialib *gml; GtkTreeIter iter; gint32 pos; }; static int n_update_playlist_entry(xmmsv_t *val, void *arg) { struct params_entry_update *p = (struct params_entry_update *)arg; GtkTreeIter iter; char const *xerr; iter = p->iter; if (xmmsv_get_error(val, &xerr)) printf("%s\n", xerr); else { xmmsv_t *info = xmmsv_propdict_to_dict(val, NULL); update_pl_entry(info, p->gml, &iter, p->pos); xmmsv_unref(info); } g_free(p); return FALSE; } void gml_playlist_update_entry(GMedialib *gml, guint pos) { struct params_entry_update *p = g_malloc(sizeof(struct params_entry_update)); GtkTreeModel *model = GTK_TREE_MODEL(gml->playlist.ls); GtkTreeIter iter; guint poscnt = 0; p->gml = gml; if (gtk_tree_model_get_iter_first(model, &iter)) { do { gint id; xmmsc_result_t *res; gtk_tree_model_get(model, &iter, 1, &id, -1); if (pos == poscnt) { p->iter = iter; p->pos = pos; res = xmmsc_medialib_get_info(connection, id); xmmsc_result_notifier_set(res, n_update_playlist_entry, p); xmmsc_result_unref(res); } poscnt++; } while (gtk_tree_model_iter_next(model, &iter)); } } static int n_idlist_ready(xmmsv_t *val, void *pt) { xmmsc_result_t *res2; int i, j, cnt_item = 0, length, rnd[10]; xmmsv_list_iter_t *it; length = xmmsv_list_get_size(val); /* create ten random numbers between 0 and length: */ srand(time(NULL)); for (i = 0; i < 10; i++) rnd[i] = rand() % length; /* sort the random numbers: */ for (i = 0; i < 10; i++) for (j = 0; j < 10; j++) if (rnd[i] < rnd[j]) { int b = rnd[i]; rnd[i] = rnd[j]; rnd[j] = b; } i = 0; xmmsv_get_list_iter(val, &it); for (; xmmsv_list_iter_valid(it); xmmsv_list_iter_next(it)) { xmmsv_t *entry; gint id; xmmsv_list_iter_entry(it, &entry); if (!xmmsv_get_int(entry, &id)) { printf("gxmms2: Broken resultset.\n"); } if (cnt_item < 10 && i == rnd[cnt_item]) { res2 = xmmsc_playlist_add_id(connection, NULL, id); xmmsc_result_unref(res2); cnt_item++; } i++; } return FALSE; } static void cb_pl_add_rnd_button_pressed(GtkWidget *widget, gpointer userdata) { xmmsc_result_t *res; GMedialib *gml = (GMedialib *)userdata; xmmsc_coll_t *universe; gml_set_statusbar_text(gml, "Adding random songs..."); universe = xmmsc_coll_universe(); res = xmmsc_coll_query_ids(connection, universe, NULL, 0, 0); xmmsc_result_notifier_set(res, n_idlist_ready, userdata); xmmsc_result_unref(res); } static void cb_pl_reload_button_pressed(GtkWidget *widget, gpointer pt); static GList *selection_list = NULL; static void pl_delete_selection(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer userdata) { guint pos, *value; gtk_tree_model_get(model, iter, 0, &pos, -1); value = g_malloc(sizeof(guint)); *value = pos; selection_list = g_list_append(selection_list, (gpointer)value); } static gint comp_func(gconstpointer a, gconstpointer b) { return (*(guint *)a > *(guint *)b ? -1 : 1); } static int n_playlist_remove(xmmsv_t *val, void *arguments) { char const *xerr; if (xmmsv_get_error(val, &xerr)) { fprintf(stderr, "Couldn't remove item (%s)\n", xerr); } return FALSE; } static void cb_pl_button_delete_pressed(GtkWidget *widget, gpointer userdata) { GMedialib *gml = (GMedialib *)userdata; GtkTreeSelection *sel; GList *element; sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(gml->playlist.list)); gtk_tree_selection_selected_foreach(sel, pl_delete_selection, NULL); selection_list = g_list_sort(selection_list, comp_func); element = selection_list; while (element != NULL) { xmmsc_result_t *res; guint pos = *(guint *)(element->data); res = xmmsc_playlist_remove_entry(connection, NULL, pos); xmmsc_result_notifier_set(res, n_playlist_remove, NULL); xmmsc_result_unref(res); g_free(element->data); element = element->next; } g_list_free(selection_list); selection_list = NULL; update_current_pl_pos(gml); } static gboolean cb_pl_selection_key_press(GtkWidget *treeview, GdkEventKey *event, gpointer userdata) { gboolean result = FALSE; if (event->type == GDK_KEY_PRESS && (event->keyval == GDK_Delete || event->keyval == GDK_KP_Delete)) { cb_pl_button_delete_pressed(treeview, userdata); result = TRUE; } if (event->type == GDK_KEY_PRESS && event->state == GDK_MOD1_MASK) { switch (event->keyval) { case GDK_Up: pl_move_item((GMedialib *)userdata, UP); result = TRUE; break; case GDK_Down: pl_move_item((GMedialib *)userdata, DOWN); result = TRUE; break; } } return result; } static void pl_play_selection(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer userdata) { guint pos; xmmsc_result_t *res; gtk_tree_model_get(model, iter, 0, &pos, -1); /* jump to track */ res = xmmsc_playlist_set_next(connection, pos); xmmsc_result_notifier_set(res, n_jump_to_track, userdata); xmmsc_result_unref(res); } static int n_media_lib_get_info(xmmsv_t *val, void *arg) { trackinfo track; GtkWidget *dialog; trackinfo_update(val, &track); dialog = gtrackinfo_new(); gtrackinfo_set_info(GTRACKINFO(dialog), &track); gtk_widget_show(dialog); return FALSE; } static void pl_info_about_selection(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer userdata) { guint id; xmmsc_result_t *res; gtk_tree_model_get(model, iter, 1, &id, -1); res = xmmsc_medialib_get_info(connection, id); xmmsc_result_notifier_set(res, n_media_lib_get_info, NULL); xmmsc_result_unref(res); } struct params { GMedialib *gml; GtkTreeIter iter; }; static int n_playlist_current_pos(xmmsv_t *val, void *arguments) { struct params *pm = (struct params *)arguments; gint pos = 0, p = 0; GtkTreePath *path; xmmsv_dict_entry_get_int(val, "position", &pos); pm->gml->playlist.current_pos = pos; gtk_tree_model_get(GTK_TREE_MODEL(pm->gml->playlist.ls), &(pm->iter), 0, &p, -1); while (p != pos && gtk_tree_model_iter_next(GTK_TREE_MODEL(pm->gml->playlist.ls), &(pm->iter))) { gtk_tree_model_get(GTK_TREE_MODEL(pm->gml->playlist.ls), &(pm->iter), 0, &p, -1); } path = gtk_tree_model_get_path(GTK_TREE_MODEL(pm->gml->playlist.ls), &(pm->iter)); gtk_tree_view_set_cursor(GTK_TREE_VIEW(pm->gml->playlist.list), path, NULL, FALSE); gtk_widget_grab_focus(GTK_WIDGET(pm->gml->playlist.list)); gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(pm->gml->playlist.list), path, NULL, TRUE, 0.5, 0.5); gtk_tree_path_free(path); g_free(pm); return FALSE; } static void cb_pl_button_track_pressed(GtkWidget *widget, gpointer userdata) { xmmsc_result_t *res; struct params *p; p = g_malloc(sizeof(struct params)); p->gml = (GMedialib *)userdata; if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(p->gml->playlist.ls), &(p->iter))) { res = xmmsc_playlist_current_pos(connection, NULL); xmmsc_result_notifier_set(res, n_playlist_current_pos, p); xmmsc_result_unref(res); } } static void cb_pl_save_pl_button_pressed(GtkWidget *widget, gpointer userdata); static int n_playlist_loaded(xmmsv_t *val, void *userdata) { GMedialib *gml = (GMedialib *)userdata; gml_pl_refresh_playlist(gml); gml_set_statusbar_text(gml, "Ready."); return FALSE; } static int n_playlist_clear(xmmsv_t *val, void *userdata) { xmmsc_result_t *res2; res2 = xmmsc_playlist_load(connection, "_gxmms2_tmp_list"); xmmsc_result_notifier_set(res2, n_playlist_loaded, userdata); xmmsc_result_unref(res2); return FALSE; } static void cb_pl_clear_button_pressed(GtkWidget *widget, gpointer userdata) { xmmsc_result_t *res; GMedialib *gml = (GMedialib *)userdata; gint result = GTK_RESPONSE_NO; GtkWidget *checkbutton; GtkWidget *dialog; if (gml->playlist.new_playlist_confirm) { dialog = gtk_message_dialog_new(GTK_WINDOW(gml), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE, "Do you want to save the current playlist?"); gtk_dialog_add_buttons(GTK_DIALOG(dialog), GTK_STOCK_YES, GTK_RESPONSE_YES, GTK_STOCK_NO, GTK_RESPONSE_NO, GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT, NULL); checkbutton = gtk_check_button_new_with_mnemonic("_Don't ask me again"); gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), checkbutton); gtk_widget_show_all(dialog); result = gtk_dialog_run(GTK_DIALOG(dialog)); if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(checkbutton))) { gml->playlist.new_playlist_confirm = FALSE; } if (result == GTK_RESPONSE_YES) { /* save the playlist */ gtk_widget_destroy(dialog); cb_pl_save_pl_button_pressed(widget, gml); } else { gtk_widget_destroy(dialog); } } if (result != GTK_RESPONSE_REJECT) { res = xmmsc_playlist_create(connection, "_gxmms2_tmp_list"); xmmsc_result_notifier_set(res, n_playlist_clear, userdata); xmmsc_result_unref(res); } } static int n_playlist_save(xmmsv_t *val, void *userdata) { GMedialib *gml = (GMedialib *)userdata; char const *xerr; if (xmmsv_get_error(val, &xerr)) { gml_set_statusbar_text(gml, (gchar *) xerr); } else { gml_playlists_update_playlists(gml); gml_set_statusbar_text(gml, "Playlist saved successfully."); } return FALSE; } struct params_save_pl { GMedialib *gml; gchar *pl_name_str; }; static int n_coll_get(xmmsv_t *val, void *userdata) { GMedialib *gml = ((struct params_save_pl *)userdata)->gml;; char const *xerr; if (xmmsv_get_error(val, &xerr)) { gml_set_statusbar_text(gml, (gchar *) xerr); } else { xmmsc_coll_t *playlist_coll; xmmsc_result_t *res2; xmmsv_get_coll(val, &playlist_coll); res2 = xmmsc_coll_save(connection, playlist_coll, ((struct params_save_pl *)userdata)->pl_name_str, XMMS_COLLECTION_NS_PLAYLISTS); xmmsc_result_notifier_set(res2, n_playlist_save, gml); xmmsc_coll_unref(playlist_coll); } g_free(((struct params_save_pl *)userdata)->pl_name_str); return FALSE; } static void cb_pl_save_pl_button_pressed(GtkWidget *widget, gpointer userdata) { xmmsc_result_t *res; gint result; GtkWidget *dialog = gtk_dialog_new_with_buttons("Save playlist...", GTK_WINDOW(userdata), GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT, NULL); GtkWidget *label = gtk_label_new("Save as:"); GtkWidget *entry = gtk_entry_new(); static struct params_save_pl p; gtk_widget_set_size_request(GTK_WIDGET(dialog), 300, 100); gtk_window_set_resizable(GTK_WINDOW(dialog), FALSE); gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), label); gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), entry); gtk_widget_show_all(dialog); result = gtk_dialog_run(GTK_DIALOG(dialog)); if (result == GTK_RESPONSE_ACCEPT) { gint len = strlen(gtk_entry_get_text(GTK_ENTRY(entry))); gchar *pl_name_str = g_malloc(len); strncpy(pl_name_str, gtk_entry_get_text(GTK_ENTRY(entry)), len); /* save the playlist */ res = xmmsc_coll_get(connection, "_active", "Playlists"); p.gml = (GMedialib *)userdata; p.pl_name_str = pl_name_str; xmmsc_result_notifier_set(res, n_coll_get, &p); xmmsc_result_unref(res); } gtk_widget_destroy(dialog); } static void cb_pl_drag_data_get(GtkWidget *widget, GdkDragContext *drag_context, GtkSelectionData *selection, guint info, guint time, gpointer pt) { GtkTreeSelection *tree_sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget)); GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(widget)); GList *sel = gtk_tree_selection_get_selected_rows(tree_sel, &model); gchar *rows = NULL; for (; sel; sel = g_list_next(sel)) { gchar *path_string = gtk_tree_path_to_string((GtkTreePath*) sel->data); if (rows == NULL) { rows = path_string; } else { gchar *str = g_strconcat(rows, ";", path_string, NULL); g_free(rows); g_free(path_string); rows = str; } } g_list_free(sel); gtk_selection_data_set(selection, drag_atom, sizeof(guchar), (guchar *)rows, strlen(rows) + 1); } static void cb_pl_drag_data_received(GtkWidget *widget, GdkDragContext *drag_context, gint x, gint y, GtkSelectionData *selection, guint info, guint time, gpointer userdata) { guchar *data_text = selection->data; gchar **rows = g_strsplit((gchar *)data_text, ";", -1); gchar **cur_row; GtkTreePath *path; GtkTreeViewDropPosition position; GtkTreeModel *model; GtkTreeIter iter; guint pos; guint i; GMedialib *gml = (GMedialib *)userdata; g_return_if_fail(data_text != NULL); if (!gtk_tree_view_get_dest_row_at_pos( GTK_TREE_VIEW(widget), x, y, &path, &position)) return; model = gtk_tree_view_get_model(GTK_TREE_VIEW(widget)); gtk_tree_model_get_iter(model, &iter, path); gtk_tree_model_get(model, &iter, 0, &pos, -1); for (cur_row = rows; *cur_row; cur_row++) { GtkTreeIter old_iter; guint old_pos; xmmsc_result_t *res = NULL; gtk_tree_model_get_iter_from_string(model, &old_iter, *cur_row); gtk_tree_model_get(model, &old_iter, 0, &old_pos, -1); if ((gint)pos - (gint)old_pos < 0) { res = xmmsc_playlist_move_entry(connection, NULL, old_pos, pos); gtk_list_store_move_before(GTK_LIST_STORE(model), &old_iter, &iter); } else { res = xmmsc_playlist_move_entry(connection, NULL, old_pos, pos-1); gtk_list_store_move_before(GTK_LIST_STORE(model), &old_iter, &iter); } xmmsc_result_unref(res); } g_strfreev(rows); gtk_tree_model_get_iter_first(model, &iter); i = 0; do { gtk_list_store_set(GTK_LIST_STORE(model), &iter, 0, i, -1); i++; } while (gtk_tree_model_iter_next(model, &iter)); update_current_pl_pos(gml); } static void cb_pl_reload_button_pressed(GtkWidget *widget, gpointer pt) { GMedialib *gml = (GMedialib *)pt; gml_pl_refresh_playlist(gml); } static void search_for_artist_foreach_func(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *selected_row, gpointer userdata) { GMedialib *gml = (GMedialib *)userdata; gchar *artist; gtk_tree_model_get(model, selected_row, 2, &artist, -1); if (gml_notebook_is_mlib_search_visible(GMEDIALIB(gml))) { gml_search_do_search(gml, SEARCH_ARTIST, artist); gtk_notebook_set_current_page(GTK_NOTEBOOK(gml->notebook), 0); } g_free(artist); } static void cb_pl_popup_search_artist_pressed(GtkWidget *menuitem, gpointer userdata) { GMedialib *gml = (GMedialib *)userdata; GtkTreeSelection *sel; sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(gml->playlist.list)); gtk_tree_selection_selected_foreach(sel, search_for_artist_foreach_func, (gpointer)gml); } static void search_for_album_foreach_func(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *selected_row, gpointer userdata) { GMedialib *gml = (GMedialib *)userdata; gchar *album; gtk_tree_model_get(model, selected_row, 4, &album, -1); if (gml_notebook_is_mlib_search_visible(GMEDIALIB(gml))) { /* remove tracknr [xxx] from album name: */ if (album[strlen(album) - 1] == ']' && album[strlen(album) - 2 - gml->album_tracknr_digits] == '[') album[strlen(album) - 3 - gml->album_tracknr_digits] = '\0'; gml_search_do_search(gml, SEARCH_ALBUM, album); gtk_notebook_set_current_page(GTK_NOTEBOOK(gml->notebook), 0); } g_free(album); } static void cb_pl_popup_search_album_pressed(GtkWidget *menuitem, gpointer userdata) { GMedialib *gml = (GMedialib *)userdata; GtkTreeSelection *sel; sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(gml->playlist.list)); gtk_tree_selection_selected_foreach(sel, search_for_album_foreach_func, (gpointer)gml); } static void cb_pl_popup_play_pressed(GtkWidget *menuitem, gpointer userdata) { GMedialib *gml = (GMedialib *)userdata; GtkTreeSelection *sel; sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(gml->playlist.list)); gtk_tree_selection_selected_foreach(sel, pl_play_selection, (gpointer)gml); } static void cb_pl_popup_info_pressed(GtkWidget *menuitem, gpointer userdata) { GMedialib *gml = (GMedialib *)userdata; GtkTreeSelection *sel; sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(gml->playlist.list)); gtk_tree_selection_selected_foreach(sel, pl_info_about_selection, NULL); } struct params_3 { GMedialib *gml; gint rating; }; static void pl_rate_selected_tracks(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer userdata) { guint id; xmmsc_result_t *res; GMedialib *gml = ((struct params_3 *)userdata)->gml; gint rating = ((struct params_3 *)userdata)->rating; gtk_tree_model_get(model, iter, 1, &id, -1); if (rating >= 0 && rating <= 4) { gtk_list_store_set(gml->playlist.ls, iter, 5, gml->playlist.icon_rating[rating], -1); } else { gtk_list_store_set(gml->playlist.ls, iter, 5, NULL, -1); } res = xmmsc_medialib_entry_property_set_int_with_source(connection, id, "client/generic", "rating", rating+1); xmmsc_result_unref(res); } static void cb_pl_popup_rate_track_4(GtkWidget *menuitem, gpointer userdata) { GMedialib *gml = (GMedialib *)userdata; GtkTreeSelection *sel; struct params_3 params; params.gml = gml; params.rating = 4; sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(gml->playlist.list)); gtk_tree_selection_selected_foreach(sel, pl_rate_selected_tracks, ¶ms); } static void cb_pl_popup_rate_track_3(GtkWidget *menuitem, gpointer userdata) { GMedialib *gml = (GMedialib *)userdata; GtkTreeSelection *sel; struct params_3 params; params.gml = gml; params.rating = 3; sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(gml->playlist.list)); gtk_tree_selection_selected_foreach(sel, pl_rate_selected_tracks, ¶ms); } static void cb_pl_popup_rate_track_2(GtkWidget *menuitem, gpointer userdata) { GMedialib *gml = (GMedialib *)userdata; GtkTreeSelection *sel; struct params_3 params; params.gml = gml; params.rating = 2; sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(gml->playlist.list)); gtk_tree_selection_selected_foreach(sel, pl_rate_selected_tracks, ¶ms); } static void cb_pl_popup_rate_track_1(GtkWidget *menuitem, gpointer userdata) { GMedialib *gml = (GMedialib *)userdata; GtkTreeSelection *sel; struct params_3 params; params.gml = gml; params.rating = 1; sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(gml->playlist.list)); gtk_tree_selection_selected_foreach(sel, pl_rate_selected_tracks, ¶ms); } static void cb_pl_popup_rate_track_0(GtkWidget *menuitem, gpointer userdata) { GMedialib *gml = (GMedialib *)userdata; GtkTreeSelection *sel; struct params_3 params; params.gml = gml; params.rating = 0; sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(gml->playlist.list)); gtk_tree_selection_selected_foreach(sel, pl_rate_selected_tracks, ¶ms); } static void cb_pl_popup_do_not_rate(GtkWidget *menuitem, gpointer userdata) { GMedialib *gml = (GMedialib *)userdata; GtkTreeSelection *sel; struct params_3 params; params.gml = gml; params.rating = -1; sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(gml->playlist.list)); gtk_tree_selection_selected_foreach(sel, pl_rate_selected_tracks, ¶ms); } static void cb_column_pos_visible(GtkWidget *menuitem, gpointer userdata) { GMedialib *gml = (GMedialib *)userdata; gml_pl_set_column_pos_visible(gml, !gml_pl_get_column_pos_visible(gml)); } static void cb_column_id_visible(GtkWidget *menuitem, gpointer userdata) { GMedialib *gml = (GMedialib *)userdata; gml_pl_set_column_id_visible(gml, !gml_pl_get_column_id_visible(gml)); } static void cb_column_artist_visible(GtkWidget *menuitem, gpointer userdata) { GMedialib *gml = (GMedialib *)userdata; gml_pl_set_column_artist_visible(gml, !gml_pl_get_column_artist_visible(gml)); } static void cb_column_track_visible(GtkWidget *menuitem, gpointer userdata) { GMedialib *gml = (GMedialib *)userdata; gml_pl_set_column_track_visible(gml, !gml_pl_get_column_track_visible(gml)); } static void cb_column_album_visible(GtkWidget *menuitem, gpointer userdata) { GMedialib *gml = (GMedialib *)userdata; gml_pl_set_column_album_visible(gml, !gml_pl_get_column_album_visible(gml)); } static void cb_column_rating_visible(GtkWidget *menuitem, gpointer userdata) { GMedialib *gml = (GMedialib *)userdata; gml_pl_set_column_rating_visible(gml, !gml_pl_get_column_rating_visible(gml)); } static void pl_view_popup_menu(GtkWidget *treeview, GdkEventButton *event, gpointer userdata) { GtkWidget *menu, *menu_rating, *menu_columns, *menuitem; GtkTreeSelection *selection; GMedialib *gml = (GMedialib *)userdata; gboolean multiple = FALSE, none = FALSE; int i; struct submenu { gchar *name; gboolean (*get_fn)(); void (*callback_fn)(); }; struct submenu sm_columns[] = { {"#", gml_pl_get_column_pos_visible, cb_column_pos_visible}, {"ID", gml_pl_get_column_id_visible, cb_column_id_visible}, {"Artist", gml_pl_get_column_artist_visible, cb_column_artist_visible}, {"Track", gml_pl_get_column_track_visible, cb_column_track_visible}, {"Album", gml_pl_get_column_album_visible, cb_column_album_visible}, {"Rating", gml_pl_get_column_rating_visible, cb_column_rating_visible}, { NULL, NULL, NULL } }; struct submenu sm_rating[] = { {"4 (Best)", NULL, cb_pl_popup_rate_track_4}, {"3", NULL, cb_pl_popup_rate_track_3}, {"2", NULL, cb_pl_popup_rate_track_2}, {"1", NULL, cb_pl_popup_rate_track_1}, {"0 (Worst)", NULL, cb_pl_popup_rate_track_0}, {"No rating", NULL, cb_pl_popup_do_not_rate}, { NULL, NULL, NULL } }; selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(gml->playlist.list)); if (gtk_tree_selection_count_selected_rows(selection) > 1) multiple = TRUE; if (gtk_tree_selection_count_selected_rows(selection) == 0) none = TRUE; /* Submenu: Track rating */ menu_rating = gtk_menu_new(); i = 0; while (sm_rating[i].name != NULL) { menuitem = gtk_menu_item_new_with_mnemonic(sm_rating[i].name); if (none) gtk_widget_set_sensitive(menuitem, FALSE); gtk_menu_shell_append(GTK_MENU_SHELL(menu_rating), menuitem); g_signal_connect(menuitem, "activate", G_CALLBACK(sm_rating[i].callback_fn), gml); i++; } /* Submenu: Visible columns */ menu_columns = gtk_menu_new(); i = 0; while (sm_columns[i].name != NULL) { menuitem = gtk_check_menu_item_new_with_mnemonic(sm_columns[i].name); gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menuitem), sm_columns[i].get_fn(gml)); gtk_menu_shell_append(GTK_MENU_SHELL(menu_columns), menuitem); g_signal_connect(menuitem, "activate", G_CALLBACK(sm_columns[i].callback_fn), gml); i++; } /* Context menu */ menu = gtk_menu_new(); menuitem = gtk_image_menu_item_new_from_stock(GTK_STOCK_MEDIA_PLAY, NULL); if (multiple || none) gtk_widget_set_sensitive(menuitem, FALSE); g_signal_connect(menuitem, "activate", G_CALLBACK(cb_pl_popup_play_pressed), userdata); gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); menuitem = gtk_image_menu_item_new_from_stock(GTK_STOCK_DIALOG_INFO, NULL); if (multiple || none) gtk_widget_set_sensitive(menuitem, FALSE); g_signal_connect(menuitem, "activate", G_CALLBACK(cb_pl_popup_info_pressed), userdata); gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); menuitem = gtk_image_menu_item_new_from_stock(GTK_STOCK_REMOVE, NULL); if (none) gtk_widget_set_sensitive(menuitem, FALSE); g_signal_connect(menuitem, "activate", G_CALLBACK(cb_pl_button_delete_pressed), userdata); gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); menuitem = gtk_image_menu_item_new_with_mnemonic("Search for _Artist"); gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuitem), gtk_image_new_from_stock(GTK_STOCK_FIND, GTK_ICON_SIZE_SMALL_TOOLBAR)); if (multiple || none || !gml_notebook_is_mlib_search_visible(GMEDIALIB(gml))) gtk_widget_set_sensitive(menuitem, FALSE); g_signal_connect(menuitem, "activate", G_CALLBACK(cb_pl_popup_search_artist_pressed), userdata); gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); menuitem = gtk_image_menu_item_new_with_mnemonic("Search for Al_bum"); gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuitem), gtk_image_new_from_stock(GTK_STOCK_FIND, GTK_ICON_SIZE_SMALL_TOOLBAR)); if (multiple || none || !gml_notebook_is_mlib_search_visible(GMEDIALIB(gml))) gtk_widget_set_sensitive(menuitem, FALSE); g_signal_connect(menuitem, "activate", G_CALLBACK(cb_pl_popup_search_album_pressed), userdata); gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); menuitem = gtk_menu_item_new_with_mnemonic("_Rate track(s)"); if (none) gtk_widget_set_sensitive(menuitem, FALSE); gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), menu_rating); gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); menuitem = gtk_separator_menu_item_new(); gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); menuitem = gtk_menu_item_new_with_mnemonic("_Columns"); gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), menu_columns); gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); gtk_widget_show_all(menu); gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, (event != NULL) ? event->button : 0, gdk_event_get_time((GdkEvent*)event)); } static gboolean cb_pl_selection_button_press(GtkWidget *treeview, GdkEventButton *event, gpointer userdata) { gboolean result = FALSE; if (event->type == GDK_BUTTON_PRESS && event->button == 3) { pl_view_popup_menu(treeview, event, userdata); result = TRUE; } return result; } static gboolean cb_pl_selection_popup_menu(GtkWidget *treeview, gpointer userdata) { pl_view_popup_menu(treeview, NULL, userdata); return TRUE; } gboolean gml_pl_get_column_pos_visible(GMedialib *gml) { return gml->playlist.column_pos_visible; } gboolean gml_pl_get_column_id_visible(GMedialib *gml) { return gml->playlist.column_id_visible; } gboolean gml_pl_get_column_artist_visible(GMedialib *gml) { return gml->playlist.column_artist_visible; } gboolean gml_pl_get_column_track_visible(GMedialib *gml) { return gml->playlist.column_track_visible; } gboolean gml_pl_get_column_album_visible(GMedialib *gml) { return gml->playlist.column_album_visible; } gboolean gml_pl_get_column_rating_visible(GMedialib *gml) { return gml->playlist.column_rating_visible; } gboolean gml_pl_get_new_playlist_confirm(GMedialib *gml) { return gml->playlist.new_playlist_confirm; } void gml_pl_set_new_playlist_confirm(GMedialib *gml, gboolean confirm) { gml->playlist.new_playlist_confirm = confirm; } void gml_pl_set_column_pos_visible(GMedialib *gml, gboolean visible) { gml->playlist.column_pos_visible = visible; gtk_tree_view_column_set_visible(gml->playlist.column_pos, visible); } void gml_pl_set_column_id_visible(GMedialib *gml, gboolean visible) { gml->playlist.column_id_visible = visible; gtk_tree_view_column_set_visible(gml->playlist.column_id, visible); } void gml_pl_set_column_artist_visible(GMedialib *gml, gboolean visible) { gml->playlist.column_artist_visible = visible; gtk_tree_view_column_set_visible(gml->playlist.column_artist, visible); } void gml_pl_set_column_track_visible(GMedialib *gml, gboolean visible) { gml->playlist.column_track_visible = visible; gtk_tree_view_column_set_visible(gml->playlist.column_track, visible); } void gml_pl_set_column_album_visible(GMedialib *gml, gboolean visible) { gml->playlist.column_album_visible = visible; gtk_tree_view_column_set_visible(gml->playlist.column_album, visible); } void gml_pl_set_column_rating_visible(GMedialib *gml, gboolean visible) { gml->playlist.column_rating_visible = visible; gtk_tree_view_column_set_visible(gml->playlist.column_rating, visible); } void gml_pl_setup_xmms_callbacks(GMedialib *gml) { XMMS_CALLBACK_SET(connection, xmmsc_broadcast_playback_current_id, bc_handle_current_id, gml); XMMS_CALLBACK_SET(connection, xmmsc_broadcast_medialib_entry_changed, bc_handle_medialib_entry_changed, gml); XMMS_CALLBACK_SET(connection, xmmsc_broadcast_playlist_changed, bc_handle_playlist_changed, gml); } void gml_create_playlist(GMedialib *gml) { GtkCellRenderer *renderer_pixbuf; GtkTreeSelection *selection; GtkTooltips *tooltips; GdkPixbuf *icon; GtkWidget *album_item, *artist_item, *title_item, *tracknr_item; GtkTargetEntry row_targets[1]; gml->playlist.frame = gtk_frame_new("Playlist"); gtk_container_set_border_width(GTK_CONTAINER(gml->playlist.frame), 2); /* table playlist */ gml->playlist.table = gtk_table_new(2, 7, FALSE); gtk_container_set_border_width(GTK_CONTAINER(gml->playlist.table), 3); gtk_table_set_row_spacings(GTK_TABLE(gml->playlist.table), 4); gtk_table_set_col_spacings(GTK_TABLE(gml->playlist.table), 4); gtk_container_add(GTK_CONTAINER(gml->playlist.frame), gml->playlist.table); /* clear playlist button */ gml->playlist.button_new_pl = gtk_button_new(); gml->playlist.image_new = gtk_image_new_from_stock(GTK_STOCK_NEW, GTK_ICON_SIZE_LARGE_TOOLBAR); gtk_button_set_relief(GTK_BUTTON(gml->playlist.button_new_pl), GTK_RELIEF_NONE); gtk_container_add(GTK_CONTAINER(gml->playlist.button_new_pl), gml->playlist.image_new); gtk_table_attach(GTK_TABLE(gml->playlist.table), gml->playlist.button_new_pl, 0, 1, 0, 1, GTK_SHRINK, GTK_SHRINK, 0, 0); /* save playlist button */ gml->playlist.button_save_pl = gtk_button_new(); gml->playlist.image_save = gtk_image_new_from_stock(GTK_STOCK_SAVE, GTK_ICON_SIZE_LARGE_TOOLBAR); gtk_button_set_relief(GTK_BUTTON(gml->playlist.button_save_pl), GTK_RELIEF_NONE); gtk_container_add(GTK_CONTAINER(gml->playlist.button_save_pl), gml->playlist.image_save); gtk_table_attach(GTK_TABLE(gml->playlist.table), gml->playlist.button_save_pl, 1, 2, 0, 1, GTK_SHRINK, GTK_SHRINK, 0, 0); /* add 10 random songs button */ gml->playlist.button_add_rnd = gtk_button_new(); icon = gdk_pixbuf_new_from_xpm_data((const char **)addrnd_xpm); gml->playlist.image_add_rnd = gtk_image_new_from_pixbuf(icon); gtk_button_set_relief(GTK_BUTTON(gml->playlist.button_add_rnd), GTK_RELIEF_NONE); gtk_container_add(GTK_CONTAINER(gml->playlist.button_add_rnd), gml->playlist.image_add_rnd); gtk_table_attach(GTK_TABLE(gml->playlist.table), gml->playlist.button_add_rnd, 2, 3, 0, 1, GTK_SHRINK, GTK_SHRINK, 0, 0); /* shuffle playlist button */ gml->playlist.button_shuffle_pl = gtk_button_new(); icon = gdk_pixbuf_new_from_xpm_data((const char **)shuffle_xpm); gml->playlist.image_shuffle_pl = gtk_image_new_from_pixbuf(icon); gtk_button_set_relief(GTK_BUTTON(gml->playlist.button_shuffle_pl), GTK_RELIEF_NONE); gtk_container_add(GTK_CONTAINER(gml->playlist.button_shuffle_pl), gml->playlist.image_shuffle_pl); gtk_table_attach(GTK_TABLE(gml->playlist.table), gml->playlist.button_shuffle_pl, 3, 4, 0, 1, GTK_SHRINK, GTK_SHRINK, 0, 0); /* sort playlist button */ gml->playlist.button_sort_pl = gtk_button_new(); gml->playlist.image_sort_pl = gtk_image_new_from_stock( GTK_STOCK_SORT_ASCENDING, GTK_ICON_SIZE_LARGE_TOOLBAR); gtk_button_set_relief(GTK_BUTTON(gml->playlist.button_sort_pl), GTK_RELIEF_NONE); gtk_container_add(GTK_CONTAINER(gml->playlist.button_sort_pl), gml->playlist.image_sort_pl); gtk_table_attach(GTK_TABLE(gml->playlist.table), gml->playlist.button_sort_pl, 4, 5, 0, 1, GTK_SHRINK, GTK_SHRINK, 0, 0); gml->playlist.menu_sort_pl = gtk_menu_new(); /* sort playlist menu */ album_item = gtk_menu_item_new_with_label("Album"); artist_item = gtk_menu_item_new_with_label("Artist"); title_item = gtk_menu_item_new_with_label("Title"); tracknr_item = gtk_menu_item_new_with_label("Tracknr"); gtk_menu_shell_append(GTK_MENU_SHELL(gml->playlist.menu_sort_pl), album_item); gtk_menu_shell_append(GTK_MENU_SHELL(gml->playlist.menu_sort_pl), artist_item); gtk_menu_shell_append(GTK_MENU_SHELL(gml->playlist.menu_sort_pl), title_item); gtk_menu_shell_append(GTK_MENU_SHELL(gml->playlist.menu_sort_pl), tracknr_item); gtk_widget_show(album_item); gtk_widget_show(artist_item); gtk_widget_show(title_item); gtk_widget_show(tracknr_item); gtk_signal_connect(GTK_OBJECT(album_item), "activate", G_CALLBACK(cb_pl_sort_menu_activate), (gpointer)gml); gtk_signal_connect(GTK_OBJECT(artist_item), "activate", G_CALLBACK(cb_pl_sort_menu_activate), (gpointer)gml); gtk_signal_connect(GTK_OBJECT(title_item), "activate", G_CALLBACK(cb_pl_sort_menu_activate), (gpointer)gml); gtk_signal_connect(GTK_OBJECT(tracknr_item), "activate", G_CALLBACK(cb_pl_sort_menu_activate), (gpointer)gml); /* reload playlist button */ gml->playlist.button_reload_pl = gtk_button_new(); gml->playlist.image_reload = gtk_image_new_from_stock(GTK_STOCK_REFRESH, GTK_ICON_SIZE_LARGE_TOOLBAR); gtk_button_set_relief(GTK_BUTTON(gml->playlist.button_reload_pl), GTK_RELIEF_NONE); gtk_container_add(GTK_CONTAINER(gml->playlist.button_reload_pl), gml->playlist.image_reload); gtk_table_attach(GTK_TABLE(gml->playlist.table), gml->playlist.button_reload_pl, 5, 6, 0, 1, GTK_SHRINK, GTK_SHRINK, 0, 0); /* show-current-track button */ gml->playlist.button_track = gtk_button_new(); gml->playlist.image_track = gtk_image_new_from_stock(GTK_STOCK_JUMP_TO, GTK_ICON_SIZE_LARGE_TOOLBAR); gtk_button_set_relief(GTK_BUTTON(gml->playlist.button_track), GTK_RELIEF_NONE); gtk_container_add(GTK_CONTAINER(gml->playlist.button_track), gml->playlist.image_track); gtk_table_attach(GTK_TABLE(gml->playlist.table), gml->playlist.button_track, 6, 7, 0, 1, GTK_SHRINK, GTK_SHRINK, 0, 0); gtk_widget_set_sensitive(gml->playlist.button_track, TRUE); /* list playlist */ gml->playlist.ls = gtk_list_store_new(6, G_TYPE_INT, G_TYPE_INT, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, GDK_TYPE_PIXBUF); gml->playlist.list = gtk_tree_view_new_with_model(GTK_TREE_MODEL(gml->playlist.ls)); gtk_tree_view_set_enable_search(GTK_TREE_VIEW(gml->playlist.list), TRUE); row_targets[0].target = "PLAYLIST_MODEL_ROW"; row_targets[0].flags = GTK_TARGET_SAME_WIDGET; row_targets[0].info = 0; drag_atom = gdk_atom_intern(row_targets[0].target, FALSE); gtk_tree_view_enable_model_drag_source( GTK_TREE_VIEW(gml->playlist.list), GDK_BUTTON1_MASK, row_targets, G_N_ELEMENTS(row_targets), GDK_ACTION_MOVE); gtk_tree_view_enable_model_drag_dest( GTK_TREE_VIEW(gml->playlist.list), row_targets, G_N_ELEMENTS(row_targets), GDK_ACTION_MOVE); selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(gml->playlist.list)); gtk_tree_selection_set_mode(selection, GTK_SELECTION_MULTIPLE); gml->playlist.scroll_widget = gtk_scrolled_window_new(NULL, NULL); gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW(gml->playlist.scroll_widget), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS); gtk_container_add(GTK_CONTAINER(gml->playlist.scroll_widget), gml->playlist.list); gtk_table_attach(GTK_TABLE(gml->playlist.table), gml->playlist.scroll_widget, 0, 7, 1, 2, GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, 0, 0); gml->playlist.column_pos = gtk_tree_view_column_new_with_attributes("#", gml->renderer_text, "text", 0, NULL); gtk_tree_view_append_column(GTK_TREE_VIEW(gml->playlist.list), gml->playlist.column_pos); gtk_tree_view_column_set_resizable(gml->playlist.column_pos, TRUE); gtk_tree_view_column_set_cell_data_func(gml->playlist.column_pos, gml->renderer_text, pl_cell_data_function, gml, NULL); gml->playlist.column_id = gtk_tree_view_column_new_with_attributes("ID", gml->renderer_text, "text", 1, NULL); gtk_tree_view_append_column(GTK_TREE_VIEW(gml->playlist.list), gml->playlist.column_id); gtk_tree_view_column_set_resizable(gml->playlist.column_id, TRUE); gtk_tree_view_column_set_cell_data_func(gml->playlist.column_id, gml->renderer_text, pl_cell_data_function, gml, NULL); gml->playlist.column_artist = gtk_tree_view_column_new_with_attributes("Artist", gml->renderer_text_ellipsize, "text", 2, NULL); gtk_tree_view_append_column(GTK_TREE_VIEW(gml->playlist.list), gml->playlist.column_artist); gtk_tree_view_column_set_resizable(gml->playlist.column_artist, TRUE); gtk_tree_view_column_set_expand(gml->playlist.column_artist, TRUE); gtk_tree_view_column_set_cell_data_func(gml->playlist.column_artist, gml->renderer_text_ellipsize, pl_cell_data_function, gml, NULL); gml->playlist.column_track = gtk_tree_view_column_new_with_attributes("Track", gml->renderer_text_ellipsize, "text", 3, NULL); gtk_tree_view_append_column(GTK_TREE_VIEW(gml->playlist.list), gml->playlist.column_track); gtk_tree_view_column_set_resizable(gml->playlist.column_track, TRUE); gtk_tree_view_column_set_expand(gml->playlist.column_track, TRUE); gtk_tree_view_column_set_cell_data_func(gml->playlist.column_track, gml->renderer_text_ellipsize, pl_cell_data_function, gml, NULL); gml->playlist.column_album = gtk_tree_view_column_new_with_attributes("Album [#]", gml->renderer_text_ellipsize, "text", 4, NULL); gtk_tree_view_append_column(GTK_TREE_VIEW(gml->playlist.list), gml->playlist.column_album); gtk_tree_view_column_set_resizable(gml->playlist.column_album, TRUE); gtk_tree_view_column_set_expand(gml->playlist.column_album, TRUE); gtk_tree_view_column_set_cell_data_func(gml->playlist.column_album, gml->renderer_text_ellipsize, pl_cell_data_function, gml, NULL); renderer_pixbuf = gtk_cell_renderer_pixbuf_new(); gml->playlist.column_rating = gtk_tree_view_column_new_with_attributes("Rating", renderer_pixbuf, "pixbuf", 5, NULL); gtk_tree_view_append_column(GTK_TREE_VIEW(gml->playlist.list), gml->playlist.column_rating); gtk_tree_view_column_set_resizable(gml->playlist.column_rating, FALSE); /* rating icons */ gml->playlist.icon_rating[0] = gdk_pixbuf_new_from_xpm_data((const char **)rank0_xpm); gml->playlist.icon_rating[1] = gdk_pixbuf_new_from_xpm_data((const char **)rank1_xpm); gml->playlist.icon_rating[2] = gdk_pixbuf_new_from_xpm_data((const char **)rank2_xpm); gml->playlist.icon_rating[3] = gdk_pixbuf_new_from_xpm_data((const char **)rank3_xpm); gml->playlist.icon_rating[4] = gdk_pixbuf_new_from_xpm_data((const char **)rank4_xpm); /* tooltips */ tooltips = gtk_tooltips_new(); gtk_tooltips_set_tip(tooltips, gml->playlist.button_new_pl, "New playlist", NULL); gtk_tooltips_set_tip(tooltips, gml->playlist.button_save_pl, "Save playlist", NULL); gtk_tooltips_set_tip(tooltips, gml->playlist.button_shuffle_pl, "Shuffle the playlist", NULL); gtk_tooltips_set_tip(tooltips, gml->playlist.button_sort_pl, "Sort the playlist", NULL); gtk_tooltips_set_tip(tooltips, gml->playlist.button_add_rnd, "Add 10 random songs to the playlist", NULL); gtk_tooltips_set_tip(tooltips, gml->playlist.button_reload_pl, "Refresh the playlist\n(Useful if another XMMS2 " \ "client has altered the playlist)", NULL); gtk_tooltips_set_tip(tooltips, gml->playlist.button_track, "Show currently played track", NULL); gml_pl_set_column_pos_visible (gml, TRUE); gml_pl_set_column_id_visible (gml, TRUE); gml_pl_set_column_artist_visible(gml, TRUE); gml_pl_set_column_track_visible (gml, TRUE); gml_pl_set_column_album_visible (gml, TRUE); gml_pl_set_column_rating_visible(gml, TRUE); g_signal_connect(G_OBJECT(gml->playlist.list), "drag-data-get", G_CALLBACK(cb_pl_drag_data_get), (gpointer)gml); g_signal_connect(G_OBJECT(gml->playlist.list), "drag_data_received", G_CALLBACK(cb_pl_drag_data_received), (gpointer)gml); g_signal_connect(G_OBJECT(gml->playlist.button_reload_pl), "clicked", G_CALLBACK(cb_pl_reload_button_pressed), (gpointer)gml); g_signal_connect(G_OBJECT(gml->playlist.button_shuffle_pl), "clicked", G_CALLBACK(cb_pl_shuffle_button_pressed), (gpointer)gml); g_signal_connect(G_OBJECT(gml->playlist.button_sort_pl), "button-press-event", G_CALLBACK(cb_pl_sort_button_raw_pressed), (gpointer)gml); g_signal_connect(G_OBJECT(gml->playlist.button_add_rnd), "clicked", G_CALLBACK(cb_pl_add_rnd_button_pressed), (gpointer)gml); g_signal_connect(G_OBJECT(gml->playlist.button_new_pl), "clicked", G_CALLBACK(cb_pl_clear_button_pressed), (gpointer)gml); g_signal_connect(G_OBJECT(gml->playlist.button_save_pl), "clicked", G_CALLBACK(cb_pl_save_pl_button_pressed), (gpointer)gml); g_signal_connect(G_OBJECT(gml->playlist.button_track), "clicked", G_CALLBACK(cb_pl_button_track_pressed), (gpointer)gml); g_signal_connect(G_OBJECT(gml->playlist.list), "row-activated", G_CALLBACK(cb_pl_on_tree_view_row_activated), (gpointer)gml); gml->playlist.sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(gml->playlist.list)); g_signal_connect(G_OBJECT(gml->playlist.list), "button-press-event", G_CALLBACK(cb_pl_selection_button_press), (gpointer)gml); g_signal_connect(G_OBJECT(gml->playlist.list), "popup-menu", G_CALLBACK(cb_pl_selection_popup_menu), (gpointer)gml); g_signal_connect(G_OBJECT(gml->playlist.list), "key-press-event", G_CALLBACK(cb_pl_selection_key_press), (gpointer)gml); gml_pl_setup_xmms_callbacks(gml); update_current_pl_pos(gml); gml->playlist.move_finished = TRUE; gml->playlist.refresh = FALSE; gml->playlist.refresh_counter = 0; gml->playlist.new_playlist_confirm = TRUE; } gxmms2-0.7.1/gmedialib/gmlplaylists.h0000644000175000017500000000075210601276546016255 0ustar wejpwejp/* * File: gmlplaylists.h * * Medialib search and playlist editor * Copyright (c) 2005 Johannes Heimansberg * * requires GTK+ 2.6 or better and XMMS2 DR2 or better * * Released under the GNU General Public License v2 */ #ifndef __GMLPLAYLISTS_H__ #define __GMLPLAYLISTS_H__ #include #include struct _GMLPlaylists { GtkWidget *frame, *table; GtkWidget *list, *scroll_widget; GtkWidget *button_load; GtkListStore *ls; }; #endif gxmms2-0.7.1/gmedialib/gmlsearch.c0000644000175000017500000010103211213135526015452 0ustar wejpwejp/* * File: gmlsearch.c * * Medialib search and playlist editor * Copyright (c) 2005-2008 Johannes Heimansberg * * requires GTK+ 2.6 or better and XMMS2 * * Released under the GNU General Public License v2 */ #include #include #include #include #include #include "gmedialib.h" #include "gtrackinfo/trackinfo.h" #include "gtrackinfo/gtrackinfo.h" #include "sdecode/sdecode.h" void gmedialib_refresh(GMedialib*, xmmsc_connection_t*); extern xmmsc_connection_t *connection; /* available from gxmms2.c */ struct search_params { GMedialib *gml; xmmsc_connection_t *conn; gchar *category; gchar *search_str; gboolean start; xmmsc_coll_t *coll_query; }; struct rehash_notify_data { GMedialib *gml; guint remaining_ids; }; void gml_search_do_search(GMedialib *gml, guint search_for, gchar* search_str) { gtk_entry_set_text(GTK_ENTRY(gml->search.entry_searchstring), search_str); gtk_combo_box_set_active(GTK_COMBO_BOX(gml->search.search_combo), search_for); gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(gml->search.checkbutton_exact), TRUE); gtk_button_clicked(GTK_BUTTON(gml->search.button_search)); } static void cb_search_on_tree_view_row_activated(GtkTreeView *view, GtkTreePath *path, GtkTreeViewColumn *col, gpointer userdata) { GtkTreeModel *model; GtkTreeIter iter; xmmsc_result_t *res; guint id; model = gtk_tree_view_get_model(view); if (gtk_tree_model_get_iter(model, &iter, path)) { gtk_tree_model_get(model, &iter, 0, &id, -1); res = xmmsc_playlist_add_id(connection, NULL, id); xmmsc_result_unref(res); } } static void add_selected_foreach_func(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *selected_row, gpointer userdata) { xmmsc_result_t *res; guint id; gtk_tree_model_get(model, selected_row, 0, &id, -1); res = xmmsc_playlist_add_id(connection, NULL, id); xmmsc_result_unref(res); } static void cb_search_add_button_pressed(GtkWidget *widget, gpointer pt) { GMedialib *gml = (GMedialib *)pt; GtkTreeSelection *sel; sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(gml->search.list_results)); gtk_tree_selection_selected_foreach(sel, add_selected_foreach_func, (gpointer)gml); } static void insert_selected_foreach_func(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *selected_row, gpointer userdata) { xmmsc_result_t *res; guint id; GMedialib *gml = (GMedialib *)userdata; gint pos = gml_pl_get_selected_pos(gml); gtk_tree_model_get(model, selected_row, 0, &id, -1); res = xmmsc_playlist_insert_id(connection, NULL, pos + 1, id); xmmsc_result_unref(res); } static void cb_search_popup_insert_pressed(GtkWidget *widget, gpointer pt) { GMedialib *gml = (GMedialib *)pt; gint pos = gml_pl_get_selected_pos(gml); GtkTreeSelection *sel; if (pos != -1) { sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(gml->search.list_results)); gtk_tree_selection_selected_foreach(sel, insert_selected_foreach_func, (gpointer)gml); } } static int n_rehash(xmmsv_t *val, void *userdata) { struct rehash_notify_data* data = (struct rehash_notify_data *)userdata; data->remaining_ids--; if (data->remaining_ids == 0) gmedialib_refresh(data->gml, connection); return FALSE; } static void cb_search_rehash_button_pressed(GtkWidget *widget, gpointer pt) { GMedialib *gml = (GMedialib *)pt; GtkTreeView *tree_view = GTK_TREE_VIEW(gml->search.list_results); GtkTreeSelection *selection = gtk_tree_view_get_selection(tree_view); GtkTreeModel *model = gtk_tree_view_get_model(tree_view); GList *sel, *cur; static struct rehash_notify_data data; sel = gtk_tree_selection_get_selected_rows(selection, &model); data.gml = gml; data.remaining_ids = g_list_length(sel); for (cur = sel; cur; cur = g_list_next(cur)) { GtkTreeIter iter; xmmsc_result_t *res; guint id; gtk_tree_model_get_iter(model, &iter, (GtkTreePath*)cur->data); gtk_tree_model_get(model, &iter, 0, &id, -1); res = xmmsc_medialib_rehash (connection, id); xmmsc_result_notifier_set(res, n_rehash, &data); xmmsc_result_unref(res); } g_list_free(sel); } static void cb_search_remove_button_pressed(GtkWidget *widget, gpointer pt) { GMedialib *gml = (GMedialib *)pt; GtkTreeView *tree_view = GTK_TREE_VIEW(gml->search.list_results); GtkTreeSelection *selection = gtk_tree_view_get_selection(tree_view); GtkTreeModel *model = gtk_tree_view_get_model(tree_view); GList *sel, *cur; sel = g_list_last(gtk_tree_selection_get_selected_rows(selection, &model)); for (cur = sel; cur; cur = g_list_previous(cur)) { GtkTreeIter iter; xmmsc_result_t *res; guint id; gtk_tree_model_get_iter(model, &iter, (GtkTreePath*) cur->data); gtk_tree_model_get(model, &iter, 0, &id, -1); res = xmmsc_medialib_remove_entry(connection, id); xmmsc_result_unref(res); gtk_list_store_remove(GTK_LIST_STORE(model), &iter); } g_list_free(sel); } gchar* map_category(gint category) { gchar *str = NULL; switch (category) { case 0: break; case 1: str = "artist"; break; case 2: str = "title"; break; case 3: str = "album"; break; case 4: str = "url"; break; default: g_return_val_if_reached(NULL); } return g_strdup(str); } static void cb_search_search_button_pressed(GtkWidget *widget, gpointer pt) { GMedialib *gml = (GMedialib *)pt; gchar *str, *category; gint active_category; gboolean exact; str = (gchar *)gtk_entry_get_text(GTK_ENTRY(gml->search.entry_searchstring)); active_category = gtk_combo_box_get_active( GTK_COMBO_BOX(gml->search.search_combo)); category = map_category(active_category); exact = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(gml->search.checkbutton_exact)); if (strlen(str) > 2 || exact) { gtk_widget_set_sensitive(gml->search.button_search, FALSE); gtk_widget_set_sensitive(gml->search.entry_searchstring, FALSE); gtk_widget_set_sensitive(gml->search.search_combo, FALSE); gtk_widget_set_sensitive(gml->search.checkbutton_exact, FALSE); if (gml->search.ls != NULL) gtk_list_store_clear(gml->search.ls); g_free(gml->search.last_search_str); gml->search.last_search_str = g_strdup(str); gml->search.last_category = active_category; gml->search.last_exact = exact; gmedialib_search(gml, connection, category, str, exact); g_free(category); } } static void cb_search_popup_search_artist_pressed(GtkWidget *menuitem, gpointer userdata) { GMedialib *gml = (GMedialib *)userdata; GtkTreeSelection *sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(gml->search.list_results)); GtkTreeModel *model = GTK_TREE_MODEL(gml->search.ls); GList *list = gtk_tree_selection_get_selected_rows(sel, &model); GtkTreePath *path = list->data; GtkTreeIter selected_row; gchar *artist; gtk_tree_model_get_iter(GTK_TREE_MODEL(gml->search.ls), &selected_row, path); gtk_tree_model_get(model, &selected_row, 1, &artist, -1); gml_search_do_search(gml, SEARCH_ARTIST, artist); g_free(artist); g_list_foreach(list, (GFunc)gtk_tree_path_free, NULL); g_list_free(list); } static void cb_search_popup_search_album_pressed(GtkWidget *menuitem, gpointer userdata) { GMedialib *gml = (GMedialib *)userdata; GtkTreeSelection *sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(gml->search.list_results)); GtkTreeModel *model = GTK_TREE_MODEL(gml->search.ls); GList *list = gtk_tree_selection_get_selected_rows(sel, &model); GtkTreePath *path = list->data; GtkTreeIter selected_row; gchar *album; gtk_tree_model_get_iter(GTK_TREE_MODEL(gml->search.ls), &selected_row, path); gtk_tree_model_get(model, &selected_row, 3, &album, -1); /* remove tracknr [xxx] from album name: */ if (album[strlen(album) - 1] == ']' && album[strlen(album) - 2 - gml->album_tracknr_digits] == '[') album[strlen(album) - 3 - gml->album_tracknr_digits] = '\0'; gml_search_do_search(gml, SEARCH_ALBUM, album); g_free(album); g_list_foreach(list, (GFunc)gtk_tree_path_free, NULL); g_list_free(list); } static int n_media_lib_get_info(xmmsv_t *val, void *arg) { trackinfo track; GtkWidget *dialog; trackinfo_update(val, &track); dialog = gtrackinfo_new(); gtrackinfo_set_info(GTRACKINFO(dialog), &track); gtk_widget_show(dialog); return FALSE; } static void search_info_about_selection(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer userdata) { guint id; xmmsc_result_t *res; gtk_tree_model_get(model, iter, 0, &id, -1); res = xmmsc_medialib_get_info(connection, id); xmmsc_result_notifier_set(res, n_media_lib_get_info, NULL); xmmsc_result_unref(res); } static void cb_search_popup_info_pressed(GtkWidget *menuitem, gpointer userdata) { GMedialib *gml = (GMedialib *)userdata; GtkTreeSelection *sel; sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(gml->search.list_results)); gtk_tree_selection_selected_foreach(sel, search_info_about_selection, NULL); } static void cb_column_id_visible(GtkWidget *menuitem, gpointer userdata) { GMedialib *gml = (GMedialib *)userdata; gml_search_set_column_id_visible(gml, !gml_search_get_column_id_visible(gml)); } static void cb_column_artist_visible(GtkWidget *menuitem, gpointer userdata) { GMedialib *gml = (GMedialib *)userdata; gml_search_set_column_artist_visible(gml, !gml_search_get_column_artist_visible(gml)); } static void cb_column_track_visible(GtkWidget *menuitem, gpointer userdata) { GMedialib *gml = (GMedialib *)userdata; gml_search_set_column_track_visible(gml, !gml_search_get_column_track_visible(gml)); } static void cb_column_album_visible(GtkWidget *menuitem, gpointer userdata) { GMedialib *gml = (GMedialib *)userdata; gml_search_set_column_album_visible(gml, !gml_search_get_column_album_visible(gml)); } static void cb_column_rating_visible(GtkWidget *menuitem, gpointer userdata) { GMedialib *gml = (GMedialib *)userdata; gml_search_set_column_rating_visible(gml, !gml_search_get_column_rating_visible(gml)); } static void search_view_popup_menu(GtkWidget *treeview, GdkEventButton *event, gpointer userdata) { GtkWidget *menu, *menu_columns, *menuitem; GtkTreeSelection *selection; GMedialib *gml = (GMedialib *)userdata; gboolean multiple = FALSE, none = FALSE; int i; struct submenu { gchar *name; gboolean (*get_fn)(); void (*callback_fn)(); }; struct submenu sm_columns[] = { {"ID", gml_search_get_column_id_visible, cb_column_id_visible}, {"Artist", gml_search_get_column_artist_visible, cb_column_artist_visible}, {"Track", gml_search_get_column_track_visible, cb_column_track_visible}, {"Album", gml_search_get_column_album_visible, cb_column_album_visible}, {"Rating", gml_search_get_column_rating_visible, cb_column_rating_visible}, { NULL, NULL, NULL } }; /* Submenu: Visible columns */ menu_columns = gtk_menu_new(); i = 0; while (sm_columns[i].name != NULL) { menuitem = gtk_check_menu_item_new_with_mnemonic(sm_columns[i].name); gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menuitem), sm_columns[i].get_fn(gml)); gtk_menu_shell_append(GTK_MENU_SHELL(menu_columns), menuitem); g_signal_connect(menuitem, "activate", G_CALLBACK(sm_columns[i].callback_fn), gml); i++; } selection = gtk_tree_view_get_selection( GTK_TREE_VIEW(gml->search.list_results)); if (gtk_tree_selection_count_selected_rows(selection) > 1) multiple = TRUE; if (gtk_tree_selection_count_selected_rows(selection) == 0) none = TRUE; menu = gtk_menu_new(); menuitem = gtk_image_menu_item_new_from_stock(GTK_STOCK_ADD, NULL); if (none) gtk_widget_set_sensitive(menuitem, FALSE); g_signal_connect(menuitem, "activate", G_CALLBACK(cb_search_add_button_pressed), userdata); gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); menuitem = gtk_image_menu_item_new_with_mnemonic("_Insert after selected playlist item"); gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuitem), gtk_image_new_from_stock(GTK_STOCK_ADD, GTK_ICON_SIZE_SMALL_TOOLBAR)); if (none || gml_pl_get_selected_pos(gml) == -1) gtk_widget_set_sensitive(menuitem, FALSE); g_signal_connect(menuitem, "activate", G_CALLBACK(cb_search_popup_insert_pressed), userdata); gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); menuitem = gtk_image_menu_item_new_from_stock(GTK_STOCK_DIALOG_INFO, NULL); if (multiple || none) gtk_widget_set_sensitive(menuitem, FALSE); g_signal_connect(menuitem, "activate", G_CALLBACK(cb_search_popup_info_pressed), userdata); gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); menuitem = gtk_image_menu_item_new_with_mnemonic("Search for _Artist"); gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuitem), gtk_image_new_from_stock(GTK_STOCK_FIND, GTK_ICON_SIZE_SMALL_TOOLBAR)); if (multiple || none) gtk_widget_set_sensitive(menuitem, FALSE); g_signal_connect(menuitem, "activate", G_CALLBACK(cb_search_popup_search_artist_pressed), userdata); gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); menuitem = gtk_image_menu_item_new_with_mnemonic("Search for Al_bum"); gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuitem), gtk_image_new_from_stock(GTK_STOCK_FIND, GTK_ICON_SIZE_SMALL_TOOLBAR)); if (multiple || none) gtk_widget_set_sensitive(menuitem, FALSE); g_signal_connect(menuitem, "activate", G_CALLBACK(cb_search_popup_search_album_pressed), userdata); gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); menuitem = gtk_image_menu_item_new_with_mnemonic("Re_hash"); gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuitem), gtk_image_new_from_stock(GTK_STOCK_EXECUTE, GTK_ICON_SIZE_SMALL_TOOLBAR)); if (none) gtk_widget_set_sensitive(menuitem, FALSE); g_signal_connect(menuitem, "activate", G_CALLBACK(cb_search_rehash_button_pressed), userdata); gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); menuitem = gtk_image_menu_item_new_with_mnemonic("_Remove from Medialib"); gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuitem), gtk_image_new_from_stock(GTK_STOCK_DELETE, GTK_ICON_SIZE_SMALL_TOOLBAR)); if (none) gtk_widget_set_sensitive(menuitem, FALSE); g_signal_connect(menuitem, "activate", G_CALLBACK(cb_search_remove_button_pressed), userdata); gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); menuitem = gtk_separator_menu_item_new(); gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); menuitem = gtk_menu_item_new_with_mnemonic("_Columns"); gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), menu_columns); gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); gtk_widget_show_all(menu); gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, (event != NULL) ? event->button : 0, gdk_event_get_time((GdkEvent*)event)); } static gboolean cb_search_selection_button_press(GtkWidget *treeview, GdkEventButton *event, gpointer userdata) { gboolean result = FALSE; if (event->type == GDK_BUTTON_PRESS && event->button == 3) { search_view_popup_menu(treeview, event, userdata); result = TRUE; } return result; } static gboolean cb_search_selection_popup_menu(GtkWidget *treeview, gpointer userdata) { search_view_popup_menu(treeview, NULL, userdata); return TRUE; } static int n_add_result_notified(xmmsv_t *val, void *arguments) { static const char *pref[] = { "client/generic", "server", "plugins/*", "client/*", "*", NULL }; struct search_params *arg = (struct search_params*)arguments; gchar *artist = "[Unknown Artist]"; gchar *album = "[Unknown Album]"; gchar *title = "[Unknown Title]"; gchar *filename = NULL; gint32 id, tracknr = -1, rating = -1; static gint tmp_id = -1; GtkTreeIter iter; val = xmmsv_propdict_to_dict(val, pref); xmmsv_dict_entry_get_int(val, "id", &id); xmmsv_dict_entry_get_int(val, "tracknr", &tracknr); xmmsv_dict_entry_get_int(val, "rating", &rating); rating--; if (xmmsv_dict_entry_get_string(val, "title", (const gchar **)&title)) { xmmsv_dict_entry_get_string(val, "artist", (const gchar **)&artist); xmmsv_dict_entry_get_string(val, "album", (const gchar **)&album); } else { gchar *url, *url_utf8; xmmsv_dict_entry_get_string(val, "url", (const gchar **)&url); if (url) { url_utf8 = decode_url(url); filename = g_path_get_basename(url_utf8); g_free(url_utf8); if (filename) { artist = filename; title = filename; } } } if (tmp_id != id) { gchar album_with_tracknr[256]; if (tracknr > 0 && arg->gml->album_tracknr_digits > 0) if (arg->gml->album_tracknr_digits >= 3) snprintf(album_with_tracknr, 256, "%s [%03d]", album, tracknr); else snprintf(album_with_tracknr, 256, "%s [%02d]", album, tracknr); else snprintf(album_with_tracknr, 256, "%s", album); tmp_id = id; if (arg->gml->search.ls != NULL) { gtk_list_store_append(arg->gml->search.ls, &iter); gtk_list_store_set(arg->gml->search.ls, &iter, 0, id, 1, artist, 2, title, 3, album_with_tracknr, -1); if (rating >= 0 && rating <= 4) gtk_list_store_set(arg->gml->search.ls, &iter, 4, arg->gml->playlist.icon_rating[rating], -1); } } if (filename) g_free(filename); xmmsv_unref(val); return FALSE; } static void add_results(GList *n, struct search_params *arg) { for (; n; n = g_list_next(n)) { gint32 id = 0; xmmsc_result_t *res = NULL; id = *(gint32 *)(n->data); g_free(n->data); if (id) { res = xmmsc_medialib_get_info(arg->conn, id); xmmsc_result_notifier_set(res, n_add_result_notified, arg); xmmsc_result_unref(res); } else { printf("Empty result!\n"); } } g_list_free(n); } static int n_continue_search(xmmsv_t *val, void *arguments) { struct search_params *arg = (struct search_params*)arguments; GList *n = NULL; xmmsv_list_iter_t *it; char const *xerr; if (xmmsv_get_error(val, &xerr)) { printf("%s\n", xerr); } xmmsv_get_list_iter(val, &it); for (; xmmsv_list_iter_valid(it); xmmsv_list_iter_next(it)) { gint32 *id = g_malloc(sizeof(gint32)); xmmsv_t *entry; xmmsv_list_iter_entry(it, &entry); if (!xmmsv_get_int(entry, id)) { printf("gxmms2: Broken resultset.\n"); } n = g_list_prepend(n, id); } add_results(n, arg); xmmsc_coll_unref(arg->coll_query); gml_set_statusbar_text(arg->gml, "Ready."); gtk_widget_set_sensitive(arg->gml->search.button_search, TRUE); gtk_widget_set_sensitive(arg->gml->search.entry_searchstring, TRUE); gtk_widget_set_sensitive(arg->gml->search.search_combo, TRUE); gtk_widget_set_sensitive(arg->gml->search.checkbutton_exact, TRUE); return FALSE; } gboolean gml_search_get_column_id_visible(GMedialib *gml) { return gml->search.column_id_visible; } gboolean gml_search_get_column_artist_visible(GMedialib *gml) { return gml->search.column_artist_visible; } gboolean gml_search_get_column_track_visible(GMedialib *gml) { return gml->search.column_track_visible; } gboolean gml_search_get_column_album_visible(GMedialib *gml) { return gml->search.column_album_visible; } gboolean gml_search_get_column_rating_visible(GMedialib *gml) { return gml->search.column_rating_visible; } void gml_search_set_column_id_visible(GMedialib *gml, gboolean visible) { gml->search.column_id_visible = visible; gtk_tree_view_column_set_visible(gml->search.column_id, visible); } void gml_search_set_column_artist_visible(GMedialib *gml, gboolean visible) { gml->search.column_artist_visible = visible; gtk_tree_view_column_set_visible(gml->search.column_artist, visible); } void gml_search_set_column_track_visible(GMedialib *gml, gboolean visible) { gml->search.column_track_visible = visible; gtk_tree_view_column_set_visible(gml->search.column_track, visible); } void gml_search_set_column_album_visible(GMedialib *gml, gboolean visible) { gml->search.column_album_visible = visible; gtk_tree_view_column_set_visible(gml->search.column_album, visible); } void gml_search_set_column_rating_visible(GMedialib *gml, gboolean visible) { gml->search.column_rating_visible = visible; gtk_tree_view_column_set_visible(gml->search.column_rating, visible); } gchar *mask_sql_quotes(gchar *string) { int i, j; gchar *result = g_malloc((strlen(string) + 1) * 2 * sizeof(gchar)); /* mask sql single quotes ' with '' : */ for (i = 0, j = 0; i < strlen(string); i++) { if (string[i] == '\'') { result[j] = '\''; result[j+1] = '\''; j+=2; } else { result[j] = string[i]; j++; } } result[j] = '\0'; return result; } void gmedialib_search(GMedialib *gml, xmmsc_connection_t *conn, gchar *category, gchar *search_str, gboolean exact) { xmmsc_result_t *res; static struct search_params p; xmmsc_coll_t *coll_query; gchar pattern[1024]; if (category == NULL) category = ""; gml_set_statusbar_text(gml, "Searching..."); if (!exact) snprintf(pattern, 1023, "%s~\"%s\"", category, search_str); else snprintf(pattern, 1023, "%s:\"%s\"", category, search_str); if (!xmmsc_coll_parse(pattern, &coll_query)) printf("gxmms2: Unable to generate query: %s\n", pattern); res = xmmsc_coll_query_ids(conn, coll_query, NULL, 0, 0); p.gml = gml; p.conn = connection; p.category = category; p.search_str = search_str; p.coll_query = coll_query; xmmsc_result_notifier_set(res, n_continue_search, &p); xmmsc_result_unref(res); } void gmedialib_refresh(GMedialib *gml, xmmsc_connection_t *conn) { gchar *category = map_category(gml->search.last_category); gtk_entry_set_text( GTK_ENTRY(gml->search.entry_searchstring), gml->search.last_search_str); gtk_combo_box_set_active( GTK_COMBO_BOX(gml->search.search_combo), gml->search.last_category); gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(gml->search.checkbutton_exact), gml->search.last_exact); gmedialib_search(gml, conn, category, gml->search.last_search_str, gml->search.last_exact); g_free(category); } void gml_create_mlib_search(GMedialib *gml) { GtkCellRenderer *renderer_pixbuf; GtkTreeSelection *selection; GtkTooltips *tooltips; gml->search.frame = gtk_frame_new("Media Lib"); gtk_container_set_border_width(GTK_CONTAINER(gml->search.frame), 2); /* table mlib search */ gml->search.table = gtk_table_new(3, 5, FALSE); gtk_container_set_border_width(GTK_CONTAINER(gml->search.table), 3); gtk_table_set_row_spacings(GTK_TABLE(gml->search.table), 4); gtk_table_set_col_spacings(GTK_TABLE(gml->search.table), 4); gtk_container_add(GTK_CONTAINER(gml->search.frame), gml->search.table); /* ... */ gml->search.label_search = gtk_label_new("Search for:"); gtk_table_attach(GTK_TABLE(gml->search.table), gml->search.label_search, 0, 1, 0, 1, GTK_SHRINK, GTK_SHRINK, 0, 0); gml->search.search_combo = gtk_combo_box_new_text(); gtk_combo_box_append_text(GTK_COMBO_BOX(gml->search.search_combo), "Anything"); gtk_combo_box_append_text(GTK_COMBO_BOX(gml->search.search_combo), "Artist"); gtk_combo_box_append_text(GTK_COMBO_BOX(gml->search.search_combo), "Track"); gtk_combo_box_append_text(GTK_COMBO_BOX(gml->search.search_combo), "Album"); gtk_combo_box_append_text(GTK_COMBO_BOX(gml->search.search_combo), "URL"); gtk_combo_box_set_active(GTK_COMBO_BOX(gml->search.search_combo), 0); gtk_table_attach(GTK_TABLE(gml->search.table), gml->search.search_combo, 1, 2, 0, 1, GTK_SHRINK, GTK_SHRINK, 0, 0); gml->search.entry_searchstring = gtk_entry_new(); gtk_table_attach(GTK_TABLE(gml->search.table), gml->search.entry_searchstring, 2, 3, 0, 1, GTK_FILL | GTK_EXPAND, GTK_SHRINK, 0, 0); /* exact button */ gml->search.checkbutton_exact = gtk_check_button_new_with_mnemonic("e_xact"); gtk_table_attach(GTK_TABLE(gml->search.table), gml->search.checkbutton_exact, 3, 4, 0, 1, GTK_SHRINK, GTK_SHRINK, 0, 0); /* search button */ gml->search.button_search = gtk_button_new(); gml->search.image_search = gtk_image_new_from_stock(GTK_STOCK_FIND, GTK_ICON_SIZE_MENU); gtk_container_add(GTK_CONTAINER(gml->search.button_search), gml->search.image_search); gtk_table_attach(GTK_TABLE(gml->search.table), gml->search.button_search, 4, 5, 0, 1, GTK_SHRINK, GTK_SHRINK, 0, 0); /* list mlib */ gml->search.ls = gtk_list_store_new(5, G_TYPE_INT, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, GDK_TYPE_PIXBUF); gml->search.list_results = gtk_tree_view_new_with_model(GTK_TREE_MODEL(gml->search.ls)); gtk_tree_view_set_enable_search(GTK_TREE_VIEW(gml->search.list_results), TRUE); selection = gtk_tree_view_get_selection( GTK_TREE_VIEW(gml->search.list_results)); gtk_tree_selection_set_mode(selection, GTK_SELECTION_MULTIPLE); gml->search.scroll_widget = gtk_scrolled_window_new(NULL, NULL); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(gml->search.scroll_widget), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS); gtk_table_attach(GTK_TABLE(gml->search.table), gml->search.scroll_widget, 0, 5, 1, 2, GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, 0, 0); gtk_container_add(GTK_CONTAINER(gml->search.scroll_widget), gml->search.list_results); gml->search.column_id = gtk_tree_view_column_new_with_attributes("ID", gml->renderer_text, "text", 0, NULL); gtk_tree_view_append_column(GTK_TREE_VIEW(gml->search.list_results), gml->search.column_id); gtk_tree_view_column_set_sort_column_id(gml->search.column_id, 0); gtk_tree_view_column_set_resizable(gml->search.column_id, TRUE); gtk_tree_view_column_set_cell_data_func(gml->search.column_id, gml->renderer_text, gml_cell_data_function, gml, NULL); gml->search.column_artist = gtk_tree_view_column_new_with_attributes("Artist", gml->renderer_text_ellipsize, "text", 1, NULL); gtk_tree_view_append_column(GTK_TREE_VIEW(gml->search.list_results), gml->search.column_artist); gtk_tree_view_column_set_sort_column_id(gml->search.column_artist, 1); gtk_tree_view_column_set_expand(gml->search.column_artist, TRUE); gtk_tree_view_column_set_resizable(gml->search.column_artist, TRUE); gtk_tree_view_column_set_cell_data_func(gml->search.column_artist, gml->renderer_text_ellipsize, gml_cell_data_function, gml, NULL); gml->search.column_track = gtk_tree_view_column_new_with_attributes("Track", gml->renderer_text_ellipsize, "text", 2, NULL); gtk_tree_view_append_column(GTK_TREE_VIEW(gml->search.list_results), gml->search.column_track); gtk_tree_view_column_set_sort_column_id(gml->search.column_track, 2); gtk_tree_view_column_set_expand(gml->search.column_track, TRUE); gtk_tree_view_column_set_resizable(gml->search.column_track, TRUE); gtk_tree_view_column_set_cell_data_func(gml->search.column_track, gml->renderer_text_ellipsize, gml_cell_data_function, gml, NULL); gml->search.column_album = gtk_tree_view_column_new_with_attributes("Album [#]", gml->renderer_text_ellipsize, "text", 3, NULL); gtk_tree_view_append_column(GTK_TREE_VIEW(gml->search.list_results), gml->search.column_album); gtk_tree_view_column_set_sort_column_id(gml->search.column_album, 3); gtk_tree_view_column_set_expand(gml->search.column_album, TRUE); gtk_tree_view_column_set_resizable(gml->search.column_album, TRUE); gtk_tree_view_column_set_cell_data_func(gml->search.column_album, gml->renderer_text_ellipsize, gml_cell_data_function, gml, NULL); renderer_pixbuf = gtk_cell_renderer_pixbuf_new(); gml->search.column_rating = gtk_tree_view_column_new_with_attributes("Rating", renderer_pixbuf, "pixbuf", 4, NULL); gtk_tree_view_append_column(GTK_TREE_VIEW(gml->search.list_results), gml->search.column_rating); /*gtk_tree_view_column_set_sort_column_id(column_rating, 4);*/ gtk_tree_view_column_set_resizable(gml->search.column_rating, FALSE); /* add to playlist button */ gml->search.button_add = gtk_button_new_from_stock(GTK_STOCK_ADD); gtk_table_attach(GTK_TABLE(gml->search.table), gml->search.button_add, 0, 5, 2, 3, GTK_SHRINK, GTK_SHRINK, 0, 0); /* tooltips */ tooltips = gtk_tooltips_new(); gtk_tooltips_set_tip(tooltips, gml->search.button_search, "Search", NULL); gtk_tooltips_set_tip(tooltips, gml->search.entry_searchstring, "Enter at least 3 characters (or use exact search)", NULL); gtk_tooltips_set_tip(tooltips, gml->search.button_add, "Add selection to playlist", NULL); gml_search_set_column_id_visible (gml, TRUE); gml_search_set_column_artist_visible(gml, TRUE); gml_search_set_column_track_visible (gml, TRUE); gml_search_set_column_album_visible (gml, TRUE); gml_search_set_column_rating_visible(gml, TRUE); g_signal_connect(G_OBJECT(gml->search.button_search), "clicked", G_CALLBACK(cb_search_search_button_pressed), (gpointer)gml); g_signal_connect(G_OBJECT(gml->search.entry_searchstring), "activate", G_CALLBACK(cb_search_search_button_pressed), (gpointer)gml); g_signal_connect(G_OBJECT(gml->search.button_add), "clicked", G_CALLBACK(cb_search_add_button_pressed), (gpointer)gml); g_signal_connect(G_OBJECT(gml->search.list_results), "row-activated", G_CALLBACK(cb_search_on_tree_view_row_activated), (gpointer)gml); g_signal_connect(G_OBJECT(gml->search.list_results), "button-press-event", G_CALLBACK(cb_search_selection_button_press), (gpointer)gml); g_signal_connect(G_OBJECT(gml->search.list_results), "popup-menu", G_CALLBACK(cb_search_selection_popup_menu), (gpointer)gml); } gxmms2-0.7.1/gmedialib/gmladdfiles.h0000644000175000017500000000061110601276546015776 0ustar wejpwejp/* * File: gmladdfiles.h * * Medialib search and playlist editor * Copyright (c) 2005 Johannes Heimansberg * * requires GTK+ 2.6 or better and XMMS2 DR2 or better * * Released under the GNU General Public License v2 */ #ifndef __GMLADDFILES_H__ #define __GMLADDFILES_H__ #include struct _GMLAddFiles { GtkWidget *frame, *file_selector, *button_add; }; #endif gxmms2-0.7.1/gmedialib/gmlplaylist.h0000644000175000017500000000307110717125141016057 0ustar wejpwejp/* * File: gmlplaylist.h * * Medialib search and playlist editor * Copyright (c) 2005-2007 Johannes Heimansberg * * requires GTK+ 2.6 or better and XMMS2 * * Released under the GNU General Public License v2 */ #ifndef __GMLPLAYLIST_H__ #define __GMLPLAYLIST_H__ #include #include struct _GMLPlaylist { GtkWidget *frame, *table; GtkWidget *list, *scroll_widget; GtkWidget *button_reload_pl, *image_reload; GtkWidget *button_new_pl, *image_new; GtkWidget *button_up, *button_down, *image_up, *image_down; GtkWidget *button_play, *button_delete, *image_play, *image_delete; GtkWidget *button_info, *image_info, *button_track, *image_track; GtkWidget *button_shuffle_pl, *image_shuffle_pl; GtkWidget *button_add_rnd, *image_add_rnd; GtkWidget *button_sort_pl, *image_sort_pl, *menu_sort_pl; GtkWidget *button_save_pl, *image_save; GtkListStore *ls; GtkTreeSelection *sel; guint length, current_pos; gboolean move_finished, refresh; gint refresh_counter; GdkPixbuf *icon_rating[5]; GtkTreeViewColumn *column_pos, *column_id; GtkTreeViewColumn *column_artist, *column_track; GtkTreeViewColumn *column_album, *column_rating; gboolean column_pos_visible, column_id_visible; gboolean column_artist_visible, column_track_visible; gboolean column_album_visible, column_rating_visible; gboolean new_playlist_confirm; }; #endif gxmms2-0.7.1/gmedialib/rank3.xpm0000644000175000017500000000212510601276546015120 0ustar wejpwejp/* XPM */ static char * rank3_xpm[] = { "48 16 15 1", " c None", ". c #000000", "+ c #EEF63E", "@ c #EAF13D", "# c #F0F83F", "$ c #CBD235", "% c #E9F03D", "& c #E5EC3C", "* c #E8F03D", "= c #ABB02D", "- c #ECF33E", "; c #EFF73F", "> c #CED636", ", c #B4BA2F", "' c #CDD435", " ", " ", " ", " ", " . . . . ", " .+. .+. .+. . . ", " ..@#$.. ..@#$.. ..@#$.. .. .. ", " .######%. .######%. .######%. . . ", " .####&. .####&. .####&. . . ", " .*###=. .*###=. .*###=. . . ", " .#-.;>. .#-.;>. .#-.;>. . . . ", " .,. .'. .,. .'. .,. .'. . . . . ", " . . . . . . . . ", " ", " ", " "}; gxmms2-0.7.1/gmedialib/rank0.xpm0000644000175000017500000000162110601276546015115 0ustar wejpwejp/* XPM */ static char * rank0_xpm[] = { "48 16 2 1", " c None", ". c #000000", " ", " ", " ", " ", " . . . . ", " . . . . . . . . ", " .. .. .. .. .. .. .. .. ", " . . . . . . . . ", " . . . . . . . . ", " . . . . . . . . ", " . . . . . . . . . . . . ", " . . . . . . . . . . . . . . . . ", " . . . . . . . . ", " ", " ", " "}; gxmms2-0.7.1/gmedialib/rank4.xpm0000644000175000017500000000212510601276546015121 0ustar wejpwejp/* XPM */ static char * rank4_xpm[] = { "48 16 15 1", " c None", ". c #000000", "+ c #EEF63E", "@ c #EAF13D", "# c #F0F83F", "$ c #CBD235", "% c #E9F03D", "& c #E5EC3C", "* c #E8F03D", "= c #ABB02D", "- c #ECF33E", "; c #EFF73F", "> c #CED636", ", c #B4BA2F", "' c #CDD435", " ", " ", " ", " ", " . . . . ", " .+. .+. .+. .+. ", " ..@#$.. ..@#$.. ..@#$.. ..@#$.. ", " .######%. .######%. .######%. .######%. ", " .####&. .####&. .####&. .####&. ", " .*###=. .*###=. .*###=. .*###=. ", " .#-.;>. .#-.;>. .#-.;>. .#-.;>. ", " .,. .'. .,. .'. .,. .'. .,. .'. ", " . . . . . . . . ", " ", " ", " "}; gxmms2-0.7.1/gmedialib/gmedialib.h0000644000175000017500000001467311130200116015427 0ustar wejpwejp/* * File: gmedialib.h * * Medialib search and playlist editor * Copyright (c) 2005 Johannes Heimansberg * * requires GTK+ 2.6 or better and XMMS2 DR2 or better * * Released under the GNU General Public License v2 */ #ifndef __GMEDIALIB_H__ #define __GMEDIALIB_H__ #include #include #include #include #include "gtrackinfo/trackinfo.h" #include "gmlplaylist.h" #include "gmlsearch.h" #include "gmlbrowser.h" #include "gmlplaylists.h" #include "gmladdfiles.h" G_BEGIN_DECLS #define GMEDIALIB_TYPE (gmedialib_get_type ()) #define GMEDIALIB(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMEDIALIB_TYPE, GMedialib)) #define GMEDIALIB_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMEDIALIB_TYPE, GMedialibClass)) #define IS_GMEDIALIB(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GMEDIALIB_TYPE)) #define IS_GMEDIALIB_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GMEDIALIB_TYPE)) typedef struct _GMedialib GMedialib; typedef struct _GMedialibClass GMedialibClass; typedef struct _GMLPlaylist GMLPlaylist; typedef struct _GMLSearch GMLSearch; typedef struct _GMLPlaylists GMLPlaylists; typedef struct _GMLBrowser GMLBrowser; typedef struct _GMLAddFiles GMLAddFiles; enum { SEARCH_ANYTHING, SEARCH_ARTIST, SEARCH_TRACK, SEARCH_ALBUM }; struct _GMedialib { GtkDialog dialog; GtkWidget *notebook, *statusbar, *button_close; GtkWidget *hbox_mlib_search, *image_mlib_search, *label_mlib_search; GtkWidget *hbox_mlib_browse, *image_mlib_browse, *label_mlib_browse; GtkWidget *hbox_playlists, *image_playlists, *label_playlists; GtkWidget *hbox_mlib_add_files, *image_mlib_add_files, *label_mlib_add_files; GtkWidget *hbox_playlist, *image_playlist, *label_playlist; guint statusbar_id; GtkCellRenderer *renderer_text, *renderer_text_ellipsize; GMLSearch search; GMLBrowser browser; GMLPlaylists playlists; GMLPlaylist playlist; GMLAddFiles addfiles; gint window_width, window_height, window_pos_x, window_pos_y; gint font_size; gint album_tracknr_digits; gboolean notebook_mlib_search, notebook_mlib_browser, notebook_mlib_add_files; gboolean notebook_playlists, notebook_playlist; }; struct _GMedialibClass { GtkDialogClass parent_class; void (* gmedialib)(GMedialib *gml); }; gboolean gmedialib_set_info(GMedialib *gml, trackinfo *info); GType gmedialib_get_type(void); GtkWidget* gmedialib_new(gboolean search, gboolean browser, gboolean add_files, gboolean playlists, gboolean playlist); void gmedialib_search(GMedialib *gml, xmmsc_connection_t *conn, gchar *category, gchar *search_str, gboolean exact); void gml_cell_data_function(GtkTreeViewColumn *col, GtkCellRenderer *renderer, GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data); void gml_create_mlib_search(GMedialib *gml); void gml_create_mlib_browser(GMedialib *gml); void gml_create_mlib_add_files(GMedialib *gml); void gml_create_playlists(GMedialib *gml); void gml_create_playlist(GMedialib *gml); void gml_setup_xmms_callbacks(GMedialib *gml); gboolean gml_notebook_is_mlib_search_visible(GMedialib *gml); gboolean gml_notebook_is_mlib_browser_visible(GMedialib *gml); gboolean gml_notebook_is_mlib_add_files_visible(GMedialib *gml); gboolean gml_notebook_is_playlists_visible(GMedialib *gml); gboolean gml_notebook_is_playlist_visible(GMedialib *gml); gboolean gml_pl_get_column_pos_visible(GMedialib *gml); gboolean gml_pl_get_column_id_visible(GMedialib *gml); gboolean gml_pl_get_column_artist_visible(GMedialib *gml); gboolean gml_pl_get_column_track_visible(GMedialib *gml); gboolean gml_pl_get_column_album_visible(GMedialib *gml); gboolean gml_pl_get_column_rating_visible(GMedialib *gml); gboolean gml_pl_get_new_playlist_confirm(GMedialib *gml); gint gml_pl_get_selected_pos(GMedialib *gml); void gml_pl_refresh_playlist(GMedialib *gml); void gml_pl_set_column_pos_visible(GMedialib *gml, gboolean visible); void gml_pl_set_column_id_visible(GMedialib *gml, gboolean visible); void gml_pl_set_column_artist_visible(GMedialib *gml, gboolean visible); void gml_pl_set_column_track_visible(GMedialib *gml, gboolean visible); void gml_pl_set_column_album_visible(GMedialib *gml, gboolean visible); void gml_pl_set_column_rating_visible(GMedialib *gml, gboolean visible); void gml_pl_set_new_playlist_confirm(GMedialib *gml, gboolean confirm); void gml_pl_setup_xmms_callbacks(GMedialib *gml); void gml_mlib_browse_update_artists(GMedialib *gml); void gml_playlists_update_playlists(GMedialib *gml); void gml_search_do_search(GMedialib *gml, guint search_for, gchar* search_str); gboolean gml_search_get_column_id_visible(GMedialib *gml); gboolean gml_search_get_column_artist_visible(GMedialib *gml); gboolean gml_search_get_column_track_visible(GMedialib *gml); gboolean gml_search_get_column_album_visible(GMedialib *gml); gboolean gml_search_get_column_rating_visible(GMedialib *gml); void gml_search_set_column_id_visible(GMedialib *gml, gboolean visible); void gml_search_set_column_artist_visible(GMedialib *gml, gboolean visible); void gml_search_set_column_track_visible(GMedialib *gml, gboolean visible); void gml_search_set_column_album_visible(GMedialib *gml, gboolean visible); void gml_search_set_column_rating_visible(GMedialib *gml, gboolean visible); void gml_set_album_tracknr_digits(GMedialib *gml, gint digits); void gml_set_statusbar_text(GMedialib *gml, gchar *text); void gml_set_font_size(GMedialib *gml, gint size); gint gml_window_get_pos_x(GMedialib *gml); gint gml_window_get_pos_y(GMedialib *gml); gint gml_window_get_width(GMedialib *gml); gint gml_window_get_height(GMedialib *gml); int gml_playlist_n_add_track_with_info(xmmsv_t *val, void *arg); void gml_playlist_update_entry(GMedialib *gml, guint pos); G_END_DECLS #endif gxmms2-0.7.1/xmms2ctrl/0000755000175000017500000000000011427742710013370 5ustar wejpwejpgxmms2-0.7.1/xmms2ctrl/xmms2ctrl.c0000644000175000017500000001022111213135526015455 0ustar wejpwejp/* * File: xmms2ctrl.c * * GKrellM 2 Plugin to control XMMS2 * Copyright (c) 2005 Johannes Heimansberg * * requires GKrellM 2.0.0 or better and XMMS2 DR1 or better * * Released under the GNU General Public License v2 */ #include #include #include "xmms2ctrl.h" guint connection_error = 0; guint xmms2ctrl_get_error(void) { return connection_error; } void xmms2ctrl_set_error(guint error) { connection_error = error; } static int n_check_for_error(xmmsv_t *val, void *error) { guint e = GPOINTER_TO_INT(error); char const *xerr; if (xmmsv_get_error(val, &xerr)) { fprintf(stderr, "ERROR: %s\n", xerr); connection_error = e; } else connection_error = 0; return FALSE; } static int n_player_status_play(xmmsv_t *val, void *connection) { xmmsc_connection_t *conn = (xmmsc_connection_t *)connection; gint status = -1; xmmsc_result_t *res2; xmmsv_get_int(val, &status); if (status == XMMS_PLAYBACK_STATUS_PLAY) { res2 = xmmsc_playback_tickle(conn); xmmsc_result_notifier_set(res2, n_check_for_error, (gpointer)ERROR_CONNECTION); xmmsc_result_unref(res2); } else { res2 = xmmsc_playback_start(conn); xmmsc_result_notifier_set(res2, n_check_for_error, (gpointer)ERROR_CONNECTION); xmmsc_result_unref(res2); } return FALSE; } void xmms2ctrl_play(xmmsc_connection_t *conn) { xmmsc_result_t *res; res = xmmsc_playback_status(conn); xmmsc_result_notifier_set(res, n_player_status_play, conn); xmmsc_result_unref(res); } void xmms2ctrl_pause(xmmsc_connection_t *conn) { xmmsc_result_t *res; res = xmmsc_playback_pause(conn); xmmsc_result_notifier_set(res, n_check_for_error, (gpointer)ERROR_CONNECTION); xmmsc_result_unref(res); } static int n_player_status_start_pb(xmmsv_t *val, void *connection) { xmmsc_connection_t *conn = (xmmsc_connection_t *)connection; gint status; xmmsv_get_int(val, &status); if (status == XMMS_PLAYBACK_STATUS_PLAY) xmms2ctrl_pause(conn); else xmms2ctrl_play(conn); return FALSE; } static int n_player_status(xmmsv_t *val, void *connection) { xmmsc_connection_t *conn = (xmmsc_connection_t *)connection; gint status = -1; xmmsv_get_int(val, &status); if (status == XMMS_PLAYBACK_STATUS_PLAY) xmms2ctrl_pause(conn); else if (status == XMMS_PLAYBACK_STATUS_PAUSE) xmms2ctrl_play(conn); return FALSE; } void xmms2ctrl_toggle_pause(xmmsc_connection_t *conn, gboolean start_playback) { xmmsc_result_t *res; res = xmmsc_playback_status(conn); if (!start_playback) xmmsc_result_notifier_set(res, n_player_status, conn); else xmmsc_result_notifier_set(res, n_player_status_start_pb, conn); xmmsc_result_unref(res); } void xmms2ctrl_next(xmmsc_connection_t *conn) { xmms2ctrl_do_reljump(conn, 1); } void xmms2ctrl_prev(xmmsc_connection_t *conn) { xmms2ctrl_do_reljump(conn, -1); } void xmms2ctrl_stop(xmmsc_connection_t *conn) { xmmsc_result_t *res; res = xmmsc_playback_stop(conn); xmmsc_result_notifier_set(res, n_check_for_error, (gpointer)ERROR_CONNECTION); xmmsc_result_unref(res); } static int n_tickle_on_success(xmmsv_t *val, void *connection) { xmmsc_result_t *res2; xmmsc_connection_t *conn = (xmmsc_connection_t *)connection; char const *xerr; if (xmmsv_get_error(val, &xerr)) { fprintf(stderr, "Couldn't advance in playlist: %s\n", xerr); connection_error = ERROR_ADVANCE; } else { res2 = xmmsc_playback_tickle(conn); xmmsc_result_notifier_set(res2, n_check_for_error, (gpointer)ERROR_CONNECTION); xmmsc_result_unref(res2); } return FALSE; } void xmms2ctrl_do_reljump(xmmsc_connection_t *conn, int where) { xmmsc_result_t *res; res = xmmsc_playlist_set_next_rel(conn, where); xmmsc_result_notifier_set(res, n_tickle_on_success, conn); xmmsc_result_unref(res); } void xmms2ctrl_volume_set(xmmsc_connection_t *conn, gint volume) { xmmsc_result_t *res; res = xmmsc_playback_volume_set (conn, "left", volume); xmmsc_result_unref(res); res = xmmsc_playback_volume_set (conn, "right", volume); xmmsc_result_unref(res); } gxmms2-0.7.1/xmms2ctrl/xmms2ctrl.h0000644000175000017500000000162410601276543015476 0ustar wejpwejp/* * File: xmms2ctrl.h * * GKrellM 2 Plugin to control XMMS2 * Copyright (c) 2005 Johannes Heimansberg * * requires GKrellM 2.0.0 or better and XMMS2 DR1 or better * * Released under the GNU General Public License v2 */ #ifndef _XMMS2CTRL_H #define _XMMS2CTRL_H #include enum { ERROR_NONE = 0, ERROR_CONNECTION = 1, ERROR_ADVANCE = 2 }; guint xmms2ctrl_get_error(void); void xmms2ctrl_set_error(guint error); void xmms2ctrl_play(xmmsc_connection_t *conn); void xmms2ctrl_pause(xmmsc_connection_t *conn); void xmms2ctrl_next(xmmsc_connection_t *conn); void xmms2ctrl_prev(xmmsc_connection_t *conn); void xmms2ctrl_stop(xmmsc_connection_t *conn); void xmms2ctrl_do_reljump(xmmsc_connection_t *conn, int where); void xmms2ctrl_toggle_pause(xmmsc_connection_t *conn, gboolean start_playback); void xmms2ctrl_volume_set(xmmsc_connection_t *conn, gint volume); #endif gxmms2-0.7.1/Makefile0000644000175000017500000000526511130200116013061 0ustar wejpwejp# Makefile for gxmms2 and gkrellxmms2 # Installation directory PREFIX=/usr/local KRELLPREFIX=/usr ALLFILES=gkrellxmms2/*.c gkrellxmms2/*.h gkrellxmms2/*.xpm gmedialib/*.c gmedialib/*.h gmedialib/*.xpm gtrackinfo/*.c gtrackinfo/*.h gxmms2src/*.c gxmms2src/*.h gxmms2src/*.xpm sdecode/*.c sdecode/*.h xmms2ctrl/*.c xmms2ctrl/*.h Makefile README COPYING CHANGELOG GTK_CFLAGS=$(shell pkg-config gtk+-2.0 --cflags) GTK_LIB=$(shell pkg-config gtk+-2.0 --libs) XMMS2_CFLAGS=$(shell pkg-config xmms2-client xmms2-client-glib --cflags) XMMS2_LIB=$(shell pkg-config xmms2-client xmms2-client-glib --libs) CFLAGS ?= -O2 CFLAGS := -Wall -fPIC $(GTK_CFLAGS) $(XMMS2_CFLAGS) -I. $(CFLAGS) LIBS = $(GTK_LIB) $(XMMS2_LIB) KRELLLFLAGS=-shared CC ?= gcc OBJS=gxmms2src/gxmms2.o xmms2ctrl/xmms2ctrl.o gtrackinfo/trackinfo.o gtrackinfo/gtrackinfo.o gmedialib/gmlplaylist.o gmedialib/gmedialib.o gmedialib/gmlbrowser.o gmedialib/gmlsearch.o gmedialib/gmlplaylists.o gmedialib/gmladdfiles.o sdecode/sdecode.o gxmms2src/wejpscroller.o gxmms2src/statusdisplay.o gxmms2src/wejpvolume.o gxmms2src/wejpconfig.o gxmms2src/eggtrayicon.o KRELLOBJS=gkrellxmms2/gkrellxmms2.o xmms2ctrl/xmms2ctrl.o gtrackinfo/trackinfo.o gtrackinfo/gtrackinfo.o gmedialib/gmedialib.o gmedialib/gmlplaylist.o gmedialib/gmlbrowser.o gmedialib/gmlsearch.o gmedialib/gmlplaylists.o gmedialib/gmladdfiles.o sdecode/sdecode.o gkrellxmms2/buttons.o gkrellxmms2/setupwidget.o PROJNAME=gxmms2-$(shell awk '/define VERSION_NUMBER/ { print $$3 }' gxmms2src/gxmms2.c ) all: gxmms2 gkrellxmms2 gxmms2: $(OBJS) $(CC) $(LDFLAGS) $(OBJS) -o gxmms2 $(LIBS) gkrellxmms2: $(KRELLOBJS) $(CC) $(LDFLAGS) $(KRELLOBJS) -o gkrellxmms2.so $(KRELLLFLAGS) $(LIBS) dist: -rm -rf $(PROJNAME) mkdir $(PROJNAME) cp -rl --parents $(ALLFILES) $(PROJNAME) tar chfz $(PROJNAME).tar.gz $(PROJNAME) -rm -rf $(PROJNAME) clean: rm -f $(OBJS) $(KRELLOBJS) core *.so* *.bak *~ gxmms2 %.o: %.c $(CC) $(CFLAGS) -c -o $@ $< install: install_gxmms2 install_gkrellxmms2 install_gxmms2: install -D gxmms2 $(PREFIX)/bin/gxmms2 install -D -m 644 gxmms2src/gxmms2_mini.xpm $(PREFIX)/share/gxmms2/gxmms2_mini.xpm install -D -m 644 README $(PREFIX)/share/gxmms2/README install -D -m 644 COPYING $(PREFIX)/share/gxmms2/COPYING install_gkrellxmms2: install -D gkrellxmms2.so $(KRELLPREFIX)/lib/gkrellm2/plugins/gkrellxmms2.so install -D -m 644 README $(KRELLPREFIX)/share/gkrellxmms2/README install -D -m 644 COPYING $(KRELLPREFIX)/share/gkrellxmms2/COPYING uninstall: uninstall_gxmms2 uninstall_gkrellxmms2 uninstall_gxmms2: -rm $(PREFIX)/bin/gxmms2 -rm -rf $(PREFIX)/share/gxmms2/ uninstall_gkrellxmms2: -rm $(KRELLPREFIX)/lib/gkrellm2/plugins/gkrellxmms2.so -rm -rf $(KRELLPREFIX)/share/gkrellxmms2/ gxmms2-0.7.1/CHANGELOG0000644000175000017500000000647710601276544012665 0ustar wejpwejp--- gxmms2 and gkrellxmms2 changelog --- Changes of versions older than 0.6.0 include gxmms2 changes only. Version 0.6.5: * Compatible with DrHouse * Added "SmartScroller" option. If enabled the title does not scroll if it fits in the visible width. * Medialib: Added "Don't ask me again" checkbox to clear-playlist-confirmation-dialog. * Fixed GTK 2.10 incompatibility (about dialog) * Updated wejpconfig Version 0.6.4: * Compatible with DrGonzo * Medialib: Avoid horizontal scrollbar in search and playlist view * Medialib: Added "Insert after selected playlist item" functionality to the medialib search context menu. * Decode URLs when displayed * gxmms2: Added (optional) terminate-xmms2d-on-exit feature * gxmms2: Added (optional) xmms2d autostart feature * Medialib: Disable "MLib Add Files" tab when xmms2d is not running on the local machine. * Bugfixes Version 0.6.3: * Compatible with DrEvil * gxmms2 now remembers the time display's state (elapsed/remaining) on exit * gxmms2: Added volume control * gxmms2 and gkrellxmms2: Added optional auto-reconnect feature * Track info dialog: Added file size * Some bugfixes and minor changes Version 0.6.2: * Compatible with DrDolittle * Improved Medialib browser * Added IPC-Path config file options to both gxmms2 and gkrellxmms2 * Medialib: Added progress display (remaining files) when adding files to the medialib * Added CBR/VBR display to the file details dialog * Some Bugfixes Version 0.6.1: * Compatible with DrBombay * gxmms2: Added "MedialibFontSize" option to be able to change the font size * Medialib: Added context menus to show/hide columns in mlib search and playlist * Medialib: Allow less than 3 characters when using exact search * gxmms2: Added "drag" feature to the scroller widget * gxmms2: Tray icon * gkrellxmms2: Save plugin settings in gkrellm's config file * gkrellxmms2: Improved seeking * Bugfixes Version 0.6.0: * Compatible with DrAlban * gxmms2: Replaced old scroller with new smooth scroller * Medialib: Track ranking support * gxmms2: Remember window positions and sizes * Improved title display for untagged files * gxmms2: Added option "ScrollerDelay" to adjust the speed of the title scroller * gkrellxmms2: Added seeking support * Bugfixes Version 0.5.1: * Toggle between elapsed and remaining time with mouse click on time display or with the "t" key * Show [PAUSED]/[STOPPED] behind track name when in pause/stop mode * Added icons to medialib/playlist editor tabs Version 0.5.0: * Added playlist save/load support * Basic drag & drop support to add files to the playlist/medialib * Added XMMS1-like keyboard control for play, pause, skip, stop and search * Playlist: Delete key can be used to remove selected files from the playlist * Playlist: ALT+Cursor up/down moves the selected item up/down * Improved stream support * "MLib Add files" tab added Version 0.4.2: * DR2 required * "Sort playlist by artist" button added * Statusbar added * Pause button toggles play/pause * Modified to work with latest snapshots * Added "Search for Artist/Album" items to search context menu * Improved file details dialog * Playlist: Current track is marked as bold * MLib Search: Added "exact" checkbox Version 0.4.1: * Context menus added (playlist and search tab) * Shuffle playlist button added * "Add ten random songs" button added * gmedialib source split in multiple files gxmms2-0.7.1/sdecode/0000755000175000017500000000000011427742710013043 5ustar wejpwejpgxmms2-0.7.1/sdecode/sdecode.c0000644000175000017500000000277210601276543014624 0ustar wejpwejp/* * File: sdecode.c * * Copyright (c) 2005 Johannes Heimansberg * * Released under the GNU General Public License v2 */ #include #include #include gchar hex2char(gchar first_digit, gchar second_digit) { gchar result = 0; if (first_digit >= '0' && first_digit <= '9') result = (first_digit - '0') * 16; else if (first_digit >= 'a' && first_digit <= 'f') result = (first_digit - 'a' + 10) * 16; if (second_digit >= '0' && second_digit <= '9') result += second_digit - '0'; else if (second_digit >= 'a' && second_digit <= 'f') result += second_digit - 'a' + 10; return result; } gchar *decode_string(gchar *string) { int i, j; gchar *result = g_malloc((strlen(string) + 1) * sizeof(gchar)); /* decode %XX escape sequences to their corresponding chars: */ for (i = 0, j = 0; i < strlen(string); i++) { if (string[i] == '%') { result[j] = hex2char(string[i+1], string[i+2]); i+=2; j++; } else { result[j] = string[i]; j++; } } result[j] = '\0'; return result; } gchar *get_valid_utf8_str_alloc(const gchar *str_to_validate) { gchar *result = g_malloc(strlen(str_to_validate) + 1); if (g_utf8_validate(str_to_validate, -1, NULL)) { g_strlcpy(result, str_to_validate, strlen(str_to_validate) + 1); } else { int i; for (i = 0; i < strlen(str_to_validate) + 1; i++) { if (str_to_validate[i] >= 0) /* negative chars are non-ASCII (>127) chars */ result[i] = str_to_validate[i]; else result[i] = '?'; } } return result; } gxmms2-0.7.1/sdecode/sdecode.h0000644000175000017500000000044210601276543014621 0ustar wejpwejp/* * File: sdecode.h * * Copyright (c) 2005-2006 Johannes Heimansberg * * Released under the GNU General Public License v2 */ gchar hex2char(gchar first_digit, gchar second_digit); gchar *decode_string(gchar *string); gchar *get_valid_utf8_str_alloc(const gchar *str_to_validate);