├── src ├── ui-jack │ ├── NEWS │ ├── AUTHORS │ ├── README │ ├── .gitignore │ ├── ChangeLog │ ├── INSTALL │ ├── projectM-jack.desktop │ ├── CMakeLists.txt │ ├── projectM-jack.1 │ ├── make_bundle-no-qt.sh │ ├── make_bundle.sh │ ├── ConfigFile.cpp │ ├── ConfigFile.h │ └── qprojectM-jack.cpp ├── ui-pulseaudio │ ├── NEWS │ ├── README │ ├── ChangeLog │ ├── AUTHORS │ ├── .gitignore │ ├── INSTALL │ ├── projectM-pulseaudio.desktop │ ├── projectM-pulseaudio.1 │ ├── CMakeLists.txt │ ├── QPulseAudioDeviceChooser.hpp │ ├── QPulseAudioDeviceModel.hpp │ ├── QPulseAudioDeviceModel.cpp │ ├── QPulseAudioDeviceChooser.cpp │ ├── PulseDeviceChooserDialog.ui │ ├── QPulseAudioThread.hpp │ ├── ConfigFile.cpp │ ├── qprojectM-pulseaudio.cpp │ └── ConfigFile.h ├── CMakeLists.txt └── common │ ├── images │ └── icons │ │ ├── face0.png │ │ ├── face1.png │ │ ├── face2.png │ │ ├── face3.png │ │ ├── face4.png │ │ ├── face5.png │ │ ├── rating-1.png │ │ ├── rating-2.png │ │ ├── rating-3.png │ │ ├── rating-4.png │ │ ├── rating-5.png │ │ ├── hi16-action-collection.png │ │ ├── hi16-action-projectm_back.png │ │ ├── hi16-action-projectm_burn.png │ │ ├── hi16-action-projectm_edit.png │ │ ├── hi16-action-projectm_info.png │ │ ├── hi16-action-projectm_lock.png │ │ ├── hi16-action-projectm_next.png │ │ ├── hi16-action-projectm_play.png │ │ ├── hi16-action-projectm_redo.png │ │ ├── hi16-action-projectm_save.png │ │ ├── hi16-action-projectm_stop.png │ │ ├── hi16-action-projectm_undo.png │ │ ├── hi16-action-projectm_zoom.png │ │ ├── hi16-action-projectm_album.png │ │ ├── hi16-action-projectm_artist.png │ │ ├── hi16-action-projectm_circle.png │ │ ├── hi16-action-projectm_files.png │ │ ├── hi16-action-projectm_files2.png │ │ ├── hi16-action-projectm_music.png │ │ ├── hi16-action-projectm_pause.png │ │ ├── hi16-action-projectm_queue.png │ │ ├── hi16-action-projectm_random.png │ │ ├── hi16-action-projectm_remove.png │ │ ├── hi16-action-projectm_rescan.png │ │ ├── hi16-action-projectm_rewind.png │ │ ├── hi16-action-projectm_search.png │ │ ├── hi16-action-projectm_track.png │ │ ├── hi16-action-projectm_unlock.png │ │ ├── hi16-action-projectm_configure.png │ │ ├── hi16-action-projectm_download.png │ │ ├── hi16-action-projectm_dynamic.png │ │ ├── hi16-action-projectm_editcopy.png │ │ ├── hi16-action-projectm_equalizer.png │ │ ├── hi16-action-projectm_external.png │ │ ├── hi16-action-projectm_jamendo.png │ │ ├── hi16-action-projectm_playlist.png │ │ ├── hi16-action-projectm_random_no.png │ │ ├── hi16-action-projectm_refresh.png │ │ ├── hi16-action-projectm_repeat_no.png │ │ ├── hi16-action-projectm_scripts.png │ │ ├── hi16-action-projectm_collection.png │ │ ├── hi16-action-projectm_fastforward.png │ │ ├── hi16-action-projectm_mostplayed.png │ │ ├── hi16-action-projectm_add_playlist.png │ │ ├── hi16-action-projectm_playlist_clear.png │ │ ├── hi16-action-projectm_random_album.png │ │ ├── hi16-action-projectm_random_track.png │ │ ├── hi16-action-projectm_repeat_album.png │ │ ├── hi16-action-projectm_repeat_track.png │ │ ├── hi16-action-projectm_settings_view.png │ │ ├── hi16-action-projectm_visualizations.png │ │ ├── hi16-action-projectm_change_language.png │ │ ├── hi16-action-projectm_favourite_genres.png │ │ ├── hi16-action-projectm_playlist_refresh.png │ │ ├── hi16-action-projectm_repeat_playlist.png │ │ ├── hi16-action-projectm_settings_engine.png │ │ ├── hi16-action-projectm_settings_general.png │ │ ├── hi16-action-projectm_settings_indicator.png │ │ ├── hi16-action-projectm_settings_playback.png │ │ ├── hi16-action-projectm_remove_from_playlist.png │ │ └── prjm16-transparent.svg │ ├── .gitignore │ ├── application.qrc │ ├── ReadMe │ ├── qplaylistfiledialog.cpp │ ├── CMakeLists.txt │ ├── templates │ ├── h │ └── cpp │ ├── qpresettextedit.hpp │ ├── nullable.hpp │ ├── qpresetfiledialog.hpp │ ├── qprojectmconfigdialog.hpp │ ├── qpreseteditordialog.hpp │ ├── qpresettextedit.cpp │ ├── qpreseteditordialog.ui │ ├── qprojectm.hpp │ ├── qpreseteditordialog.cpp │ ├── qplaylisttableview.hpp │ ├── qplaylistmodel.hpp │ ├── configfile.cpp │ ├── qplaylistfiledialog.hpp │ ├── qxmlplaylisthandler.hpp │ ├── qprojectm_mainwindow.hpp │ ├── qprojectmconfigdialog.cpp │ ├── configfile.hpp │ ├── qprojectmwidget.hpp │ └── qplaylistmodel.cpp ├── README.md ├── cmake ├── FindJACK.cmake └── FindPulseaudio.cmake └── CMakeLists.txt /src/ui-jack/NEWS: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/ui-jack/AUTHORS: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/ui-pulseaudio/NEWS: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/ui-jack/README: -------------------------------------------------------------------------------- 1 | see INSTALL -------------------------------------------------------------------------------- /src/ui-jack/.gitignore: -------------------------------------------------------------------------------- 1 | projectM_jack -------------------------------------------------------------------------------- /src/ui-pulseaudio/README: -------------------------------------------------------------------------------- 1 | see INSTALL -------------------------------------------------------------------------------- /src/ui-jack/ChangeLog: -------------------------------------------------------------------------------- 1 | 10/10/2007 FIRST RELEASE! -------------------------------------------------------------------------------- /src/ui-pulseaudio/ChangeLog: -------------------------------------------------------------------------------- 1 | 10/10/2007 FIRST RELEASE! -------------------------------------------------------------------------------- /src/ui-pulseaudio/AUTHORS: -------------------------------------------------------------------------------- 1 | Carmelo Piccione (carmelo.piccione+projectM@gmail.com) 2 | 3 | -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(common) 2 | add_subdirectory(ui-jack) 3 | add_subdirectory(ui-pulseaudio) 4 | -------------------------------------------------------------------------------- /src/common/images/icons/face0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectM-visualizer/frontend-qt/HEAD/src/common/images/icons/face0.png -------------------------------------------------------------------------------- /src/common/images/icons/face1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectM-visualizer/frontend-qt/HEAD/src/common/images/icons/face1.png -------------------------------------------------------------------------------- /src/common/images/icons/face2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectM-visualizer/frontend-qt/HEAD/src/common/images/icons/face2.png -------------------------------------------------------------------------------- /src/common/images/icons/face3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectM-visualizer/frontend-qt/HEAD/src/common/images/icons/face3.png -------------------------------------------------------------------------------- /src/common/images/icons/face4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectM-visualizer/frontend-qt/HEAD/src/common/images/icons/face4.png -------------------------------------------------------------------------------- /src/common/images/icons/face5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectM-visualizer/frontend-qt/HEAD/src/common/images/icons/face5.png -------------------------------------------------------------------------------- /src/common/images/icons/rating-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectM-visualizer/frontend-qt/HEAD/src/common/images/icons/rating-1.png -------------------------------------------------------------------------------- /src/common/images/icons/rating-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectM-visualizer/frontend-qt/HEAD/src/common/images/icons/rating-2.png -------------------------------------------------------------------------------- /src/common/images/icons/rating-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectM-visualizer/frontend-qt/HEAD/src/common/images/icons/rating-3.png -------------------------------------------------------------------------------- /src/common/images/icons/rating-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectM-visualizer/frontend-qt/HEAD/src/common/images/icons/rating-4.png -------------------------------------------------------------------------------- /src/common/images/icons/rating-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectM-visualizer/frontend-qt/HEAD/src/common/images/icons/rating-5.png -------------------------------------------------------------------------------- /src/common/images/icons/hi16-action-collection.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectM-visualizer/frontend-qt/HEAD/src/common/images/icons/hi16-action-collection.png -------------------------------------------------------------------------------- /src/common/images/icons/hi16-action-projectm_back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectM-visualizer/frontend-qt/HEAD/src/common/images/icons/hi16-action-projectm_back.png -------------------------------------------------------------------------------- /src/common/images/icons/hi16-action-projectm_burn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectM-visualizer/frontend-qt/HEAD/src/common/images/icons/hi16-action-projectm_burn.png -------------------------------------------------------------------------------- /src/common/images/icons/hi16-action-projectm_edit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectM-visualizer/frontend-qt/HEAD/src/common/images/icons/hi16-action-projectm_edit.png -------------------------------------------------------------------------------- /src/common/images/icons/hi16-action-projectm_info.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectM-visualizer/frontend-qt/HEAD/src/common/images/icons/hi16-action-projectm_info.png -------------------------------------------------------------------------------- /src/common/images/icons/hi16-action-projectm_lock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectM-visualizer/frontend-qt/HEAD/src/common/images/icons/hi16-action-projectm_lock.png -------------------------------------------------------------------------------- /src/common/images/icons/hi16-action-projectm_next.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectM-visualizer/frontend-qt/HEAD/src/common/images/icons/hi16-action-projectm_next.png -------------------------------------------------------------------------------- /src/common/images/icons/hi16-action-projectm_play.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectM-visualizer/frontend-qt/HEAD/src/common/images/icons/hi16-action-projectm_play.png -------------------------------------------------------------------------------- /src/common/images/icons/hi16-action-projectm_redo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectM-visualizer/frontend-qt/HEAD/src/common/images/icons/hi16-action-projectm_redo.png -------------------------------------------------------------------------------- /src/common/images/icons/hi16-action-projectm_save.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectM-visualizer/frontend-qt/HEAD/src/common/images/icons/hi16-action-projectm_save.png -------------------------------------------------------------------------------- /src/common/images/icons/hi16-action-projectm_stop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectM-visualizer/frontend-qt/HEAD/src/common/images/icons/hi16-action-projectm_stop.png -------------------------------------------------------------------------------- /src/common/images/icons/hi16-action-projectm_undo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectM-visualizer/frontend-qt/HEAD/src/common/images/icons/hi16-action-projectm_undo.png -------------------------------------------------------------------------------- /src/common/images/icons/hi16-action-projectm_zoom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectM-visualizer/frontend-qt/HEAD/src/common/images/icons/hi16-action-projectm_zoom.png -------------------------------------------------------------------------------- /src/common/images/icons/hi16-action-projectm_album.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectM-visualizer/frontend-qt/HEAD/src/common/images/icons/hi16-action-projectm_album.png -------------------------------------------------------------------------------- /src/common/images/icons/hi16-action-projectm_artist.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectM-visualizer/frontend-qt/HEAD/src/common/images/icons/hi16-action-projectm_artist.png -------------------------------------------------------------------------------- /src/common/images/icons/hi16-action-projectm_circle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectM-visualizer/frontend-qt/HEAD/src/common/images/icons/hi16-action-projectm_circle.png -------------------------------------------------------------------------------- /src/common/images/icons/hi16-action-projectm_files.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectM-visualizer/frontend-qt/HEAD/src/common/images/icons/hi16-action-projectm_files.png -------------------------------------------------------------------------------- /src/common/images/icons/hi16-action-projectm_files2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectM-visualizer/frontend-qt/HEAD/src/common/images/icons/hi16-action-projectm_files2.png -------------------------------------------------------------------------------- /src/common/images/icons/hi16-action-projectm_music.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectM-visualizer/frontend-qt/HEAD/src/common/images/icons/hi16-action-projectm_music.png -------------------------------------------------------------------------------- /src/common/images/icons/hi16-action-projectm_pause.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectM-visualizer/frontend-qt/HEAD/src/common/images/icons/hi16-action-projectm_pause.png -------------------------------------------------------------------------------- /src/common/images/icons/hi16-action-projectm_queue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectM-visualizer/frontend-qt/HEAD/src/common/images/icons/hi16-action-projectm_queue.png -------------------------------------------------------------------------------- /src/common/images/icons/hi16-action-projectm_random.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectM-visualizer/frontend-qt/HEAD/src/common/images/icons/hi16-action-projectm_random.png -------------------------------------------------------------------------------- /src/common/images/icons/hi16-action-projectm_remove.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectM-visualizer/frontend-qt/HEAD/src/common/images/icons/hi16-action-projectm_remove.png -------------------------------------------------------------------------------- /src/common/images/icons/hi16-action-projectm_rescan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectM-visualizer/frontend-qt/HEAD/src/common/images/icons/hi16-action-projectm_rescan.png -------------------------------------------------------------------------------- /src/common/images/icons/hi16-action-projectm_rewind.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectM-visualizer/frontend-qt/HEAD/src/common/images/icons/hi16-action-projectm_rewind.png -------------------------------------------------------------------------------- /src/common/images/icons/hi16-action-projectm_search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectM-visualizer/frontend-qt/HEAD/src/common/images/icons/hi16-action-projectm_search.png -------------------------------------------------------------------------------- /src/common/images/icons/hi16-action-projectm_track.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectM-visualizer/frontend-qt/HEAD/src/common/images/icons/hi16-action-projectm_track.png -------------------------------------------------------------------------------- /src/common/images/icons/hi16-action-projectm_unlock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectM-visualizer/frontend-qt/HEAD/src/common/images/icons/hi16-action-projectm_unlock.png -------------------------------------------------------------------------------- /src/common/images/icons/hi16-action-projectm_configure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectM-visualizer/frontend-qt/HEAD/src/common/images/icons/hi16-action-projectm_configure.png -------------------------------------------------------------------------------- /src/common/images/icons/hi16-action-projectm_download.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectM-visualizer/frontend-qt/HEAD/src/common/images/icons/hi16-action-projectm_download.png -------------------------------------------------------------------------------- /src/common/images/icons/hi16-action-projectm_dynamic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectM-visualizer/frontend-qt/HEAD/src/common/images/icons/hi16-action-projectm_dynamic.png -------------------------------------------------------------------------------- /src/common/images/icons/hi16-action-projectm_editcopy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectM-visualizer/frontend-qt/HEAD/src/common/images/icons/hi16-action-projectm_editcopy.png -------------------------------------------------------------------------------- /src/common/images/icons/hi16-action-projectm_equalizer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectM-visualizer/frontend-qt/HEAD/src/common/images/icons/hi16-action-projectm_equalizer.png -------------------------------------------------------------------------------- /src/common/images/icons/hi16-action-projectm_external.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectM-visualizer/frontend-qt/HEAD/src/common/images/icons/hi16-action-projectm_external.png -------------------------------------------------------------------------------- /src/common/images/icons/hi16-action-projectm_jamendo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectM-visualizer/frontend-qt/HEAD/src/common/images/icons/hi16-action-projectm_jamendo.png -------------------------------------------------------------------------------- /src/common/images/icons/hi16-action-projectm_playlist.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectM-visualizer/frontend-qt/HEAD/src/common/images/icons/hi16-action-projectm_playlist.png -------------------------------------------------------------------------------- /src/common/images/icons/hi16-action-projectm_random_no.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectM-visualizer/frontend-qt/HEAD/src/common/images/icons/hi16-action-projectm_random_no.png -------------------------------------------------------------------------------- /src/common/images/icons/hi16-action-projectm_refresh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectM-visualizer/frontend-qt/HEAD/src/common/images/icons/hi16-action-projectm_refresh.png -------------------------------------------------------------------------------- /src/common/images/icons/hi16-action-projectm_repeat_no.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectM-visualizer/frontend-qt/HEAD/src/common/images/icons/hi16-action-projectm_repeat_no.png -------------------------------------------------------------------------------- /src/common/images/icons/hi16-action-projectm_scripts.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectM-visualizer/frontend-qt/HEAD/src/common/images/icons/hi16-action-projectm_scripts.png -------------------------------------------------------------------------------- /src/common/images/icons/hi16-action-projectm_collection.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectM-visualizer/frontend-qt/HEAD/src/common/images/icons/hi16-action-projectm_collection.png -------------------------------------------------------------------------------- /src/common/images/icons/hi16-action-projectm_fastforward.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectM-visualizer/frontend-qt/HEAD/src/common/images/icons/hi16-action-projectm_fastforward.png -------------------------------------------------------------------------------- /src/common/images/icons/hi16-action-projectm_mostplayed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectM-visualizer/frontend-qt/HEAD/src/common/images/icons/hi16-action-projectm_mostplayed.png -------------------------------------------------------------------------------- /src/ui-pulseaudio/.gitignore: -------------------------------------------------------------------------------- 1 | QPulseAudioDeviceChooser_moc.cpp 2 | QPulseAudioDeviceModel_moc.cpp 3 | QPulseAudioThread_moc.cpp 4 | projectM-pulseaudio 5 | ui_PulseDeviceChooserDialog.h 6 | -------------------------------------------------------------------------------- /src/common/images/icons/hi16-action-projectm_add_playlist.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectM-visualizer/frontend-qt/HEAD/src/common/images/icons/hi16-action-projectm_add_playlist.png -------------------------------------------------------------------------------- /src/common/images/icons/hi16-action-projectm_playlist_clear.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectM-visualizer/frontend-qt/HEAD/src/common/images/icons/hi16-action-projectm_playlist_clear.png -------------------------------------------------------------------------------- /src/common/images/icons/hi16-action-projectm_random_album.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectM-visualizer/frontend-qt/HEAD/src/common/images/icons/hi16-action-projectm_random_album.png -------------------------------------------------------------------------------- /src/common/images/icons/hi16-action-projectm_random_track.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectM-visualizer/frontend-qt/HEAD/src/common/images/icons/hi16-action-projectm_random_track.png -------------------------------------------------------------------------------- /src/common/images/icons/hi16-action-projectm_repeat_album.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectM-visualizer/frontend-qt/HEAD/src/common/images/icons/hi16-action-projectm_repeat_album.png -------------------------------------------------------------------------------- /src/common/images/icons/hi16-action-projectm_repeat_track.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectM-visualizer/frontend-qt/HEAD/src/common/images/icons/hi16-action-projectm_repeat_track.png -------------------------------------------------------------------------------- /src/common/images/icons/hi16-action-projectm_settings_view.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectM-visualizer/frontend-qt/HEAD/src/common/images/icons/hi16-action-projectm_settings_view.png -------------------------------------------------------------------------------- /src/common/images/icons/hi16-action-projectm_visualizations.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectM-visualizer/frontend-qt/HEAD/src/common/images/icons/hi16-action-projectm_visualizations.png -------------------------------------------------------------------------------- /src/common/images/icons/hi16-action-projectm_change_language.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectM-visualizer/frontend-qt/HEAD/src/common/images/icons/hi16-action-projectm_change_language.png -------------------------------------------------------------------------------- /src/common/images/icons/hi16-action-projectm_favourite_genres.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectM-visualizer/frontend-qt/HEAD/src/common/images/icons/hi16-action-projectm_favourite_genres.png -------------------------------------------------------------------------------- /src/common/images/icons/hi16-action-projectm_playlist_refresh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectM-visualizer/frontend-qt/HEAD/src/common/images/icons/hi16-action-projectm_playlist_refresh.png -------------------------------------------------------------------------------- /src/common/images/icons/hi16-action-projectm_repeat_playlist.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectM-visualizer/frontend-qt/HEAD/src/common/images/icons/hi16-action-projectm_repeat_playlist.png -------------------------------------------------------------------------------- /src/common/images/icons/hi16-action-projectm_settings_engine.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectM-visualizer/frontend-qt/HEAD/src/common/images/icons/hi16-action-projectm_settings_engine.png -------------------------------------------------------------------------------- /src/common/images/icons/hi16-action-projectm_settings_general.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectM-visualizer/frontend-qt/HEAD/src/common/images/icons/hi16-action-projectm_settings_general.png -------------------------------------------------------------------------------- /src/common/images/icons/hi16-action-projectm_settings_indicator.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectM-visualizer/frontend-qt/HEAD/src/common/images/icons/hi16-action-projectm_settings_indicator.png -------------------------------------------------------------------------------- /src/common/images/icons/hi16-action-projectm_settings_playback.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectM-visualizer/frontend-qt/HEAD/src/common/images/icons/hi16-action-projectm_settings_playback.png -------------------------------------------------------------------------------- /src/ui-pulseaudio/INSTALL: -------------------------------------------------------------------------------- 1 | 2 | cmake . -DCMAKE_BUILD_TYPE=RELEASE 3 | make 4 | make install 5 | 6 | You may need to type ccmake . and change the PREFIX if your system prefers /usr instead of /usr/local. -------------------------------------------------------------------------------- /src/common/images/icons/hi16-action-projectm_remove_from_playlist.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/projectM-visualizer/frontend-qt/HEAD/src/common/images/icons/hi16-action-projectm_remove_from_playlist.png -------------------------------------------------------------------------------- /src/ui-jack/INSTALL: -------------------------------------------------------------------------------- 1 | First install JACK and projectM 1.0 2 | 3 | cmake . -DCMAKE_BUILD_TYPE=RELEASE 4 | make 5 | make install 6 | 7 | You may need to type ccmake . and change the PREFIX if your system prefers /usr instead of /usr/local. -------------------------------------------------------------------------------- /src/ui-pulseaudio/projectM-pulseaudio.desktop: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Name=projectM PulseAudio Visualization 3 | GenericName=PulseAudio Stream Visualization 4 | Comment=Visualization of PulseAudio streams with projectM 5 | Exec=projectM-pulseaudio 6 | Icon=projectM 7 | Terminal=false 8 | Type=Application 9 | Categories=AudioVideo;Audio; 10 | Keywords=audio;sound;video; 11 | -------------------------------------------------------------------------------- /src/ui-jack/projectM-jack.desktop: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Name=projectM Jack Audio Visualization 3 | GenericName=JACK Audio Stream Visualization 4 | Comment=A milkdrop based music visualizer visualizing JackAudio streams on a Qt5 GUI 5 | Exec=projectM-jack 6 | Icon=projectM 7 | Type=Application 8 | Categories=AudioVideo;Audio; 9 | Keywords=audio;sound;jackd;video; 10 | Terminal=false 11 | -------------------------------------------------------------------------------- /src/common/.gitignore: -------------------------------------------------------------------------------- 1 | application_qrc.cpp 2 | qplaylistfiledialog_moc.cpp 3 | qplaylistmodel_moc.cpp 4 | qplaylisttableview_moc.cpp 5 | qpreseteditordialog_moc.cpp 6 | qpresetfiledialog_moc.cpp 7 | qpresettextedit_moc.cpp 8 | qprojectm_mainwindow_moc.cpp 9 | qprojectm_moc.cpp 10 | qprojectmconfigdialog_moc.cpp 11 | qprojectmwidget_moc.cpp 12 | ui_qpreseteditordialog.h 13 | ui_qprojectm_mainwindow.h 14 | ui_qprojectmconfigdialog.h 15 | -------------------------------------------------------------------------------- /src/ui-pulseaudio/projectM-pulseaudio.1: -------------------------------------------------------------------------------- 1 | .TH projectM-PulseAudio 1 "June 24, 2010" 2 | .SH NAME 3 | projectM-pulseaudio \- ProjectM module for PulseAudio 4 | .SH DESCRIPTION 5 | This manual page documents the 6 | .B projectM-pulseaudio 7 | command. 8 | .PP 9 | .B projectM-pulseaudio 10 | provides direct visualisation of PulseAudio streams using 11 | the projectM audio visualisation library. 12 | .PP 13 | .B projectM-pulseaudio 14 | can be run from the 15 | .B Applications 16 | menu after it was installed. 17 | .SH AUTHOR 18 | projectM-PulseAudio was written by Carmelo Piccione . 19 | .PP 20 | This manual page was written by Matthias Klumpp , 21 | for the Debian project (and may be used by others). 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | projectM Qt-based Standalone Application 2 | ======================================== 3 | 4 | This repository contains the sources of the Qt-based standalone application. This application can be used to run 5 | projectM on your local system's audio devices. It uses Qt for the graphical frontend, providing a few more features than 6 | the SDL-based application: 7 | 8 | - Preset playlist editor with XML-based load and save functionality 9 | - Changing and remembering preset ratings per playlist 10 | - A graphical dialog to change the projectM settings 11 | 12 | Currently, the application only runs on Linux-based desktops using either PulseAudio or JACK as audio backends. This 13 | will change in the future to bring the application to other Qt-supported operating systems as well. -------------------------------------------------------------------------------- /src/ui-jack/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | if(NOT ENABLE_JACK) 2 | return() 3 | endif() 4 | 5 | add_executable(projectM-Qt-JACK 6 | ConfigFile.h 7 | ConfigFile.cpp 8 | qprojectM-jack.cpp 9 | ) 10 | 11 | target_compile_definitions(projectM-Qt-JACK 12 | PRIVATE 13 | PROJECTM_PREFIX="${CMAKE_INSTALL_PREFIX}" 14 | RESOURCE_PREFIX="share/projectM" 15 | ) 16 | 17 | target_link_libraries(projectM-Qt-JACK 18 | PRIVATE 19 | projectM-Qt-Common 20 | JACK::JACK 21 | ${CMAKE_DL_LIBS} 22 | ) 23 | 24 | set_target_properties(projectM-Qt-JACK PROPERTIES 25 | OUTPUT_NAME projectM-jack 26 | ) 27 | 28 | install(TARGETS projectM-Qt-JACK 29 | RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" 30 | COMPONENT Applications 31 | ) 32 | -------------------------------------------------------------------------------- /src/common/application.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | images/icons/hi16-action-projectm_add_playlist.png 4 | images/icons/hi16-action-projectm_edit.png 5 | images/icons/hi16-action-projectm_lock.png 6 | images/icons/hi16-action-projectm_playlist_clear.png 7 | images/icons/hi16-action-projectm_random.png 8 | images/icons/hi16-action-projectm_random_no.png 9 | images/icons/hi16-action-projectm_remove.png 10 | images/icons/hi16-action-projectm_save.png 11 | images/icons/hi16-action-projectm_unlock.png 12 | images/icons/prjm16-transparent.svg 13 | images/icons/rating-1.png 14 | images/icons/rating-2.png 15 | images/icons/rating-3.png 16 | images/icons/rating-4.png 17 | images/icons/rating-5.png 18 | 19 | 20 | -------------------------------------------------------------------------------- /cmake/FindJACK.cmake: -------------------------------------------------------------------------------- 1 | # First try to use PKG_CONFIG to find JACK. 2 | find_package(PkgConfig QUIET) 3 | if(PKG_CONFIG_FOUND) 4 | pkg_check_modules(JACK jack QUIET) 5 | endif() 6 | 7 | if(NOT JACK_INCLUDEDIR OR NOT JACK_LIBRARIES) 8 | find_path(JACK_INCLUDEDIR 9 | jack/jack.h 10 | ) 11 | 12 | find_library(JACK_LIBRARIES 13 | jack 14 | ) 15 | endif() 16 | 17 | include(FindPackageHandleStandardArgs) 18 | 19 | find_package_handle_standard_args(JACK 20 | REQUIRED_VARS JACK_LIBRARIES JACK_INCLUDEDIR 21 | VERSION_VAR JACK_VERSION 22 | ) 23 | 24 | if(JACK_FOUND AND NOT TARGET JACK::JACK) 25 | add_library(JACK::JACK INTERFACE IMPORTED) 26 | 27 | set_target_properties(JACK::JACK PROPERTIES 28 | INTERFACE_LINK_LIBRARIES "${JACK_LIBRARIES}" 29 | INTERFACE_LINK_DIRECTORIES "${JACK_LIBRARY_DIRS}" 30 | INTERFACE_INCLUDE_DIRECTORIES "${JACK_INCLUDEDIR}" 31 | INTERFACE_COMPILE_OPTIONS "${JACK_CFLAGS}" 32 | ) 33 | endif() 34 | -------------------------------------------------------------------------------- /src/common/ReadMe: -------------------------------------------------------------------------------- 1 | PROJECTM-QT README 2 | ------------------ 3 | 4 | projectM-qt is a GUI designed to enhance the projectM user and preset writer 5 | experience. I could say it's the best direction for projectM and that's why I 6 | wrote it, but it was really a curious digression in Qt4. 7 | 8 | Please visit the wiki at http://projectm.wiki.sf.net for build instructions. 9 | If you're lazy, just make sure you have cmake installed and type 10 | 11 | - 12 | cmake . 13 | - 14 | 15 | then 16 | 17 | - 18 | make 19 | make install 20 | - 21 | 22 | If this fails, go online and get help! 23 | 24 | 25 | WARNING: This is my first Qt4 (or Qt*) experience. As such, there will be bugs. 26 | Please notify me if something goes wrong! There will be incremental 27 | releases henceforth fixing bugs and adding minor features. 28 | 29 | As an ode to Qt, the Qt4 platform has been generally a fun experience and 30 | is much recommended to the developer. As for cross platform support, 31 | it will be severely tested as projectM-qt for mac and win rolls out in 32 | the near future. 33 | 34 | 35 | Thanks for using projectM-Qt and good luck! 36 | 37 | - struktured of the projectM team (Carmelo.Piccione+projectM@gmail.com) 38 | 39 | -------------------------------------------------------------------------------- /src/common/qplaylistfiledialog.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * projectM-qt -- Qt4 based projectM GUI 3 | * Copyright (C)2003-2004 projectM Team 4 | * 5 | * This library is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public 7 | * License as published by the Free Software Foundation; either 8 | * version 2.1 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public 16 | * License along with this library; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | * See 'LICENSE.txt' included within this release 19 | * 20 | */ 21 | 22 | 23 | #include "qplaylistfiledialog.hpp" 24 | 25 | QString QPlaylistFileDialog::OPEN_PLAYLIST_TITLE("Open a playlist file"); 26 | QString QPlaylistFileDialog::OPEN_PLAYLIST_OR_DIRECTORY_TITLE("Open a playlist or directory"); 27 | QString QPlaylistFileDialog::SAVE_PLAYLIST_TITLE("Save a playlist"); 28 | 29 | -------------------------------------------------------------------------------- /src/common/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_library(projectM-Qt-Common STATIC 2 | application.qrc 3 | configfile.cpp 4 | configfile.hpp 5 | nullable.hpp 6 | qplaylistfiledialog.cpp 7 | qplaylistfiledialog.hpp 8 | qplaylistmodel.cpp 9 | qplaylistmodel.hpp 10 | qplaylisttableview.hpp 11 | qpreseteditordialog.cpp 12 | qpreseteditordialog.hpp 13 | qpreseteditordialog.ui 14 | qpresetfiledialog.hpp 15 | qpresettextedit.cpp 16 | qpresettextedit.hpp 17 | qprojectm.hpp 18 | qprojectm_mainwindow.cpp 19 | qprojectm_mainwindow.hpp 20 | qprojectm_mainwindow.ui 21 | qprojectmconfigdialog.cpp 22 | qprojectmconfigdialog.hpp 23 | qprojectmconfigdialog.ui 24 | qprojectmwidget.hpp 25 | qxmlplaylisthandler.hpp 26 | ) 27 | 28 | set_target_properties(projectM-Qt-Common PROPERTIES 29 | C_VISIBILITY_PRESET default 30 | CXX_VISIBILITY_PRESET default 31 | VISIBILITY_INLINES_HIDDEN OFF 32 | ) 33 | 34 | target_include_directories(projectM-Qt-Common 35 | PUBLIC 36 | "${CMAKE_CURRENT_SOURCE_DIR}" 37 | ) 38 | 39 | target_link_libraries(projectM-Qt-Common 40 | PUBLIC 41 | libprojectM::$,shared,static> 42 | ${QT_LINK_TARGETS} 43 | ) 44 | -------------------------------------------------------------------------------- /src/common/templates/h: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (C) 2007 by carm * 3 | * carm@localhost * 4 | * * 5 | * This program is free software; you can redistribute it and/or modify * 6 | * it under the terms of the GNU General Public License as published by * 7 | * the Free Software Foundation; either version 2 of the License, or * 8 | * (at your option) any later version. * 9 | * * 10 | * This program is distributed in the hope that it will be useful, * 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 13 | * GNU General Public License for more details. * 14 | * * 15 | * You should have received a copy of the GNU General Public License * 16 | * along with this program; if not, write to the * 17 | * Free Software Foundation, Inc., * 18 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 19 | ***************************************************************************/ 20 | -------------------------------------------------------------------------------- /src/common/templates/cpp: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Copyright (C) 2007 by carm * 3 | * carm@localhost * 4 | * * 5 | * This program is free software; you can redistribute it and/or modify * 6 | * it under the terms of the GNU General Public License as published by * 7 | * the Free Software Foundation; either version 2 of the License, or * 8 | * (at your option) any later version. * 9 | * * 10 | * This program is distributed in the hope that it will be useful, * 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 13 | * GNU General Public License for more details. * 14 | * * 15 | * You should have received a copy of the GNU General Public License * 16 | * along with this program; if not, write to the * 17 | * Free Software Foundation, Inc., * 18 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 19 | ***************************************************************************/ 20 | -------------------------------------------------------------------------------- /src/ui-jack/projectM-jack.1: -------------------------------------------------------------------------------- 1 | .TH projectM-Jack 1 "July 29, 2020" 2 | .SH NAME 3 | projectM-jack \- ProjectM module for JackAudio 4 | .SH DESCRIPTION 5 | This manual page documents the 6 | .B projectM-jack 7 | command. 8 | .PP 9 | .B projectM-jack 10 | provides direct visualisation of a JackAudio stream using 11 | the projectM audio visualisation tool. 12 | .PP 13 | .B projectM-jack 14 | offers a stereo-input-channel to connect Jack devices with. 15 | .PP 16 | .B projectM-jack 17 | can be run from the 18 | .B Applications 19 | menu after it was installed. 20 | .SH Keyboard Controls 21 | .B Up: 22 | increase beat sensitivity (max 5) 23 | .PP 24 | .B Down: 25 | decrease beat sensitivity (min 0) 26 | .PP 27 | .B Y: 28 | toggle shuffle enabled 29 | .PP 30 | .B R: 31 | jump to random preset 32 | .PP 33 | .B N: 34 | next preset 35 | .PP 36 | .B P: 37 | previous preset 38 | .PP 39 | .B Shift-N: 40 | next preset with hard cut 41 | .PP 42 | .B Shift-P: 43 | previous preset with hard cut 44 | .PP 45 | .B L: 46 | lock current preset 47 | .PP 48 | .B H or F1: 49 | show help (if supported) 50 | .PP 51 | .B F3: 52 | show preset (if supported) 53 | .PP 54 | .B F4: 55 | show stats (if supported) 56 | .PP 57 | .B F5: 58 | show FPS (if supported) 59 | .SH AUTHOR 60 | projectM-Jack was written by the projectM-Team. 61 | .PP 62 | This manual page was written by Matthias Klumpp and 63 | Dennis Braun for the Debian project (and may be used by others). 64 | -------------------------------------------------------------------------------- /src/common/qpresettextedit.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * projectM-qt -- Qt4 based projectM GUI 3 | * Copyright (C)2003-2004 projectM Team 4 | * 5 | * This library is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public 7 | * License as published by the Free Software Foundation; either 8 | * version 2.1 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public 16 | * License along with this library; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | * See 'LICENSE.txt' included within this release 19 | * 20 | */ 21 | 22 | #ifndef QPRESET_EDITOR_HPP 23 | #define QPRESET_EDITOR_HPP 24 | #include 25 | #include 26 | 27 | class QPresetTextEdit: public QTextEdit 28 | { 29 | Q_OBJECT // must include this if you use Qt signals/slots 30 | 31 | public: 32 | inline QPresetTextEdit(QWidget * parent = 0): QTextEdit(parent) {} 33 | 34 | bool loadPresetText(QString url); 35 | 36 | void keyReleaseEvent(QKeyEvent * e); 37 | 38 | signals: 39 | void applyRequested(); 40 | 41 | public slots: 42 | 43 | private: 44 | 45 | }; 46 | 47 | 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /src/common/nullable.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * projectM-qt -- Qt4 based projectM GUI 3 | * Copyright (C)2003-2004 projectM Team 4 | * 5 | * This library is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public 7 | * License as published by the Free Software Foundation; either 8 | * version 2.1 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public 16 | * License along with this library; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | * See 'LICENSE.txt' included within this release 19 | * 20 | */ 21 | 22 | #ifndef NULLABLE_HPP 23 | #define NULLABLE_HPP 24 | 25 | template 26 | class Nullable { 27 | public: 28 | Nullable(const Value & value) : m_value(value), m_hasValue(true) {} 29 | Nullable() :m_hasValue(false) {} 30 | 31 | Nullable & operator=(const Value & value) { 32 | m_value = value; 33 | m_hasValue = true; 34 | static Nullable tmp = 0; 35 | return tmp; 36 | } 37 | 38 | void nullify() { 39 | m_hasValue = false; 40 | } 41 | 42 | const Value & value() const { return m_value;} 43 | bool hasValue() const { return m_hasValue;} 44 | private: 45 | Value m_value; 46 | bool m_hasValue; 47 | }; 48 | #endif 49 | -------------------------------------------------------------------------------- /cmake/FindPulseaudio.cmake: -------------------------------------------------------------------------------- 1 | # First try to use PKG_CONFIG to find Pulseaudio. 2 | find_package(PkgConfig QUIET) 3 | if(PKG_CONFIG_FOUND) 4 | pkg_check_modules(PULSEAUDIO libpulse QUIET) 5 | endif() 6 | 7 | if(NOT PULSEAUDIO_INCLUDEDIR OR NOT PULSEAUDIO_LIBRARIES) 8 | find_path(PULSEAUDIO_INCLUDEDIR 9 | pulse/pulseaudio.h 10 | ) 11 | 12 | find_library(PULSEAUDIO_LIBRARIES 13 | pulse 14 | ) 15 | 16 | if(PULSEAUDIO_INCLUDEDIR AND EXISTS "${PULSEAUDIO_INCLUDEDIR}/pulse/version.h") 17 | file(STRINGS "${PULSEAUDIO_INCLUDEDIR}/pulse/version.h" pulseaudio_version_str 18 | REGEX "pa_get_headers_version\(\)" 19 | ) 20 | if(pulseaudio_version_str AND "${pulseaudio_version_str}" MATCHES "\\(\"([0-9.]+)\"\\)") 21 | set(PULSEAUDIO_VERSION "${CMAKE_MATCH_1}") 22 | endif() 23 | endif() 24 | 25 | set(PULSEAUDIO_CFLAGS "-D_REENTRANT") 26 | endif() 27 | 28 | include(FindPackageHandleStandardArgs) 29 | 30 | find_package_handle_standard_args(Pulseaudio 31 | REQUIRED_VARS PULSEAUDIO_LIBRARIES PULSEAUDIO_INCLUDEDIR 32 | VERSION_VAR PULSEAUDIO_VERSION 33 | ) 34 | 35 | if(Pulseaudio_FOUND AND NOT TARGET Pulseaudio::Pulseaudio) 36 | add_library(Pulseaudio::Pulseaudio INTERFACE IMPORTED) 37 | 38 | set_target_properties(Pulseaudio::Pulseaudio PROPERTIES 39 | INTERFACE_LINK_LIBRARIES "${PULSEAUDIO_LIBRARIES}" 40 | INTERFACE_LINK_DIRECTORIES "${PULSEAUDIO_LIBRARY_DIRS}" 41 | INTERFACE_INCLUDE_DIRECTORIES "${PULSEAUDIO_INCLUDEDIR}" 42 | INTERFACE_COMPILE_OPTIONS "${PULSEAUDIO_CFLAGS}" 43 | ) 44 | endif() 45 | -------------------------------------------------------------------------------- /src/common/qpresetfiledialog.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * projectM-qt -- Qt4 based projectM GUI 3 | * Copyright (C)2003-2004 projectM Team 4 | * 5 | * This library is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public 7 | * License as published by the Free Software Foundation; either 8 | * version 2.1 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public 16 | * License along with this library; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | * See 'LICENSE.txt' included within this release 19 | * 20 | */ 21 | 22 | #ifndef QPRESET_FILEDIALOG_H 23 | #define QPRESET_FILEDIALOG_H 24 | 25 | 26 | #define CONFIG_FILE "/share/projectM/config.inp" 27 | 28 | #include 29 | #include 30 | #include 31 | 32 | #include 33 | #include 34 | 35 | class QPresetFileDialog : public QFileDialog 36 | { 37 | Q_OBJECT // must include this if you use Qt signals/slots 38 | 39 | public: 40 | QPresetFileDialog(QWidget * parent = 0): 41 | QFileDialog(parent, "Add preset files", QString(), "Presets (*.prjm *.milk *.so)" ) { 42 | 43 | this->setOption(QFileDialog::DontUseNativeDialog); 44 | 45 | this->setFileMode(QFileDialog::ExistingFiles); 46 | } 47 | 48 | ~QPresetFileDialog() { } 49 | private: 50 | 51 | 52 | }; 53 | #endif 54 | -------------------------------------------------------------------------------- /src/ui-jack/make_bundle-no-qt.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | ### make_bundle-no-qt.sh A simple script to create a mac bundle without qt 3 | ### included in the bundle (depends on standard framework paths instead) 4 | ### Author: Carmelo Piccione (carmelo.piccione+projectM@gmail.com) 5 | 6 | # Path to installed qt framework on your machine 7 | PATH_TO_QT=/Developer/SDKs/MacOSX10.4u.sdk/Library/Frameworks/ 8 | BUILD_PATH=/Users/struktured/projects/projectm_trunk/src 9 | PROJECTM_QT_BUILD_PATH=${BUILD_PATH}/projectM-qt/libprojectM-qt.1.dylib 10 | 11 | # the version of qt to bundle 12 | QT_VERSION=4 13 | 14 | # The bundle top level directory 15 | APP=projectM-jack.app 16 | 17 | ## [0] Clean 18 | rm -rf ${APP} 19 | 20 | ## [1] Create framework directory 21 | mkdir ${APP} 22 | mkdir ${APP}/Contents 23 | mkdir ${APP}/Contents/Frameworks 24 | mkdir ${APP}/Contents/Plugins 25 | mkdir ${APP}/Contents/MacOs 26 | mkdir ${APP}/Contents/Resources 27 | mkdir ${APP}/Contents/Resources/fonts 28 | mkdir ${APP}/Contents/Resources/presets 29 | 30 | cp projectM-jack ${APP}/Contents/MacOs/ 31 | cp -f ${PROJECTM_QT_BUILD_PATH} ${APP}/Contents/Plugins/libprojectM-qt.dylib 32 | cp -Rf ../../fonts/*.ttf ${APP}/Contents/Resources/fonts 33 | cp -Rf ../../presets_projectM/*.prjm ${APP}/Contents/Resources/presets 34 | cp -Rf ../../presets_projectM/*.milk ${APP}/Contents/Resources/presets 35 | cp -f ${BUILD_PATH}/projectM-engine/config.inp ${APP}/Contents/Resources 36 | 37 | ## [3] Change id of each qt framework to specialized one for this bundle 38 | 39 | install_name_tool -id @executable_path/../Plugins/libprojectM-qt.dylib ${APP}/Contents/Plugins/libprojectM-qt.dylib 40 | 41 | install_name_tool -change ${PROJECTM_QT_BUILD_PATH} @executable_path/../Plugins/libprojectM-qt.dylib ${APP}/Contents/MacOs/projectM-jack 42 | 43 | -------------------------------------------------------------------------------- /src/ui-pulseaudio/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(projectM-Qt-PulseAudio 2 | ConfigFile.h 3 | ConfigFile.cpp 4 | PulseDeviceChooserDialog.ui 5 | qprojectM-pulseaudio.cpp 6 | QPulseAudioDeviceChooser.cpp 7 | QPulseAudioDeviceChooser.hpp 8 | QPulseAudioDeviceModel.cpp 9 | QPulseAudioDeviceModel.hpp 10 | QPulseAudioThread.cpp 11 | QPulseAudioDeviceModel.hpp 12 | ) 13 | 14 | target_compile_definitions(projectM-Qt-PulseAudio 15 | PRIVATE 16 | PROJECTM_PREFIX="${CMAKE_INSTALL_PREFIX}" 17 | ) 18 | 19 | # Application includes a header file from libprojectM with its full path in the source dir. 20 | target_include_directories(projectM-Qt-PulseAudio 21 | PRIVATE 22 | "${CMAKE_SOURCE_DIR}" 23 | ) 24 | 25 | target_link_libraries(projectM-Qt-PulseAudio 26 | PRIVATE 27 | projectM-Qt-Common 28 | Pulseaudio::Pulseaudio 29 | ${CMAKE_DL_LIBS} 30 | ) 31 | 32 | install(TARGETS projectM-Qt-PulseAudio 33 | RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" 34 | COMPONENT Applications 35 | ) 36 | 37 | if(CMAKE_SYSTEM_NAME STREQUAL "Linux") 38 | install(FILES "${CMAKE_SOURCE_DIR}/src/projectM-qt/images/icons/prjm16-transparent.svg" 39 | DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/scalable/apps" 40 | COMPONENT Applications 41 | RENAME projectM.svg 42 | ) 43 | 44 | install(FILES projectM-pulseaudio.desktop 45 | DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/applications" 46 | COMPONENT Applications 47 | ) 48 | 49 | install(FILES projectM-pulseaudio.1 50 | DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/man/man1" 51 | COMPONENT Applications 52 | ) 53 | endif() 54 | -------------------------------------------------------------------------------- /src/ui-pulseaudio/QPulseAudioDeviceChooser.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * projectM -- Milkdrop-esque visualisation SDK 3 | * Copyright (C)2003-2004 projectM Team 4 | * 5 | * This library is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public 7 | * License as published by the Free Software Foundation; either 8 | * version 2.1 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public 16 | * License along with this library; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | * See 'LICENSE.txt' included within this release 19 | * 20 | */ 21 | 22 | #ifndef QPULSEAUDIO_DEV_CHOOSER_HPP 23 | #define QPULSEAUDIO_DEV_CHOOSER_HPP 24 | #include "ui_PulseDeviceChooserDialog.h" 25 | #include "QPulseAudioDeviceModel.hpp" 26 | #include "QPulseAudioThread.hpp" 27 | 28 | class QDialog; 29 | 30 | 31 | class QPulseAudioDeviceChooser : public QDialog, public Ui::pulseDeviceChooserDialog { 32 | 33 | Q_OBJECT 34 | 35 | public: 36 | QPulseAudioDeviceChooser(QPulseAudioThread * pulseAudioThread, QWidget * parent, Qt::WindowFlags f = Qt::WindowFlags()); 37 | 38 | typedef QHash SourceContainer; 39 | public slots: 40 | void updateDevicesListViewLock(int state); 41 | void open(); 42 | void writeSettings(); 43 | private slots: 44 | void readSettings(); 45 | 46 | private: 47 | QPulseAudioDeviceModel _qpulseAudioDeviceModel; 48 | QPulseAudioThread * _qpulseAudioThread; 49 | }; 50 | #endif 51 | -------------------------------------------------------------------------------- /src/ui-pulseaudio/QPulseAudioDeviceModel.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * projectM -- Milkdrop-esque visualisation SDK 3 | * Copyright (C)2003-2004 projectM Team 4 | * 5 | * This library is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public 7 | * License as published by the Free Software Foundation; either 8 | * version 2.1 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public 16 | * License along with this library; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | * See 'LICENSE.txt' included within this release 19 | * 20 | */ 21 | 22 | 23 | #ifndef QPULSEAUDIODEVICEMODEL_HPP 24 | #define QPULSEAUDIODEVICEMODEL_HPP 25 | 26 | #include 27 | 28 | #include 29 | #include 30 | 31 | class QPulseAudioDeviceModel : public QAbstractListModel 32 | { 33 | Q_OBJECT // must include this if you use Qt signals/slots 34 | 35 | public slots: 36 | void updateItemHighlights(); 37 | 38 | public: 39 | QPulseAudioDeviceModel(const QHash & devices, const QHash::const_iterator & devicePosition , QObject * parent); 40 | ~QPulseAudioDeviceModel() { } 41 | 42 | 43 | 44 | QVariant data ( const QModelIndex & index, int role) const; 45 | int rowCount ( const QModelIndex & parent = QModelIndex()) const ; 46 | 47 | private: 48 | const QHash & _devices; 49 | const QHash::const_iterator & _devicePosition; 50 | }; 51 | #endif 52 | -------------------------------------------------------------------------------- /src/common/qprojectmconfigdialog.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * projectM-qt -- Qt4 based projectM GUI 3 | * Copyright (C)2003-2004 projectM Team 4 | * 5 | * This library is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public 7 | * License as published by the Free Software Foundation; either 8 | * version 2.1 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public 16 | * License along with this library; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | * See 'LICENSE.txt' included within this release 19 | * 20 | */ 21 | #ifndef QPROJECTM_CONFIG_DIALOG_HPP 22 | #define QPROJECTM_CONFIG_DIALOG_HPP 23 | #include "ui_qprojectmconfigdialog.h" 24 | #include "qprojectm_mainwindow.hpp" 25 | #include 26 | class QProjectMConfigDialog : public QDialog { 27 | 28 | Q_OBJECT 29 | 30 | public: 31 | QProjectMConfigDialog(const QString& configFile, QProjectMWidget * widget, QWidget * parent = 0, Qt::WindowFlags f = Qt::WindowFlags()); 32 | private: 33 | void loadConfig(); 34 | private slots: 35 | void openPlaylistFileDialog(); 36 | void openPlaylistDirectoryDialog(); 37 | 38 | void openMenuFontFileDialog(); 39 | void openTitleFontFileDialog(); 40 | void saveConfig(); 41 | void buttonBoxHandler(QAbstractButton * button); 42 | 43 | private: 44 | QSettings _settings; 45 | const QString _configFile; 46 | QProjectMWidget * _qprojectMWidget; 47 | Ui::QProjectMConfigDialog _ui; 48 | void populateTextureSizeComboBox(); 49 | signals: 50 | void projectM_Reset(); 51 | }; 52 | #endif 53 | -------------------------------------------------------------------------------- /src/common/qpreseteditordialog.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * projectM-qt -- Qt4 based projectM GUI 3 | * Copyright (C)2003-2004 projectM Team 4 | * 5 | * This library is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public 7 | * License as published by the Free Software Foundation; either 8 | * version 2.1 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public 16 | * License along with this library; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | * See 'LICENSE.txt' included within this release 19 | * 20 | */ 21 | 22 | #ifndef QPRESET_EDITOR_DIALOG_HPP 23 | #define QPRESET_EDITOR_DIALOG_HPP 24 | #include "ui_qpreseteditordialog.h" 25 | class QProjectMWidget; 26 | #include 27 | class QPresetEditorDialog : public QDialog { 28 | 29 | Q_OBJECT 30 | 31 | public: 32 | QPresetEditorDialog(QProjectMWidget * widget, QWidget * parent = 0, Qt::WindowFlags f = Qt::WindowFlags()); 33 | void setPreset(QString url, int rowIndex); 34 | const QString & presetUrl() const; 35 | 36 | inline int presetIndex() const { 37 | return m_index; 38 | } 39 | signals: 40 | void presetModified(int rowIndex); 41 | protected: 42 | //void keyReleaseEvent(QKeyEvent * e); 43 | public slots: 44 | 45 | 46 | private slots: 47 | void buttonBoxHandler(QAbstractButton * button); 48 | void saveFile(); 49 | void saveAndNotify(); 50 | void updateWindowTitle(); 51 | 52 | private: 53 | int m_index; 54 | void revertBuffer(); 55 | QProjectMWidget * _qprojectMWidget; 56 | Ui::QPresetEditorDialog _ui; 57 | QString m_presetUrl; 58 | 59 | 60 | 61 | 62 | }; 63 | #endif 64 | -------------------------------------------------------------------------------- /src/common/qpresettextedit.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * projectM-qt -- Qt4 based projectM GUI 3 | * Copyright (C)2003-2004 projectM Team 4 | * 5 | * This library is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public 7 | * License as published by the Free Software Foundation; either 8 | * version 2.1 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public 16 | * License along with this library; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | * See 'LICENSE.txt' included within this release 19 | * 20 | */ 21 | 22 | #include "qpresettextedit.hpp" 23 | #include 24 | #include 25 | 26 | #include 27 | 28 | void QPresetTextEdit::keyReleaseEvent(QKeyEvent * e) { 29 | 30 | switch (e->key()) { 31 | case Qt::Key_S: 32 | if (e->modifiers() & Qt::ControlModifier) { 33 | emit(applyRequested()); 34 | } 35 | e->accept(); 36 | break; 37 | default: 38 | e->ignore(); 39 | } 40 | 41 | } 42 | 43 | bool QPresetTextEdit::loadPresetText(QString url) { 44 | QFile qfile(url); 45 | if (!qfile.open(QIODevice::ReadOnly | QIODevice::Text)) { 46 | QMessageBox::warning (0, "Preset File Error", QString(tr("There was a problem trying to open the preset \"%1\". The file may no longer exist or you may not have permission to read the file.")).arg(url)); 47 | return false; 48 | } 49 | 50 | 51 | QTextStream in(&qfile); 52 | 53 | QString buffer; 54 | QTextStream out(&buffer); 55 | while (!in.atEnd()) { 56 | QString line = in.readLine(); 57 | out << line << "\n"; 58 | } 59 | 60 | this->setPlainText(out.readAll()); 61 | 62 | return true; 63 | } 64 | -------------------------------------------------------------------------------- /src/common/images/icons/prjm16-transparent.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 19 | 21 | 39 | 41 | 42 | 44 | image/svg+xml 45 | 47 | 48 | 49 | 50 | 54 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /src/ui-pulseaudio/QPulseAudioDeviceModel.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * projectM -- Milkdrop-esque visualisation SDK 3 | * Copyright (C)2003-2004 projectM Team 4 | * 5 | * This library is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public 7 | * License as published by the Free Software Foundation; either 8 | * version 2.1 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public 16 | * License along with this library; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | * See 'LICENSE.txt' included within this release 19 | * 20 | */ 21 | 22 | #include "QPulseAudioDeviceModel.hpp" 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | QPulseAudioDeviceModel::QPulseAudioDeviceModel(const QHash & devices, const QHash::const_iterator & devicePosition, QObject * parent): QAbstractListModel(parent), _devices(devices), _devicePosition(devicePosition) { 30 | 31 | } 32 | 33 | void QPulseAudioDeviceModel::updateItemHighlights() 34 | { 35 | if ( rowCount() == 0 ) 36 | return; 37 | 38 | emit ( dataChanged ( this->index (0), this->index ( rowCount()-1 ) )); 39 | } 40 | 41 | QVariant QPulseAudioDeviceModel::data ( const QModelIndex & index, int role = Qt::DisplayRole ) const 42 | { 43 | if (!index.isValid()) 44 | return QVariant(); 45 | 46 | if (index.row() >= rowCount()) 47 | return QVariant(); 48 | 49 | switch ( role ) 50 | { 51 | case Qt::DisplayRole: 52 | return _devices[index.row()]; 53 | case Qt::DecorationRole: 54 | { 55 | QIcon icon(":/check.png"); 56 | return icon; 57 | break; 58 | 59 | } 60 | 61 | case Qt::ToolTipRole: 62 | if (_devicePosition.key() == index.row()) 63 | return _devices[index.row()] + " (active)"; 64 | else 65 | return _devices[index.row()] + " (inactive)"; 66 | 67 | 68 | case Qt::BackgroundRole: 69 | if (_devicePosition.key() == index.row()) { 70 | return QColor(Qt::green); 71 | } else { 72 | return QColor(Qt::white); 73 | } 74 | default: 75 | 76 | return QVariant(); 77 | } 78 | } 79 | 80 | int QPulseAudioDeviceModel::rowCount ( const QModelIndex & parent) const 81 | { 82 | Q_UNUSED(parent); 83 | 84 | return _devices.count(); 85 | } 86 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /src/common/qpreseteditordialog.ui: -------------------------------------------------------------------------------- 1 | 2 | QPresetEditorDialog 3 | 4 | 5 | 6 | 0 7 | 0 8 | 464 9 | 383 10 | 11 | 12 | 13 | Dialog 14 | 15 | 16 | true 17 | 18 | 19 | true 20 | 21 | 22 | 23 | 24 | 1 25 | 1 26 | 461 27 | 381 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 1 36 | 2 37 | 38 | 39 | 40 | false 41 | 42 | 43 | 44 | 45 | 46 | 47 | Qt::Vertical 48 | 49 | 50 | QDialogButtonBox::Apply|QDialogButtonBox::Close|QDialogButtonBox::NoButton|QDialogButtonBox::Reset 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | QPresetTextEdit 60 | QTextEdit 61 |
qpresettextedit.hpp
62 |
63 |
64 | 65 | 66 | 67 | buttonBox 68 | accepted() 69 | QPresetEditorDialog 70 | accept() 71 | 72 | 73 | 248 74 | 254 75 | 76 | 77 | 157 78 | 274 79 | 80 | 81 | 82 | 83 | buttonBox 84 | rejected() 85 | QPresetEditorDialog 86 | reject() 87 | 88 | 89 | 316 90 | 260 91 | 92 | 93 | 286 94 | 274 95 | 96 | 97 | 98 | 99 |
100 | -------------------------------------------------------------------------------- /src/common/qprojectm.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * projectM-qt -- Qt4 based projectM GUI 3 | * Copyright (C)2003-2004 projectM Team 4 | * 5 | * This library is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public 7 | * License as published by the Free Software Foundation; either 8 | * version 2.1 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public 16 | * License along with this library; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | * See 'LICENSE.txt' included within this release 19 | * 20 | */ 21 | 22 | #ifndef QPROJECTM_HPP 23 | #define QPROJECTM_HPP 24 | 25 | #include 26 | 27 | #include 28 | #include 29 | 30 | class QProjectM : public QObject 31 | { 32 | 33 | Q_OBJECT 34 | 35 | public: 36 | explicit QProjectM(const QString& config_file) 37 | : _projectM(projectm_create(config_file.toLocal8Bit().data(), projectm_flags::PROJECTM_FLAG_DISABLE_PLAYLIST_LOAD)) 38 | { 39 | projectm_set_preset_switched_event_callback(_projectM, &QProjectM::presetSwitchedEvent, this); 40 | projectm_set_preset_switch_failed_event_callback(_projectM, &QProjectM::presetSwitchFailedEvent, this); 41 | projectm_set_preset_rating_changed_event_callback(_projectM, &QProjectM::presetRatingChanged, this); 42 | } 43 | 44 | projectm* instance() const 45 | { 46 | return _projectM; 47 | } 48 | 49 | signals: 50 | 51 | void presetSwitchedSignal(bool hardCut, unsigned int index) const; 52 | 53 | void presetSwitchFailedSignal(bool hardCut, unsigned int index, const QString& message) const; 54 | 55 | void presetRatingChangedSignal(unsigned int index, int rating, 56 | projectm_preset_rating_type ratingType) const; 57 | 58 | protected: 59 | 60 | static void presetSwitchedEvent(bool hardCut, unsigned int index, void* context) 61 | { 62 | auto qProjectM = reinterpret_cast(context); 63 | qProjectM->presetSwitchedSignal(hardCut, index); 64 | } 65 | 66 | static void presetSwitchFailedEvent(bool hardCut, unsigned int index, const char* message, void* context) 67 | { 68 | auto qProjectM = reinterpret_cast(context); 69 | qProjectM->presetSwitchFailedSignal(hardCut, index, QString(message)); 70 | } 71 | 72 | static void presetRatingChanged(unsigned int index, int rating, 73 | projectm_preset_rating_type ratingType, void* context) 74 | { 75 | auto qProjectM = reinterpret_cast(context); 76 | qProjectM->presetRatingChangedSignal(index, rating, ratingType); 77 | } 78 | 79 | projectm* _projectM{ nullptr }; 80 | }; 81 | 82 | #endif 83 | -------------------------------------------------------------------------------- /src/common/qpreseteditordialog.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * projectM-qt -- Qt4 based projectM GUI 3 | * Copyright (C)2003-2004 projectM Team 4 | * 5 | * This library is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public 7 | * License as published by the Free Software Foundation; either 8 | * version 2.1 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public 16 | * License along with this library; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | * See 'LICENSE.txt' included within this release 19 | * 20 | */ 21 | 22 | #include "qpreseteditordialog.hpp" 23 | #include 24 | #include 25 | #include 26 | 27 | QPresetEditorDialog::QPresetEditorDialog(QProjectMWidget * widget, QWidget * parent, Qt::WindowFlags f): QDialog(parent,f), _qprojectMWidget(widget) { 28 | _ui.setupUi(this); 29 | 30 | QHBoxLayout * hboxLayout = new QHBoxLayout(); 31 | 32 | hboxLayout->addWidget(_ui.layoutWidget); 33 | this->setLayout(hboxLayout); 34 | 35 | connect(_ui.buttonBox, SIGNAL(clicked(QAbstractButton*)), this, SLOT(buttonBoxHandler(QAbstractButton*))); 36 | 37 | } 38 | 39 | void QPresetEditorDialog::setPreset(QString url, int rowIndex) { 40 | 41 | disconnect(_ui.presetTextEdit, 0, this, 0); 42 | 43 | m_index = rowIndex; 44 | 45 | m_presetUrl = url; 46 | _ui.presetTextEdit->loadPresetText(url); 47 | 48 | this->setWindowTitle(QString("Preset Editor - %1 [*]").arg(url)); 49 | this->setWindowModified(false); 50 | 51 | connect(_ui.presetTextEdit, SIGNAL(textChanged()), this, SLOT(updateWindowTitle())); 52 | connect(_ui.presetTextEdit, SIGNAL(applyRequested()), this, SLOT(saveAndNotify()), Qt::DirectConnection); 53 | } 54 | 55 | 56 | void QPresetEditorDialog::updateWindowTitle() { 57 | this->setWindowModified(true); 58 | } 59 | 60 | const QString & QPresetEditorDialog::presetUrl() const { 61 | return m_presetUrl; 62 | } 63 | 64 | void QPresetEditorDialog::revertBuffer() { 65 | setPreset(m_presetUrl, m_index); 66 | } 67 | 68 | void QPresetEditorDialog::saveFile() { 69 | QFile qfile(presetUrl()); 70 | 71 | if (!qfile.open(QIODevice::ReadWrite | QIODevice::Text)) { 72 | QMessageBox::warning (0, "Preset File Error", QString(tr("There was a problem trying to save the preset \"%1\". You may not have permission to write to the file.")).arg(presetUrl())); 73 | return ; 74 | } 75 | 76 | QTextStream textStream(&qfile); 77 | 78 | textStream << _ui.presetTextEdit->toPlainText(); 79 | 80 | textStream.flush(); 81 | this->setWindowModified(false); 82 | } 83 | 84 | void QPresetEditorDialog::saveAndNotify() { 85 | 86 | qDebug() << "save and notify"; 87 | saveFile(); 88 | 89 | emit(presetModified(m_index)); 90 | } 91 | 92 | void QPresetEditorDialog::buttonBoxHandler(QAbstractButton * button) { 93 | switch (_ui.buttonBox->standardButton(button)) { 94 | case QDialogButtonBox::Close: 95 | this->hide(); 96 | break; 97 | case QDialogButtonBox::Apply: 98 | saveAndNotify(); 99 | break; 100 | case QDialogButtonBox::Reset: 101 | revertBuffer(); 102 | break; 103 | default: 104 | break; 105 | } 106 | } 107 | 108 | -------------------------------------------------------------------------------- /src/ui-pulseaudio/QPulseAudioDeviceChooser.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * projectM -- Milkdrop-esque visualisation SDK 3 | * Copyright (C)2003-2004 projectM Team 4 | * 5 | * This library is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public 7 | * License as published by the Free Software Foundation; either 8 | * version 2.1 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public 16 | * License along with this library; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | * See 'LICENSE.txt' included within this release 19 | * 20 | */ 21 | 22 | #include "QPulseAudioDeviceChooser.hpp" 23 | #include 24 | #include 25 | #include 26 | 27 | void QPulseAudioDeviceChooser::writeSettings() 28 | { 29 | 30 | QSettings settings ( "projectM", "qprojectM-pulseaudio" ); 31 | settings.setValue ( "tryFirstAvailablePlaybackMonitor", 32 | this->tryFirstPlayBackMonitorCheckBox->checkState() == Qt::Checked ); 33 | 34 | if ( _qpulseAudioThread != 0 && (_qpulseAudioThread->devices().size() > 0) && _qpulseAudioThread->sourcePosition() != _qpulseAudioThread->devices().end()) 35 | settings.setValue("pulseAudioDeviceName", *_qpulseAudioThread->sourcePosition()); 36 | 37 | } 38 | 39 | 40 | void QPulseAudioDeviceChooser::readSettings() 41 | { 42 | 43 | QSettings settings ( "projectM", "qprojectM-pulseaudio" ); 44 | 45 | bool tryFirst = settings.value 46 | ( "tryFirstAvailablePlaybackMonitor", true ).toBool() ; 47 | 48 | this->tryFirstPlayBackMonitorCheckBox->setCheckState 49 | ( tryFirst ? Qt::Checked : Qt::Unchecked ); 50 | 51 | if ( tryFirst ) 52 | { 53 | this->devicesListView->setEnabled(false); 54 | } else { 55 | this->devicesListView->setEnabled(true); 56 | } 57 | 58 | } 59 | 60 | 61 | void QPulseAudioDeviceChooser::updateDevicesListViewLock(int state) { 62 | 63 | 64 | devicesListView->setEnabled(state != Qt::Checked); 65 | 66 | if (state == Qt::Checked) { 67 | if (_qpulseAudioThread != 0) 68 | _qpulseAudioThread->connectDevice(); 69 | } 70 | } 71 | 72 | 73 | QPulseAudioDeviceChooser::QPulseAudioDeviceChooser ( QPulseAudioThread * qpulseAudioThread, QWidget * parent = 0, Qt::WindowFlags f ) : QDialog ( parent, f ), _qpulseAudioDeviceModel ( qpulseAudioThread->devices(), qpulseAudioThread->sourcePosition(), this), _qpulseAudioThread ( qpulseAudioThread ) 74 | { 75 | 76 | setupUi ( this ); 77 | readSettings(); 78 | this->devicesListView->setModel ( &_qpulseAudioDeviceModel ); 79 | 80 | 81 | QHBoxLayout * hboxLayout = new QHBoxLayout(); 82 | 83 | hboxLayout->addWidget(this->layoutWidget); 84 | this->setLayout(hboxLayout); 85 | 86 | connect ( tryFirstPlayBackMonitorCheckBox, 87 | SIGNAL(stateChanged(int)), this, SLOT(updateDevicesListViewLock(int))); 88 | 89 | // Using the display index is fine as as we are getting the text associated with it 90 | // and passing the raw string to pulse audio. 91 | connect ( devicesListView, SIGNAL ( doubleClicked ( const QModelIndex& ) ), 92 | _qpulseAudioThread, SLOT ( connectDevice ( const QModelIndex& ) ) ); 93 | 94 | connect ( _qpulseAudioThread, SIGNAL ( deviceChanged()), 95 | &_qpulseAudioDeviceModel, SLOT (updateItemHighlights())); 96 | 97 | } 98 | 99 | void QPulseAudioDeviceChooser::open() 100 | { 101 | this->show(); 102 | } 103 | 104 | -------------------------------------------------------------------------------- /src/ui-pulseaudio/PulseDeviceChooserDialog.ui: -------------------------------------------------------------------------------- 1 | 2 | pulseDeviceChooserDialog 3 | 4 | 5 | 6 | 0 7 | 0 8 | 380 9 | 271 10 | 11 | 12 | 13 | Pulse Audio Settings 14 | 15 | 16 | 17 | 18 | 10 19 | 10 20 | 361 21 | 251 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | Select a source device below. 31 | 32 | 33 | 34 | 35 | 36 | 37 | <html><head><meta name="qrichtext" content="1" /><style type="text/css"> 38 | p, li { white-space: pre-wrap; } 39 | </style></head><body style=" font-family:'Sans Serif'; font-size:10pt; font-weight:400; font-style:normal;"> 40 | <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Double click a source device to activate it.</p></body></html> 41 | 42 | 43 | true 44 | 45 | 46 | QListView::ListMode 47 | 48 | 49 | 50 | 51 | 52 | 53 | This will try to find any available playback monitor on startup as the pulseaudio source device. This is a quick and dirty way to generally get projectM sound data without specifying a device explicitly. 54 | 55 | 56 | Try first available playback monitor 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | Qt::Vertical 66 | 67 | 68 | QDialogButtonBox::Ok 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | buttonBox 81 | rejected() 82 | pulseDeviceChooserDialog 83 | reject() 84 | 85 | 86 | 316 87 | 260 88 | 89 | 90 | 286 91 | 274 92 | 93 | 94 | 95 | 96 | buttonBox 97 | accepted() 98 | pulseDeviceChooserDialog 99 | accept() 100 | 101 | 102 | 248 103 | 254 104 | 105 | 106 | 157 107 | 274 108 | 109 | 110 | 111 | 112 | 113 | -------------------------------------------------------------------------------- /src/common/qplaylisttableview.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * projectM-qt -- Qt4 based projectM GUI 3 | * Copyright (C)2003-2004 projectM Team 4 | * 5 | * This library is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public 7 | * License as published by the Free Software Foundation; either 8 | * version 2.1 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public 16 | * License along with this library; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | * See 'LICENSE.txt' included within this release 19 | * 20 | */ 21 | 22 | #ifndef QPLAYLIST_TABLEVIEW_HPP 23 | #define QPLAYLIST_TABLEVIEW_HPP 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | class QPlaylistTableView : public QTableView 32 | { 33 | Q_OBJECT // must include this if you use Qt signals/slots 34 | 35 | public: 36 | inline QPlaylistTableView(QWidget * parent = 0): 37 | QTableView(parent) {} 38 | 39 | 40 | signals: 41 | void mousePressed(QMouseEvent*, const QModelIndexList & items); 42 | void resized(QResizeEvent * event); 43 | void deletesRequested(const QModelIndexList & items); 44 | void internalDragAndDropRequested(const QModelIndexList & items, const QModelIndex & target = QModelIndex()); 45 | 46 | public slots: 47 | void dropEvent ( QDropEvent * event ) { 48 | 49 | QModelIndex dropIndex = this->indexAt(event->pos()); 50 | 51 | if (!dropIndex.isValid()) { 52 | event->ignore(); 53 | return; 54 | } 55 | 56 | const QModelIndexList & items = selectedIndexes(); 57 | 58 | if (items.empty()) { 59 | event->ignore(); 60 | return; 61 | } 62 | 63 | int i = items[0].row(); 64 | 65 | // Don't drag and drop into same slot 66 | if (i == dropIndex.row()) { 67 | event->ignore(); 68 | return; 69 | } 70 | 71 | m_firstContiguousBlock.clear(); 72 | foreach (QModelIndex index, items) { 73 | if (index.row() == i) 74 | m_firstContiguousBlock.append(index); 75 | else 76 | break; 77 | i++; 78 | } 79 | 80 | emit(internalDragAndDropRequested(m_firstContiguousBlock, dropIndex)); 81 | event->accept(); 82 | } 83 | 84 | 85 | void dragLeaveEvent ( QDragLeaveEvent * event ) { 86 | Q_UNUSED(event); 87 | //qDebug() << "drag leave"; 88 | } 89 | 90 | void dragEnterEvent ( QDragEnterEvent * event ) { 91 | //qDebug() << "drag enter event"; 92 | event->accept(); 93 | 94 | } 95 | 96 | 97 | void dragMoveEvent ( QDragMoveEvent * event ) { 98 | //qDebug() << "drag move event"; 99 | event->accept(); 100 | } 101 | 102 | inline void resizeEvent(QResizeEvent * event) { 103 | QTableView::resizeEvent(event); 104 | emit(resized(event)); 105 | } 106 | 107 | inline void mousePressEvent(QMouseEvent * event) { 108 | QAbstractItemView::mousePressEvent(event); 109 | if (event->button() == Qt::RightButton) { 110 | emit(mousePressed(event, selectedIndexes())); 111 | } 112 | else 113 | {} 114 | } 115 | 116 | inline void keyReleaseEvent(QKeyEvent * event) { 117 | 118 | switch (event->key()) { 119 | case Qt::Key_Delete: 120 | emit(deletesRequested(selectedIndexes())); 121 | break; 122 | 123 | default: 124 | event->ignore(); 125 | break; 126 | } 127 | } 128 | 129 | private: 130 | QModelIndexList m_firstContiguousBlock; 131 | }; 132 | 133 | 134 | 135 | #endif 136 | -------------------------------------------------------------------------------- /src/common/qplaylistmodel.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * projectM-qt -- Qt4 based projectM GUI 3 | * Copyright (C)2003-2004 projectM Team 4 | * 5 | * This library is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public 7 | * License as published by the Free Software Foundation; either 8 | * version 2.1 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public 16 | * License along with this library; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | * See 'LICENSE.txt' included within this release 19 | * 20 | */ 21 | 22 | #ifndef QPROJECTM_PLAYLISTMODEL_H 23 | #define QPROJECTM_PLAYLISTMODEL_H 24 | 25 | #include 26 | #include 27 | #include 28 | 29 | #include 30 | #include 31 | 32 | class QXmlStreamReader; 33 | class QDragMoveEvent; 34 | struct projectm; 35 | 36 | class QPlaylistModel : public QAbstractTableModel 37 | { 38 | Q_OBJECT // must include this if you use Qt signals/slots 39 | 40 | public: 41 | static const int URLInfoRole = Qt::UserRole; 42 | static const int RatingRole = Qt::UserRole+1; 43 | static const int NameRole = Qt::UserRole+2; 44 | static const int BreedabilityRole = Qt::UserRole+3; 45 | 46 | QPlaylistModel(projectm* _projectM, QObject * parent = 0); 47 | ~QPlaylistModel() { } 48 | bool setData(const QModelIndex & index, const QVariant & value, int role=Qt::EditRole); 49 | 50 | void appendRow (const QString & presetURL, const QString & presetName, int rating, int breedability); 51 | void insertRow (int index, const QString & presetURL, const QString & presetName, int rating, int breedability); 52 | 53 | bool removeRow (int index, const QModelIndex & parent = QModelIndex()); 54 | bool removeRows ( int row, int count, const QModelIndex & parent = QModelIndex()); 55 | QVariant headerData ( int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const; 56 | 57 | void clear(); 58 | 59 | QVariant data ( const QModelIndex & index, int role) const; 60 | int rowCount ( const QModelIndex & parent = QModelIndex()) const ; 61 | int columnCount ( const QModelIndex & parent= QModelIndex()) const ; 62 | 63 | bool readPlaylist(const QString & file); 64 | bool writePlaylist ( const QString & file ); 65 | QVariant breedabilityToIcon( int rating ) const; 66 | QString getBreedabilityToolTip(int rating) const; 67 | Qt::ItemFlags flags(const QModelIndex &index) const; 68 | 69 | 70 | inline const QString & playlistDesc() { 71 | return m_playlistDesc; 72 | } 73 | 74 | 75 | inline void setPlaylistDesc(const QString & desc) { 76 | m_playlistDesc = desc; 77 | } 78 | 79 | inline Qt::DropActions supportedDropActions() const 80 | { 81 | return Qt::MoveAction; 82 | } 83 | 84 | void notifyDataChanged(unsigned int index); 85 | 86 | inline QStringList mimeTypes () const { 87 | QStringList mimeTypes; 88 | mimeTypes << PRESET_MIME_TYPE; 89 | return mimeTypes; 90 | } 91 | 92 | bool dropMimeData(const QMimeData *data, Qt::DropAction action, 93 | int row, int column, const QModelIndex &parent); 94 | void clearItems(); 95 | 96 | public slots: 97 | void updateItemHighlights(); 98 | 99 | private: 100 | static QString getSillyRatingToolTip(int rating); 101 | void readPlaylistItem(QXmlStreamReader & reader); 102 | static QString PRESET_MIME_TYPE; 103 | QVariant ratingToIcon(int rating) const; 104 | projectm* m_projectM; 105 | QString m_playlistName; 106 | QString m_playlistDesc; 107 | 108 | private: 109 | bool softCutRatingsEnabled() const; 110 | }; 111 | #endif 112 | -------------------------------------------------------------------------------- /src/ui-jack/make_bundle.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | ### make_bund.sh A simple script to create a mac bundle #### 3 | ### Author: Carmelo Piccione (carmelo.piccione+projectM@gmail.com) ### 4 | 5 | # Path to installed qt framework on your machine 6 | PATH_TO_QT=/Developer/SDKs/MacOSX10.4u.sdk/Library/Frameworks/ 7 | BUILD_PATH=/Users/struktured/projects/projectm_trunk/src 8 | PROJECTM_QT_BUILD_PATH=${BUILD_PATH}/projectM-qt/libprojectM-qt.1.dylib 9 | 10 | # the version of qt to bundle 11 | QT_VERSION=4 12 | 13 | # The bundle top level directory 14 | APP=projectM-jack.app 15 | 16 | ## [0] Clean 17 | rm -rf ${APP} 18 | 19 | ## [1] Create framework directory 20 | mkdir ${APP} 21 | mkdir ${APP}/Contents 22 | mkdir ${APP}/Contents/Frameworks 23 | mkdir ${APP}/Contents/Plugins 24 | mkdir ${APP}/Contents/MacOs 25 | 26 | cp projectM-jack ${APP}/Contents/MAcOs/ 27 | cp -f ${PROJECTM_QT_BUILD_PATH} ${APP}/Contents/Plugins/libprojectM-qt.dylib 28 | 29 | ## [2] Copy each qt framework into the bundle 30 | cp -Rf ${PATH_TO_QT}/QtCore.framework ${APP}/Contents/Frameworks 31 | cp -Rf ${PATH_TO_QT}/QtGui.framework ${APP}/Contents/Frameworks 32 | cp -Rf ${PATH_TO_QT}/QtXml.framework ${APP}/Contents/Frameworks 33 | cp -Rf ${PATH_TO_QT}/QtOpenGL.framework ${APP}/Contents/Frameworks 34 | 35 | 36 | ## [3] Change id of each qt framework to specialized one for this bundle 37 | install_name_tool -id @executable_path/../Frameworks/QtCore.framework/Versions/${QT_VERSION}/QtCore ${APP}/Contents/Frameworks/QtCore.framework/Versions/${QT_VERSION}/QtCore 38 | 39 | install_name_tool -id @executable_path/../Frameworks/QtGui.framework/Versions/${QT_VERSION}/QtGui ${APP}/Contents/Frameworks/QtGui.framework/Versions/${QT_VERSION}/QtGui 40 | 41 | install_name_tool -id @executable_path/../Frameworks/QtXml.framework/Versions/${QT_VERSION}/QtXml ${APP}/Contents/Frameworks/QtXml.framework/Versions/${QT_VERSION}/QtXml 42 | 43 | install_name_tool -id @executable_path/../Frameworks/QtOpenGL.framework/Versions/${QT_VERSION}/QtOpenGL ${APP}/Contents/Frameworks/QtOpenGL.framework/Versions/${QT_VERSION}/QtOpenGL 44 | install_name_tool -id @executable_path/../Plugins/libprojectM-qt.dylib ${APP}/Contents/Plugins/libprojectM-qt.dylib 45 | 46 | 47 | ## [4] Change reference ids in projectM-jack to the local referred to id's 48 | install_name_tool -change QtCore.framework/Versions/${QT_VERSION}/QtCore @executable_path/../Frameworks/QtCore.framework/Versions/${QT_VERSION}/QtCore ${APP}/Contents/MacOs/projectM-jack 49 | 50 | install_name_tool -change QtGui.framework/Versions/${QT_VERSION}/QtGui @executable_path/../Frameworks/QtGui.framework/Versions/${QT_VERSION}/QtGui ${APP}/Contents/MacOs/projectM-jack 51 | 52 | install_name_tool -change QtXml.framework/Versions/${QT_VERSION}/QtXml @executable_path/../Frameworks/QtXml.framework/Versions/${QT_VERSION}/QtXml ${APP}/Contents/MacOs/projectM-jack 53 | 54 | install_name_tool -change QtOpenGL.framework/Versions/${QT_VERSION}/QtOpenGL @executable_path/../Frameworks/QtOpenGL.framework/Versions/${QT_VERSION}/QtOpenGL ${APP}/Contents/MacOs/projectM-jack 55 | 56 | install_name_tool -change ${PROJECTM_QT_BUILD_PATH} @executable_path/../Plugins/libprojectM-qt.dylib ${APP}/Contents/MacOs/projectM-jack 57 | 58 | # [4b] Change projectM-qt library reference to bundle version 59 | 60 | ## [5] Change references from one qt lib to another qt lib from system to local 61 | install_name_tool -change QtCore.framework/Versions/${QT_VERSION}/QtCore @executable_path/../Frameworks/QtCore.framework/Versions/${QT_VERSION}/QtCore ${APP}/Contents/Frameworks/QtGui.framework/Versions/${QT_VERSION}/QtGui 62 | install_name_tool -change QtCore.framework/Versions/${QT_VERSION}/QtCore @executable_path/../Frameworks/QtCore.framework/Versions/${QT_VERSION}/QtCore ${APP}/Contents/Frameworks/QtXml.framework/Versions/${QT_VERSION}/QtXml 63 | 64 | install_name_tool -change QtCore.framework/Versions/${QT_VERSION}/QtCore @executable_path/../Frameworks/QtCore.framework/Versions/${QT_VERSION}/QtCore ${APP}/Contents/Frameworks/QtOpenGL.framework/Versions/${QT_VERSION}/QtOpenGL 65 | install_name_tool -change QtGui.framework/Versions/${QT_VERSION}/QtGui @executable_path/../Frameworks/QtGui.framework/Versions/${QT_VERSION}/QtGui ${APP}/Contents/Frameworks/QtOpenGL.framework/Versions/${QT_VERSION}/QtOpenGL 66 | 67 | install_name_tool -change QtCore.framework/Versions/${QT_VERSION}/QtCore @executable_path/../Frameworks/QtCore.framework/Versions/${QT_VERSION}/QtCore ${APP}/Contents/Plugins/libprojectM-qt.dylib 68 | install_name_tool -change QtGui.framework/Versions/${QT_VERSION}/QtGui @executable_path/../Frameworks/QtGui.framework/Versions/${QT_VERSION}/QtGui ${APP}/Contents/Plugins/libprojectM-qt.dylib 69 | install_name_tool -change QtXml.framework/Versions/${QT_VERSION}/QtXml @executable_path/../Frameworks/QtXml.framework/Versions/${QT_VERSION}/QtXml ${APP}/Contents/Plugins/libprojectM-qt.dylib 70 | install_name_tool -change QtOpenGL.framework/Versions/${QT_VERSION}/QtOpenGL @executable_path/../Frameworks/QtOpenGL.framework/Versions/${QT_VERSION}/QtOpenGL ${APP}/Contents/Plugins/libprojectM-qt.dylib 71 | -------------------------------------------------------------------------------- /src/ui-pulseaudio/QPulseAudioThread.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * projectM -- Milkdrop-esque visualisation SDK 3 | * Copyright (C)2003-2004 projectM Team 4 | * 5 | * This library is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public 7 | * License as published by the Free Software Foundation; either 8 | * version 2.1 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public 16 | * License along with this library; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | * See 'LICENSE.txt' included within this release 19 | * 20 | */ 21 | 22 | #ifndef QPULSE_AUDIO_THREAD 23 | #define QPULSE_AUDIO_THREAD 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | extern "C" 34 | { 35 | #include 36 | #include 37 | } 38 | 39 | #include "qprojectm_mainwindow.hpp" 40 | 41 | 42 | class QPulseAudioThread : public QThread 43 | { 44 | Q_OBJECT 45 | public: 46 | typedef QHash SourceContainer; 47 | QPulseAudioThread () {} 48 | QPulseAudioThread 49 | (int _argc, char **_argv, QProjectM_MainWindow * qprojectM_MainWindow); 50 | virtual ~QPulseAudioThread(); 51 | void run(); 52 | 53 | QMutex * mutex(); 54 | 55 | inline const SourceContainer & devices() { 56 | return s_sourceList; 57 | } 58 | void writeSettings(); 59 | 60 | inline const SourceContainer::const_iterator & sourcePosition() { 61 | return s_sourcePosition; 62 | } 63 | 64 | public slots: 65 | 66 | void cork(); 67 | 68 | inline void insertSource(int index, const QString & name) { 69 | s_sourceList[index] = name; 70 | } 71 | 72 | void cleanup(); 73 | 74 | void connectDevice(const QModelIndex & index = QModelIndex()); 75 | 76 | signals: 77 | void deviceChanged(); 78 | void threadCleanedUp(); 79 | private: 80 | 81 | static SourceContainer::const_iterator readSettings(); 82 | 83 | static void reconnect(SourceContainer::const_iterator pos); 84 | 85 | static SourceContainer::const_iterator scanForPlaybackMonitor(); 86 | static void connectHelper (SourceContainer::const_iterator pos); 87 | static void pulseQuit ( int ret ); 88 | static void stream_moved_callback(pa_stream *s, void *userdata); 89 | static void stream_read_callback ( pa_stream *s, size_t length, void *userdata ); 90 | static void stream_state_callback ( pa_stream *s, void *userdata ); 91 | static void context_state_callback ( pa_context *c, void *userdata ); 92 | static void initialize_callbacks ( QPulseAudioThread * pulseThread ); 93 | static void context_drain_complete ( pa_context*c, void *userdata ); 94 | static void stream_drain_complete ( pa_stream*s, int success, void *userdata ); 95 | static void stdout_callback ( pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_event_flags_t f, void *userdata ); 96 | static void exit_signal_callback ( pa_mainloop_api*m, pa_signal_event *e, int sig, void *userdata ); 97 | static void stream_update_timing_callback ( pa_stream *s, int success, void *userdata ); 98 | static void sigusr1_signal_callback ( pa_mainloop_api*m, pa_signal_event *e, int sig, void *userdata ); 99 | static void pa_source_info_callback ( pa_context *c, const pa_source_info *i, int eol, void *userdata ); 100 | static void subscribe_callback ( struct pa_context *c, enum pa_subscription_event_type t, uint32_t index, void *userdata ); 101 | static void time_event_callback ( pa_mainloop_api*m, pa_time_event *e, const struct timeval *tv, void *userdata ); 102 | 103 | static void pa_stream_success_callback(pa_stream *s, int success, void *userdata); 104 | 105 | static QMutex * s_audioMutex; 106 | static SourceContainer s_sourceList; 107 | static SourceContainer::const_iterator s_sourcePosition; 108 | int argc; 109 | char ** argv; 110 | QProjectM_MainWindow * m_qprojectM_MainWindow; 111 | static pa_context *context; 112 | static pa_stream *stream; 113 | static pa_mainloop_api *mainloop_api; 114 | static pa_time_event *time_event; 115 | static float * buffer; 116 | static size_t buffer_length, buffer_index; 117 | static pa_threaded_mainloop * mainloop; 118 | static pa_io_event * stdio_event; 119 | static char * server; 120 | static char * stream_name, *client_name, *device; 121 | static QProjectM_MainWindow ** s_qprojectM_MainWindowPtr; 122 | 123 | static int verbose; 124 | 125 | static pa_volume_t volume; 126 | 127 | static pa_channel_map channel_map; 128 | static int channel_map_set;; 129 | static pa_sample_spec sample_spec ; 130 | 131 | 132 | }; 133 | #endif 134 | -------------------------------------------------------------------------------- /src/common/configfile.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * projectM-qt -- Qt4 based projectM GUI 3 | * Copyright (C)2003-2004 projectM Team 4 | * 5 | * This library is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public 7 | * License as published by the Free Software Foundation; either 8 | * version 2.1 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public 16 | * License along with this library; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | * See 'LICENSE.txt' included within this release 19 | * 20 | */ 21 | 22 | 23 | #include "configfile.hpp" 24 | 25 | using std::string; 26 | 27 | ConfigFile::ConfigFile( string filename, string delimiter, 28 | string comment, string sentry ) 29 | : myDelimiter(delimiter), myComment(comment), mySentry(sentry) 30 | { 31 | // Construct a ConfigFile, getting keys and values from given file 32 | 33 | std::ifstream in( filename.c_str() ); 34 | 35 | if( !in ) throw file_not_found( filename ); 36 | 37 | in >> (*this); 38 | } 39 | 40 | 41 | ConfigFile::ConfigFile() 42 | : myDelimiter( string(1,'=') ), myComment( string(1,'#') ) 43 | { 44 | // Construct a ConfigFile without a file; empty 45 | } 46 | 47 | 48 | void ConfigFile::remove( const string& key ) 49 | { 50 | // Remove key and its value 51 | myContents.erase( myContents.find( key ) ); 52 | return; 53 | } 54 | 55 | 56 | bool ConfigFile::keyExists( const string& key ) const 57 | { 58 | // Indicate whether key is found 59 | mapci p = myContents.find( key ); 60 | return ( p != myContents.end() ); 61 | } 62 | 63 | 64 | /* static */ 65 | void ConfigFile::trim( string& s ) 66 | { 67 | // Remove leading and trailing whitespace 68 | static const char whitespace[] = " \n\t\v\r\f"; 69 | s.erase( 0, s.find_first_not_of(whitespace) ); 70 | s.erase( s.find_last_not_of(whitespace) + 1U ); 71 | } 72 | 73 | 74 | std::ostream& operator<<( std::ostream& os, const ConfigFile& cf ) 75 | { 76 | // Save a ConfigFile to os 77 | for( ConfigFile::mapci p = cf.myContents.begin(); 78 | p != cf.myContents.end(); 79 | ++p ) 80 | { 81 | os << p->first << " " << cf.myDelimiter << " "; 82 | os << p->second << std::endl; 83 | } 84 | return os; 85 | } 86 | 87 | 88 | std::istream& operator>>( std::istream& is, ConfigFile& cf ) 89 | { 90 | // Load a ConfigFile from is 91 | // Read in keys and values, keeping internal whitespace 92 | typedef string::size_type pos; 93 | const string& delim = cf.myDelimiter; // separator 94 | const string& comm = cf.myComment; // comment 95 | const string& sentry = cf.mySentry; // end of file sentry 96 | const pos skip = delim.length(); // length of separator 97 | 98 | string nextline = ""; // might need to read ahead to see where value ends 99 | 100 | while( is || nextline.length() > 0 ) 101 | { 102 | // Read an entire line at a time 103 | string line; 104 | if( nextline.length() > 0 ) 105 | { 106 | line = nextline; // we read ahead; use it now 107 | nextline = ""; 108 | } 109 | else 110 | { 111 | std::getline( is, line ); 112 | } 113 | 114 | // Ignore comments 115 | line = line.substr( 0, line.find(comm) ); 116 | 117 | // Check for end of file sentry 118 | if( sentry != "" && line.find(sentry) != string::npos ) return is; 119 | 120 | // Parse the line if it contains a delimiter 121 | pos delimPos = line.find( delim ); 122 | if( delimPos < string::npos ) 123 | { 124 | // Extract the key 125 | string key = line.substr( 0, delimPos ); 126 | line.replace( 0, delimPos+skip, "" ); 127 | 128 | // See if value continues on the next line 129 | // Stop at blank line, next line with a key, end of stream, 130 | // or end of file sentry 131 | bool terminate = false; 132 | while( !terminate && is ) 133 | { 134 | std::getline( is, nextline ); 135 | terminate = true; 136 | 137 | string nlcopy = nextline; 138 | ConfigFile::trim(nlcopy); 139 | if( nlcopy == "" ) continue; 140 | 141 | nextline = nextline.substr( 0, nextline.find(comm) ); 142 | if( nextline.find(delim) != string::npos ) 143 | continue; 144 | if( sentry != "" && nextline.find(sentry) != string::npos ) 145 | continue; 146 | 147 | nlcopy = nextline; 148 | ConfigFile::trim(nlcopy); 149 | if( nlcopy != "" ) line += "\n"; 150 | line += nextline; 151 | terminate = false; 152 | } 153 | 154 | // Store key and value 155 | ConfigFile::trim(key); 156 | ConfigFile::trim(line); 157 | cf.myContents[key] = line; // overwrites if key is repeated 158 | } 159 | } 160 | 161 | return is; 162 | } 163 | -------------------------------------------------------------------------------- /src/common/qplaylistfiledialog.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * projectM-qt -- Qt4 based projectM GUI 3 | * Copyright (C)2003-2004 projectM Team 4 | * 5 | * This library is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public 7 | * License as published by the Free Software Foundation; either 8 | * version 2.1 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public 16 | * License along with this library; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | * See 'LICENSE.txt' included within this release 19 | * 20 | */ 21 | 22 | 23 | 24 | #ifndef QPLAYLIST_FILEDIALOG_HPP 25 | #define QPLAYLIST_FILEDIALOG_HPP 26 | 27 | #include 28 | #include 29 | #include 30 | 31 | class QPlaylistFileDialog : public QFileDialog 32 | { 33 | Q_OBJECT // must include this if you use Qt signals/slots 34 | 35 | public: 36 | static QString OPEN_PLAYLIST_TITLE; 37 | static QString OPEN_PLAYLIST_OR_DIRECTORY_TITLE; 38 | static QString SAVE_PLAYLIST_TITLE; 39 | 40 | inline QPlaylistFileDialog(QWidget * parent = 0): 41 | QFileDialog(parent, OPEN_PLAYLIST_OR_DIRECTORY_TITLE, QString()), m_directorySelectAllowed(true), m_fileSelectAllowed(true) { 42 | 43 | this->setOption(QFileDialog::DontUseNativeDialog); 44 | 45 | updateFileMode(selectedFiles()); 46 | 47 | //connect(this, SIGNAL(filesSelected(const QStringList&)), 48 | // this, SLOT(updateFileMode(const QStringList&))); 49 | 50 | connect(this, SIGNAL(currentChanged(const QString&)), 51 | this, SLOT(updateFileMode(const QString&))); 52 | } 53 | 54 | inline bool isPlaylistSaveMode() { 55 | return this->acceptMode() == QFileDialog::AcceptSave; 56 | } 57 | 58 | inline void setPlaylistSaveMode(bool isSaveMode) { 59 | if (isSaveMode) { 60 | this->setAcceptMode(QFileDialog::AcceptSave); 61 | updateWindowTitle(); 62 | updateFileMode(selectedFiles()); 63 | } 64 | else { 65 | this->setAcceptMode(QFileDialog::AcceptOpen); 66 | updateWindowTitle(); 67 | updateFileMode(selectedFiles()); 68 | } 69 | } 70 | 71 | inline void setAllowDirectorySelect(bool isAllowed) { 72 | m_directorySelectAllowed = isAllowed; 73 | updateFileMode(selectedFiles()); 74 | updateWindowTitle(); 75 | } 76 | 77 | inline void setAllowFileSelect(bool isAllowed) { 78 | m_fileSelectAllowed = isAllowed; 79 | updateFileMode(selectedFiles()); 80 | updateWindowTitle(); 81 | } 82 | 83 | 84 | inline bool isFileSelectAllowed() const { 85 | return m_fileSelectAllowed; 86 | } 87 | 88 | 89 | inline bool isDirectorySelectAllowed() const { 90 | return m_directorySelectAllowed; 91 | } 92 | 93 | 94 | 95 | ~QPlaylistFileDialog() { } 96 | 97 | private: 98 | 99 | bool m_directorySelectAllowed; 100 | bool m_fileSelectAllowed; 101 | QString getFilter() { 102 | QString filter; 103 | if (isDirectorySelectAllowed()) { 104 | 105 | filter += "Directories"; 106 | } 107 | 108 | if (isFileSelectAllowed()) { 109 | if (filter != QString()) 110 | filter += " and "; 111 | 112 | filter += "Preset Playlists (*.ppl)"; 113 | } 114 | 115 | return filter; 116 | } 117 | 118 | void updateWindowTitle() { 119 | if (isPlaylistSaveMode()) 120 | setWindowTitle(SAVE_PLAYLIST_TITLE); 121 | else { 122 | if (isDirectorySelectAllowed() && isFileSelectAllowed()) 123 | setWindowTitle(OPEN_PLAYLIST_OR_DIRECTORY_TITLE); 124 | else 125 | setWindowTitle(OPEN_PLAYLIST_TITLE); 126 | } 127 | } 128 | 129 | private slots: 130 | 131 | void updateFileMode(const QString fileName) { 132 | 133 | 134 | if (fileName == QString()) { 135 | if (isPlaylistSaveMode()) 136 | this->setFileMode(QFileDialog::AnyFile); 137 | else 138 | this->setFileMode(QFileDialog::ExistingFile); 139 | } 140 | 141 | else if (QFileInfo(fileName).isDir()) { 142 | if (isPlaylistSaveMode()) 143 | this->setFileMode(QFileDialog::AnyFile); 144 | else if (isDirectorySelectAllowed()) 145 | this->setFileMode(QFileDialog::Directory); 146 | else 147 | this->setFileMode(QFileDialog::ExistingFile); 148 | } 149 | else if (QFileInfo(fileName).isFile()) { 150 | 151 | if (isPlaylistSaveMode()) 152 | this->setFileMode(QFileDialog::AnyFile); 153 | else if (isFileSelectAllowed()) 154 | this->setFileMode(QFileDialog::ExistingFile); 155 | else 156 | this->setFileMode(QFileDialog::Directory); 157 | } 158 | 159 | this->setFilter(filter()); 160 | } 161 | 162 | void updateFileMode(const QStringList & selectedFiles) { 163 | if (selectedFiles.empty()) 164 | updateFileMode(QString()); 165 | else 166 | updateFileMode(selectedFiles[0]); 167 | } 168 | }; 169 | 170 | 171 | #endif 172 | -------------------------------------------------------------------------------- /src/ui-pulseaudio/ConfigFile.cpp: -------------------------------------------------------------------------------- 1 | 2 | // Class for reading named values from configuration files 3 | // Richard J. Wagner v2.1 24 May 2004 wagnerr@umich.edu 4 | 5 | // Copyright (c) 2004 Richard J. Wagner 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy 8 | // of this software and associated documentation files (the "Software"), to 9 | // deal in the Software without restriction, including without limitation the 10 | // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 11 | // sell copies of the Software, and to permit persons to whom the Software is 12 | // furnished to do so, subject to the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in 15 | // all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 23 | // IN THE SOFTWARE. 24 | 25 | // ConfigFile.cpp 26 | 27 | #include "ConfigFile.h" 28 | 29 | using std::string; 30 | 31 | ConfigFile::ConfigFile( string filename, string delimiter, 32 | string comment, string sentry ) 33 | : myDelimiter(delimiter), myComment(comment), mySentry(sentry) 34 | { 35 | // Construct a ConfigFile, getting keys and values from given file 36 | 37 | std::ifstream in( filename.c_str() ); 38 | 39 | if( !in ) throw file_not_found( filename ); 40 | 41 | in >> (*this); 42 | } 43 | 44 | 45 | ConfigFile::ConfigFile() 46 | : myDelimiter( string(1,'=') ), myComment( string(1,'#') ) 47 | { 48 | // Construct a ConfigFile without a file; empty 49 | } 50 | 51 | 52 | void ConfigFile::remove( const string& key ) 53 | { 54 | // Remove key and its value 55 | myContents.erase( myContents.find( key ) ); 56 | return; 57 | } 58 | 59 | 60 | bool ConfigFile::keyExists( const string& key ) const 61 | { 62 | // Indicate whether key is found 63 | mapci p = myContents.find( key ); 64 | return ( p != myContents.end() ); 65 | } 66 | 67 | 68 | /* static */ 69 | void ConfigFile::trim( string& s ) 70 | { 71 | // Remove leading and trailing whitespace 72 | static const char whitespace[] = " \n\t\v\r\f"; 73 | s.erase( 0, s.find_first_not_of(whitespace) ); 74 | s.erase( s.find_last_not_of(whitespace) + 1U ); 75 | } 76 | 77 | 78 | std::ostream& operator<<( std::ostream& os, const ConfigFile& cf ) 79 | { 80 | // Save a ConfigFile to os 81 | for( ConfigFile::mapci p = cf.myContents.begin(); 82 | p != cf.myContents.end(); 83 | ++p ) 84 | { 85 | os << p->first << " " << cf.myDelimiter << " "; 86 | os << p->second << std::endl; 87 | } 88 | return os; 89 | } 90 | 91 | 92 | std::istream& operator>>( std::istream& is, ConfigFile& cf ) 93 | { 94 | // Load a ConfigFile from is 95 | // Read in keys and values, keeping internal whitespace 96 | typedef string::size_type pos; 97 | const string& delim = cf.myDelimiter; // separator 98 | const string& comm = cf.myComment; // comment 99 | const string& sentry = cf.mySentry; // end of file sentry 100 | const pos skip = delim.length(); // length of separator 101 | 102 | string nextline = ""; // might need to read ahead to see where value ends 103 | 104 | while( is || nextline.length() > 0 ) 105 | { 106 | // Read an entire line at a time 107 | string line; 108 | if( nextline.length() > 0 ) 109 | { 110 | line = nextline; // we read ahead; use it now 111 | nextline = ""; 112 | } 113 | else 114 | { 115 | std::getline( is, line ); 116 | } 117 | 118 | // Ignore comments 119 | line = line.substr( 0, line.find(comm) ); 120 | 121 | // Check for end of file sentry 122 | if( sentry != "" && line.find(sentry) != string::npos ) return is; 123 | 124 | // Parse the line if it contains a delimiter 125 | pos delimPos = line.find( delim ); 126 | if( delimPos < string::npos ) 127 | { 128 | // Extract the key 129 | string key = line.substr( 0, delimPos ); 130 | line.replace( 0, delimPos+skip, "" ); 131 | 132 | // See if value continues on the next line 133 | // Stop at blank line, next line with a key, end of stream, 134 | // or end of file sentry 135 | bool terminate = false; 136 | while( !terminate && is ) 137 | { 138 | std::getline( is, nextline ); 139 | terminate = true; 140 | 141 | string nlcopy = nextline; 142 | ConfigFile::trim(nlcopy); 143 | if( nlcopy == "" ) continue; 144 | 145 | nextline = nextline.substr( 0, nextline.find(comm) ); 146 | if( nextline.find(delim) != string::npos ) 147 | continue; 148 | if( sentry != "" && nextline.find(sentry) != string::npos ) 149 | continue; 150 | 151 | nlcopy = nextline; 152 | ConfigFile::trim(nlcopy); 153 | if( nlcopy != "" ) line += "\n"; 154 | line += nextline; 155 | terminate = false; 156 | } 157 | 158 | // Store key and value 159 | ConfigFile::trim(key); 160 | ConfigFile::trim(line); 161 | cf.myContents[key] = line; // overwrites if key is repeated 162 | } 163 | } 164 | 165 | return is; 166 | } 167 | -------------------------------------------------------------------------------- /src/ui-jack/ConfigFile.cpp: -------------------------------------------------------------------------------- 1 | // ConfigFile.cpp 2 | 3 | 4 | // ConfigFile.h 5 | // Class for reading named values from configuration files 6 | // Richard J. Wagner v2.1 24 May 2004 wagnerr@umich.edu 7 | 8 | // Copyright (c) 2004 Richard J. Wagner 9 | // 10 | // Permission is hereby granted, free of charge, to any person obtaining a copy 11 | // of this software and associated documentation files (the "Software"), to 12 | // deal in the Software without restriction, including without limitation the 13 | // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 14 | // sell copies of the Software, and to permit persons to whom the Software is 15 | // furnished to do so, subject to the following conditions: 16 | // 17 | // The above copyright notice and this permission notice shall be included in 18 | // all copies or substantial portions of the Software. 19 | // 20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 25 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 26 | // IN THE SOFTWARE. 27 | 28 | 29 | #include "ConfigFile.h" 30 | 31 | using std::string; 32 | 33 | ConfigFile::ConfigFile( string filename, string delimiter, 34 | string comment, string sentry ) 35 | : myDelimiter(delimiter), myComment(comment), mySentry(sentry) 36 | { 37 | // Construct a ConfigFile, getting keys and values from given file 38 | 39 | std::ifstream in( filename.c_str() ); 40 | 41 | if( !in ) throw file_not_found( filename ); 42 | 43 | in >> (*this); 44 | } 45 | 46 | 47 | ConfigFile::ConfigFile() 48 | : myDelimiter( string(1,'=') ), myComment( string(1,'#') ) 49 | { 50 | // Construct a ConfigFile without a file; empty 51 | } 52 | 53 | 54 | void ConfigFile::remove( const string& key ) 55 | { 56 | // Remove key and its value 57 | myContents.erase( myContents.find( key ) ); 58 | return; 59 | } 60 | 61 | 62 | bool ConfigFile::keyExists( const string& key ) const 63 | { 64 | // Indicate whether key is found 65 | mapci p = myContents.find( key ); 66 | return ( p != myContents.end() ); 67 | } 68 | 69 | 70 | /* static */ 71 | void ConfigFile::trim( string& s ) 72 | { 73 | // Remove leading and trailing whitespace 74 | static const char whitespace[] = " \n\t\v\r\f"; 75 | s.erase( 0, s.find_first_not_of(whitespace) ); 76 | s.erase( s.find_last_not_of(whitespace) + 1U ); 77 | } 78 | 79 | 80 | std::ostream& operator<<( std::ostream& os, const ConfigFile& cf ) 81 | { 82 | // Save a ConfigFile to os 83 | for( ConfigFile::mapci p = cf.myContents.begin(); 84 | p != cf.myContents.end(); 85 | ++p ) 86 | { 87 | os << p->first << " " << cf.myDelimiter << " "; 88 | os << p->second << std::endl; 89 | } 90 | return os; 91 | } 92 | 93 | 94 | std::istream& operator>>( std::istream& is, ConfigFile& cf ) 95 | { 96 | // Load a ConfigFile from is 97 | // Read in keys and values, keeping internal whitespace 98 | typedef string::size_type pos; 99 | const string& delim = cf.myDelimiter; // separator 100 | const string& comm = cf.myComment; // comment 101 | const string& sentry = cf.mySentry; // end of file sentry 102 | const pos skip = delim.length(); // length of separator 103 | 104 | string nextline = ""; // might need to read ahead to see where value ends 105 | 106 | while( is || nextline.length() > 0 ) 107 | { 108 | // Read an entire line at a time 109 | string line; 110 | if( nextline.length() > 0 ) 111 | { 112 | line = nextline; // we read ahead; use it now 113 | nextline = ""; 114 | } 115 | else 116 | { 117 | std::getline( is, line ); 118 | } 119 | 120 | // Ignore comments 121 | line = line.substr( 0, line.find(comm) ); 122 | 123 | // Check for end of file sentry 124 | if( sentry != "" && line.find(sentry) != string::npos ) return is; 125 | 126 | // Parse the line if it contains a delimiter 127 | pos delimPos = line.find( delim ); 128 | if( delimPos < string::npos ) 129 | { 130 | // Extract the key 131 | string key = line.substr( 0, delimPos ); 132 | line.replace( 0, delimPos+skip, "" ); 133 | 134 | // See if value continues on the next line 135 | // Stop at blank line, next line with a key, end of stream, 136 | // or end of file sentry 137 | bool terminate = false; 138 | while( !terminate && is ) 139 | { 140 | std::getline( is, nextline ); 141 | terminate = true; 142 | 143 | string nlcopy = nextline; 144 | ConfigFile::trim(nlcopy); 145 | if( nlcopy == "" ) continue; 146 | 147 | nextline = nextline.substr( 0, nextline.find(comm) ); 148 | if( nextline.find(delim) != string::npos ) 149 | continue; 150 | if( sentry != "" && nextline.find(sentry) != string::npos ) 151 | continue; 152 | 153 | nlcopy = nextline; 154 | ConfigFile::trim(nlcopy); 155 | if( nlcopy != "" ) line += "\n"; 156 | line += nextline; 157 | terminate = false; 158 | } 159 | 160 | // Store key and value 161 | ConfigFile::trim(key); 162 | ConfigFile::trim(line); 163 | cf.myContents[key] = line; // overwrites if key is repeated 164 | } 165 | } 166 | 167 | return is; 168 | } 169 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14 FATAL_ERROR) 2 | 3 | if(CMAKE_VERSION VERSION_LESS 3.19 AND CMAKE_GENERATOR STREQUAL "Xcode") 4 | message(AUTHOR_WARNING "Using a CMake version before 3.19 with a recent Xcode SDK and the Xcode generator " 5 | "will likely result in CMake failing to find the AppleClang compiler. Either upgrade CMake to at least " 6 | "version 3.19 or use a different generator, e.g. \"Unix Makefiles\" or \"Ninja\".") 7 | endif() 8 | 9 | set(CMAKE_CXX_STANDARD 14) 10 | set(CMAKE_CXX_STANDARD_REQUIRED YES) 11 | set(CMAKE_POSITION_INDEPENDENT_CODE YES) 12 | 13 | # Automatically create .moc files and run the UIC and resource compilers 14 | set(CMAKE_AUTOMOC ON) 15 | set(CMAKE_AUTOUIC ON) 16 | set(CMAKE_AUTORCC ON) 17 | 18 | set_property(GLOBAL PROPERTY USE_FOLDERS ON) 19 | 20 | option(ENABLE_DEBUG_POSTFIX "Add \"d\" after library names for debug builds" ON) 21 | if(ENABLE_DEBUG_POSTFIX) 22 | set(CMAKE_DEBUG_POSTFIX d) 23 | endif() 24 | 25 | project(projectM-Qt 26 | LANGUAGES C CXX 27 | VERSION 1.0.0 28 | ) 29 | 30 | list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") 31 | 32 | if(CMAKE_SYSTEM_NAME STREQUAL "Linux") 33 | include(GNUInstallDirs) 34 | else() 35 | set(CMAKE_INSTALL_BINDIR "." STRING CACHE "Install directory for executables") 36 | set(CMAKE_INSTALL_LIBDIR "." STRING CACHE "Install directory for libraries") 37 | set(CMAKE_INSTALL_DATAROOTDIR "." STRING CACHE "Install root directory for read-only data files") 38 | endif() 39 | 40 | # Feature options 41 | option(ENABLE_SHARED_LINKING "Link the Qt frontend against the shared projectM library." ON) 42 | option(ENABLE_GLES "Enable OpenGL ES support" OFF) 43 | option(ENABLE_JACK "Build JACK-based UI" OFF) 44 | 45 | if(ENABLE_DOXYGEN) 46 | find_package(Doxygen REQUIRED) 47 | endif() 48 | 49 | if(ENABLE_GLES) 50 | if(NOT CMAKE_SYSTEM_NAME STREQUAL Linux) 51 | message(FATAL_ERROR "OpenGL ES 3 support is currently only available for Linux platforms.") 52 | endif() 53 | 54 | # We use a local find script for OpenGL::GLES3 until the proposed changes are merged upstream. 55 | list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/gles") 56 | find_package(OpenGL REQUIRED COMPONENTS GLES3) 57 | if(NOT TARGET OpenGL::GLES3) 58 | message(FATAL_ERROR "No suitable GLES3 library was found.") 59 | endif() 60 | 61 | set(PROJECTM_OPENGL_LIBRARIES OpenGL::GLES3) 62 | set(USE_GLES ON) 63 | else() 64 | find_package(OpenGL REQUIRED) 65 | set(PROJECTM_OPENGL_LIBRARIES OpenGL::GL) 66 | # GLX is required by SOIL2 on platforms with the X Window System (e.g. most Linux distributions) 67 | if(TARGET OpenGL::GLX) 68 | list(APPEND PROJECTM_OPENGL_LIBRARIES OpenGL::GLX) 69 | endif() 70 | if(CMAKE_SYSTEM_NAME STREQUAL "Windows") 71 | find_package(GLEW REQUIRED) 72 | list(APPEND PROJECTM_OPENGL_LIBRARIES GLEW::glew) 73 | endif() 74 | endif() 75 | 76 | find_package(libprojectM REQUIRED) 77 | find_package(Pulseaudio REQUIRED) 78 | 79 | if(ENABLE_JACK) 80 | find_package(JACK REQUIRED) 81 | endif() 82 | 83 | set(QT_REQUIRED_COMPONENTS Gui Widgets OpenGL Xml) 84 | if(DEFINED QT_VERSION) 85 | find_package(Qt${QT_VERSION} REQUIRED COMPONENTS ${QT_REQUIRED_COMPONENTS}) 86 | else() 87 | # Try to determine the Qt version available, starting with Qt6 88 | message(STATUS "Determining Qt version. To use a specific version, set QT_VERSION to either 5 or 6.") 89 | find_package(Qt6 QUIET COMPONENTS ${QT_REQUIRED_COMPONENTS}) 90 | if(TARGET Qt6::Core) 91 | set(QT_VERSION 6) 92 | else() 93 | find_package(Qt5 QUIET COMPONENTS ${QT_REQUIRED_COMPONENTS}) 94 | if(TARGET Qt5::Core) 95 | set(QT_VERSION 5) 96 | else() 97 | message(FATAL_ERROR "Could not find either Qt 5 or 6, one is required to build the PulseAudio or JACK UIs.") 98 | endif() 99 | endif() 100 | endif() 101 | 102 | # OpenGLWidgets were put into their own component since Qt 6. 103 | if(QT_VERSION EQUAL 6) 104 | list(APPEND QT_REQUIRED_COMPONENTS OpenGLWidgets) 105 | find_package(Qt6 REQUIRED COMPONENTS OpenGLWidgets) 106 | endif() 107 | 108 | set(QT_LINK_TARGETS "") 109 | foreach(component ${QT_REQUIRED_COMPONENTS}) 110 | list(APPEND QT_LINK_TARGETS Qt${QT_VERSION}::${component}) 111 | endforeach() 112 | 113 | add_subdirectory(src) 114 | 115 | message(STATUS "") 116 | message(STATUS "projectM Qt Frontend v${PROJECT_VERSION}") 117 | message(STATUS "==============================================") 118 | message(STATUS "") 119 | message(STATUS " prefix: ${CMAKE_INSTALL_PREFIX}") 120 | message(STATUS "") 121 | message(STATUS " compiler: ${CMAKE_CXX_COMPILER}") 122 | message(STATUS " cflags: ${CMAKE_C_FLAGS}") 123 | message(STATUS " cxxflags: ${CMAKE_CXX_FLAGS}") 124 | message(STATUS " ldflags: ${CMAKE_SHARED_LINKER_FLAGS}") 125 | message(STATUS "") 126 | message(STATUS "Features:") 127 | message(STATUS "==============================================") 128 | message(STATUS "") 129 | message(STATUS " OpenGL ES: ${ENABLE_GLES}") 130 | message(STATUS " Link UI with shared lib: ${ENABLE_SHARED_LINKING}") 131 | message(STATUS "") 132 | message(STATUS "Targets and applications:") 133 | message(STATUS "==============================================") 134 | message(STATUS "") 135 | message(STATUS " PulseAudio UI: ON") 136 | message(STATUS " PulseAudio version: ${PULSEAUDIO_VERSION}") 137 | message(STATUS " JACK UI: ${ENABLE_JACK}") 138 | if(ENABLE_JACK) 139 | message(STATUS " JACK version: ${JACK_VERSION}") 140 | endif() 141 | message(STATUS " Qt version: ${Qt${QT_VERSION}_VERSION}") 142 | message(STATUS "") 143 | 144 | # Create CPack configuration 145 | set(CPACK_PACKAGE_NAME "projectM-Qt") 146 | set(CPACK_VERBATIM_VARIABLES YES) 147 | include(CPack) 148 | -------------------------------------------------------------------------------- /src/common/qxmlplaylisthandler.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * projectM-qt -- Qt4 based projectM GUI 3 | * Copyright (C)2003-2004 projectM Team 4 | * 5 | * This library is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public 7 | * License as published by the Free Software Foundation; either 8 | * version 2.1 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public 16 | * License along with this library; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | * See 'LICENSE.txt' included within this release 19 | * 20 | */ 21 | 22 | #ifndef QXML_PLAYLIST_HANDLER_HPP 23 | #define QXML_PLAYLIST_HANDLER_HPP 24 | #include 25 | #include 26 | 27 | class QXmlPlaylistHandler { 28 | 29 | public : 30 | template 31 | static QXmlStreamReader::Error readPlaylist (QIODevice * device, ReadFunctor & readFunc); 32 | 33 | template 34 | static void writePlaylist (QIODevice * device, WriteFunctor & writeFunc); 35 | 36 | private: 37 | 38 | template 39 | static QXmlStreamReader::Error readPlaylistItem(QXmlStreamReader & reader, ReadFunctor & functor); 40 | 41 | 42 | }; 43 | 44 | template 45 | QXmlStreamReader::Error QXmlPlaylistHandler::readPlaylist (QIODevice * device, ReadFunctor & readFunc) 46 | { 47 | QXmlStreamReader reader ( device ); 48 | 49 | QXmlStreamReader::TokenType token; 50 | 51 | try { 52 | while ( !reader.atEnd() ) { 53 | token = reader.readNext(); 54 | switch ( token ) 55 | { 56 | case QXmlStreamReader::StartElement: 57 | 58 | if (reader.name().toString() == "presetplaylist") { 59 | 60 | } 61 | else if (reader.name().toString() == "description") { 62 | reader.readNext(); 63 | readFunc.setPlaylistDesc(reader.text().toString().replace("&", "&")); 64 | 65 | } 66 | else if (reader.name().toString() == "item") { 67 | readPlaylistItem(reader, readFunc); 68 | break; 69 | } 70 | break; 71 | case QXmlStreamReader::NoToken: 72 | break; 73 | case QXmlStreamReader::Invalid: 74 | break; 75 | case QXmlStreamReader::StartDocument: 76 | break; 77 | case QXmlStreamReader::EndDocument: 78 | break; 79 | case QXmlStreamReader::EndElement: 80 | break; 81 | case QXmlStreamReader::Characters: 82 | case QXmlStreamReader::Comment: 83 | case QXmlStreamReader::DTD: 84 | case QXmlStreamReader::EntityReference: 85 | case QXmlStreamReader::ProcessingInstruction: 86 | default: 87 | break; 88 | } 89 | } 90 | } catch (const QXmlStreamReader::Error & id) { 91 | return id; 92 | 93 | } 94 | 95 | if (reader.hasError()) 96 | return reader.error(); 97 | else 98 | return QXmlStreamReader::NoError; 99 | } 100 | 101 | 102 | template 103 | QXmlStreamReader::Error QXmlPlaylistHandler::readPlaylistItem(QXmlStreamReader & reader, ReadFunctor & readFunctor) { 104 | 105 | QString url, name; 106 | int rating = 3; 107 | int breedability = 3; 108 | 109 | while (reader.readNext() != QXmlStreamReader::EndElement) 110 | if (reader.name().toString() == "url") { 111 | bool repeat; 112 | int result; 113 | 114 | while ((repeat = (result = reader.readNext()) == QXmlStreamReader::Characters)) 115 | url += reader.text().toString(); 116 | 117 | } else if (reader.name().toString() == "rating") { 118 | reader.readNext(); 119 | rating = reader.text().toString().toInt(); 120 | reader.readNext(); 121 | } else if (reader.name().toString() == "breedability") { 122 | reader.readNext(); 123 | breedability = reader.text().toString().toInt(); 124 | reader.readNext(); 125 | } else if (reader.name().toString() == "name") { 126 | bool repeat; 127 | int result; 128 | 129 | while ((repeat = (result = reader.readNext()) == QXmlStreamReader::Characters)) 130 | name += reader.text().toString(); 131 | } else { 132 | if (reader.name().toString() == "") 133 | continue; 134 | else if (reader.hasError()) 135 | return reader.error(); 136 | else { 137 | try { 138 | reader.raiseError(QString("Unknown element name %1 ").arg(reader.name().toString())); 139 | } catch (...) { 140 | return reader.error(); 141 | } 142 | } 143 | } 144 | 145 | readFunctor.appendItem(url, QFileInfo(url).fileName(), rating, breedability); 146 | 147 | return QXmlStreamReader::NoError; 148 | 149 | } 150 | 151 | 152 | template 153 | void QXmlPlaylistHandler::writePlaylist (QIODevice * device, WriteFunctor & writeFunctor ) { 154 | 155 | 156 | QXmlStreamWriter writer(device); 157 | 158 | writer.writeStartDocument(); 159 | 160 | writer.writeStartElement("presetplaylist"); 161 | 162 | 163 | writer.writeStartElement("description"); 164 | writer.writeCharacters(writeFunctor.playlistDesc()); 165 | writer.writeEndElement(); 166 | 167 | QString name; 168 | QString url; 169 | int rating; 170 | int breedability; 171 | 172 | while (writeFunctor.nextItem(name, url, rating, breedability)) { 173 | writer.writeStartElement("item"); 174 | 175 | 176 | writer.writeStartElement("name"); 177 | 178 | writer.writeCharacters(name.replace("&", "&")); 179 | writer.writeEndElement(); 180 | 181 | writer.writeStartElement("url"); 182 | 183 | writer.writeCharacters(url.replace("&", "&")); 184 | writer.writeEndElement(); 185 | 186 | writer.writeStartElement("rating"); 187 | writer.writeCharacters(QString("%1").arg(rating)+"\n"); 188 | writer.writeEndElement(); 189 | 190 | writer.writeStartElement("breedability"); 191 | writer.writeCharacters(QString("%1").arg(breedability)+"\n"); 192 | writer.writeEndElement(); 193 | 194 | writer.writeEndElement(); 195 | 196 | } 197 | 198 | writer.writeEndElement(); 199 | 200 | writer.writeEndDocument(); 201 | 202 | return; 203 | } 204 | 205 | 206 | /// @idea Instead of templates, allow subclassing of the playlist handler 207 | #if 0 208 | virtual void QXmlPlaylistHandler::readPresetItem(const QString & url, int rating) {} 209 | 210 | 211 | virtual bool QXmlPlaylistHandler::nextPresetItem(QString & url, int & rating) { 212 | return false; 213 | } 214 | #endif 215 | 216 | #endif 217 | -------------------------------------------------------------------------------- /src/common/qprojectm_mainwindow.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * projectM-qt -- Qt4 based projectM GUI 3 | * Copyright (C)2003-2004 projectM Team 4 | * 5 | * This library is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public 7 | * License as published by the Free Software Foundation; either 8 | * version 2.1 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public 16 | * License along with this library; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | * See 'LICENSE.txt' included within this release 19 | * 20 | */ 21 | 22 | #ifndef QPROJECTM_MAINWINDOW_H 23 | #define QPROJECTM_MAINWINDOW_H 24 | #define CONFIG_FILE "/share/projectM/config.inp" 25 | 26 | #include 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | 36 | #include 37 | 38 | class QHeaderView; 39 | class QAction; 40 | class QMenu; 41 | class QPresetFileDialog; 42 | class QPlaylistFileDialog; 43 | class QPlaylistModel; 44 | class QModelIndex; 45 | class QProjectMConfigDialog; 46 | class QPresetEditorDialog; 47 | class QProjectM; 48 | class QProjectMWidget; 49 | 50 | template 51 | class Nullable; 52 | 53 | struct projectm; 54 | 55 | namespace Ui { 56 | class QProjectM_MainWindow; 57 | } 58 | 59 | #include 60 | 61 | 62 | class QProjectM_MainWindow:public QMainWindow 63 | { 64 | Q_OBJECT 65 | 66 | signals: 67 | void shuttingDown(); 68 | public: 69 | 70 | projectm* GetProjectM(); 71 | 72 | typedef struct PlaylistItemMetaData { 73 | PlaylistItemMetaData() {} 74 | PlaylistItemMetaData(const QString & _url, const QString & _name, int _rating, int _breed, long _id): 75 | url(_url), name(_name), rating(_rating), breedability(_breed), id(_id) {} 76 | 77 | QString url; 78 | QString name; 79 | int rating; 80 | int breedability; 81 | long id; 82 | inline bool operator==(const PlaylistItemMetaData & data) { 83 | return data.id == id; 84 | } 85 | 86 | 87 | inline bool operator==(long rhs_id) { 88 | return rhs_id == id; 89 | } 90 | } PlaylistItemMetaData; 91 | 92 | 93 | void addPCM(float * buffer, unsigned int bufferSize); 94 | 95 | 96 | typedef QVector PlaylistItemVector; 97 | 98 | QProjectM_MainWindow(const QString& config_file, QMutex * audioMutex); 99 | virtual ~QProjectM_MainWindow(); 100 | void registerSettingsAction(QAction * action); 101 | void unregisterSettingsAction(QAction * action); 102 | void setMenuVisible(bool visible); 103 | void setMenuAndStatusBarsVisible(bool visible); 104 | void keyReleaseEvent ( QKeyEvent * e ); 105 | QProjectM * qprojectM(); 106 | void refreshPlaylist(); 107 | bool eventFilter(QObject *obj, QEvent *event); 108 | 109 | QProjectMWidget * qprojectMWidget() { return m_QProjectMWidget; } 110 | 111 | 112 | void registerAction(const QAction &); 113 | 114 | public slots: 115 | protected: 116 | 117 | 118 | void closeEvent(QCloseEvent *event); 119 | 120 | private slots: 121 | void dockLocationChanged(Qt::DockWidgetArea area); 122 | void presetRatingChanged(unsigned int, int, projectm_preset_rating_type); 123 | void handleFailedPresetSwitch(const bool isHardCut, const unsigned int index, 124 | const QString & message); 125 | 126 | void presetHardCut(); 127 | void presetSoftCut(); 128 | void insertPresetsDialog() ; 129 | void removeSelectedPlaylistItems(); 130 | 131 | void openPresetEditorDialogForSelectedPreset(); 132 | void popupPlaylistContextMenu(QMouseEvent *, const QModelIndexList & items); 133 | void hotkeyReference(); 134 | void selectPlaylistItem ( int rowIndex); 135 | void clearPlaylistModel(); 136 | void openPresetEditorDialog(int rowIndex); 137 | void aboutQt(); 138 | 139 | void clearPlaylist(); 140 | void addPresetsDialog(); 141 | void addPresetsDialog(const QModelIndex & index); 142 | void openPlaylistDialog(); 143 | void savePlaylistButtonClick(); 144 | void savePlaylistAsDialog(); 145 | void about(); 146 | void postProjectM_Initialize(); 147 | void updatePlaylistSelection(bool hardCut, unsigned int index); 148 | void selectPlaylistItem(const QModelIndex & index); 149 | void changePresetAttribute(const QModelIndex & index); 150 | void openSettingsDialog(); 151 | void updateFilteredPlaylist(const QString & text); 152 | void refreshHeaders(QResizeEvent * event = 0); 153 | void removePlaylistItems(const QModelIndexList & items); 154 | void dragAndDropPlaylistItems(const QModelIndexList &, const QModelIndex &); 155 | 156 | 157 | private: 158 | void readPlaylistSettings(); 159 | bool warnIfPlaylistModified(); 160 | 161 | void insertPlaylistItem(const PlaylistItemMetaData & data, int targetIndex); 162 | 163 | void savePlaylist(); 164 | void updatePlaylistUrl(const QString & url); 165 | unsigned long playlistItemCounter; 166 | QSize _oldPlaylistSize; 167 | void readConfig(const QString& configFile); 168 | void writeConfig(); 169 | void copyPlaylist(); 170 | 171 | QPresetEditorDialog * m_QPresetEditorDialog; 172 | QHeaderView * hHeader; 173 | QHeaderView * vHeader; 174 | QString m_currentPlaylistUrl; 175 | QModelIndexList selectedPlaylistIndexes; 176 | 177 | QPlaylistModel * playlistModel; 178 | Ui::QProjectM_MainWindow * ui; 179 | QProjectMConfigDialog * configDialog; 180 | 181 | QHash playlistItemMetaDataHash; 182 | 183 | QHash historyHash; 184 | Nullable * activePresetIndex; 185 | 186 | bool _menuVisible; 187 | bool _menuAndStatusBarsVisible; 188 | QTimer * m_timer; 189 | 190 | void createActions(); 191 | void createMenus(); 192 | void createToolBars(); 193 | void createStatusBar(); 194 | void readSettings(); 195 | void writeSettings(); 196 | void loadFile(const QString &fileName, int rating , int breed, const Nullable & row); 197 | QString strippedName(const QString &fullFileName); 198 | 199 | QProjectMWidget * m_QProjectMWidget; 200 | 201 | QMenu *playlistContextMenu; 202 | QToolBar *fileToolBar; 203 | 204 | QAction *openAct;; 205 | QAction *exitAct; 206 | QAction *aboutAct; 207 | QAction *aboutQtAct; 208 | 209 | QString previousFilter; 210 | Qt::DockWidgetArea dockWidgetArea; 211 | 212 | QPresetFileDialog * m_QPresetFileDialog; 213 | QPlaylistFileDialog * m_QPlaylistFileDialog; 214 | 215 | }; 216 | 217 | #endif 218 | -------------------------------------------------------------------------------- /src/ui-pulseaudio/qprojectM-pulseaudio.cpp: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * projectM -- Milkdrop-esque visualisation SDK 4 | * Copyright (C)2003-2004 projectM Team 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2.1 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public 17 | * License along with this library; if not, write to the Free Software 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 | * See 'LICENSE.txt' included within this release 20 | * 21 | */ 22 | 23 | /* $Id: parec-simple.c 1418 2007-01-04 13:43:45Z ossman $ */ 24 | 25 | /*** 26 | This file was copied from PulseAudio. 27 | 28 | PulseAudio is free software; you can redistribute it and/or modify 29 | it under the terms of the GNU Lesser General Public License as published 30 | by the Free Software Foundation; either version 2 of the License, 31 | or (at your option) any later version. 32 | 33 | PulseAudio is distributed in the hope that it will be useful, but 34 | WITHOUT ANY WARRANTY; without even the implied warranty of 35 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 36 | General Public License for more details. 37 | 38 | You should have received a copy of the GNU Lesser General Public License 39 | along with PulseAudio; if not, write to the Free Software 40 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 41 | USA. 42 | ***/ 43 | 44 | #include "QPulseAudioThread.hpp" 45 | #include "QPulseAudioDeviceChooser.hpp" 46 | 47 | #include 48 | 49 | #include 50 | 51 | #include 52 | #include 53 | #include 54 | 55 | #include 56 | #include 57 | #include 58 | #include 59 | #include 60 | 61 | #define CONFIG_FILE "/share/projectM/config.inp" 62 | 63 | QString read_config(); 64 | 65 | int dumpFrame = 0; 66 | int frameNumber = 0; 67 | 68 | int texsize=512; 69 | int gx=32,gy=24; 70 | int wvw=512,wvh=512; 71 | int fvw=1024,fvh=768; 72 | int fps=30, fullscreen=0; 73 | 74 | class ProjectMApplication : public QApplication { 75 | public: 76 | ProjectMApplication(int& argc, char ** argv) : 77 | QApplication(argc, argv) { 78 | } 79 | virtual ~ProjectMApplication() { } 80 | 81 | // catch exceptions which are thrown in slots 82 | virtual bool notify(QObject * receiver, QEvent * event) { 83 | try { 84 | return QApplication::notify(receiver, event); 85 | } catch (std::exception& e) { 86 | qCritical() << "Exception thrown:" << e.what(); 87 | } 88 | return false; 89 | } 90 | }; 91 | 92 | int main ( int argc, char*argv[] ) 93 | { 94 | // if (!TestRunner::run()) exit(1); 95 | 96 | ProjectMApplication app ( argc, argv ); 97 | 98 | QString config_file; 99 | config_file = read_config(); 100 | 101 | 102 | QMutex audioMutex; 103 | 104 | QProjectM_MainWindow * mainWindow = new QProjectM_MainWindow ( config_file, &audioMutex); 105 | 106 | QAction pulseAction("Pulse audio settings...", mainWindow); 107 | 108 | 109 | mainWindow->registerSettingsAction(&pulseAction); 110 | mainWindow->show(); 111 | 112 | QPulseAudioThread * pulseThread = new QPulseAudioThread(argc, argv, mainWindow); 113 | 114 | pulseThread->start(); 115 | 116 | //QApplication::connect 117 | // (mainWindow->qprojectMWidget(), SIGNAL(projectM_Initialized(QProjectM *)), pulseThread, SLOT(setQrojectMWidget(QProjectMWidget*))); 118 | 119 | QPulseAudioDeviceChooser devChooser(pulseThread, mainWindow); 120 | QApplication::connect(&pulseAction, SIGNAL(triggered()), &devChooser, SLOT(open())); 121 | //QApplication::connect(pulseThread, SIGNAL(threadCleanedUp()), mainWindow, SLOT(close())); 122 | 123 | //QApplication::connect(mainWindow, SIGNAL(shuttingDown()), pulseThread, SLOT(cleanup()), Qt::DirectConnection); 124 | int ret = app.exec(); 125 | if (pulseThread != 0) 126 | devChooser.writeSettings(); 127 | 128 | if (mainWindow) 129 | mainWindow->unregisterSettingsAction(&pulseAction); 130 | 131 | pulseThread->cleanup(); 132 | 133 | delete(pulseThread); 134 | return ret; 135 | } 136 | 137 | 138 | QString read_config() 139 | { 140 | char num[512]; 141 | FILE *in; 142 | FILE *out; 143 | 144 | char* home; 145 | char* xdg_home; 146 | 147 | char projectM_config[1024]; 148 | char default_config[1024]; 149 | 150 | strcpy(default_config, PROJECTM_PREFIX); 151 | strcat(default_config, CONFIG_FILE); 152 | printf("Default config: %s\n", default_config); 153 | 154 | home=getenv("HOME"); 155 | xdg_home = getenv("XDG_CONFIG_HOME"); 156 | 157 | strcpy(projectM_config, home); 158 | strcat(projectM_config, "/.projectM/config.inp"); 159 | 160 | if ( ( in = fopen ( projectM_config, "r" ) ) != 0 ) 161 | { 162 | printf ( "reading %s \n", projectM_config ); 163 | fclose ( in ); 164 | return projectM_config; 165 | } 166 | else { 167 | if (xdg_home) { 168 | strcpy(projectM_config, xdg_home); 169 | strcat(projectM_config, "/projectM/config.inp"); 170 | if ( ( in = fopen ( projectM_config, "r" ) ) != 0 ) { 171 | printf ( "reading %s \n", projectM_config ); 172 | fclose ( in ); 173 | return projectM_config; 174 | } 175 | else { 176 | strcpy(projectM_config, xdg_home); 177 | strcat(projectM_config, "/projectM"); 178 | } 179 | } 180 | else { 181 | strcpy(projectM_config, home); 182 | strcat(projectM_config, "/.projectM"); 183 | } 184 | mkdir(projectM_config, 0755); 185 | strcat(projectM_config, "/config.inp"); 186 | printf ("trying to create %s \n", projectM_config); 187 | 188 | if ( ( out = fopen ( projectM_config,"w" ) ) !=0 ) 189 | { 190 | 191 | if ( ( in = fopen ( default_config, "r" ) ) != 0 ) 192 | { 193 | 194 | while ( fgets ( num,80,in ) !=NULL ) 195 | { 196 | fputs ( num,out ); 197 | } 198 | fclose ( in ); 199 | fclose ( out ); 200 | 201 | 202 | if ( ( in = fopen ( projectM_config, "r" ) ) != 0 ) 203 | { 204 | printf ( "created %s successfully\n", projectM_config ); 205 | fclose ( in ); 206 | return projectM_config; 207 | } 208 | else{printf ( "This shouldn't happen, using implementation defaults\n" );abort();} 209 | } 210 | else{printf ( "Cannot find projectM default config, using implementation defaults\n" );abort();} 211 | } 212 | else 213 | { 214 | printf ( "Cannot create %s, using default config file\n", projectM_config ); 215 | if ( ( in = fopen ( default_config, "r" ) ) != 0 ) 216 | { 217 | printf ( "Successfully opened default config file\n" ); 218 | fclose ( in ); 219 | return default_config; 220 | } 221 | else{ printf ( "Using implementation defaults, your system is really messed up, I'm surprised we even got this far\n" ); abort();} 222 | 223 | } 224 | 225 | } 226 | 227 | 228 | abort(); 229 | } 230 | 231 | 232 | -------------------------------------------------------------------------------- /src/common/qprojectmconfigdialog.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * projectM-qt -- Qt4 based projectM GUI 3 | * Copyright (C)2003-2004 projectM Team 4 | * 5 | * This library is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public 7 | * License as published by the Free Software Foundation; either 8 | * version 2.1 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public 16 | * License along with this library; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | * See 'LICENSE.txt' included within this release 19 | * 20 | */ 21 | #include "qprojectmconfigdialog.hpp" 22 | #include 23 | #include 24 | #include "qplaylistfiledialog.hpp" 25 | #include 26 | #include "qprojectmwidget.hpp" 27 | 28 | QProjectMConfigDialog::QProjectMConfigDialog(const QString& configFile, QProjectMWidget * qprojectMWidget, QWidget * parent, Qt::WindowFlags f) : QDialog(parent, f), _settings("projectM", "qprojectM"), _configFile(configFile), _qprojectMWidget(qprojectMWidget) { 29 | 30 | 31 | _ui.setupUi(this); 32 | 33 | QHBoxLayout * hboxLayout = new QHBoxLayout(); 34 | 35 | hboxLayout->addWidget(_ui.layoutWidget); 36 | this->setLayout(hboxLayout); 37 | 38 | connect(_ui.buttonBox, SIGNAL(clicked(QAbstractButton*)), this, SLOT(buttonBoxHandler(QAbstractButton*))); 39 | connect(this, SIGNAL(projectM_Reset()), _qprojectMWidget, SLOT(resetProjectM())); 40 | connect (_ui.startupPlaylistFileToolButton, SIGNAL(clicked()), this, SLOT(openPlaylistFileDialog())); 41 | connect (_ui.startupPlaylistDirectoryToolButton, SIGNAL(clicked()), this, SLOT(openPlaylistDirectoryDialog())); 42 | connect (_ui.titleFontPathToolButton, SIGNAL(clicked()), this, SLOT(openTitleFontFileDialog())); 43 | connect (_ui.menuFontPathToolButton, SIGNAL(clicked()), this, SLOT(openMenuFontFileDialog())); 44 | loadConfig(); 45 | } 46 | 47 | void QProjectMConfigDialog::buttonBoxHandler(QAbstractButton * button) { 48 | 49 | switch (_ui.buttonBox->standardButton(button)) { 50 | case QDialogButtonBox::Close: 51 | this->hide(); 52 | break; 53 | case QDialogButtonBox::Save: 54 | saveConfig(); 55 | #ifdef PROJECTM_RESET_IS_THREAD_SAFE 56 | emit(projectM_Reset()); 57 | #endif 58 | break; 59 | case QDialogButtonBox::Reset: 60 | loadConfig(); 61 | break; 62 | default: 63 | break; 64 | } 65 | } 66 | 67 | void QProjectMConfigDialog::openPlaylistFileDialog() { 68 | 69 | QPlaylistFileDialog dialog(this); 70 | 71 | dialog.setAllowFileSelect(true); 72 | dialog.setAllowDirectorySelect(false); 73 | 74 | if (dialog.exec()) 75 | { 76 | Q_ASSERT(!dialog.selectedFiles().empty()); 77 | _ui.startupPlaylistFileLineEdit->setText(dialog.selectedFiles()[0]); 78 | 79 | } 80 | } 81 | 82 | 83 | void QProjectMConfigDialog::openPlaylistDirectoryDialog() { 84 | 85 | QPlaylistFileDialog dialog(this); 86 | 87 | dialog.setAllowFileSelect(false); 88 | dialog.setAllowDirectorySelect(true); 89 | 90 | if (dialog.exec()) 91 | { 92 | Q_ASSERT(!dialog.selectedFiles().empty()); 93 | _ui.startupPlaylistDirectoryLineEdit->setText(dialog.selectedFiles()[0]); 94 | 95 | } 96 | } 97 | void QProjectMConfigDialog::openMenuFontFileDialog() { 98 | 99 | 100 | QFileDialog dialog(this, "Select a menu font", _settings.value("Menu Font Directory", QString()).toString(), "True Type Fonts (*.ttf)" ); 101 | dialog.setFileMode(QFileDialog::ExistingFile); 102 | 103 | if (dialog.exec()) { 104 | Q_ASSERT(!dialog.selectedFiles().empty()); 105 | _ui.menuFontPathLineEdit->setText(dialog.selectedFiles()[0]); 106 | 107 | _settings.setValue("Menu Font Directory", dialog.directory().absolutePath()); 108 | } 109 | 110 | 111 | } 112 | 113 | void QProjectMConfigDialog::openTitleFontFileDialog() { 114 | QFileDialog dialog(this, "Select a title font", _settings.value("Title Font Directory", QString()).toString(), "True Type Fonts (*.ttf)" ); 115 | dialog.setFileMode(QFileDialog::ExistingFile); 116 | 117 | if (dialog.exec()) { 118 | Q_ASSERT(!dialog.selectedFiles().empty()); 119 | _ui.titleFontPathLineEdit->setText(dialog.selectedFiles()[0]); 120 | _settings.setValue("Title Font Directory", dialog.directory().absolutePath()); 121 | } 122 | 123 | } 124 | 125 | void QProjectMConfigDialog::saveConfig() { 126 | // Will only keep data_dir. 127 | auto settings = projectm_get_settings(_qprojectMWidget->qprojectM()->instance()); 128 | 129 | projectm_free_string(settings->preset_path); 130 | 131 | settings->mesh_x = _ui.meshSizeWidthSpinBox->value(); 132 | settings->mesh_y = _ui.meshSizeHeightSpinBox->value(); 133 | settings->window_height = _ui.windowHeightSpinBox->value(); 134 | settings->window_width = _ui.windowWidthSpinBox->value(); 135 | settings->preset_path = projectm_alloc_string(_ui.startupPlaylistDirectoryLineEdit->text().length() + 1); 136 | strncpy(settings->preset_path, _ui.startupPlaylistDirectoryLineEdit->text().toLocal8Bit().data(), _ui.startupPlaylistDirectoryLineEdit->text().length()); 137 | settings->texture_size = _ui.textureSizeComboBox->itemData(_ui.textureSizeComboBox->currentIndex()).toInt(); 138 | settings->soft_cut_duration = _ui.smoothPresetDurationSpinBox->value(); 139 | settings->preset_duration = _ui.presetDurationSpinBox->value(); 140 | settings->fps = _ui.maxFPSSpinBox->value(); 141 | settings->aspect_correction = _ui.useAspectCorrectionCheckBox->checkState() == Qt::Checked; 142 | settings->beat_sensitivity = _ui.beatSensitivitySpinBox->value(); 143 | settings->easter_egg = _ui.easterEggParameterSpinBox->value(); 144 | settings->shuffle_enabled = _ui.shuffleOnStartupCheckBox->checkState() == Qt::Checked; 145 | settings->soft_cut_ratings_enabled = _ui.softCutRatingsEnabledCheckBox->checkState() == Qt::Checked; 146 | 147 | projectm_write_config(_configFile.toLocal8Bit().data(), settings); 148 | 149 | projectm_free_settings(settings); 150 | 151 | QSettings qSettings("projectM", "qprojectM"); 152 | 153 | qSettings.setValue("FullscreenOnStartup", _ui.fullscreenOnStartupCheckBox->checkState() == Qt::Checked); 154 | qSettings.setValue("MenuOnStartup", _ui.menuOnStartupCheckBox->checkState() == Qt::Checked); 155 | 156 | qSettings.setValue("PlaylistFile", _ui.startupPlaylistFileLineEdit->text()); 157 | 158 | qSettings.setValue("MouseHideOnTimeout", _ui.mouseHideTimeoutSpinBox->value()); 159 | } 160 | 161 | 162 | 163 | void QProjectMConfigDialog::populateTextureSizeComboBox() { 164 | 165 | _ui.textureSizeComboBox->clear(); 166 | for (int textureSize = 1<<1; textureSize < 1<<14; textureSize<<=1) { 167 | _ui.textureSizeComboBox->addItem(QString("%1").arg(textureSize), textureSize); 168 | } 169 | } 170 | 171 | void QProjectMConfigDialog::loadConfig() { 172 | 173 | auto settings = projectm_get_settings(_qprojectMWidget->qprojectM()->instance()); 174 | 175 | _ui.meshSizeWidthSpinBox->setValue(settings->mesh_x); 176 | _ui.meshSizeHeightSpinBox->setValue(settings->mesh_y); 177 | 178 | _ui.startupPlaylistDirectoryLineEdit->setText(settings->preset_path); 179 | _ui.useAspectCorrectionCheckBox->setCheckState(settings->aspect_correction ? Qt::Checked : Qt::Unchecked); 180 | _ui.maxFPSSpinBox->setValue(settings->fps); 181 | _ui.beatSensitivitySpinBox->setValue(settings->beat_sensitivity); 182 | _ui.windowHeightSpinBox->setValue(settings->window_height); 183 | _ui.windowWidthSpinBox->setValue(settings->window_width); 184 | _ui.shuffleOnStartupCheckBox->setCheckState(settings->shuffle_enabled ? Qt::Checked : Qt::Unchecked); 185 | populateTextureSizeComboBox(); 186 | _ui.textureSizeComboBox->insertItem(0, QString("%1").arg(settings->texture_size), settings->texture_size); 187 | _ui.textureSizeComboBox->setCurrentIndex(0); 188 | 189 | _ui.smoothPresetDurationSpinBox->setValue(settings->soft_cut_duration); 190 | _ui.presetDurationSpinBox->setValue(settings->preset_duration); 191 | _ui.easterEggParameterSpinBox->setValue(settings->easter_egg); 192 | _ui.softCutRatingsEnabledCheckBox->setCheckState(settings->soft_cut_ratings_enabled ? Qt::Checked : Qt::Unchecked); 193 | 194 | projectm_free_settings(settings); 195 | 196 | QSettings qSettings("projectM", "qprojectM"); 197 | _ui.fullscreenOnStartupCheckBox->setCheckState(qSettings.value("FullscreenOnStartup", false).toBool() ? Qt::Checked : Qt::Unchecked); 198 | _ui.menuOnStartupCheckBox->setCheckState(qSettings.value("MenuOnStartup", false).toBool() ? Qt::Checked : Qt::Unchecked); 199 | _ui.startupPlaylistFileLineEdit->setText(qSettings.value("PlaylistFile", QString()).toString() ); 200 | _ui.mouseHideTimeoutSpinBox->setValue(qSettings.value("MouseHideOnTimeout", 5).toInt()); 201 | 202 | } 203 | -------------------------------------------------------------------------------- /src/common/configfile.hpp: -------------------------------------------------------------------------------- 1 | // ConfigFile.h 2 | // Class for reading named values from configuration files 3 | // Richard J. Wagner v2.1 24 May 2004 wagnerr@umich.edu 4 | 5 | // Copyright (c) 2004 Richard J. Wagner 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy 8 | // of this software and associated documentation files (the "Software"), to 9 | // deal in the Software without restriction, including without limitation the 10 | // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 11 | // sell copies of the Software, and to permit persons to whom the Software is 12 | // furnished to do so, subject to the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in 15 | // all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 23 | // IN THE SOFTWARE. 24 | 25 | // Typical usage 26 | // ------------- 27 | // 28 | // Given a configuration file "settings.inp": 29 | // atoms = 25 30 | // length = 8.0 # nanometers 31 | // name = Reece Surcher 32 | // 33 | // Named values are read in various ways, with or without default values: 34 | // ConfigFile config( "settings.inp" ); 35 | // int atoms = config.read( "atoms" ); 36 | // double length = config.read( "length", 10.0 ); 37 | // string author, title; 38 | // config.readInto( author, "name" ); 39 | // config.readInto( title, "title", string("Untitled") ); 40 | // 41 | // See file example.cpp for more examples. 42 | 43 | #ifndef CONFIGFILE_H 44 | #define CONFIGFILE_H 45 | 46 | #include 47 | #include 48 | #include 49 | #include 50 | #include 51 | 52 | using std::string; 53 | 54 | class ConfigFile { 55 | // Data 56 | protected: 57 | string myDelimiter; // separator between key and value 58 | string myComment; // separator between value and comments 59 | string mySentry; // optional string to signal end of file 60 | std::map myContents; // extracted keys and values 61 | 62 | typedef std::map::iterator mapi; 63 | typedef std::map::const_iterator mapci; 64 | 65 | // Methods 66 | public: 67 | ConfigFile( string filename, 68 | string delimiter = "=", 69 | string comment = "#", 70 | string sentry = "EndConfigFile" ); 71 | ConfigFile(); 72 | 73 | // Search for key and read value or optional default value 74 | template T read( const string& key ) const; // call as read 75 | template T read( const string& key, const T& value ) const; 76 | template bool readInto( T& var, const string& key ) const; 77 | template 78 | bool readInto( T& var, const string& key, const T& value ) const; 79 | 80 | // Modify keys and values 81 | template void add( string key, const T& value ); 82 | void remove( const string& key ); 83 | 84 | // Check whether key exists in configuration 85 | bool keyExists( const string& key ) const; 86 | 87 | // Check or change configuration syntax 88 | string getDelimiter() const { return myDelimiter; } 89 | string getComment() const { return myComment; } 90 | string getSentry() const { return mySentry; } 91 | string setDelimiter( const string& s ) 92 | { string old = myDelimiter; myDelimiter = s; return old; } 93 | string setComment( const string& s ) 94 | { string old = myComment; myComment = s; return old; } 95 | 96 | // Write or read configuration 97 | friend std::ostream& operator<<( std::ostream& os, const ConfigFile& cf ); 98 | friend std::istream& operator>>( std::istream& is, ConfigFile& cf ); 99 | 100 | protected: 101 | template static string T_as_string( const T& t ); 102 | template static T string_as_T( const string& s ); 103 | static void trim( string& s ); 104 | 105 | 106 | // Exception types 107 | public: 108 | struct file_not_found { 109 | string filename; 110 | file_not_found( const string& filename_ = string() ) 111 | : filename(filename_) {} }; 112 | struct key_not_found { // thrown only by T read(key) variant of read() 113 | string key; 114 | key_not_found( const string& key_ = string() ) 115 | : key(key_) {} }; 116 | }; 117 | 118 | 119 | /* static */ 120 | template 121 | string ConfigFile::T_as_string( const T& t ) 122 | { 123 | // Convert from a T to a string 124 | // Type T must support << operator 125 | std::ostringstream ost; 126 | ost << t; 127 | return ost.str(); 128 | } 129 | 130 | 131 | /* static */ 132 | template 133 | T ConfigFile::string_as_T( const string& s ) 134 | { 135 | // Convert from a string to a T 136 | // Type T must support >> operator 137 | T t; 138 | std::istringstream ist(s); 139 | ist >> t; 140 | return t; 141 | } 142 | 143 | 144 | /* static */ 145 | template<> 146 | inline string ConfigFile::string_as_T( const string& s ) 147 | { 148 | // Convert from a string to a string 149 | // In other words, do nothing 150 | return s; 151 | } 152 | 153 | 154 | /* static */ 155 | template<> 156 | inline bool ConfigFile::string_as_T( const string& s ) 157 | { 158 | // Convert from a string to a bool 159 | // Interpret "false", "F", "no", "n", "0" as false 160 | // Interpret "true", "T", "yes", "y", "1", "-1", or anything else as true 161 | bool b = true; 162 | string sup = s; 163 | for( string::iterator p = sup.begin(); p != sup.end(); ++p ) 164 | *p = toupper(*p); // make string all caps 165 | if( sup==string("FALSE") || sup==string("F") || 166 | sup==string("NO") || sup==string("N") || 167 | sup==string("0") || sup==string("NONE") ) 168 | b = false; 169 | return b; 170 | } 171 | 172 | 173 | template 174 | T ConfigFile::read( const string& key ) const 175 | { 176 | // Read the value corresponding to key 177 | mapci p = myContents.find(key); 178 | if( p == myContents.end() ) throw key_not_found(key); 179 | return string_as_T( p->second ); 180 | } 181 | 182 | 183 | template 184 | T ConfigFile::read( const string& key, const T& value ) const 185 | { 186 | // Return the value corresponding to key or given default value 187 | // if key is not found 188 | mapci p = myContents.find(key); 189 | if( p == myContents.end() ) return value; 190 | return string_as_T( p->second ); 191 | } 192 | 193 | 194 | template 195 | bool ConfigFile::readInto( T& var, const string& key ) const 196 | { 197 | // Get the value corresponding to key and store in var 198 | // Return true if key is found 199 | // Otherwise leave var untouched 200 | mapci p = myContents.find(key); 201 | bool found = ( p != myContents.end() ); 202 | if( found ) var = string_as_T( p->second ); 203 | return found; 204 | } 205 | 206 | 207 | template 208 | bool ConfigFile::readInto( T& var, const string& key, const T& value ) const 209 | { 210 | // Get the value corresponding to key and store in var 211 | // Return true if key is found 212 | // Otherwise set var to given default 213 | mapci p = myContents.find(key); 214 | bool found = ( p != myContents.end() ); 215 | if( found ) 216 | var = string_as_T( p->second ); 217 | else 218 | var = value; 219 | return found; 220 | } 221 | 222 | 223 | template 224 | void ConfigFile::add( string key, const T& value ) 225 | { 226 | // Add a key with given value 227 | string v = T_as_string( value ); 228 | trim(key); 229 | trim(v); 230 | myContents[key] = v; 231 | return; 232 | } 233 | 234 | #endif // CONFIGFILE_H 235 | 236 | // Release notes: 237 | // v1.0 21 May 1999 238 | // + First release 239 | // + Template read() access only through non-member readConfigFile() 240 | // + ConfigurationFileBool is only built-in helper class 241 | // 242 | // v2.0 3 May 2002 243 | // + Shortened name from ConfigurationFile to ConfigFile 244 | // + Implemented template member functions 245 | // + Changed default comment separator from % to # 246 | // + Enabled reading of multiple-line values 247 | // 248 | // v2.1 24 May 2004 249 | // + Made template specializations inline to avoid compiler-dependent linkage 250 | // + Allowed comments within multiple-line values 251 | // + Enabled blank line termination for multiple-line values 252 | // + Added optional sentry to detect end of configuration file 253 | // + Rewrote messy trimWhitespace() function as elegant trim() 254 | -------------------------------------------------------------------------------- /src/ui-jack/ConfigFile.h: -------------------------------------------------------------------------------- 1 | // ConfigFile.h 2 | // Class for reading named values from configuration files 3 | // Richard J. Wagner v2.1 24 May 2004 wagnerr@umich.edu 4 | 5 | // Copyright (c) 2004 Richard J. Wagner 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy 8 | // of this software and associated documentation files (the "Software"), to 9 | // deal in the Software without restriction, including without limitation the 10 | // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 11 | // sell copies of the Software, and to permit persons to whom the Software is 12 | // furnished to do so, subject to the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in 15 | // all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 23 | // IN THE SOFTWARE. 24 | 25 | // Typical usage 26 | // ------------- 27 | // 28 | // Given a configuration file "settings.inp": 29 | // atoms = 25 30 | // length = 8.0 # nanometers 31 | // name = Reece Surcher 32 | // 33 | // Named values are read in various ways, with or without default values: 34 | // ConfigFile config( "settings.inp" ); 35 | // int atoms = config.read( "atoms" ); 36 | // double length = config.read( "length", 10.0 ); 37 | // string author, title; 38 | // config.readInto( author, "name" ); 39 | // config.readInto( title, "title", string("Untitled") ); 40 | // 41 | // See file example.cpp for more examples. 42 | 43 | #ifndef CONFIGFILE_H 44 | #define CONFIGFILE_H 45 | 46 | #include 47 | #include 48 | #include 49 | #include 50 | #include 51 | 52 | using std::string; 53 | 54 | class ConfigFile { 55 | // Data 56 | protected: 57 | string myDelimiter; // separator between key and value 58 | string myComment; // separator between value and comments 59 | string mySentry; // optional string to signal end of file 60 | std::map myContents; // extracted keys and values 61 | 62 | typedef std::map::iterator mapi; 63 | typedef std::map::const_iterator mapci; 64 | 65 | // Methods 66 | public: 67 | ConfigFile( string filename, 68 | string delimiter = "=", 69 | string comment = "#", 70 | string sentry = "EndConfigFile" ); 71 | ConfigFile(); 72 | 73 | // Search for key and read value or optional default value 74 | template T read( const string& key ) const; // call as read 75 | template T read( const string& key, const T& value ) const; 76 | template bool readInto( T& var, const string& key ) const; 77 | template 78 | bool readInto( T& var, const string& key, const T& value ) const; 79 | 80 | // Modify keys and values 81 | template void add( string key, const T& value ); 82 | void remove( const string& key ); 83 | 84 | // Check whether key exists in configuration 85 | bool keyExists( const string& key ) const; 86 | 87 | // Check or change configuration syntax 88 | string getDelimiter() const { return myDelimiter; } 89 | string getComment() const { return myComment; } 90 | string getSentry() const { return mySentry; } 91 | string setDelimiter( const string& s ) 92 | { string old = myDelimiter; myDelimiter = s; return old; } 93 | string setComment( const string& s ) 94 | { string old = myComment; myComment = s; return old; } 95 | 96 | // Write or read configuration 97 | friend std::ostream& operator<<( std::ostream& os, const ConfigFile& cf ); 98 | friend std::istream& operator>>( std::istream& is, ConfigFile& cf ); 99 | 100 | protected: 101 | template static string T_as_string( const T& t ); 102 | template static T string_as_T( const string& s ); 103 | static void trim( string& s ); 104 | 105 | 106 | // Exception types 107 | public: 108 | struct file_not_found { 109 | string filename; 110 | file_not_found( const string& filename_ = string() ) 111 | : filename(filename_) {} }; 112 | struct key_not_found { // thrown only by T read(key) variant of read() 113 | string key; 114 | key_not_found( const string& key_ = string() ) 115 | : key(key_) {} }; 116 | }; 117 | 118 | 119 | /* static */ 120 | template 121 | string ConfigFile::T_as_string( const T& t ) 122 | { 123 | // Convert from a T to a string 124 | // Type T must support << operator 125 | std::ostringstream ost; 126 | ost << t; 127 | return ost.str(); 128 | } 129 | 130 | 131 | /* static */ 132 | template 133 | T ConfigFile::string_as_T( const string& s ) 134 | { 135 | // Convert from a string to a T 136 | // Type T must support >> operator 137 | T t; 138 | std::istringstream ist(s); 139 | ist >> t; 140 | return t; 141 | } 142 | 143 | 144 | /* static */ 145 | template<> 146 | inline string ConfigFile::string_as_T( const string& s ) 147 | { 148 | // Convert from a string to a string 149 | // In other words, do nothing 150 | return s; 151 | } 152 | 153 | 154 | /* static */ 155 | template<> 156 | inline bool ConfigFile::string_as_T( const string& s ) 157 | { 158 | // Convert from a string to a bool 159 | // Interpret "false", "F", "no", "n", "0" as false 160 | // Interpret "true", "T", "yes", "y", "1", "-1", or anything else as true 161 | bool b = true; 162 | string sup = s; 163 | for( string::iterator p = sup.begin(); p != sup.end(); ++p ) 164 | *p = toupper(*p); // make string all caps 165 | if( sup==string("FALSE") || sup==string("F") || 166 | sup==string("NO") || sup==string("N") || 167 | sup==string("0") || sup==string("NONE") ) 168 | b = false; 169 | return b; 170 | } 171 | 172 | 173 | template 174 | T ConfigFile::read( const string& key ) const 175 | { 176 | // Read the value corresponding to key 177 | mapci p = myContents.find(key); 178 | if( p == myContents.end() ) throw key_not_found(key); 179 | return string_as_T( p->second ); 180 | } 181 | 182 | 183 | template 184 | T ConfigFile::read( const string& key, const T& value ) const 185 | { 186 | // Return the value corresponding to key or given default value 187 | // if key is not found 188 | mapci p = myContents.find(key); 189 | if( p == myContents.end() ) return value; 190 | return string_as_T( p->second ); 191 | } 192 | 193 | 194 | template 195 | bool ConfigFile::readInto( T& var, const string& key ) const 196 | { 197 | // Get the value corresponding to key and store in var 198 | // Return true if key is found 199 | // Otherwise leave var untouched 200 | mapci p = myContents.find(key); 201 | bool found = ( p != myContents.end() ); 202 | if( found ) var = string_as_T( p->second ); 203 | return found; 204 | } 205 | 206 | 207 | template 208 | bool ConfigFile::readInto( T& var, const string& key, const T& value ) const 209 | { 210 | // Get the value corresponding to key and store in var 211 | // Return true if key is found 212 | // Otherwise set var to given default 213 | mapci p = myContents.find(key); 214 | bool found = ( p != myContents.end() ); 215 | if( found ) 216 | var = string_as_T( p->second ); 217 | else 218 | var = value; 219 | return found; 220 | } 221 | 222 | 223 | template 224 | void ConfigFile::add( string key, const T& value ) 225 | { 226 | // Add a key with given value 227 | string v = T_as_string( value ); 228 | trim(key); 229 | trim(v); 230 | myContents[key] = v; 231 | return; 232 | } 233 | 234 | #endif // CONFIGFILE_H 235 | 236 | // Release notes: 237 | // v1.0 21 May 1999 238 | // + First release 239 | // + Template read() access only through non-member readConfigFile() 240 | // + ConfigurationFileBool is only built-in helper class 241 | // 242 | // v2.0 3 May 2002 243 | // + Shortened name from ConfigurationFile to ConfigFile 244 | // + Implemented template member functions 245 | // + Changed default comment separator from % to # 246 | // + Enabled reading of multiple-line values 247 | // 248 | // v2.1 24 May 2004 249 | // + Made template specializations inline to avoid compiler-dependent linkage 250 | // + Allowed comments within multiple-line values 251 | // + Enabled blank line termination for multiple-line values 252 | // + Added optional sentry to detect end of configuration file 253 | // + Rewrote messy trimWhitespace() function as elegant trim() 254 | -------------------------------------------------------------------------------- /src/ui-pulseaudio/ConfigFile.h: -------------------------------------------------------------------------------- 1 | // ConfigFile.h 2 | // Class for reading named values from configuration files 3 | // Richard J. Wagner v2.1 24 May 2004 wagnerr@umich.edu 4 | 5 | // Copyright (c) 2004 Richard J. Wagner 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy 8 | // of this software and associated documentation files (the "Software"), to 9 | // deal in the Software without restriction, including without limitation the 10 | // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 11 | // sell copies of the Software, and to permit persons to whom the Software is 12 | // furnished to do so, subject to the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in 15 | // all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 23 | // IN THE SOFTWARE. 24 | 25 | // Typical usage 26 | // ------------- 27 | // 28 | // Given a configuration file "settings.inp": 29 | // atoms = 25 30 | // length = 8.0 # nanometers 31 | // name = Reece Surcher 32 | // 33 | // Named values are read in various ways, with or without default values: 34 | // ConfigFile config( "settings.inp" ); 35 | // int atoms = config.read( "atoms" ); 36 | // double length = config.read( "length", 10.0 ); 37 | // string author, title; 38 | // config.readInto( author, "name" ); 39 | // config.readInto( title, "title", string("Untitled") ); 40 | // 41 | // See file example.cpp for more examples. 42 | 43 | #ifndef CONFIGFILE_H 44 | #define CONFIGFILE_H 45 | 46 | #include 47 | #include 48 | #include 49 | #include 50 | #include 51 | 52 | using std::string; 53 | 54 | class ConfigFile { 55 | // Data 56 | protected: 57 | string myDelimiter; // separator between key and value 58 | string myComment; // separator between value and comments 59 | string mySentry; // optional string to signal end of file 60 | std::map myContents; // extracted keys and values 61 | 62 | typedef std::map::iterator mapi; 63 | typedef std::map::const_iterator mapci; 64 | 65 | // Methods 66 | public: 67 | ConfigFile( string filename, 68 | string delimiter = "=", 69 | string comment = "#", 70 | string sentry = "EndConfigFile" ); 71 | ConfigFile(); 72 | 73 | // Search for key and read value or optional default value 74 | template T read( const string& key ) const; // call as read 75 | template T read( const string& key, const T& value ) const; 76 | template bool readInto( T& var, const string& key ) const; 77 | template 78 | bool readInto( T& var, const string& key, const T& value ) const; 79 | 80 | // Modify keys and values 81 | template void add( string key, const T& value ); 82 | void remove( const string& key ); 83 | 84 | // Check whether key exists in configuration 85 | bool keyExists( const string& key ) const; 86 | 87 | // Check or change configuration syntax 88 | string getDelimiter() const { return myDelimiter; } 89 | string getComment() const { return myComment; } 90 | string getSentry() const { return mySentry; } 91 | string setDelimiter( const string& s ) 92 | { string old = myDelimiter; myDelimiter = s; return old; } 93 | string setComment( const string& s ) 94 | { string old = myComment; myComment = s; return old; } 95 | 96 | // Write or read configuration 97 | friend std::ostream& operator<<( std::ostream& os, const ConfigFile& cf ); 98 | friend std::istream& operator>>( std::istream& is, ConfigFile& cf ); 99 | 100 | protected: 101 | template static string T_as_string( const T& t ); 102 | template static T string_as_T( const string& s ); 103 | static void trim( string& s ); 104 | 105 | 106 | // Exception types 107 | public: 108 | struct file_not_found { 109 | string filename; 110 | file_not_found( const string& filename_ = string() ) 111 | : filename(filename_) {} }; 112 | struct key_not_found { // thrown only by T read(key) variant of read() 113 | string key; 114 | key_not_found( const string& key_ = string() ) 115 | : key(key_) {} }; 116 | }; 117 | 118 | 119 | /* static */ 120 | template 121 | string ConfigFile::T_as_string( const T& t ) 122 | { 123 | // Convert from a T to a string 124 | // Type T must support << operator 125 | std::ostringstream ost; 126 | ost << t; 127 | return ost.str(); 128 | } 129 | 130 | 131 | /* static */ 132 | template 133 | T ConfigFile::string_as_T( const string& s ) 134 | { 135 | // Convert from a string to a T 136 | // Type T must support >> operator 137 | T t; 138 | std::istringstream ist(s); 139 | ist >> t; 140 | return t; 141 | } 142 | 143 | 144 | /* static */ 145 | template<> 146 | inline string ConfigFile::string_as_T( const string& s ) 147 | { 148 | // Convert from a string to a string 149 | // In other words, do nothing 150 | return s; 151 | } 152 | 153 | 154 | /* static */ 155 | template<> 156 | inline bool ConfigFile::string_as_T( const string& s ) 157 | { 158 | // Convert from a string to a bool 159 | // Interpret "false", "F", "no", "n", "0" as false 160 | // Interpret "true", "T", "yes", "y", "1", "-1", or anything else as true 161 | bool b = true; 162 | string sup = s; 163 | for( string::iterator p = sup.begin(); p != sup.end(); ++p ) 164 | *p = toupper(*p); // make string all caps 165 | if( sup==string("FALSE") || sup==string("F") || 166 | sup==string("NO") || sup==string("N") || 167 | sup==string("0") || sup==string("NONE") ) 168 | b = false; 169 | return b; 170 | } 171 | 172 | 173 | template 174 | T ConfigFile::read( const string& key ) const 175 | { 176 | // Read the value corresponding to key 177 | mapci p = myContents.find(key); 178 | if( p == myContents.end() ) throw key_not_found(key); 179 | return string_as_T( p->second ); 180 | } 181 | 182 | 183 | template 184 | T ConfigFile::read( const string& key, const T& value ) const 185 | { 186 | // Return the value corresponding to key or given default value 187 | // if key is not found 188 | mapci p = myContents.find(key); 189 | if( p == myContents.end() ) return value; 190 | return string_as_T( p->second ); 191 | } 192 | 193 | 194 | template 195 | bool ConfigFile::readInto( T& var, const string& key ) const 196 | { 197 | // Get the value corresponding to key and store in var 198 | // Return true if key is found 199 | // Otherwise leave var untouched 200 | mapci p = myContents.find(key); 201 | bool found = ( p != myContents.end() ); 202 | if( found ) var = string_as_T( p->second ); 203 | return found; 204 | } 205 | 206 | 207 | template 208 | bool ConfigFile::readInto( T& var, const string& key, const T& value ) const 209 | { 210 | // Get the value corresponding to key and store in var 211 | // Return true if key is found 212 | // Otherwise set var to given default 213 | mapci p = myContents.find(key); 214 | bool found = ( p != myContents.end() ); 215 | if( found ) 216 | var = string_as_T( p->second ); 217 | else 218 | var = value; 219 | return found; 220 | } 221 | 222 | 223 | template 224 | void ConfigFile::add( string key, const T& value ) 225 | { 226 | // Add a key with given value 227 | string v = T_as_string( value ); 228 | trim(key); 229 | trim(v); 230 | myContents[key] = v; 231 | return; 232 | } 233 | 234 | #endif // CONFIGFILE_H 235 | 236 | // Release notes: 237 | // v1.0 21 May 1999 238 | // + First release 239 | // + Template read() access only through non-member readConfigFile() 240 | // + ConfigurationFileBool is only built-in helper class 241 | // 242 | // v2.0 3 May 2002 243 | // + Shortened name from ConfigurationFile to ConfigFile 244 | // + Implemented template member functions 245 | // + Changed default comment separator from % to # 246 | // + Enabled reading of multiple-line values 247 | // 248 | // v2.1 24 May 2004 249 | // + Made template specializations inline to avoid compiler-dependent linkage 250 | // + Allowed comments within multiple-line values 251 | // + Enabled blank line termination for multiple-line values 252 | // + Added optional sentry to detect end of configuration file 253 | // + Rewrote messy trimWhitespace() function as elegant trim() 254 | -------------------------------------------------------------------------------- /src/common/qprojectmwidget.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * projectM-qt -- Qt4 based projectM GUI 3 | * Copyright (C)2003-2004 projectM Team 4 | * 5 | * This library is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public 7 | * License as published by the Free Software Foundation; either 8 | * version 2.1 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public 16 | * License along with this library; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | * See 'LICENSE.txt' included within this release 19 | * 20 | */ 21 | 22 | #ifndef QPROJECTM_WIDGET_HPP 23 | #define QPROJECTM_WIDGET_HPP 24 | 25 | #include 26 | #include "qprojectm.hpp" 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | class QProjectMWidget : public QOpenGLWidget 36 | { 37 | 38 | Q_OBJECT // must include this if you use Qt signals/slots 39 | 40 | public: 41 | static const int MOUSE_VISIBLE_TIMEOUT_MS = 5000; 42 | QProjectMWidget ( const QString& config_file, QWidget * parent, QMutex * audioMutex = 0 ) 43 | : QOpenGLWidget ( parent ), m_config_file ( config_file ), m_projectM ( 0 ), m_mouseTimer ( 0 ), m_audioMutex ( audioMutex ) 44 | { 45 | 46 | m_mouseTimer = new QTimer ( this ); 47 | 48 | QSettings settings("projectM", "qprojectM"); 49 | mouseHideTimeoutSeconds = 50 | settings.value("MouseHideOnTimeout", MOUSE_VISIBLE_TIMEOUT_MS/1000).toInt(); 51 | 52 | if (mouseHideTimeoutSeconds > 0) 53 | m_mouseTimer->start ( mouseHideTimeoutSeconds * 1000); 54 | 55 | connect ( m_mouseTimer, SIGNAL ( timeout() ), this, SLOT ( hideMouse() ) ); 56 | this->setMouseTracking ( true ); 57 | 58 | } 59 | 60 | ~QProjectMWidget() { destroyProjectM(); } 61 | 62 | 63 | 64 | void resizeGL ( int w, int h ) override 65 | { 66 | // Setup viewport, projection etc 67 | setup_opengl ( w,h ); 68 | projectm_set_window_size(m_projectM->instance(), static_cast(w), static_cast(h)); 69 | } 70 | 71 | inline const QString& configFile() 72 | { 73 | return m_config_file; 74 | } 75 | 76 | inline void seizePresetLock() 77 | { 78 | m_presetSeizeMutex.lock(); 79 | m_presetWasLocked = projectm_is_preset_locked(qprojectM()->instance()); 80 | projectm_lock_preset(qprojectM()->instance(), true); 81 | } 82 | 83 | inline void releasePresetLock() 84 | { 85 | projectm_lock_preset(qprojectM()->instance(), m_presetWasLocked); 86 | m_presetSeizeMutex.unlock(); 87 | } 88 | 89 | 90 | inline QProjectM * qprojectM() { return m_projectM; } 91 | 92 | protected slots: 93 | inline void mouseMoveEvent ( QMouseEvent * event ) 94 | { 95 | Q_UNUSED(event); 96 | 97 | m_mouseTimer->stop(); 98 | QApplication::restoreOverrideCursor(); 99 | if (mouseHideTimeoutSeconds > 0) 100 | m_mouseTimer->start ( mouseHideTimeoutSeconds*1000 ); 101 | 102 | } 103 | 104 | inline void leaveEvent ( QEvent * event ) 105 | { 106 | Q_UNUSED(event); 107 | /// @bug testing if this resolves a bug for ubuntu users 108 | QApplication::restoreOverrideCursor(); 109 | } 110 | 111 | public slots: 112 | 113 | void resetProjectM() 114 | { 115 | std::cout << "resetting" << std::endl; 116 | qDebug() << "reset start"; 117 | 118 | emit ( projectM_BeforeDestroy() ); 119 | 120 | if ( m_audioMutex ) 121 | m_audioMutex->lock(); 122 | 123 | destroyProjectM(); 124 | 125 | // Make a new projectM instance and reset the opengl state 126 | initializeGL(); 127 | 128 | // Allow audio thread to continue its business 129 | if ( m_audioMutex ) 130 | { 131 | m_audioMutex->unlock(); 132 | } 133 | qDebug() << "reinit'ed"; 134 | } 135 | 136 | void setAudioMutex ( QMutex * mutex ) 137 | { 138 | m_audioMutex = mutex; 139 | } 140 | 141 | void setPresetLock ( int state ) 142 | { 143 | projectm_lock_preset(m_projectM->instance(), static_cast(state)); 144 | emit ( presetLockChanged ( ( bool ) state ) ); 145 | } 146 | 147 | void setShuffleEnabled ( int state ) 148 | { 149 | projectm_set_shuffle_enabled(m_projectM->instance(), static_cast(state)); 150 | emit ( shuffleEnabledChanged ( ( bool ) state ) ); 151 | } 152 | 153 | void mousePressEvent ( QMouseEvent * event ) 154 | { 155 | Q_UNUSED(event); 156 | 157 | this->setFocus(); 158 | } 159 | 160 | void updateGL() 161 | { 162 | paintGL(); 163 | } 164 | 165 | signals: 166 | void projectM_Initialized ( QProjectM * ); 167 | void projectM_BeforeDestroy(); 168 | void presetLockChanged ( bool isLocked ); 169 | void shuffleEnabledChanged ( bool isShuffleEnabled ); 170 | 171 | private slots: 172 | void hideMouse() 173 | { 174 | if ( this->underMouse() && this->hasFocus() ) 175 | QApplication::setOverrideCursor ( Qt::BlankCursor ); 176 | } 177 | private: 178 | QString m_config_file; 179 | QProjectM * m_projectM; 180 | void destroyProjectM() 181 | { 182 | 183 | if ( m_projectM ) 184 | { 185 | delete ( m_projectM ); 186 | m_projectM = 0; 187 | } 188 | } 189 | 190 | QTimer * m_mouseTimer; 191 | QMutex * m_audioMutex; 192 | QMutex m_presetSeizeMutex; 193 | bool m_presetWasLocked; 194 | protected: 195 | 196 | 197 | void keyReleaseEvent ( QKeyEvent * e ) 198 | { 199 | 200 | projectMKeycode pkey; 201 | bool ignore = false; 202 | switch ( e->key() ) 203 | { 204 | case Qt::Key_F4: 205 | pkey = PROJECTM_K_F4; 206 | break; 207 | case Qt::Key_F3: 208 | pkey = PROJECTM_K_F3; 209 | break; 210 | case Qt::Key_F2: 211 | pkey = PROJECTM_K_F2; 212 | break; 213 | case Qt::Key_F1: 214 | pkey = PROJECTM_K_F1; 215 | break; 216 | case Qt::Key_R: 217 | if (e->modifiers() & Qt::ShiftModifier) 218 | pkey = PROJECTM_K_R; 219 | else 220 | pkey = PROJECTM_K_r; 221 | break; 222 | case Qt::Key_L: 223 | pkey = PROJECTM_K_l; 224 | ignore = true; 225 | break; 226 | case Qt::Key_N: 227 | if (e->modifiers() & Qt::ShiftModifier) 228 | pkey = PROJECTM_K_N; 229 | else 230 | pkey = PROJECTM_K_n; 231 | break; 232 | case Qt::Key_P: 233 | if (e->modifiers() & Qt::ShiftModifier) 234 | pkey = PROJECTM_K_P; 235 | else 236 | pkey = PROJECTM_K_p; 237 | break; 238 | case Qt::Key_F5: 239 | pkey = PROJECTM_K_F5; 240 | break; 241 | case Qt::Key_Plus: 242 | pkey = PROJECTM_K_PLUS; 243 | break; 244 | case Qt::Key_Minus: 245 | pkey = PROJECTM_K_MINUS; 246 | break; 247 | case Qt::Key_Equal: 248 | pkey = PROJECTM_K_EQUALS; 249 | break; 250 | default: 251 | e->ignore(); 252 | return; 253 | } 254 | projectMModifier modifier = PROJECTM_KMOD_NONE; 255 | 256 | projectm_key_handler(m_projectM->instance(), PROJECTM_KEYDOWN, pkey, modifier); 257 | if ( ignore ) 258 | e->ignore(); 259 | 260 | 261 | } 262 | 263 | void initializeGL() override 264 | { 265 | 266 | if (m_projectM == 0) { 267 | this->m_projectM = new QProjectM ( m_config_file ); 268 | projectM_Initialized ( m_projectM ); 269 | } 270 | } 271 | 272 | void paintGL() override 273 | { 274 | projectm_render_frame(m_projectM->instance()); 275 | } 276 | 277 | private: 278 | int mouseHideTimeoutSeconds; 279 | void setup_opengl ( int w, int h ) 280 | { 281 | 282 | /* Our shading model--Gouraud (smooth). */ 283 | glShadeModel ( GL_SMOOTH ); 284 | /* Culling. */ 285 | // glCullFace( GL_BACK ); 286 | // glFrontFace( GL_CCW ); 287 | // glEnable( GL_CULL_FACE ); 288 | /* Set the clear color. */ 289 | glClearColor ( 0, 0, 0, 0 ); 290 | /* Setup our viewport. */ 291 | glViewport ( 0, 0, w, h ); 292 | /* 293 | * Change to the projection matrix and set 294 | * our viewing volume. 295 | */ 296 | glMatrixMode ( GL_TEXTURE ); 297 | glLoadIdentity(); 298 | 299 | // gluOrtho2D(0.0, (GLfloat) width, 0.0, (GLfloat) height); 300 | glMatrixMode ( GL_PROJECTION ); 301 | glLoadIdentity(); 302 | 303 | // glFrustum(0.0, height, 0.0,width,10,40); 304 | glMatrixMode ( GL_MODELVIEW ); 305 | glLoadIdentity(); 306 | 307 | glDrawBuffer ( GL_BACK ); 308 | glReadBuffer ( GL_BACK ); 309 | glEnable ( GL_BLEND ); 310 | 311 | glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); 312 | // glBlendFunc(GL_SRC_ALPHA, GL_ONE); 313 | glEnable ( GL_LINE_SMOOTH ); 314 | glEnable ( GL_POINT_SMOOTH ); 315 | glClearColor ( 0.0f, 0.0f, 0.0f, 0.0f ); 316 | // glClear(GL_COLOR_BUFFER_BIT); 317 | 318 | // glCopyTexImage2D(GL_TEXTURE_2D,0,GL_RGB,0,0,texsize,texsize,0); 319 | //glCopyTexSubImage2D(GL_TEXTURE_2D,0,0,0,0,0,texsize,texsize); 320 | glLineStipple ( 2, 0xAAAA ); 321 | } 322 | 323 | 324 | }; 325 | #endif 326 | -------------------------------------------------------------------------------- /src/ui-jack/qprojectM-jack.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * projectM -- Milkdrop-esque visualisation SDK 3 | * Copyright (C)2003-2004 projectM Team 4 | * 5 | * This library is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public 7 | * License as published by the Free Software Foundation; either 8 | * version 2.1 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public 16 | * License along with this library; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | * See 'LICENSE.txt' included within this release 19 | * 20 | */ 21 | 22 | #include 23 | 24 | #include 25 | 26 | #include 27 | 28 | #include 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include // for mkdir 35 | 36 | #define QPROJECTM_JACK_CONFIG_FILE "/config.inp" 37 | 38 | QString read_config(); 39 | 40 | jack_port_t *input_port; 41 | jack_client_t *client; 42 | jack_default_audio_sample_t out[1024*1000]; 43 | 44 | #ifdef DEBUG 45 | FILE *debugFile = NULL; 46 | #endif 47 | 48 | volatile enum ClientState { 49 | Init, 50 | Run, 51 | Exit 52 | } client_state = Init; 53 | 54 | 55 | projectm* globalPM = nullptr; 56 | 57 | int dumpFrame = 0; 58 | int frameNumber = 0; 59 | 60 | int texsize=512; 61 | int gx=32,gy=24; 62 | int wvw=512,wvh=512; 63 | int fvw=1024,fvh=768; 64 | int fps=30, fullscreen=0; 65 | 66 | class ProjectMApplication : public QApplication { 67 | public: 68 | ProjectMApplication(int& argc, char ** argv) : 69 | QApplication(argc, argv) { } 70 | virtual ~ProjectMApplication() { } 71 | 72 | // catch exceptions which are thrown in slots 73 | virtual bool notify(QObject * receiver, QEvent * event) { 74 | try { 75 | return QApplication::notify(receiver, event); 76 | } catch (std::exception& e) { 77 | qCritical() << "Exception thrown:" << e.what(); 78 | } 79 | return false; 80 | } 81 | }; 82 | 83 | QString read_config() 84 | { 85 | 86 | char num[512]; 87 | FILE *f_in; 88 | FILE *f_out; 89 | 90 | char * home; 91 | char projectM_home[1024]; 92 | char projectM_config[1024]; 93 | 94 | int len; 95 | strcpy(projectM_config, PROJECTM_PREFIX); 96 | strcpy(projectM_config + (len = strlen(PROJECTM_PREFIX)), "/"); 97 | 98 | strcpy(projectM_config+(len += strlen("/")), RESOURCE_PREFIX); 99 | strcpy(projectM_config+(len += strlen(RESOURCE_PREFIX)), QPROJECTM_JACK_CONFIG_FILE); 100 | projectM_config[len += strlen(QPROJECTM_JACK_CONFIG_FILE)]='\0'; 101 | 102 | printf("dir:%s \n",projectM_config); 103 | home=getenv("HOME"); 104 | strcpy(projectM_home, home); 105 | strcpy(projectM_home+strlen(home), "/.projectM/config.inp"); 106 | projectM_home[strlen(home)+strlen("/.projectM/config.inp")]='\0'; 107 | 108 | 109 | if ((f_in = fopen(projectM_home, "r")) != 0) 110 | { 111 | printf("reading ~/.projectM/config.inp \n"); 112 | fclose(f_in); 113 | return projectM_home; 114 | } 115 | else 116 | { 117 | printf("trying to create ~/.projectM/config.inp \n"); 118 | 119 | strcpy(projectM_home, home); 120 | strcpy(projectM_home+strlen(home), "/.projectM"); 121 | projectM_home[strlen(home)+strlen("/.projectM")]='\0'; 122 | mkdir(projectM_home,0755); 123 | 124 | strcpy(projectM_home, home); 125 | strcpy(projectM_home+strlen(home), "/.projectM/config.inp"); 126 | projectM_home[strlen(home)+strlen("/.projectM/config.inp")]='\0'; 127 | 128 | if((f_out = fopen(projectM_home,"w"))!=0) 129 | { 130 | 131 | if ((f_in = fopen(projectM_config, "r")) != 0) 132 | { 133 | 134 | while(fgets(num,80,f_in)!=NULL) 135 | { 136 | fputs(num,f_out); 137 | } 138 | fclose(f_in); 139 | fclose(f_out); 140 | 141 | 142 | if ((f_in = fopen(projectM_home, "r")) != 0) 143 | { 144 | printf("created ~/.projectM/config.inp successfully\n"); 145 | fclose(f_in); 146 | return projectM_home; 147 | } 148 | else{printf("This shouldn't happen, using implementation defaults\n");abort();} 149 | } 150 | else{printf("Cannot find projectM default config, using implementation defaults\n");abort();} 151 | } 152 | else 153 | { 154 | printf("Cannot create ~/.projectM/config.inp, using default config file\n"); 155 | if ((f_in = fopen(projectM_config, "r")) != 0) 156 | { printf("Successfully opened default config file\n"); 157 | fclose(f_in); 158 | return projectM_config;} 159 | else{ printf("Using implementation defaults, your system is really messed up, I'm surprised we even got this far\n"); abort();} 160 | 161 | } 162 | 163 | } 164 | 165 | 166 | abort(); 167 | } 168 | 169 | int 170 | process (jack_nframes_t nframes, void *arg) 171 | { 172 | Q_UNUSED(arg); 173 | 174 | jack_default_audio_sample_t *in; 175 | 176 | in = (jack_default_audio_sample_t*)jack_port_get_buffer (input_port, nframes); 177 | 178 | //memcpy (out, in,sizeof (jack_default_audio_sample_t) * nframes); 179 | 180 | projectm_pcm_add_float_1ch_data(globalPM, in, nframes); 181 | // printf("%x %f\n",nframes,in[128]); 182 | 183 | return 0; 184 | } 185 | 186 | void jack_shutdown (void *arg) 187 | { 188 | Q_UNUSED(arg); 189 | exit (1); 190 | } 191 | 192 | int main (int argc, char **argv) { 193 | const char **ports; 194 | const char *client_name; 195 | const char *server_name = NULL; 196 | jack_options_t options = JackNullOption; 197 | jack_status_t status; 198 | int i; 199 | 200 | // Start a new application 201 | ProjectMApplication app(argc, argv); 202 | 203 | auto config_file = read_config(); 204 | 205 | 206 | QProjectM_MainWindow * mainWindow = new QProjectM_MainWindow(config_file, 0); 207 | mainWindow->show(); 208 | 209 | globalPM = mainWindow->GetProjectM(); 210 | 211 | 212 | 213 | //JACK INIT 214 | //---------------------------------------------- 215 | if (argc >= 2) { /* client name specified? */ 216 | client_name = argv[1]; 217 | if (argc >= 3) { /* server name specified? */ 218 | server_name = argv[2]; 219 | // options |= JackServerName; 220 | } 221 | } else { /* use basename of argv[0] */ 222 | client_name = strrchr(argv[0], '/'); 223 | if (client_name == 0) { 224 | client_name = argv[0]; 225 | } else { 226 | client_name++; 227 | } 228 | } 229 | 230 | /* open a client connection to the JACK server */ 231 | 232 | client = jack_client_open (client_name, options, &status, server_name); 233 | if (client == NULL) { 234 | fprintf (stderr, "jack_client_open() failed, " 235 | "status = 0x%2.0x\n", status); 236 | if (status & JackServerFailed) { 237 | fprintf (stderr, "Unable to connect to JACK server\n"); 238 | } 239 | exit (1); 240 | } 241 | 242 | if (status & JackServerStarted) { 243 | fprintf (stderr, "JACK server started\n"); 244 | } 245 | 246 | if (status & JackNameNotUnique) { 247 | client_name = jack_get_client_name(client); 248 | fprintf (stderr, "unique name `%s' assigned\n", client_name); 249 | } 250 | 251 | /* tell the JACK server to call `process()' whenever 252 | there is work to be done. 253 | */ 254 | 255 | if (jack_set_process_callback (client, process, 0)) { 256 | std::cerr << "qprojectM-jack: failed to set process callbank!. quitting..." << std::endl; 257 | exit(EXIT_FAILURE); 258 | } 259 | 260 | /* tell the JACK server to call `jack_shutdown()' if 261 | it ever shuts down, either entirely, or if it 262 | just decides to stop calling us. 263 | */ 264 | 265 | jack_on_shutdown (client, jack_shutdown, 0); 266 | 267 | /* display the current sample rate. 268 | */ 269 | 270 | printf ("engine sample rate: %d\n", 271 | jack_get_sample_rate (client)); 272 | 273 | /* create two ports */ 274 | 275 | input_port = jack_port_register (client, "input", 276 | JACK_DEFAULT_AUDIO_TYPE, 277 | JackPortIsInput, 0); 278 | 279 | if (input_port == NULL) { 280 | fprintf(stderr, "no more JACK ports available\n"); 281 | exit (1); 282 | } 283 | 284 | /* Tell the JACK server that we are ready to roll. Our 285 | * process() callback will start running now. */ 286 | 287 | // END JACK INIT ---------------------------------- 288 | 289 | //JACK BEGIN----------------------------- 290 | 291 | if (jack_activate (client)) { 292 | fprintf (stderr, "cannot activate client"); 293 | exit (1); 294 | } 295 | 296 | /* Connect the ports. You can't do this before the client is 297 | * activated, because we can't make connections to clients 298 | * that aren't running. Note the confusing (but necessary) 299 | * orientation of the driver backend ports: playback ports are 300 | * "input" to the backend, and capture ports are "output" from 301 | * it. 302 | */ 303 | 304 | ports = jack_get_ports (client, NULL, NULL, JackPortIsOutput); 305 | if (ports == NULL) { 306 | fprintf(stderr, "no physical capture ports\n"); 307 | exit (1); 308 | } 309 | 310 | 311 | i=0; 312 | while (ports[i]!=NULL) 313 | { 314 | printf("Connecting to Jack port %s\n",ports[i]); 315 | if (jack_connect (client, ports[i], jack_port_name (input_port))) { 316 | fprintf (stderr, "cannot connect input ports\n"); 317 | } 318 | i++; 319 | } 320 | 321 | free (ports); 322 | 323 | 324 | #ifdef HTTP_REMOTE_CONTROL 325 | uint port=qgetenv("HTTP_PORT").toUInt(); 326 | QxtHttpServerConnector connector; 327 | 328 | QxtHttpSessionManager session; 329 | printf("session.setPort(%i\n", port); fflush(stdout); 330 | session.setPort(port); 331 | session.setConnector(&connector); 332 | 333 | HTTPRemoteControl s1(&session, mainWindow->qprojectM()); 334 | session.setStaticContentService ( &s1); 335 | 336 | printf("session.start()\n"); fflush(stdout); 337 | if(port>0) { // I think it didn't work when the conditional was further up 338 | session.start(); 339 | } 340 | #endif 341 | 342 | 343 | //----------------------------------END 344 | 345 | //return 1; 346 | return app.exec(); 347 | } 348 | 349 | 350 | -------------------------------------------------------------------------------- /src/common/qplaylistmodel.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * projectM-qt -- Qt4 based projectM GUI 3 | * Copyright (C)2003-2004 projectM Team 4 | * 5 | * This library is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public 7 | * License as published by the Free Software Foundation; either 8 | * version 2.1 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public 16 | * License along with this library; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | * See 'LICENSE.txt' included within this release 19 | * 20 | */ 21 | 22 | #include 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | #include "qxmlplaylisthandler.hpp" 32 | #include "qplaylistmodel.hpp" 33 | #include 34 | 35 | QString QPlaylistModel::PRESET_MIME_TYPE("text/x-projectM-preset"); 36 | 37 | class XmlReadFunctor { 38 | public: 39 | XmlReadFunctor(QPlaylistModel & model) : m_model(model) {} 40 | 41 | inline void setPlaylistDesc(const QString & desc) { 42 | m_model.setPlaylistDesc(desc); 43 | } 44 | 45 | inline void appendItem(const QString & url, const QString & name, int rating, int breedability) { 46 | m_model.appendRow(url, name, rating, breedability); 47 | } 48 | 49 | 50 | private: 51 | QPlaylistModel & m_model; 52 | 53 | }; 54 | 55 | 56 | class XmlWriteFunctor { 57 | public: 58 | XmlWriteFunctor(QPlaylistModel & model) : m_model(model), m_index(0) {} 59 | 60 | 61 | inline const QString & playlistDesc() const { 62 | return m_model.playlistDesc(); 63 | } 64 | 65 | inline bool nextItem(QString & name, QString & url, int & rating, int & breedability) { 66 | Q_UNUSED(name); 67 | 68 | if (m_index >= m_model.rowCount()) 69 | return false; 70 | 71 | QModelIndex modelIndex = m_model.index(m_index, 0); 72 | url = m_model.data(modelIndex, QPlaylistModel::URLInfoRole).toString(); 73 | rating = m_model.data(modelIndex, QPlaylistModel::RatingRole).toInt(); 74 | 75 | breedability = m_model.data(modelIndex, QPlaylistModel::BreedabilityRole).toInt(); 76 | 77 | m_index++; 78 | return true; 79 | } 80 | private: 81 | QPlaylistModel & m_model; 82 | int m_index; 83 | 84 | }; 85 | 86 | bool QPlaylistModel::softCutRatingsEnabled() const { 87 | auto projectMSettings = projectm_get_settings(m_projectM); 88 | auto softCutRatingsEnabledValue = projectMSettings->soft_cut_ratings_enabled; 89 | projectm_free_settings(projectMSettings); 90 | return softCutRatingsEnabledValue; 91 | } 92 | 93 | QPlaylistModel::QPlaylistModel ( projectm* _projectM, QObject * parent ) : 94 | QAbstractTableModel ( parent ), m_projectM ( _projectM ) 95 | { 96 | 97 | } 98 | 99 | 100 | void QPlaylistModel::updateItemHighlights() 101 | { 102 | if ( rowCount() == 0 ) 103 | return; 104 | 105 | emit ( dataChanged ( this->index ( 0,0 ), this->index ( rowCount()-1,columnCount()-1 ) ) ); 106 | } 107 | 108 | bool QPlaylistModel::setData ( const QModelIndex & index, const QVariant & value, int role ) 109 | { 110 | if ( role == QPlaylistModel::RatingRole ) 111 | { 112 | projectm_set_preset_rating(m_projectM, index.row(), value.toInt(), PROJECTM_HARD_CUT_RATING_TYPE); 113 | return true; 114 | } else if (role == QPlaylistModel::BreedabilityRole) { 115 | projectm_set_preset_rating(m_projectM, index.row(), value.toInt(), PROJECTM_SOFT_CUT_RATING_TYPE); 116 | return true; 117 | } else if (role == QPlaylistModel::NameRole) { 118 | projectm_set_preset_name(m_projectM, index.row(), value.toString().toLocal8Bit().data()); 119 | return true; 120 | } 121 | else 122 | return QAbstractTableModel::setData ( index, value, role ); 123 | 124 | } 125 | 126 | Qt::ItemFlags QPlaylistModel::flags(const QModelIndex &index) const 127 | { 128 | Qt::ItemFlags defaultFlags = QAbstractTableModel::flags(index); 129 | 130 | if (index.isValid()) 131 | return Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | defaultFlags; 132 | else 133 | return Qt::ItemIsDropEnabled | defaultFlags; 134 | } 135 | 136 | 137 | bool QPlaylistModel::dropMimeData(const QMimeData *data, Qt::DropAction action, 138 | int row, int column, const QModelIndex &parent) 139 | { 140 | Q_UNUSED(row); 141 | Q_UNUSED(parent); 142 | if (!data->hasFormat(PRESET_MIME_TYPE)) 143 | return false; 144 | 145 | if (action == Qt::IgnoreAction) 146 | return true; 147 | 148 | if (column > 0) 149 | return false; 150 | 151 | return true; 152 | } 153 | 154 | QVariant QPlaylistModel::ratingToIcon ( int rating ) const 155 | { 156 | switch ( rating ) 157 | { 158 | case 1: 159 | return QVariant (); 160 | case 2: 161 | return QVariant ( QIcon ( ":/images/icons/rating-1.png" ) ); 162 | case 3: 163 | return QVariant ( QIcon ( ":/images/icons/rating-2.png" ) ); 164 | case 4: 165 | return QVariant ( QIcon ( ":/images/icons/rating-3.png" ) ); 166 | case 5: 167 | return QVariant ( QIcon ( ":/images/icons/rating-4.png" ) ); 168 | case 6: 169 | return QVariant ( QIcon ( ":/images/icons/rating-5.png" ) ); 170 | default: 171 | if (rating <= 0) 172 | return QVariant (); 173 | else 174 | return QVariant ( QIcon ( ":/images/icons/rating-5.png" ) ); 175 | } 176 | } 177 | 178 | 179 | QVariant QPlaylistModel::breedabilityToIcon( int rating ) const 180 | { 181 | switch ( rating ) 182 | { 183 | case 1: 184 | return QVariant (); 185 | case 2: 186 | return QVariant ( QIcon ( ":/images/icons/rating-1.png" ) ); 187 | case 3: 188 | return QVariant ( QIcon ( ":/images/icons/rating-2.png" ) ); 189 | case 4: 190 | return QVariant ( QIcon ( ":/images/icons/rating-3.png" ) ); 191 | case 5: 192 | return QVariant ( QIcon ( ":/images/icons/rating-4.png" ) ); 193 | case 6: 194 | return QVariant ( QIcon ( ":/images/icons/rating-5.png" ) ); 195 | default: 196 | if (rating <= 0) 197 | return QVariant (); 198 | else 199 | return QVariant ( QIcon ( ":/images/icons/rating-5.png" ) ); 200 | } 201 | } 202 | 203 | QString QPlaylistModel::getSillyRatingToolTip(int rating) { 204 | 205 | switch (rating) { 206 | case 1: 207 | return QString("Rather watch grass grow than watch this"); 208 | case 2: 209 | return QString("A very poor preset"); 210 | case 3: 211 | return QString("Tolerable"); 212 | case 4: 213 | return QString("Pretty good"); 214 | case 5: 215 | return QString("Trippy eye candy"); 216 | case 6: 217 | return QString("Crafted by a psychotic deity"); 218 | default: 219 | if (rating <= 0 ) 220 | return QString("So bad it literally makes other presets bad!"); 221 | else 222 | return QString("Better than projectM itself!"); 223 | } 224 | } 225 | 226 | 227 | QString QPlaylistModel::getBreedabilityToolTip(int rating) const { 228 | 229 | switch (rating) { 230 | case 1: 231 | return QString("Hidious."); 232 | case 2: 233 | return QString("Ugly."); 234 | case 3: 235 | return QString("Doable."); 236 | case 4: 237 | return QString("Hot."); 238 | case 5: 239 | return QString("Preset Magnet."); 240 | case 6: 241 | return QString("Preset Whore."); 242 | default: 243 | if (rating <= 0 ) 244 | return QString("Infertile."); 245 | else 246 | return QString("Diseased slut."); 247 | } 248 | } 249 | 250 | QVariant QPlaylistModel::data ( const QModelIndex & index, int role = Qt::DisplayRole ) const 251 | { 252 | 253 | if (!index.isValid()) 254 | return QVariant(); 255 | 256 | unsigned int pos; 257 | const int rowidx = index.row(); 258 | 259 | switch ( role ) 260 | { 261 | case Qt::DisplayRole: 262 | if ( index.column() == 0 ) 263 | { 264 | auto presetName = projectm_get_preset_name(m_projectM, rowidx); 265 | QString qPresetName = QString(presetName); 266 | projectm_free_string(presetName); 267 | return qPresetName; 268 | } 269 | else if (index.column() == 1) 270 | return ratingToIcon (projectm_get_preset_rating(m_projectM, rowidx, PROJECTM_HARD_CUT_RATING_TYPE) ); 271 | else 272 | return ratingToIcon ( projectm_get_preset_rating(m_projectM, rowidx, PROJECTM_SOFT_CUT_RATING_TYPE) ); 273 | case Qt::ToolTipRole: 274 | if ( index.column() == 0 ) 275 | { 276 | auto presetName = projectm_get_preset_name(m_projectM, rowidx); 277 | QString qPresetName = QString(presetName); 278 | projectm_free_string(presetName); 279 | return qPresetName; 280 | } 281 | else if (index.column() == 1) 282 | return QString ( getSillyRatingToolTip(projectm_get_preset_rating(m_projectM, rowidx, PROJECTM_HARD_CUT_RATING_TYPE))); 283 | else return getBreedabilityToolTip(projectm_get_preset_rating(m_projectM, rowidx, PROJECTM_SOFT_CUT_RATING_TYPE)); 284 | case Qt::DecorationRole: 285 | if ( index.column() == 1 ) 286 | return ratingToIcon (projectm_get_preset_rating(m_projectM, rowidx, PROJECTM_HARD_CUT_RATING_TYPE) ); 287 | else if (index.column() == 2) 288 | return breedabilityToIcon ( projectm_get_preset_rating(m_projectM, rowidx, PROJECTM_SOFT_CUT_RATING_TYPE) ); 289 | else 290 | return QVariant(); 291 | case QPlaylistModel::RatingRole: 292 | return QVariant ( projectm_get_preset_rating(m_projectM, rowidx, PROJECTM_HARD_CUT_RATING_TYPE) ); 293 | case QPlaylistModel::BreedabilityRole: 294 | return QVariant ( projectm_get_preset_rating(m_projectM, rowidx, PROJECTM_SOFT_CUT_RATING_TYPE) ); 295 | case Qt::BackgroundRole: 296 | 297 | if (!projectm_get_selected_preset_index(m_projectM, &pos)) 298 | return QVariant(); 299 | if (projectm_is_preset_locked(m_projectM) && rowidx >= 0 && static_cast(rowidx) == pos ) 300 | return QColor(Qt::red); 301 | if (!projectm_is_preset_locked(m_projectM) && rowidx >= 0 && static_cast(rowidx) == pos ) 302 | return QColor(Qt::green); 303 | return QVariant(); 304 | case QPlaylistModel::URLInfoRole: 305 | { 306 | auto presetUrl = projectm_get_preset_filename(m_projectM, rowidx); 307 | QString qPresetUrl(presetUrl); 308 | projectm_free_string(presetUrl); 309 | return qPresetUrl; 310 | } 311 | default: 312 | 313 | return {}; 314 | } 315 | } 316 | 317 | QVariant QPlaylistModel::headerData ( int section, Qt::Orientation orientation, int role ) const 318 | { 319 | 320 | if ( orientation == Qt::Vertical ) 321 | return QAbstractTableModel::headerData ( section, orientation, role ); 322 | if ( ( section == 0 ) && ( role == Qt::DisplayRole ) ) 323 | return QString ( tr ( "Preset" ) ); 324 | 325 | /// @bug hack. this should be formalized like it is in libprojectM. 326 | if ( ( section == 1 ) && ( role == Qt::DisplayRole )) { 327 | if (columnCount() == 2) 328 | return QString ( tr ( "Rating" ) ); 329 | else 330 | return QString ( tr ( "Hard Rating" ) ); 331 | } 332 | if ( ( section == 2 ) && ( role == Qt::DisplayRole ) ) 333 | return QString ( tr ( "Soft Rating" ) ); 334 | 335 | return QAbstractTableModel::headerData ( section, orientation, role ); 336 | } 337 | 338 | int QPlaylistModel::rowCount ( const QModelIndex & parent ) const 339 | { 340 | Q_UNUSED(parent); 341 | 342 | return projectm_get_playlist_size(m_projectM); 343 | } 344 | 345 | 346 | int QPlaylistModel::columnCount ( const QModelIndex & parent ) const 347 | { 348 | Q_UNUSED(parent); 349 | 350 | return softCutRatingsEnabled() ? 3 : 2; 351 | } 352 | 353 | void QPlaylistModel::appendRow ( const QString & presetURL, const QString & presetName, int rating, int breedability ) 354 | { 355 | auto ratings = new int[2]{ rating, breedability }; 356 | 357 | beginInsertRows ( QModelIndex(), rowCount(), rowCount() ); 358 | projectm_add_preset_url(m_projectM, presetURL.toLocal8Bit().data(), presetName.toLocal8Bit().data(), ratings, 2); 359 | endInsertRows(); 360 | 361 | delete[] ratings; 362 | } 363 | 364 | void QPlaylistModel::insertRow (int index, const QString & presetURL, const QString & presetName, int rating, int breedability) { 365 | auto ratings = new int[2]{ rating, breedability }; 366 | 367 | beginInsertRows ( QModelIndex(), index, index); 368 | projectm_insert_preset_url(m_projectM, index, presetURL.toLocal8Bit().data(), presetName.toLocal8Bit().data(), ratings, 2); 369 | endInsertRows(); 370 | } 371 | 372 | bool QPlaylistModel::removeRows ( int row, int count, const QModelIndex & parent) { 373 | Q_UNUSED(parent); 374 | 375 | beginRemoveRows ( QModelIndex(), row, count); 376 | 377 | for (int i = 0; i < count; i++) { 378 | projectm_remove_preset(m_projectM, row); 379 | } 380 | endRemoveRows(); 381 | return true; 382 | } 383 | 384 | bool QPlaylistModel::removeRow ( int index, const QModelIndex & parent) 385 | { 386 | Q_UNUSED(parent); 387 | 388 | beginRemoveRows ( QModelIndex(), index, index ); 389 | projectm_remove_preset(m_projectM, index); 390 | endRemoveRows(); 391 | return true; 392 | } 393 | 394 | void QPlaylistModel::clear() 395 | { 396 | clearItems(); 397 | m_playlistName = ""; 398 | m_playlistDesc = ""; 399 | } 400 | 401 | void QPlaylistModel::clearItems() 402 | { 403 | if (rowCount() > 0) 404 | { 405 | beginRemoveRows(QModelIndex(), 0, rowCount() - 1); 406 | projectm_clear_playlist(m_projectM); 407 | endRemoveRows(); 408 | } 409 | } 410 | 411 | 412 | bool QPlaylistModel::writePlaylist ( const QString & file ) { 413 | 414 | QFile qfile(file); 415 | 416 | if (!qfile.open(QIODevice::WriteOnly)) { 417 | QMessageBox::warning (0, "Playlist Save Error", QString("There was a problem trying to save the playlist \"%1\". You may not have permission to modify this file.").arg(file)); 418 | return false; 419 | } 420 | 421 | XmlWriteFunctor writeFunctor(*this); 422 | 423 | QXmlPlaylistHandler::writePlaylist(&qfile, writeFunctor); 424 | return true; 425 | } 426 | 427 | bool QPlaylistModel::readPlaylist ( const QString & file ) 428 | { 429 | 430 | if (QFileInfo(file).isDir()) { 431 | if (!QDir(file).isReadable()) { 432 | QMessageBox::warning (0, "Playlist Directory Error", QString(tr("There was a problem trying to open the playlist directory \"%1\". The directory doesn't exist or you may not have permission to open it. ")).arg(file)); 433 | return false; 434 | } 435 | 436 | foreach (QFileInfo info, QDir(file).entryInfoList()) { 437 | if (info.fileName().toLower().endsWith(".prjm") || info.fileName().toLower().endsWith(".milk") || info.fileName().toLower().endsWith(".so")) 438 | appendRow(info.absoluteFilePath(), info.fileName(), 3,3); 439 | } 440 | return true; 441 | } 442 | 443 | QFile qfile(file); 444 | if (!qfile.open(QIODevice::ReadOnly)) { 445 | QMessageBox::warning (0, "Playlist File Error", QString(tr("There was a problem trying to open the playlist \"%1\". The file may no longer exist or you may not have permission to read the file.")).arg(file)); 446 | return false; 447 | } 448 | 449 | XmlReadFunctor readFunctor(*this); 450 | 451 | if (QXmlPlaylistHandler::readPlaylist(&qfile, readFunctor) != QXmlStreamReader::NoError) { 452 | QMessageBox::warning ( 0, "Playlist Parse Error", QString(tr("There was a problem trying to parse the playlist \"%1\". Some of your playlist items may have loaded correctly, but don't expect miracles.")).arg(file)); 453 | } 454 | 455 | return true; 456 | } 457 | 458 | void QPlaylistModel::notifyDataChanged(unsigned int ind) 459 | { 460 | 461 | 462 | QModelIndex modelIndex = index (ind, 1); 463 | emit ( dataChanged ( modelIndex, modelIndex)); 464 | } 465 | 466 | --------------------------------------------------------------------------------